-2

我有一个 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;

在运行时,我收到错误消息,提示“系统找不到指定的路径”。为什么?

4

3 回答 3

3

您正在保存到一个名为:

'ResourceSavingPathAndFileName01\MyFile.dll'

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

显然你的意思是写:

ResourceSavingPathAndFileName01+'\MyFile.dll'
于 2013-04-14T11:30:15.933 回答
1

您没有正确格式化目标文件名,并且在确定正确的系统文件夹路径时根本没有考虑 WOW64。在 WOW64 模拟器下运行时,您必须使用sysnative别名从 32 位进程访问 64 位系统文件夹。在 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;
于 2013-04-14T19:16:54.640 回答
-1

谢谢大家。我有它,因为我是初学者,我对$IfNDef Compiler Directive感到不舒服。我使用了Ken Whites 的代码如何检查 delphi 操作系统版本?Windows 7 或 Server 2008 R2?)用于 Windows 检测和Remy Lebeau 示例系统目录中的资源保存)。它在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.
于 2013-04-15T16:35:09.440 回答