namespace X.Reflection
{
using System;
using System.IO;
public static partial class ReflectionX
{
public static PeType GetPeType(this string filepath)
{
using (var fs = File.OpenRead(filepath))
using (var br = new BinaryReader(fs))
{
try
{
if (IMAGE_DOS_SIGNATURE != br.ReadInt16()) return PeType.NotExecutable; fs.Seek(offset__IMAGE_DOS_HEADER__e_lfanew, SeekOrigin.Begin);
var offsetNH = br.ReadUInt32();
if (offsetNH > fs.Length || != offsetNH % || == offsetNH) return PeType.MsDosExecutable;
if (offsetNH + + sizeof__IMAGE_FILE_HEADER + >= fs.Length) return PeType.OptionalHeaderMagicExceedFileLength; fs.Seek(offsetNH, SeekOrigin.Begin);
switch (br.ReadInt16())
{
case IMAGE_NT_SIGNATURE_LOWORD:
if (IMAGE_NT_SIGNATURE_HIWORD == br.ReadInt16()) break;
return PeType.MsDosExecutable; case IMAGE_OS2_SIGNATURE: return PeType.Windows16BitExecutable;
case IMAGE_VXD_SIGNATURE: return PeType.Windows16BitVirtualDeviceDriver;
default: return PeType.MsDosExecutable;
} //fs.Seek //紧跟前面的 pimNH64->Signature,所以不用 fs.Seek
//var machine = br.ReadUInt16();
fs.Seek(offsetNH + offset__IMAGE_NT_HEADERS__FileHeader__Characteristics, SeekOrigin.Begin);
var characteristics = br.ReadUInt16();
//var is32bit = IMAGE_FILE_32BIT_MACHINE & characteristics;
var dllfile = IMAGE_FILE_DLL & characteristics;
//fs.Seek //紧跟前面的 pimNH64->OptionalHeader.Magic,所以不用 fs.Seek
var magic = br.ReadUInt16(); //get RVA
uint rvaCH;
switch (magic)
{
case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
//if (IMAGE_FILE_MACHINE_I386 != machine)
// throw new BadImageFormatException(
// $"幻数值与目标机器类型不一致: IMAGE_NT_HEADERS.OptionalHeader.Magic({magic:X4})/IMAGE_NT_HEADERS.FileHeader.Machine({machine:X4})",
// filepath);
if (offsetNH + offset__IMAGE_NT_HEADERS__OptionalHeader + sizeof__IMAGE_OPTIONAL_HEADER32 > fs.Length)
return PeType.OptionalHeader32ExceedFileLength;
fs.Seek(offsetNH + offset__IMAGE_NT_HEADERS32__OptionalHeader__DataDirectory__14__VirtualAddress, SeekOrigin.Begin);
rvaCH = br.ReadUInt32();
break; case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
//if (IMAGE_FILE_MACHINE_AMD64 != machine)
// throw new BadImageFormatException(
// $"幻数值与目标机器类型不一致: IMAGE_NT_HEADERS.OptionalHeader.Magic({magic:X4})/IMAGE_NT_HEADERS.FileHeader.Machine({machine:X4})",
// filepath);
if (offsetNH + offset__IMAGE_NT_HEADERS__OptionalHeader + sizeof__IMAGE_OPTIONAL_HEADER64 > fs.Length)
return PeType.OptionalHeader64ExceedFileLength;
fs.Seek(offsetNH + offset__IMAGE_NT_HEADERS64__OptionalHeader__DataDirectory__14__VirtualAddress, SeekOrigin.Begin);
rvaCH = br.ReadUInt32();
break; default:
//throw new BadImageFormatException(
// //$"预料之外的幻数值: IMAGE_NT_HEADERS.OptionalHeader.Magic({magic:X4})/IMAGE_NT_HEADERS.FileHeader.Machine({machine:X4})",
// $"预料之外的幻数值: IMAGE_NT_HEADERS.OptionalHeader.Magic({magic:X4})",
// filepath);
return PeType.OptionalHeaderMagicNot3264;
} fs.Seek(offsetNH + offset__IMAGE_NT_HEADERS__OptionalHeader__Subsystem, SeekOrigin.Begin);
var subSystem = br.ReadInt16(); PeType pt;
if ( != rvaCH)
{
//translate RVA to file offset
uint offsetCH = ;
fs.Seek(offsetNH + offset__IMAGE_NT_HEADERS__FileHeader__SizeOfOptionalHeader, SeekOrigin.Begin);
uint offsetSH = offsetNH + offset__IMAGE_NT_HEADERS__OptionalHeader + br.ReadUInt16();
fs.Seek(offsetNH + offset__IMAGE_NT_HEADERS__FileHeader__NumberOfSections, SeekOrigin.Begin);
var numberOfSections = br.ReadUInt16();
while (numberOfSections-- > )
{
if (offsetSH + sizeof__IMAGE_SECTION_HEADER > fs.Length) return PeType.SectionHeaderExceedFileLength;
fs.Seek(offsetSH + offset__IMAGE_SECTION_HEADER__VirtualAddress, SeekOrigin.Begin);
var VirtualAddress = br.ReadUInt32();
var SizeOfRawData = br.ReadUInt32();
if (VirtualAddress <= rvaCH && rvaCH < VirtualAddress + SizeOfRawData)
{
offsetCH = br.ReadUInt32() + rvaCH - VirtualAddress;
break;
}
offsetSH += sizeof__IMAGE_SECTION_HEADER;
}
if (offsetCH + sizeof__IMAGE_COR20_HEADER > fs.Length) return PeType.Cor20HeaderExceedFileLength;
fs.Seek(offsetCH + offset__IMAGE_COR20_HEADER__Flags, SeekOrigin.Begin);
uint chFlags = br.ReadUInt32(); if ( != (COMIMAGE_FLAGS_ILONLY & chFlags))
{
if ( != (COMIMAGE_FLAGS_32BITREQUIRED & chFlags)) //X86
{
pt = (PeType)PeTypeBitness.X86 | (( != (COMIMAGE_FLAGS_32BITPREFERRED & chFlags))
? (PeType)PeTypePlatform.AnyCPU //AnyCPU32
: (PeType)PeTypePlatform.ILOnly //ILOnly32
);
}
else //X64
{
pt = (PeType)PeTypeBitness.X64;
switch (magic)
{
case IMAGE_NT_OPTIONAL_HDR32_MAGIC: pt |= (PeType)PeTypePlatform.AnyCPU; break; //AnyCPU64
case IMAGE_NT_OPTIONAL_HDR64_MAGIC: pt |= (PeType)PeTypePlatform.ILOnly; break; //ILOnly64
}
}
}
else //Mixed
{
pt = (PeType)PeTypePlatform.Mixing;
switch (magic)
{
case IMAGE_NT_OPTIONAL_HDR32_MAGIC: pt |= (PeType)PeTypeBitness.X86; break; //Mixed32
case IMAGE_NT_OPTIONAL_HDR64_MAGIC: pt |= (PeType)PeTypeBitness.X64; break; //Mixed64
}
} //file ext & subsystem
if ( == dllfile)
{
pt |= (PeType)PeTypeExt.Exe;
switch (subSystem)
{
case IMAGE_SUBSYSTEM_WINDOWS_GUI: pt |= (PeType)PeTypeSubSystem.WindowsGui; break;
case IMAGE_SUBSYSTEM_WINDOWS_CUI: pt |= (PeType)PeTypeSubSystem.ConsoleCui; break;
}
}
else
{
pt |= (PeType)PeTypeExt.Dll;
}
}
else //Native
{
pt = (PeType)PeTypePlatform.Native;
switch (magic)
{
case IMAGE_NT_OPTIONAL_HDR32_MAGIC: pt |= (PeType)PeTypeBitness.X86; break; //Native32
case IMAGE_NT_OPTIONAL_HDR64_MAGIC: pt |= (PeType)PeTypeBitness.X64; break; //Native64
} //file ext & subsystem
if (IMAGE_SUBSYSTEM_NATIVE == subSystem)
{
pt |= (PeType)PeTypeExt.Drv;
}
else if ( == dllfile)
{
pt |= (PeType)PeTypeExt.Exe;
switch (subSystem)
{
case IMAGE_SUBSYSTEM_WINDOWS_GUI: pt |= (PeType)PeTypeSubSystem.WindowsGui; break;
case IMAGE_SUBSYSTEM_WINDOWS_CUI: pt |= (PeType)PeTypeSubSystem.ConsoleCui; break;
}
}
else
{
pt |= (PeType)PeTypeExt.Dll;
}
}
return pt;
}
catch (Exception ex)
{
return PeType.ErrorOccurred;
}
}
} private const int offset__IMAGE_DOS_HEADER__e_lfanew = ;
private const int offset__IMAGE_NT_HEADERS__FileHeader__NumberOfSections = + ;
private const int offset__IMAGE_NT_HEADERS__FileHeader__SizeOfOptionalHeader = + ;
private const int offset__IMAGE_NT_HEADERS__FileHeader__Characteristics = + ;
private const int offset__IMAGE_NT_HEADERS__OptionalHeader = + sizeof__IMAGE_FILE_HEADER;
private const int offset__IMAGE_NT_HEADERS__OptionalHeader__Subsystem = offset__IMAGE_NT_HEADERS__OptionalHeader + * ;
private const int offset__IMAGE_NT_HEADERS32__OptionalHeader__DataDirectory__14__VirtualAddress = offset__IMAGE_NT_HEADERS__OptionalHeader + + * ;
private const int offset__IMAGE_NT_HEADERS64__OptionalHeader__DataDirectory__14__VirtualAddress = offset__IMAGE_NT_HEADERS__OptionalHeader + + * ;
private const int offset__IMAGE_SECTION_HEADER__VirtualAddress = + ;
private const int offset__IMAGE_COR20_HEADER__Flags = + + + ; private const int sizeof__IMAGE_FILE_HEADER = ;
private const int sizeof__IMAGE_OPTIONAL_HEADER32 = + * ;
private const int sizeof__IMAGE_OPTIONAL_HEADER64 = + * ;
private const int sizeof__IMAGE_SECTION_HEADER = ;
private const int sizeof__IMAGE_COR20_HEADER = ; private const int IMAGE_DOS_SIGNATURE = 0x5A4D;
private const int IMAGE_OS2_SIGNATURE = 0x454E;
private const int IMAGE_VXD_SIGNATURE = 0x454C;
private const int IMAGE_NT_SIGNATURE_LOWORD = 0x4550;
private const int IMAGE_NT_SIGNATURE_HIWORD = 0x0000;
private const int IMAGE_FILE_MACHINE_I386 = 0x014C;
private const int IMAGE_FILE_MACHINE_AMD64 = 0x8664;
private const int IMAGE_FILE_32BIT_MACHINE = 0x0100;
private const int IMAGE_FILE_DLL = 0x2000;
private const int IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10B;
private const int IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20B; //private const int IMAGE_SUBSYSTEM_UNKNOWN = 0; // Unknown subsystem.
private const int IMAGE_SUBSYSTEM_NATIVE = ; // Image doesn't require a subsystem.
private const int IMAGE_SUBSYSTEM_WINDOWS_GUI = ; // Image runs in the Windows GUI subsystem.
private const int IMAGE_SUBSYSTEM_WINDOWS_CUI = ; // Image runs in the Windows character subsystem.
//private const int IMAGE_SUBSYSTEM_OS2_CUI = 5; // image runs in the OS/2 character subsystem.
//private const int IMAGE_SUBSYSTEM_POSIX_CUI = 7; // image runs in the Posix character subsystem.
//private const int IMAGE_SUBSYSTEM_NATIVE_WINDOWS = 8; // image is a native Win9x driver.
//private const int IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9; // Image runs in the Windows CE subsystem.
//private const int IMAGE_SUBSYSTEM_EFI_APPLICATION = 10; //
//private const int IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11; //
//private const int IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12; //
//private const int IMAGE_SUBSYSTEM_EFI_ROM = 13;
//private const int IMAGE_SUBSYSTEM_XBOX = 14;
//private const int IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION = 16;
//private const int IMAGE_SUBSYSTEM_XBOX_CODE_CATALOG = 17; private const int COMIMAGE_FLAGS_ILONLY = 0x00000001;
private const int COMIMAGE_FLAGS_32BITREQUIRED = 0x00000002;
//private const int COMIMAGE_FLAGS_IL_LIBRARY = 0x00000004;
//private const int COMIMAGE_FLAGS_STRONGNAMESIGNED = 0x00000008;
//private const int COMIMAGE_FLAGS_NATIVE_ENTRYPOINT = 0x00000010;
//private const int COMIMAGE_FLAGS_TRACKDEBUGDATA = 0x00010000;
private const int COMIMAGE_FLAGS_32BITPREFERRED = 0x00020000;
}
[Flags]
public enum PeTypePlatform
{
AnyCPU = 0x0001,
ILOnly = 0x0002,
Native = 0x0004,
Mixing = 0x0008, Unknow = 0x0000,
BitMask = 0x00FF,
BitMastDotNet = 0x0007,
}
[Flags]
public enum PeTypeBitness
{
X64 = 0x0100,
X86 = 0x0200, NoBit = 0x0000,
BitMask = 0x0F00,
}
[Flags]
public enum PeTypeExt
{
Exe = 0x1000,
Dll = 0x2000,
Drv = 0x3000, NoExt = 0x0000,
BitMask = 0xF000,
}
[Flags]
public enum PeTypeSubSystem
{
//DeviceDrv = 0x1_0000,
WindowsGui = 0x2_0000,
ConsoleCui = 0x3_0000,
//Win9xDrv = 0x8_0000, Unknow = 0x0_0000,
BitMask = 0xF_0000,
}
[Flags]
public enum PeType
{
AnyCPU32BitExeWindowsGui = PeTypePlatform.AnyCPU | PeTypeBitness.X86 | PeTypeExt.Exe | PeTypeSubSystem.WindowsGui,
AnyCPU64BitExeWindowsGui = PeTypePlatform.AnyCPU | PeTypeBitness.X64 | PeTypeExt.Exe | PeTypeSubSystem.WindowsGui,
ILOnly32BitExeWindowsGui = PeTypePlatform.ILOnly | PeTypeBitness.X86 | PeTypeExt.Exe | PeTypeSubSystem.WindowsGui,
ILOnly64BitExeWindowsGui = PeTypePlatform.ILOnly | PeTypeBitness.X64 | PeTypeExt.Exe | PeTypeSubSystem.WindowsGui,
Native32BitExeWindowsGui = PeTypePlatform.Native | PeTypeBitness.X86 | PeTypeExt.Exe | PeTypeSubSystem.WindowsGui,
Native64BitExeWindowsGui = PeTypePlatform.Native | PeTypeBitness.X64 | PeTypeExt.Exe | PeTypeSubSystem.WindowsGui,
Mixing32BitExeWindowsGui = PeTypePlatform.Mixing | PeTypeBitness.X86 | PeTypeExt.Exe | PeTypeSubSystem.WindowsGui,
Mixing64BitExeWindowsGui = PeTypePlatform.Mixing | PeTypeBitness.X64 | PeTypeExt.Exe | PeTypeSubSystem.WindowsGui, AnyCPU32BitExeConsoleCui = PeTypePlatform.AnyCPU | PeTypeBitness.X86 | PeTypeExt.Exe | PeTypeSubSystem.ConsoleCui,
AnyCPU64BitExeConsoleCui = PeTypePlatform.AnyCPU | PeTypeBitness.X64 | PeTypeExt.Exe | PeTypeSubSystem.ConsoleCui,
ILOnly32BitExeConsoleCui = PeTypePlatform.ILOnly | PeTypeBitness.X86 | PeTypeExt.Exe | PeTypeSubSystem.ConsoleCui,
ILOnly64BitExeConsoleCui = PeTypePlatform.ILOnly | PeTypeBitness.X64 | PeTypeExt.Exe | PeTypeSubSystem.ConsoleCui,
Native32BitExeConsoleCui = PeTypePlatform.Native | PeTypeBitness.X86 | PeTypeExt.Exe | PeTypeSubSystem.ConsoleCui,
Native64BitExeConsoleCui = PeTypePlatform.Native | PeTypeBitness.X64 | PeTypeExt.Exe | PeTypeSubSystem.ConsoleCui,
Mixing32BitExeConsoleCui = PeTypePlatform.Mixing | PeTypeBitness.X86 | PeTypeExt.Exe | PeTypeSubSystem.ConsoleCui,
Mixing64BitExeConsoleCui = PeTypePlatform.Mixing | PeTypeBitness.X64 | PeTypeExt.Exe | PeTypeSubSystem.ConsoleCui, AnyCPU32BitExe = PeTypePlatform.AnyCPU | PeTypeBitness.X86 | PeTypeExt.Exe,
AnyCPU64BitExe = PeTypePlatform.AnyCPU | PeTypeBitness.X64 | PeTypeExt.Exe,
ILOnly32BitExe = PeTypePlatform.ILOnly | PeTypeBitness.X86 | PeTypeExt.Exe,
ILOnly64BitExe = PeTypePlatform.ILOnly | PeTypeBitness.X64 | PeTypeExt.Exe,
Native32BitExe = PeTypePlatform.Native | PeTypeBitness.X86 | PeTypeExt.Exe,
Native64BitExe = PeTypePlatform.Native | PeTypeBitness.X64 | PeTypeExt.Exe,
Mixing32BitExe = PeTypePlatform.Mixing | PeTypeBitness.X86 | PeTypeExt.Exe,
Mixing64BitExe = PeTypePlatform.Mixing | PeTypeBitness.X64 | PeTypeExt.Exe, AnyCPU32BitDll = PeTypePlatform.AnyCPU | PeTypeBitness.X86 | PeTypeExt.Dll,
AnyCPU64BitDll = PeTypePlatform.AnyCPU | PeTypeBitness.X64 | PeTypeExt.Dll,
ILOnly32BitDll = PeTypePlatform.ILOnly | PeTypeBitness.X86 | PeTypeExt.Dll,
ILOnly64BitDll = PeTypePlatform.ILOnly | PeTypeBitness.X64 | PeTypeExt.Dll,
Native32BitDll = PeTypePlatform.Native | PeTypeBitness.X86 | PeTypeExt.Dll,
Native64BitDll = PeTypePlatform.Native | PeTypeBitness.X64 | PeTypeExt.Dll,
Mixing32BitDll = PeTypePlatform.Mixing | PeTypeBitness.X86 | PeTypeExt.Dll,
Mixing64BitDll = PeTypePlatform.Mixing | PeTypeBitness.X64 | PeTypeExt.Dll, AnyCPU32BitDrv = PeTypePlatform.AnyCPU | PeTypeBitness.X86 | PeTypeExt.Drv,
AnyCPU64BitDrv = PeTypePlatform.AnyCPU | PeTypeBitness.X64 | PeTypeExt.Drv,
ILOnly32BitDrv = PeTypePlatform.ILOnly | PeTypeBitness.X86 | PeTypeExt.Drv,
ILOnly64BitDrv = PeTypePlatform.ILOnly | PeTypeBitness.X64 | PeTypeExt.Drv,
Native32BitDrv = PeTypePlatform.Native | PeTypeBitness.X86 | PeTypeExt.Drv,
Native64BitDrv = PeTypePlatform.Native | PeTypeBitness.X64 | PeTypeExt.Drv,
Mixing32BitDrv = PeTypePlatform.Mixing | PeTypeBitness.X86 | PeTypeExt.Drv,
Mixing64BitDrv = PeTypePlatform.Mixing | PeTypeBitness.X64 | PeTypeExt.Drv, MsDosExecutable,
Windows16BitExecutable,
Windows16BitVirtualDeviceDriver, Unknow = PeTypePlatform.Unknow | PeTypeBitness.NoBit | PeTypeExt.NoExt, ErrorOccurred = int.MinValue,
NotExecutable,
OptionalHeaderMagicNot3264,
OptionalHeaderMagicExceedFileLength,
OptionalHeader32ExceedFileLength,
OptionalHeader64ExceedFileLength,
SectionHeaderExceedFileLength,
Cor20HeaderExceedFileLength,
}
}

读文件头数据判断 PE 文件格式和类型的更多相关文章

  1. PE文件格式详解(下)

    作者:MSDN译者:李马 预定义段 一个Windows NT的应用程序典型地拥有9个预定义段,它们是.text..bss..rdata..data..rsrc..edata..idata..pdata ...

  2. Python学习入门基础教程(learning Python)--5.6 Python读文件操作高级

    前文5.2节和5.4节分别就Python下读文件操作做了基础性讲述和提升性介绍,但是仍有些问题,比如在5.4节里涉及到一个多次读文件的问题,实际上我们还没有完全阐述完毕,下面这个图片的问题在哪呢? 问 ...

  3. (四)关于读文件的结束的判别方法(EOF和feof)以及区别

    关于读文件的时候判断文本是否读完的方式一般可以通过EOF,一般宏定义为-1.因为ASCII码中不可能出现-1. 当以文本形式读取文件内容, 读入的字符值等于EOF时, 表示读入的已不是正常的字符而是文 ...

  4. C++PE文件格式解析类(轻松制作自己的PE文件解析器)

    PE是Portable Executable File Format(可移植的运行体)简写,它是眼下Windows平台上的主流可运行文件格式. PE文件里包括的内容非常多,详细我就不在这解释了,有兴趣 ...

  5. python读文件判断是否已到EOF

    python读文件判断是否已到EOF,也即结尾,一般其它语言都是以EOF直接来判断的,比如 if ( fp.read(chunk_size) == EOF), 但python到结尾后是返回空字符串的, ...

  6. 0day笔记(1)PE文件格式与虚拟文件内存的映射

    PE文件格式 PE 文件格式把可执行文件分成若干个数据节(section),不同的资源被存放在不同的节中. 一个典型的 PE 文件中包含的节如下: .text 存放着二进制的机器代码 .data 初始 ...

  7. 深入理解 Win32 PE 文件格式

    深入理解 Win32 PE 文件格式 Matt Pietrek 这篇文章假定你熟悉C++和Win32. 概述 理解可移植可执行文件格式(PE)可以更好地了解操作系统.如果你知道DLL和EXE中都有些什 ...

  8. PE文件格式分析

    PE文件格式分析 PE 的意思是 Portable Executable(可移植的执行体).它是 Win32环境自身所带的执行文件格式.它的一些特性继承自Unix的Coff(common object ...

  9. 深入理解 Win32 PE 文件格式 Matt Pietrek(慢慢体会)

    这篇文章假定你熟悉C++和Win32. 概述 理解可移植可执行文件格式(PE)可以更好地了解操作系统.如果你知道DLL和EXE中都有些什么东西,那么你就是一个知识渊博的程序员.这一系列文章的第一部分, ...

随机推荐

  1. 各消息队列对比,Kafka深度解析,众人推荐,精彩好文!

    http://blog.csdn.net/allthesametome/article/details/47362451

  2. WMI获取进程CPU占用率

    Monitor % Process CPU Usage (specific process) http://www.tek-tips.com/viewthread.cfm?qid=395765 for ...

  3. 将yyyyMMdd格式的字符串转成日期DateTime格式

    1.DateTime dt= DateTime.ParseExact("20110720", "yyyyMMdd", Thread.CurrentThread. ...

  4. Junit4.x高级使用方法具体解释(一)

    近期整理代码的时候,总习惯把一些经常使用的工具类和方法等都写在junit中,这样能够方便于在想用的时候直接copy,在用junit的时候学到了一些比較实用的东西.记录例如以下: 1.使用junit进行 ...

  5. 为SSD编程(4)——高级功能和内部并行

    原文 http://codecapsule.com/2014/02/12/coding-for-ssds-part-4-advanced-functionalities-and-internal-pa ...

  6. 华为荣耀3C最新版ROM的root,(4.7.1和4.8.1等等通用方法)

    手头一台honor 3c的机器.应该是线刷的时候,把IMEI给刷掉了.导致移动2G卡无法上网. 刷了4.7.1或者4.8.1.尝试了全部方法都root失败了. 正好我手头有6582的代码.我想.既然系 ...

  7. SQL 增删改查(具体)

    一.增:有3种方法 1.使用insert插入单行数据: insert [into] <表名> [列名] values <列值> insert into Strdents (na ...

  8. cocos2d-x的声音控制

    声音控制SimpleAudioEngine是单例.下面是其方法. [cpp] view plaincopy //获得SimpleAudioEngine的实例 static SimpleAudioEng ...

  9. C#与Linux守护进程

    用C#编写Linux守护进程   如果要在Red Hat Enterprise Linux上将.NET Core进程作为后台进程运行,则可以创建自定义systemd单元.今天我将为.NET Core编 ...

  10. js中的组合模式

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...