系统目录中的资源节约

时间:2013-04-14 11:26:37

标签: delphi

我正在使用一个Delphi XE2项目从Windows系统目录中的资源(资源名称= DynamicLlinkLibraryWin32)保存一个DLL文件(文件名= MyFile.dll)。我已经定义了以下代码:

function GetSysDir: string;
var
  SystemDirectory: array[0..MAX_PATH] of Char;
begin
  GetSystemDirectory(SystemDirectory, MAX_PATH - 2);
  SetLength(Result, StrLen(SystemDirectory));
  Result := SystemDirectory;
end;

procedure TForm1.BitBtn01Click(Sender: TObject);
var
  ResStream: TResourceStream;
  ResourceSavingPathAndFileName01 : string;
begin
  ResourceSavingPathAndFileName01 := ExcludeTrailingPathDelimiter(GetSysDir);
  ResStream := TResourceStream.Create(HInstance, 'DynamicLlinkLibraryWin32', RT_RCDATA); {Resource Name=DynamicLlinkLibraryWin32}
  try
    ResStream.SaveToFile('ResourceSavingPathAndFileName01\MyFile.dll'); {File Name=MyFile.dll}
  finally
    ResStream.Free;
  end;
end;

在运行时,我收到错误,告诉“系统找不到指定的路径”。为什么呢?

3 个答案:

答案 0 :(得分:3)

您要保存到名为:

的文件
'ResourceSavingPathAndFileName01\MyFile.dll'

因此系统将其视为相对路径,似乎工作目录中没有包含名为'ResourceSavingPathAndFileName01'的目录。

显然你打算写:

ResourceSavingPathAndFileName01+'\MyFile.dll'

答案 1 :(得分:1)

您没有正确格式化目标文件名,并且在确定正确的系统文件夹路径时根本没有考虑WOW64。在WOW64仿真器下运行时,必须使用sysnative别名从32位进程访问64位System文件夹。在32位系统上的32位进程和64位系统上的64位进程中,GetSystemDirectory()将返回正确的路径。使用IsWow64Process()检测您的32位应用是否在WOW64下运行。

请改为尝试:

function GetSysDir: string;
var
  Buf: array[0..MAX_PATH] of Char;
  Len: UINT;
  S: String;
  {$IFNDEF WIN64}
  IsWow64: BOOL;
  {$ENDIF}
begin
  {$IFNDEF WIN64}
  IsWow64 := FALSE;
  if not IsWow64Process(GetCurrentProcess(), @IsWow64) then RaoseLastOSError;
  if IsWow64 then
  begin
    Len := GetWindowsDirectory(Buf, MAX_PATH);
    if Len = 0 then RaiseLastOSError;
    SetString(S, Buf, Len);
    Result := IncludeTrailingPathDelimiter(S) + 'Sysnative\';
    Exit;
  end;
  {$ENDIF}
  Len := GetSystemDirectory(Buf, MAX_PATH);
  if Len = 0 then RaiseLastOSError;
  SetString(S, Buf, Len);
  Result := IncludeTrailingPathDelimiter(S);
end;

procedure TForm1.BitBtn01Click(Sender: TObject);
var
  ResStream: TResourceStream;
begin
  ResStream := TResourceStream.Create(HInstance, 'DynamicLlinkLibraryWin32', RT_RCDATA);
  try
    ResStream.SaveToFile(GetSysDir + 'MyFile.dll');
  finally
    ResStream.Free;
  end;
end;

答案 2 :(得分:-1)

谢谢大家。我有它,因为我是初学者,我对 $ IfNDef编译器指令感到不舒服。我使用 Ken Whites的代码How to check in delphi the OS version? Windows 7 or Server 2008 R2?)进行Windows检测, Remy Lebeau示例Resource Saving In System Directory)。它在 Delphi XE2 中完美运行。我的代码如下:

unit ApplicationWizard01;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Buttons;

type
  TMainForm = class(TForm)
    BitBtn01: TBitBtn;
    procedure BitBtn01Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

var
  GetNativeSystemInfo: function(var SysInfo: TSystemInfo): BOOL stdcall = nil;
var
  GetProductInfo: function (dwOSMajorVersion, dwOSMinorVersion,
                            dwSpMajorVersion, dwSpMinorVersion: DWORD;
                            var pdwReturnedProductType: DWORD): BOOL stdcall = nil;

implementation

{$R *.dfm}

function GetSysDir: string;
var
  SystemDirectory: array[0..MAX_PATH] of Char;
begin
  GetSystemDirectory(SystemDirectory, MAX_PATH - 1);
  SetLength(Result, StrLen(SystemDirectory));
  Result := IncludeTrailingPathDelimiter(SystemDirectory);
end;

function GetSysNativeDir: string;
var
  WindowsDirectory: array[0..MAX_PATH] of Char;
begin
   GetWindowsDirectory(WindowsDirectory, MAX_PATH - 1);
   SetLength(Result, StrLen(WindowsDirectory));
   Result := IncludeTrailingPathDelimiter(WindowsDirectory)  + 'Sysnative\';
end;

procedure TMainForm.BitBtn01Click(Sender: TObject);
var
  NTBres, BRes: Boolean;
  OSVI: TOSVERSIONINFO;
  OSVI_NT: TOSVERSIONINFOEX;
  SI: TSystemInfo;
  ResStream: TResourceStream;
  ResourceSavingPathAndFileName : string;
begin
  NTBRes := false;
  try
    OSVI_NT.dwOSVersionInfoSize := SizeOf(TOSVERSIONINFOEX);
    NTBRes := GetVersionEx(OSVI_NT);
    OSVI.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
    BRes := GetVersionEx(OSVI);
  except
    OSVI.dwOSVersionInfoSize := SizeOf(TOSVersionInfo);
    BRes := GetVersionEx(OSVI);
  end;
  if (not BRes) and (not NTBres) then Exit;
  Move( OSVI, OSVI_NT, SizeOf(TOSVersionInfo) );
  if Assigned(GetNativeSystemInfo) then GetNativeSystemInfo(SI) else GetSystemInfo(SI);
  if (SI.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL) then
    begin
      ResourceSavingPathAndFileName := (GetSysDir);
      ResStream := TResourceStream.Create(HInstance, 'DynamicLlinkLibraryWin32', RT_RCDATA);
      try
        ResStream.SaveToFile(ResourceSavingPathAndFileName + 'FileWin32.dll');
      finally
        ResStream.Free;
      end;
    end
  else if (SI.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_AMD64) then
    begin
      ResourceSavingPathAndFileName := (GetSysNativeDir);
      ResStream := TResourceStream.Create(HInstance, 'DynamicLlinkLibraryWin64', RT_RCDATA);
      try
        ResStream.SaveToFile(ResourceSavingPathAndFileName + 'FileWin64.dll');
      finally
        ResStream.Free;
      end;
    end;
  ShowMessage ('Resource Has Been Saved Successfully');
end;

initialization
  @GetProductInfo := GetProcAddress(GetModuleHandle('KERNEL32.DLL'),
                                     'GetProductInfo');

  @GetNativeSystemInfo := GetProcAddress(GetModuleHandle('KERNEL32.DLL'),
                                         'GetNativeSystemInfo');

end.