2013-04-14 178 views
-2

我有一个Delphi XE2项目,用于在Windows系统目录中从Resource(Resource Name = 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

您是否知道1.您需要升级到那里写入,并且2.由于系统目录对于系统是私有的,因此应用程序不能在那里写入。所以,一旦你解决这个问题,你的应用程序将违反规则。 –

+0

你提升了吗? http://en.wikipedia.org/wiki/User_Account_Control –

+0

是清单是“AsAdministrator”。 –

回答

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; 
+0

谢谢。非常感谢。您的解决方案运作完美。 –

+0

@Rubi关于这一切有什么奇怪的是,雷米正在处理的要点都是基于我对答案的评论。所以你的接受是基于雷米解决所有其他问题的事实,即那些不在问题中的问题。至少你应该编辑问题来匹配答案! –

+0

@DavidHeffernan:或许,但他们在你的评论中,而不是你的回答,我提供了工作代码,你没有。我确实解决了Rubi提出的所有问题。 –

3

您保存到一个文件名为:

'ResourceSavingPathAndFileName01\MyFile.dll' 

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

显然你的意思是写:

ResourceSavingPathAndFileName01+'\MyFile.dll' 
+0

是的。我想写** ResourceSavingPathAndFileName01 +'\ MyFile.dll'**。非常感谢。你的语法工作正常。但问题是在Win64Bit操作系统的情况下,它始终会检测到** SysWOW64 **作为系统目录。所以我想** GetWinDir **函数添加** \ System32 **。再次感谢。 –

+1

这不会改变一点点。文件系统重定向器仍将它放入SysWOW64中。如果你需要64位系统目录,你需要写入'C:\ Windows \ Sysnative'。如果DLL是32位的,那么它需要进入32位系统目录,如果你想要任何东西能够找到它。但是,您不应该写入系统目录。你为什么要这样做? –

+0

我的DLL文件是64Bit,所以它总是保存在** SysWOW64 **目录中,以防Win ** Bit操作系统兼有** GetWinDir **功能和** GetSysDir **功能。我的要求是仅保存在** System32 **目录中。请帮帮我。我无法做到。 –

-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)。它在德尔福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.