我正在使用一个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;
在运行时,我收到错误,告诉“系统找不到指定的路径”。为什么呢?
答案 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.