C# 實現從內存加載動態鏈接庫(支持加了殼的DLL)

 

很早的時候用VB6.0寫過一次,今天找出來做成C# 的

完整源碼下載地址

https://download.csdn.net/download/vblegend_2013/10653851

 從內存加載DLL 步驟

1.加載DLLByte數組並校驗數據有效性,通過校驗 DOSHEADER、NTHEADER、SECTION_HEADER 三個位置實現驗證

2.計算Dll加載到內存後所需要的空間,

3.申請內存,並設置爲可讀可寫可執行

4.拷貝DLL中 步驟1中提到的三個段頭,和所有區段數據到內存

5.重定位 IMAGE_DIRECTORY_ENTRY_BASERELOC 區段的重定位表

6.填充IMAGE_DIRECTORY_ENTRY_IMPORT 導入表裏所有導入函數

7.調用Dll的DllMain函數通知DLL加載(加殼的DLL會在DllMain裏進行殼的初始化)

使用方法

使用委託的方式調用API函數 下面例子演示了調用zlib.dLL裏的compress函數

using System;
using System.IO;

namespace InvokeDll
{
    class Program
    {
        public delegate Int32 CompressHandle(ref Byte dest,ref Int32 len, Byte [] source,Int32 sourcelen);

        static void Main(string[] args)
        {
            Byte[] source = new byte[10000];
            Byte[] dest = new byte[10000];
            Int32 len = source.Length;
            Byte[] dllBin = File.ReadAllBytes("zlib1.dll");

            using (var dll = new DllLoader())
            {
                if (dll.LoadLibrary(dllBin))
                {
                    var Compress = dll.GetProcDelegate<CompressHandle>("compress");
                    if (Compress != null)
                    {
                        var result = Compress.Invoke(ref dest[0], ref len, source, len);
                        Console.WriteLine(result);
                    }
                }
            }
        }
    }
}

 需要使用到的WindowsAPI

using System;
using System.Runtime.InteropServices;

namespace InvokeDll.Win32
{
    public enum IMAGE_DIRECTORY_ENTRY
    {
        IMAGE_DIRECTORY_ENTRY_EXPORT = 0,//                    ' Export Directory
        IMAGE_DIRECTORY_ENTRY_IMPORT = 1,//                ' Import Directory
        IMAGE_DIRECTORY_ENTRY_RESOURCE = 2,//                 ' Resource Directory
        IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3,//                 ' Exception Directory
        IMAGE_DIRECTORY_ENTRY_SECURITY = 4,//                ' Security Directory
        IMAGE_DIRECTORY_ENTRY_BASERELOC = 5,//                ' Base Relocation Table
        IMAGE_DIRECTORY_ENTRY_DEBUG = 6,//             ' Debug Directory
        IMAGE_DIRECTORY_ENTRY_ARCHITECTURE = 7,//                    ' Architecture Specific Data
        IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8,//               ' RVA of GP
        IMAGE_DIRECTORY_ENTRY_TLS = 9,//          ' TLS Directory
        IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10,//                  ' Load Configuration Directory
        IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11,//                ' Bound Import Directory in headers
        IMAGE_DIRECTORY_ENTRY_IAT = 12,//       ;//   ' Import Address Table
        IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13,//                  ' Delay Load Import Descriptors
        IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14//                 ' COM Runtime descriptor
    }

    public class API
    {
        public const Int32 MEM_COMMIT = 0x1000;
        public const Int32 MEM_RESERVE = 0x2000;
        public const Int32 MEM_RELEASE = 0x8000;
        public const Int32 IMAGE_NT_SIGNATURE = 0x4550;
        public const Int32 IMAGE_FILE_DLL = 0x2000;
        public const Int32 PAGE_EXECUTE_READWRITE = 0x40;
        public const Int32 IMAGE_REL_BASED_HIGHLOW = 3;
        public const Int32 DLL_PROCESS_ATTACH = 1;
        public const Int32 DLL_THREAD_ATTACH = 2;
        public const Int32 DLL_THREAD_DETACH = 3;
        public const Int32 DLL_PROCESS_DETACH = 0;


        [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
        public static extern IntPtr VirtualAllocEx(Int32 hProcess, Int32 lpAddress, Int32 dwSize, Int32 flAllocationType, Int32 flProtect);

        [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
        public static extern bool VirtualFreeEx(Int32 hProcess, IntPtr lpAddress, int dwSize, Int32 dwFreeType);

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetModuleHandle(string lpModuleName);

        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern IntPtr LoadLibrary(string lpFileName);

        [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
        public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

        [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
        public static extern IntPtr GetProcAddress(IntPtr hModule, Int32 procName);


        [DllImport("kernel32.dll")]
        public static extern void CopyMemory(IntPtr Destination, IntPtr Source, int Length);
    }

    public unsafe struct IMAGE_FILE_HEADER
    {
        public Int16 Machine { get; set; }
        public Int16 NumberOfSections { get; set; }
        public Int32 TimeDateStamp { get; set; }
        public Int32 PointerToSymbolTable { get; set; }
        public Int32 NumberOfSymbols { get; set; }
        public Int16 SizeOfOptionalHeader { get; set; }
        public Int16 Characteristics { get; set; }
    }

    public unsafe struct IMAGE_DATA_DIRECTORY
    {
        public Int32 VirtualAddress { get; set; }
        public Int32 Size { get; set; }
    }


    public unsafe struct IMAGE_MISC
    {
        public Int32 PhysicalAddress { get; set; }
        public Int32 VirtualSize { get; set; }
    }

    public unsafe struct IMAGE_IMPORT_DESCRIPTOR
    {
        public Int32 OriginalFirstThunk { get; set; }
        public Int32 TimeDateStamp { get; set; }
        public Int32 ForwarderChain { get; set; }
        public Int32 Name { get; set; }
        public Int32 FirstThunk { get; set; }
    }

    public unsafe struct IMAGE_IMPORT_BY_NAME
    {
        public Int16 Hint { get; set; }
        public fixed Byte Name_[260];
    }

    public unsafe struct IMAGE_EXPORT_DIRECTORY
    {
        public Int32 Characteristics { get; set; }
        public Int32 TimeDateStamp { get; set; }
        public Int16 MajorVersion { get; set; }
        public Int16 MinorVersion { get; set; }
        public Int32 pName { get; set; }
        public Int32 Base { get; set; }
        public Int32 NumberOfFunctions { get; set; }
        public Int32 NumberOfNames { get; set; }
        public Int32 AddressOfFunctions { get; set; }
        public Int32 AddressOfNames { get; set; }
        public Int32 AddressOfNameOrdinals { get; set; }
    }

    public unsafe struct IMAGE_DOS_HEADER
    {
        public Int16 e_magic { get; set; }
        public Int16 e_cblp { get; set; }
        public Int16 e_cp { get; set; }
        public Int16 e_crlc { get; set; }
        public Int16 e_cparhdr { get; set; }
        public Int16 e_minalloc { get; set; }
        public Int16 e_maxalloc { get; set; }
        public Int16 e_ss { get; set; }
        public Int16 e_sp { get; set; }
        public Int16 e_csum { get; set; }
        public Int16 e_ip { get; set; }
        public Int16 e_cs { get; set; }
        public Int16 e_lfarlc { get; set; }
        public Int16 e_ovno { get; set; }
        public fixed Int16 e_res[4];
        public Int16 e_oemid { get; set; }
        public Int16 e_oeminfo { get; set; }
        public fixed Int16 e_res2[10];
        public Int16 e_lfanew { get; set; }

    }



    public unsafe struct IMAGE_OPTIONAL_HEADER32
    {
        public Int16 Magic { get; set; }
        public Byte MajorLinkerVersion { get; set; }
        public Byte MinorLinkerVersion { get; set; }
        public Int32 SizeOfCode { get; set; }
        public Int32 SizeOfInitializedData { get; set; }
        public Int32 SizeOfUninitializedData { get; set; }
        public Int32 AddressOfEntryPoint { get; set; }
        public Int32 BaseOfCode { get; set; }
        public Int32 BaseOfData { get; set; }
        public Int32 ImageBase { get; set; }
        public Int32 SectionAlignment { get; set; }
        public Int32 FileAlignment { get; set; }
        public Int16 MajorOperatingSystemVersion { get; set; }
        public Int16 MinorOperatingSystemVersion { get; set; }
        public Int16 MajorImageVersion { get; set; }
        public Int16 MinorImageVersion { get; set; }
        public Int16 MajorSubsystemVersion { get; set; }
        public Int16 MinorSubsystemVersion { get; set; }
        public Int32 Win32VersionValue { get; set; }
        public Int32 SizeOfImage { get; set; }
        public Int32 SizeOfHeaders { get; set; }
        public Int32 CheckSum { get; set; }
        public Int16 Subsystem { get; set; }
        public Int16 DllCharacteristics { get; set; }
        public Int32 SizeOfStackReserve { get; set; }
        public Int32 SizeOfStackCommit { get; set; }
        public Int32 SizeOfHeapReserve { get; set; }
        public Int32 SizeOfHeapCommit { get; set; }
        public Int32 LoaderFlags { get; set; }
        public Int32 NumberOfRvaAndSizes { get; set; }
        public fixed Int32 DataDirectory[32];
        /// <summary>
        /// 獲取數據目錄
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public IMAGE_DATA_DIRECTORY GetDirectory(IMAGE_DIRECTORY_ENTRY index)
        {
            fixed (int* p = DataDirectory)
            {
                IMAGE_DATA_DIRECTORY* DATA = (IMAGE_DATA_DIRECTORY*)p;
                DATA += (Int32)index;
                return *DATA;
            }
        }
    }

    public unsafe struct IMAGE_NT_HEADERS
    {
        public Int32 Signature { get; set; }
        public IMAGE_FILE_HEADER FileHeader { get; set; }
        public IMAGE_OPTIONAL_HEADER32 OptionalHeader { get; set; }
    }

    //Public Const IMAGE_SIZEOF_SHORT_NAME             As Long = 8&
    public unsafe struct IMAGE_SECTION_HEADER
    {
        public fixed Byte Name_[8];
        public Int32 Misc { get; set; }
        public Int32 VirtualAddress { get; set; }
        public Int32 SizeOfRawData { get; set; }
        public Int32 PointerToRawData { get; set; }
        public Int32 PointerToRelocations { get; set; }
        public Int32 PointerToLinenumbers { get; set; }
        public Int16 NumberOfRelocations { get; set; }
        public Int16 NumberOfLinenumbers { get; set; }
        public Int32 Characteristics { get; set; }
    }

    public unsafe struct IMAGE_BASE_RELOCATION
    {
        public Int32 VirtualAddress { get; set; }
        public Int32 SizeOfBlock { get; set; }
    }
}

 DllLoader 類

using System;
using System.IO;
using System.Runtime.InteropServices;
using InvokeDll.Win32;

namespace InvokeDll
{
    /// <summary>
    /// DllMain函數委託
    /// </summary>
    /// <param name="hModule"></param>
    /// <param name="ul_reason_for_call"></param>
    /// <param name="lpReserved"></param>
    /// <returns></returns>
    public delegate Boolean DllMainHandle(IntPtr hModule, UInt32 ul_reason_for_call, IntPtr lpReserved);
    /// <summary>
    /// 動態鏈接庫內存加載器
    /// </summary>
    public class DllLoader : IDisposable
    {
        /// <summary>
        /// 從Byte數組加載Dll
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public Boolean LoadLibrary(Byte[] data)
        {
            IntPtr buffer = IntPtr.Zero;
            try
            {
                buffer = Marshal.AllocHGlobal(data.Length);
                Marshal.Copy(data, 0, buffer, data.Length);
                return LoadDll(buffer, data.Length);
            }
            catch (Exception ex)
            {
                if (hModule != IntPtr.Zero)
                {
                    API.VirtualFreeEx(-1, hModule, hModuleSize, API.MEM_RELEASE);
                    hModule = IntPtr.Zero;
                }
                throw ex;
            }
            finally
            {
                Marshal.FreeHGlobal(buffer);
            }
        }
        /// <summary>
        /// 加載dLL
        /// </summary>
        /// <param name="localPtr"></param>
        /// <param name="DataLength"></param>
        /// <returns></returns>
        private unsafe Boolean LoadDll(IntPtr localPtr, Int32 DataLength)
        {
            IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)localPtr;
            IMAGE_NT_HEADERS* peHeader = (IMAGE_NT_HEADERS*)(localPtr + dosHeader->e_lfanew);
            IMAGE_SECTION_HEADER* sectionHeader = (IMAGE_SECTION_HEADER*)(localPtr + dosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS));
            if (dosHeader->e_magic != 0x5A4D)
            {
                throw new Exception("DOS file format error");
            }
            if (DataLength < dosHeader->e_lfanew + sizeof(IMAGE_DOS_HEADER))
            {
                throw new Exception("DOS file header data error");
            }
            if (peHeader->Signature != API.IMAGE_NT_SIGNATURE)
            {
                throw new Exception("windows file Signature error");
            }
            if ((peHeader->FileHeader.Characteristics & API.IMAGE_FILE_DLL) != API.IMAGE_FILE_DLL)
            {
                throw new Exception("Dll Not dynamic library");
            }
            for (int i = 0; i < peHeader->FileHeader.NumberOfSections; i++)
            {
                if (sectionHeader->PointerToRawData + sectionHeader->SizeOfRawData > DataLength)
                {
                    throw new Exception("Section data error");
                }
            }
            //計算空間
            hModuleSize = CalcTotalImageSize(dosHeader, peHeader, sectionHeader);
            if (hModuleSize <= 0 || hModuleSize > DataLength * 10)
            {
                throw new Exception("unknown error");
            }
            hModule = API.VirtualAllocEx(-1, peHeader->OptionalHeader.ImageBase, hModuleSize, API.MEM_COMMIT | API.MEM_RESERVE, API.PAGE_EXECUTE_READWRITE);
            if (hModule == IntPtr.Zero)
            {
                hModule = API.VirtualAllocEx(-1, 0, hModuleSize, API.MEM_COMMIT | API.MEM_RESERVE, API.PAGE_EXECUTE_READWRITE);
            }
            if (hModule == IntPtr.Zero)
            {
                throw new Exception("run out of memory?");
            }
            CopyDllDatas(localPtr, dosHeader, peHeader, sectionHeader);
            dosHeader = (IMAGE_DOS_HEADER*)hModule;
            peHeader = (IMAGE_NT_HEADERS*)(hModule + dosHeader->e_lfanew);
            sectionHeader = (IMAGE_SECTION_HEADER*)(hModule + dosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS));
            //重定位
            var DataDictory = peHeader->OptionalHeader.GetDirectory(IMAGE_DIRECTORY_ENTRY.IMAGE_DIRECTORY_ENTRY_BASERELOC);
            if (DataDictory.VirtualAddress > 0 && DataDictory.Size > 0)
            {
                ReLocation(peHeader);
            }
            FillImportTable(peHeader);
            DllMain = (DllMainHandle)Marshal.GetDelegateForFunctionPointer(hModule + peHeader->OptionalHeader.AddressOfEntryPoint, typeof(DllMainHandle));
            return DllMain.Invoke(hModule, API.DLL_PROCESS_ATTACH, IntPtr.Zero);
        }
        /// <summary>
        /// 填充導入表
        /// </summary>
        /// <param name="peHeader"></param>
        private unsafe void FillImportTable(IMAGE_NT_HEADERS* peHeader)
        {
            var Offset = peHeader->OptionalHeader.GetDirectory(IMAGE_DIRECTORY_ENTRY.IMAGE_DIRECTORY_ENTRY_IMPORT).VirtualAddress;
            if (Offset == 0)
            {
                return;
            }
            IMAGE_IMPORT_DESCRIPTOR* Import = (IMAGE_IMPORT_DESCRIPTOR*)(hModule + Offset);

            while (Import->FirstThunk > 0)
            {
                Int32* pRealIAT = (Int32*)(hModule + Import->FirstThunk);
                Int32* pOriginalIAT =
                    (Int32*)(hModule + (Import->OriginalFirstThunk > 0
                    ? Import->OriginalFirstThunk
                    : Import->FirstThunk));

                var DllName = Marshal.PtrToStringAnsi(hModule + Import->Name);

                var hDll = API.GetModuleHandle(DllName);
                if (hDll == IntPtr.Zero)
                {
                    hDll = API.LoadLibrary(DllName);
                }
                if (hDll == IntPtr.Zero)
                {
                    throw new Exception(String.Format("load library({0}) fail", DllName));
                }
                while (*pOriginalIAT > 0)
                {
                    IntPtr lpfunc = IntPtr.Zero;
                    if (*pOriginalIAT < 0)
                    {
                        var funid = *pOriginalIAT | 0x80000000;
                        lpfunc = API.GetProcAddress(hDll, (Int32)funid);
                    }
                    else
                    {
                        var funname = Marshal.PtrToStringAnsi(hModule + *pOriginalIAT + 2);
                        lpfunc = API.GetProcAddress(hDll, funname);
                    }
                    if (lpfunc != IntPtr.Zero)
                    {
                        *pRealIAT = (Int32)lpfunc;
                    }
                    pRealIAT++;
                    pOriginalIAT++;
                }
                Import++;

            }
        }
        /// <summary>
        /// 獲取API函數委託
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="procname"></param>
        /// <returns></returns>
        public T GetProcDelegate<T>(String procname) where T : Delegate
        {
            var addr = GetProcAddress(procname);
            if (addr == IntPtr.Zero)
            {
                return default(T);
            }
            return (T)Marshal.GetDelegateForFunctionPointer(addr, typeof(T));
        }
        /// <summary>
        /// 獲取API函數地址
        /// </summary>
        /// <param name="procName"></param>
        /// <returns></returns>
        public unsafe IntPtr GetProcAddress(String procName)
        {
            if (hModule == IntPtr.Zero)
            {
                return IntPtr.Zero;
            }
            IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)hModule;
            IMAGE_NT_HEADERS* peHeader = (IMAGE_NT_HEADERS*)(hModule + dosHeader->e_lfanew);
            var Export = peHeader->OptionalHeader.GetDirectory(IMAGE_DIRECTORY_ENTRY.IMAGE_DIRECTORY_ENTRY_EXPORT);
            if (Export.VirtualAddress == 0 || Export.Size == 0)
            {
                return IntPtr.Zero;
            }
            IMAGE_EXPORT_DIRECTORY* lpExport = (IMAGE_EXPORT_DIRECTORY*)(hModule + Export.VirtualAddress);
            Int16* ordinals = (Int16*)(hModule + lpExport->AddressOfNameOrdinals);
            Int32* lpName = (Int32*)(hModule + lpExport->AddressOfNames);
            for (int i = 0; i < lpExport->NumberOfNames; i++)
            {
                var DllName = Marshal.PtrToStringAnsi(hModule + *lpName);
                if (DllName == procName)
                {
                    if (*ordinals > 0 && *ordinals <= lpExport->NumberOfFunctions)
                    {
                        Int32* funcoffset = (Int32*)(hModule + lpExport->AddressOfFunctions + *ordinals * 4);
                        return new IntPtr((Int32)hModule + *funcoffset);
                    }
                }
                lpName++;
                ordinals++;
            }
            return IntPtr.Zero;
        }
        /// <summary>
        /// 重定位表的處理
        /// </summary>
        /// <param name="peHeader"></param>
        private unsafe void ReLocation(IMAGE_NT_HEADERS* peHeader)
        {
            Int32 delta = (Int32)hModule - peHeader->OptionalHeader.ImageBase;
            if (delta == 0)
            {
                //是不是不需要重定位了
                //return;
            }
            var adr = hModule + peHeader->OptionalHeader.GetDirectory(IMAGE_DIRECTORY_ENTRY.IMAGE_DIRECTORY_ENTRY_BASERELOC).VirtualAddress;
            IMAGE_BASE_RELOCATION* relocation = (IMAGE_BASE_RELOCATION*)adr;
            while (relocation->VirtualAddress > 0 && relocation->SizeOfBlock > 0)
            {
                var pLocData = adr + sizeof(IMAGE_BASE_RELOCATION);
                var NumberOfReloc = (relocation->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / 2;
                for (int i = 0; i < NumberOfReloc; i++)
                {
                    Int16* LONG = (Int16*)pLocData + i * 2;
                    if ((*LONG & 0xFFFF) / 4096 == API.IMAGE_REL_BASED_HIGHLOW)
                    {
                        var v = relocation->VirtualAddress + (*LONG & 0xFFF);
                        Int32* lpPoint = (Int32*)(hModule + relocation->VirtualAddress + (*LONG & 0xFFF));
                        *lpPoint += delta;
                    }
                }
                adr = adr + relocation->SizeOfBlock;
                relocation = (IMAGE_BASE_RELOCATION*)(adr);
            }
        }
        /// <summary>
        /// 拷貝區段數據到內存
        /// </summary>
        /// <param name="dosHeader"></param>
        /// <param name="peHeader"></param>
        /// <param name="sectionHeader"></param>
        private unsafe void CopyDllDatas(IntPtr localPtr, IMAGE_DOS_HEADER* dosHeader, IMAGE_NT_HEADERS* peHeader, IMAGE_SECTION_HEADER* sectionHeader)
        {
            var HeaderSize = peHeader->OptionalHeader.SizeOfHeaders;
            var SectionSize = peHeader->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
            var MoveSize = HeaderSize + SectionSize;
            API.CopyMemory(hModule, localPtr, MoveSize);
            for (int i = 0; i < peHeader->FileHeader.NumberOfSections; i++)
            {
                if (sectionHeader[i].VirtualAddress > 0 && sectionHeader[i].SizeOfRawData > 0)
                {
                    var lpSection = hModule + sectionHeader[i].VirtualAddress;
                    API.CopyMemory(lpSection, localPtr + sectionHeader[i].PointerToRawData, sectionHeader[i].SizeOfRawData);
                }
            }
        }
        /// <summary>
        /// 計算要申請的內存空間大小
        /// </summary>
        /// <param name="dosHeader"></param>
        /// <param name="peHeader"></param>
        /// <param name="sectionHeader"></param>
        /// <returns></returns>
        private unsafe Int32 CalcTotalImageSize(IMAGE_DOS_HEADER* dosHeader, IMAGE_NT_HEADERS* peHeader, IMAGE_SECTION_HEADER* sectionHeader)
        {
            var nAlign = peHeader->OptionalHeader.SectionAlignment;
            var Size = GetAlignedSize(peHeader->OptionalHeader.SizeOfHeaders, nAlign);
            for (int i = 0; i < peHeader->FileHeader.NumberOfSections; i++)
            {
                var CodeSize = sectionHeader[i].Misc;
                var LoadSize = sectionHeader[i].SizeOfRawData;
                var MaxSize = LoadSize > CodeSize ? LoadSize : CodeSize;
                var SectionSize = GetAlignedSize(sectionHeader[i].VirtualAddress + MaxSize, nAlign);
                if (Size < SectionSize)
                {
                    Size = SectionSize;
                }
            }
            return Size + 1;
        }

        /// <summary>
        /// 對齊
        /// </summary>
        /// <param name="origin"></param>
        /// <param name="Alignment"></param>
        /// <returns></returns>
        private Int32 GetAlignedSize(Int32 origin, Int32 Alignment)
        {
            return (origin + Alignment - 1) / Alignment * Alignment;
        }

        /// <summary>
        /// 釋放DLL
        /// </summary>
        /// <returns></returns>
        public Boolean FreeLibrary()
        {
            if (hModule != IntPtr.Zero)
            {
                //調用 DllMain 通知卸載DLL
                var dll = DllMain.Invoke(hModule, API.DLL_PROCESS_DETACH, IntPtr.Zero);
                if (dll)
                {
                    //釋放內存空間
                    API.VirtualFreeEx(-1, hModule, hModuleSize, API.MEM_RELEASE);
                    hModule = IntPtr.Zero;
                    return true;
                }
                else
                {
                    return false;
                }
            }
            return true;
        }
        /// <summary>
        /// 銷燬 清理
        /// </summary>
        public void Dispose()
        {
            FreeLibrary();
        }

        /// <summary>
        /// 模塊大小
        /// </summary>
        private Int32 hModuleSize { get; set; }
        /// <summary>
        /// 模塊句柄
        /// </summary>
        public IntPtr hModule { get; private set; }
        /// <summary>
        /// DllMain 函數委託,用於通知DLL 模塊加載卸載等
        /// </summary>
        public DllMainHandle DllMain { get; private set; }


    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章