-2

Windows システム ディレクトリのリソース (リソース名 = DynamicLlinkLibraryWin32) から 1 つの DLL ファイル (ファイル名 = MyFile.dll) を保存する 1 つの Delphi XE2 プロジェクトがあります。次のコードを定義しました。

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

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に慣れていないため、邪魔になります。Windows の検出とRemy Lebeau の例(システム ディレクトリでのリソースの節約) には、 Ken Whites のコード( OS のバージョンを Delphi でチェックする方法は? Windows 7 または Server 2008 R2? ) を使用しました。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 に答える