就是自己 使用 Brcc32命令制作一个包含DLL动态库的资源文件,然后我如何从程序中加载该动态库呢!
   比如 有一个动态库 Test.dll,然后我在制作资源文件如下:
    
    MyDll  DLL   Test.dll  保存为Test.rc
   然后使用 Brcc32  test.rc命令生成 Brcc32.res   然后在程序中{$R Test.res}将该资源文件作为应用程序的一个资源编译到EXE文件中去 
  
   我就想问一下,当EXE文件在运行的过程中,我如何从它的资源文件中加载我编译进去的DLL动态库,
   然后调用其中的函数   从磁盘加载用LoadLibrary就可以了,但是,此时动态库在程序的资源文件中,也就是说他在内存中。此时该如何加载呢?期待高手解答。

解决方案 »

  1.   

    然后使用   Brcc32     test.rc命令生成   Brcc32.res 
    这里说错了,应该是生成  Test.res资源文件
      

  2.   

    可以先把資源讀出來,寫到臨時文件再用 LoadLibrary 加載
      

  3.   

    需要自己实现LoadLibrary,主要是代码重定位问题,以前做过,应为编译器太多,不太稳定,也没做下去
      

  4.   

    其实,我想了一个,只是很复杂麻烦我还没有去实现他,想问一下有没有简单的办法了我的方法是 先使用 FindResource找到DLL资源,然后使用LoadResource装载资源,然后是使用LockResource锁定
    资源得到资源数据,然后通过内存影象来查找对应的函数指针,进行调用。
      

  5.   

    并不是所有的文件都支持流操作。你的意思我明白,要求直接读资源里面的文件嘛,如果是图片当然可以读到Image里面,如果是EXE或者DLL文件,不释放出来,根本不可以用。但你要求不释放到硬盘中,那是不可能的。建议你释放后,加载,程序关闭后再删除。另外,你为什么要做成DLL呢,如果你有DLL这个文件的源代码,可以直接把源代码做到EXE里面。
      

  6.   

    {
      DLL Loader by Aphex
      http://www.iamaphex.cjb.net
      [email protected]  Based on code from [email protected]  function xLoadLibrary(Src: Pointer; Imports: array of TImportItem): TLibInfo;
      procedure xFreeLibrary(hModule: TLibInfo);
    }unit DLLUnit;interfaceuses
      Windows;type
      TImportItem = record
        Name: string;
        PProcVar: PPointer;
      end;  TwordArr = array[0..0] of word;
      PwordArr = ^TwordArr;
      TdwordArr = array[0..0] of dword;
      PdwordArr = ^TdwordArr;  PImageImportDescriptor = ^TImageImportDescriptor;
      TImageImportDescriptor = packed record
        OriginalFirstThunk: dword;
        TimeDateStamp: dword;
        ForwarderChain: dword;
        Name: dword;
        FirstThunk: dword;
      end;  PImageBaseRelocation = ^TImageBaseRelocation;
      TImageBaseRelocation = packed record
        VirtualAddress: cardinal;
        SizeOfBlock: cardinal;
      end;  TDllEntryProc = function(hinstDLL: HMODULE; dwReason: dword; lpvReserved: Pointer): Boolean; stdcall;  TStringArray = array of string;  TLibInfo = record
        ImageBase: Pointer;
        DllProc: TDllEntryProc;
        LibsUsed: TStringArray;
      end;  PLibInfo = ^TLibInfo;
      PPointer = ^Pointer;  TSections = array[0..100000] of TImageSectionHeader;const
      IMPORTED_NAME_OFFSET = $00000002;
      IMAGE_ORDINAL_FLAG32 = $80000000;
      IMAGE_ORDINAL_MASK32 = $0000FFFF;function xLoadLibrary(Src: Pointer; Imports: array of TImportItem): TLibInfo;
    function xFreeLibrary(LoadedLib: TLibInfo): boolean;implementationfunction xFreeLibrary(LoadedLib: TLibInfo): boolean;
    var
      ObjectLoop: integer;
    begin
      Result := False;
      with LoadedLib do
      begin
        if @DllProc <> nil then
        begin
          DllProc(HModule(LoadedLib.ImageBase), DLL_PROCESS_DETACH, nil);
        end;
        for ObjectLoop := 0 to Length(LibsUsed) - 1 do
        begin
          if ObjectLoop >= Length(LibsUsed) then
            Exit;
          FreeLibrary(GetModuleHandle(pchar(LibsUsed[ObjectLoop])));
        end;
        SetLength(LibsUsed, 0);
      end;
      VirtualFree(LoadedLib.ImageBase, 0, MEM_RELEASE);
      Result := True;
    end;
      

  7.   

    function xLoadLibrary(Src: Pointer; Imports: array of TImportItem): TLibInfo;
    var
      ImageBase: pointer;
      ImageBaseDelta: integer;
      ImageNtHeaders: PImageNtHeaders;
      PSections: ^TSections;
      SectionLoop: integer;
      SectionBase: pointer;
      VirtualSectionSize, RawSectionSize: cardinal;
      OldProtect: cardinal;
      NewLibInfo: TLibInfo;  function StrToInt(S: string): integer;
      begin
        Val(S, Result, Result);
      end;  procedure Add(Strings: TStringArray; Text: string);
      begin
        SetLength(Strings, Length(Strings) + 1);
        Strings[Length(Strings) - 1] := Text;
      end;  function Find(Strings: array of string; Text: string; var Index: integer): boolean;
      var
        StringLoop: integer;
      begin
        Result := False;
        for StringLoop := 0 to Length(Strings) - 1 do
        begin
          if lstrcmpi(pchar(Strings[StringLoop]), pchar(Text)) = 0 then
          begin
            Index := StringLoop;
            Result := True;
          end;
        end;
      end;  function GetSectionProtection(ImageScn: cardinal): cardinal;
      begin
        Result := 0;
        if (ImageScn and IMAGE_SCN_MEM_NOT_CACHED) <> 0 then
        begin
          Result := Result or PAGE_NOCACHE;
        end;
        if (ImageScn and IMAGE_SCN_MEM_EXECUTE) <> 0 then
        begin
          if (ImageScn and IMAGE_SCN_MEM_READ) <> 0 then
          begin
            if (ImageScn and IMAGE_SCN_MEM_WRITE) <> 0 then
            begin
              Result := Result or PAGE_EXECUTE_READWRITE
            end
            else
            begin
              Result := Result or PAGE_EXECUTE_READ
            end;
          end
          else if (ImageScn and IMAGE_SCN_MEM_WRITE) <> 0 then
          begin
            Result := Result or PAGE_EXECUTE_WRITECOPY
          end
          else
          begin
            Result := Result or PAGE_EXECUTE
          end;
        end
        else if (ImageScn and IMAGE_SCN_MEM_READ) <> 0 then
        begin
          if (ImageScn and IMAGE_SCN_MEM_WRITE) <> 0 then
          begin
            Result := Result or PAGE_READWRITE
          end
          else
          begin
            Result := Result or PAGE_READONLY
          end
        end
        else if (ImageScn and IMAGE_SCN_MEM_WRITE) <> 0 then
        begin
          Result := Result or PAGE_WRITECOPY
        end
        else
        begin
          Result := Result or PAGE_NOACCESS;
        end;
      end;  procedure ProcessExports(PExports: PImageExportDirectory; BlockSize: cardinal);
      var
        ExportLoop: byte;
        ImportedFn: cardinal;
        PFnName: pchar;
        FnIndex: dword;    function IsForwarderString(Data: pchar): boolean;
        begin
          Result := Data > PExports;
          if Result then
            Result := cardinal(Data - PExports) < BlockSize;
        end;    function GetForwardedSymbol(ForwarderString: pchar): pointer;
        var
          sForwarderString, DllName: string;
          ForwarderLoop: integer;
          LibHandle: HModule;
        begin
          sForwarderString := ForwarderString;
          while ForwarderString^ <> '.' do
          begin
            Inc(ForwarderString);
          end;
          DllName := Copy(sForwarderString, 1, pos('.', sForwarderString) - 1);
          if not Find(NewLibInfo.LibsUsed, DllName, ForwarderLoop) then
          begin
            LibHandle := LoadLibrary(pchar(DllName));
            Add(NewLibInfo.LibsUsed, DllName);
          end
          else
          begin
            LibHandle := cardinal(NewLibInfo.LibsUsed[ForwarderLoop]);
          end;
          if ForwarderString^ = '#' then
            ForwarderString := pointer(StrToInt((ForwarderString + 1)));
          Result := GetProcAddress(LibHandle, ForwarderString);
        end;  begin
        for ExportLoop := 0 to PExports.NumberOfNames - 1 do
        begin
          PFnName := pchar(PdwordArr(cardinal(PExports.AddressOfNames) + cardinal(ImageBase))^[ExportLoop] + cardinal(ImageBase));
          for ImportedFn := low(Imports) to high(Imports) do
          begin
            if Imports[ImportedFn].Name = PFnName then
            begin
              FnIndex := PwordArr(cardinal(PExports.AddressOfNameOrdinals) + cardinal(ImageBase))^[ExportLoop];
              Imports[ImportedFn].PProcVar^ := pointer(PdwordArr(cardinal(PExports.AddressOfFunctions) + cardinal(ImageBase))^[FnIndex] + cardinal(ImageBase));
              if IsForwarderString(Imports[ImportedFn].PProcVar^) then
              begin
                Imports[ImportedFn].PProcVar^ := GetForwardedSymbol(Imports[ImportedFn].PProcVar^);
              end;
            end;
          end;
        end;
      end;  procedure ProcessRelocs(PRelocs: PImageBaseRelocation);
      var
        PReloc: PImageBaseRelocation;
        RelocsSize: cardinal;
        Reloc: PWord;
        ModCount: cardinal;
        RelocLoop: cardinal;
      begin
        PReloc := PRelocs;
        RelocsSize := ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
        while cardinal(PReloc) - cardinal(PRelocs) < RelocsSize do
        begin
          ModCount := (PReloc.SizeOfBlock - Sizeof(PReloc^)) div 2;
          Reloc := pointer(cardinal(PReloc) + sizeof(PReloc^));
          for RelocLoop := 0 to ModCount - 1 do
          begin
            if Reloc^ and $F000 <> 0 then
              Inc(pdword(cardinal(ImageBase) + PReloc.VirtualAddress + (Reloc^ and $0FFF))^, ImageBaseDelta);
            Inc(Reloc);
          end;
          PReloc := pointer(Reloc);
        end;
      end;  procedure ProcessImports(PImports: PImageImportDescriptor);
      var
        PImport: PImageImportDescriptor;
        Import: LPDword;
        PImportedName: pchar;
        LibHandle: HModule;
        ProcAddress: pointer;
        PLibName: pchar;
        ImportLoop: integer;    function IsImportByOrdinal(ImportDescriptor: dword; HLib: THandle): boolean;
        begin
          Result := (ImportDescriptor and IMAGE_ORDINAL_FLAG32) <> 0;
        end;  begin
        PImport := PImports;
        while PImport.Name <> 0 do
        begin
          PLibName := pchar(cardinal(PImport.Name) + cardinal(ImageBase));
          if not Find(NewLibInfo.LibsUsed, PLibName, ImportLoop) then
          begin
            LibHandle := LoadLibrary(PLibName);
            Add(NewLibInfo.LibsUsed, PLibName);
          end
          else
          begin
            LibHandle := cardinal(NewLibInfo.LibsUsed[ImportLoop]);
          end;
          if PImport.TimeDateStamp = 0 then
          begin
            Import := LPDword(pImport.FirstThunk + cardinal(ImageBase))
          end
          else
          begin
            Import := LPDword(pImport.OriginalFirstThunk + cardinal(ImageBase));
          end;
          while Import^ <> 0 do
          begin
            if IsImportByOrdinal(Import^, LibHandle) then
            begin
              ProcAddress := GetProcAddress(LibHandle, pchar(Import^ and $FFFF))
            end
            else
            begin
              PImportedName := pchar(Import^ + cardinal(ImageBase) + IMPORTED_NAME_OFFSET);
              ProcAddress := GetProcAddress(LibHandle, PImportedName);
            end;
            PPointer(Import)^ := ProcAddress;
            Inc(Import);
          end;
          Inc(PImport);
        end;
      end;
      

  8.   

    begin
      ImageNtHeaders := pointer(int64(cardinal(Src)) + PImageDosHeader(Src)._lfanew);
      ImageBase := VirtualAlloc(nil, ImageNtHeaders.OptionalHeader.SizeOfImage, MEM_RESERVE, PAGE_NOACCESS);
      ImageBaseDelta := cardinal(ImageBase) - ImageNtHeaders.OptionalHeader.ImageBase;
      SectionBase := VirtualAlloc(ImageBase, ImageNtHeaders.OptionalHeader.SizeOfHeaders, MEM_COMMIT, PAGE_READWRITE);
      Move(Src^, SectionBase^, ImageNtHeaders.OptionalHeader.SizeOfHeaders);
      VirtualProtect(SectionBase, ImageNtHeaders.OptionalHeader.SizeOfHeaders, PAGE_READONLY, OldProtect);
      PSections := pointer(pchar(@(ImageNtHeaders.OptionalHeader)) + ImageNtHeaders.FileHeader.SizeOfOptionalHeader);
      for SectionLoop := 0 to ImageNtHeaders.FileHeader.NumberOfSections - 1 do
      begin
        VirtualSectionSize := PSections[SectionLoop].Misc.VirtualSize;
        RawSectionSize := PSections[SectionLoop].SizeOfRawData;
        if VirtualSectionSize < RawSectionSize then
        begin
          VirtualSectionSize := VirtualSectionSize xor RawSectionSize;
          RawSectionSize := VirtualSectionSize xor RawSectionSize;
          VirtualSectionSize := VirtualSectionSize xor RawSectionSize;
        end;
        SectionBase := VirtualAlloc(PSections[SectionLoop].VirtualAddress + pchar(ImageBase), VirtualSectionSize, MEM_COMMIT, PAGE_READWRITE);
        FillChar(SectionBase^, VirtualSectionSize, 0);
        Move((pchar(src) + PSections[SectionLoop].PointerToRawData)^, SectionBase^, RawSectionSize);
      end;
      NewLibInfo.DllProc := TDllEntryProc(ImageNtHeaders.OptionalHeader.AddressOfEntryPoint + cardinal(ImageBase));
      NewLibInfo.ImageBase := ImageBase;
      SetLength(NewLibInfo.LibsUsed, 0);
      if ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress <> 0 then
        ProcessRelocs(pointer(ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress + cardinal(ImageBase)));
      if ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress <> 0 then
        ProcessImports(pointer(ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress + cardinal(ImageBase)));
      for SectionLoop := 0 to ImageNtHeaders.FileHeader.NumberOfSections - 1 do
      begin
        VirtualProtect(PSections[SectionLoop].VirtualAddress + pchar(ImageBase), PSections[SectionLoop].Misc.VirtualSize, GetSectionProtection(PSections[SectionLoop].Characteristics), OldProtect);
      end;
      if @NewLibInfo.DllProc <> nil then
      begin
        if not NewLibInfo.DllProc(cardinal(ImageBase), DLL_PROCESS_ATTACH, nil) then
        begin
          NewLibInfo.DllProc := nil;
          xFreeLibrary(Result);
        end;
      end;
      if ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress <> 0 then
        ProcessExports(pointer(ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress + cardinal(ImageBase)), ImageNtHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size);
      Result := NewLibInfo;
    end;{//调用示例
    program test;Uses
      Windows, DLLUnit;var
      ResourceLocation: HRSRC;
      ResourceSize: LongWord;
      ResourceHandle: THandle;
      ResourcePointer: Pointer;  TestFunction: procedure;
      MyImports: array [0..0] of TImportItem =(
       (Name: 'TestFunction'; PProcVar: @@TestFunction)
      );
      MyLibrary: TLibInfo;begin
      ResourceLocation := FindResource(HInstance, pchar('a01'), RT_RCDATA);
      if ResourceLocation <> 0 then
      begin
        ResourceSize := SizeofResource(HInstance, ResourceLocation);
        if ResourceSize <> 0 then
        begin
          ResourceHandle := LoadResource(HInstance, ResourceLocation);
          if ResourceHandle <> 0 then
          begin
            ResourcePointer := LockResource(ResourceHandle);
            if ResourcePointer <> nil then
            begin
              MyLibrary := xLoadLibrary(ResourcePointer, MyImports);
              TestFunction;
            end;
          end;
        end;
      end;
      xFreeLibrary(MyLibrary);
    end.//==============================================================================
    var
      FLibrary: TLibInfo;
      test: function(const i : Integer):integer; stdcall;const
      DllImports: array [0..0] of TImportItem =(
          (Name: 'test'; PProcVar: @@test)
          );procedure LoadLib;
    var
      Buf : Pointer;
      Size  : DWORD;
      ProcessId: Cardinal;
      ResHandle:Cardinal;
    begin
      ResHandle :=  FindResource(hInstance, 'testdll', 'DLL');
      if ResHandle > 0 then
      begin
        Size := SizeofResource(hInstance, ResHandle);
        Buf :=  LockResource(LoadResource(hInstance, ResHandle));
        FLibrary := xLoadLibrary(Buf, DllImports);
      end;
    end;procedure FreeLib;
    begin
      if FLibrary.ImageBase <> nil then
      begin
        if xFreeLibrary(FLibrary) then
          FLibrary.ImageBase  :=  nil;
      end;
    end;
    //}end.
      

  9.   

    to ysai:
       这个代码,我看到过,就是没有收集下来,这次大哥共享出来了,实在感激!呵呵!接分了。我也做了一个不过有问题,有时候喜欢出错!。可是难道就没有比这个代码更简单的吗?
    to mwy654321 :
       不是不行,只能说是你不会而已呵呵。
      

  10.   

    问一下,EXE有没有办法动态加载?
      

  11.   

    APHE 的個代碼,卡巴可能會跳出來
      

  12.   

    to   mwy654321   : 
         自然可以,上面的是通过PE文件在内存中的位置进行加载的,那么EXE也是PE文件,只要找到他在内存中的位置,一样操作
      

  13.   

    其实资源文件还有其它用法。比如说在你的程序携带其它文件,要用的时候释放出来。 
    例如: myexe exefile 'ha1.exe'//脚本文件 下面是自定义释放函数ExtractRes,本例中使用如下: 软件开发网 www.mscto.com ExtractRes('exefile','myexe','c:\new.exe'); 
    就把ha1.exe以new.exe为名字保存到C盘根目录下了. 软件开发网 www.mscto.com function TForm1.ExtractRes(ResType, ResName, ResNewName: string): boolean; var 软件开发网 www.mscto.com
    Res: TResourceStream; 软件开发网 http://bbs.mscto.combegin 软件开发网 www.mscto.comtry Res := TResourceStream.Create(Hinstance, Resname, Pchar(ResType)); try 软件开发网 http://bbs.mscto.comRes.SavetoFile(ResNewName); Result := true; finally 软件开发网 http://bbs.mscto.com Res.Free; end; 软件开发网 http://bbs.mscto.comexcept Result := false; end; end; 
      

  14.   

    to ysai:
    源码:
    {//调用示例
    program test;Uses
      Windows, DLLUnit;var
      ResourceLocation: HRSRC;
      ResourceSize: LongWord;
      ResourceHandle: THandle;
      ResourcePointer: Pointer;  TestFunction: procedure;
      MyImports: array [0..0] of TImportItem =(
       (Name: 'TestFunction'; PProcVar: @@TestFunction)
      );
      MyLibrary: TLibInfo;begin
      ResourceLocation := FindResource(HInstance, pchar('a01'), RT_RCDATA);
      if ResourceLocation <> 0 then
      begin
        ResourceSize := SizeofResource(HInstance, ResourceLocation);
        if ResourceSize <> 0 then
        begin
          ResourceHandle := LoadResource(HInstance, ResourceLocation);
          if ResourceHandle <> 0 then
          begin
            ResourcePointer := LockResource(ResourceHandle);
            if ResourcePointer <> nil then
            begin
              MyLibrary := xLoadLibrary(ResourcePointer, MyImports);
              TestFunction;
            end;
          end;
        end;
      end;
      xFreeLibrary(MyLibrary);
    end.我在WIN XP下测试了,我写的DLL中的showmessage('OK')被正常调用了。
    但有个问题想请教,该动态库中函数的入参是如何进入TestFunction的?并且如何使用返回参数?
      

  15.   

    to ambush:
       参数是如何进入的,你就要看看关于函数的参数传递的问题了,这里的从内存中加载资源DLL,其实不过是
    找该DLL的函数在内存中的地址而已了,你使用普通的LoadLibrary也一样是把DLL加载到内存中,找到其中的
    函数地址。所以总体说来就是找DLL的入口地址了。其他和LoadLibrary差不多
      

  16.   

    我做过,下面是静态类头文件//ResDll.h#ifndef _RESDLL_H_
    #define _RESDLL_H_#pragma once#include <winnt.h>class CResDll
    {
    protected:
        CResDll();
        virtual ~CResDll();    static BOOL FinalizeSections(const PIMAGE_NT_HEADERS pInh);
        static BOOL GetExportFun(const BYTE *p, const PIMAGE_NT_HEADERS pInh, void *pVoid);  
        static BOOL BuildImportTable(const BYTE *p, const PIMAGE_NT_HEADERS pNewInh, void *pVoid);   
        static BOOL CopySections(const PIMAGE_NT_HEADERS pNewInh, const BYTE *pSrcData, BYTE *pDesData);
        static BOOL PerformBaseRelocation(const BYTE *p, const PIMAGE_NT_HEADERS pNewInh, DWORD dwOffset);public:
        static BOOL FreeLibraryFromRes(HMODULE hModule);
        static FARPROC GetProcAddressFromRes(HMODULE hModule, const WCHAR *pszFunName);
        static HMODULE LoadLibraryFromRes(HMODULE hResModule, WORD wDllResId, const WCHAR *szResType);
    };#endif