![]() |
Datei ausführen unter Windows 64-Bit
Hallo Leute,
unter Windows64 ist der FileSystemRedirector aktiv, der Anfragen von 32-Bit Programmen umleitet, bsp. "sieht" eine 32-Bit-Anwendung nur den Inhalt des Ordners "Windows\SysWow64\..." während 64-Bit-Anwendungen den Ordner "Windows\System32" sehen. ![]() Mein Programm soll unter Win64 die Datei "regedit.exe" ausführen. Von dieser Datei existieren 2 Varianten: Eine C:\Windows\regedit.exe und eine C:\windows\syswow64\regedit.exe. Wenn mein (32-Bit) Programm nun ShellExecute ausführt, wird immer nur die 32-Bit Variante ausgeführt. Ich will aber die 64-Bit-Variante ausführen... Ist halt schlecht, da z.B. 32-Bit-RegEdit keine 64-Bit-Schlüssel sehen kann. Umgehen kann man das nach MS durch bestimmte Flags, etwa "Wow64DisableWow64FsRedirection" oder "Wow64EnableWow64FsRedirection", welche wohl vor API calls gesetzt werden müssen. MS hat ![]() |
Re: Datei ausführen unter Windows 64-Bit
Code:
Also wenn ich das richtig verstehe, dann wird hier (ich weis nicht was PVOID für ein Daten-Typ sein soll) in "OldValue" mithilfe von der Funktion "Wow64DisableWow64FsRedirection" der Ursprungszustand gespeichert, wenn das geglückt ist, dann wird die Datei einfach nur aufgerufen (sozusagen dem shellexecute entsprechend, bloß eben mit dem Umweg erst ein Handle der Datei zu bekommen und danach erst die Datei zu öffnen) und danach wird das mit dem Umleiten wieder auf den Ursprungswert zurückgesetzt!
#define _WIN32_WINNT 0x0501
#include <windows.h> PVOID OldValue; HANDLE hFile; BOOL bRet = Wow64DisableWow64FsRedirection (&OldValue); if (bRet == TRUE) { // Open a file hFile = CreateFile(TEXT("c:\\windows\\system32\\notepad.exe"), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); // Restore the previous WOW64 file system redirection value. Wow64RevertWow64FsRedirection (OldValue); } if( INVALID_HANDLE_VALUE != hFile ) { // Use the file handle } Das erscheint mir eigentlich ganz einleuchtend... Aber wie man diese Redirection-Funktion in Delphi verwendet (bzw. weis ich gar nicht ob es die da gibt) hab ich keine Ahnung. Weil mir C++ hab ich mich noch nie beschäftigt, aber es gibt hier im Forum glaub ich ein paar die das mal "übersetzen" könnten... :wink: |
Re: Datei ausführen unter Windows 64-Bit
Ja, vielleicht ist hier ja ein "C-ler", der eine kurze Übersetzung des Codes probieren könnte ... :-)
|
Re: Datei ausführen unter Windows 64-Bit
zwar kein alter C-ler, aber dennoch ein grober Versuch?
mit Hilfe von: ![]() ![]()
Delphi-Quellcode:
Die (aufgehobene) Umleitung sollte doch wohl auch auf ShellExecute eine Auswirkung haben.
Function Wow64DisableWow64FsRedirection(Var Wow64FsEnableRedirection: LongBool): LongBool; StdCall;
External 'Kernel32.dll' Name 'Wow64DisableWow64FsRedirection'; Function Wow64EnableWow64FsRedirection(Wow64FsEnableRedirection: LongBool): LongBool; StdCall; External 'Kernel32.dll' Name 'Wow64EnableWow64FsRedirection'; Var Wow64FsEnableRedirection: LongBool; Begin If Wow64DisableWow64FsRedirection(Wow64FsEnableRedirection) Then Begin If ShellExecute(0, nil, PChar('c:\windows\system32\notepad.exe'), nil, nil, 0) = 0 Then Error... Wow64RevertWow64FsRedirection(Wow64FsEnableRedirection); End Else Error... End; [add] ungetestet! |
Re: Datei ausführen unter Windows 64-Bit
Zitat:
besten Dank Himitsu, es hat super geklappt!!! (Bis auf eine kleine Änderung: Du hast
Delphi-Quellcode:
geschrieben; ich hab das zu einem
Wow64RevertWow64FsRedirection(Wow64FsEnableRedirection);
Delphi-Quellcode:
geändert)
Wow64EnableWow64FsRedirection(Wow64FsEnableRedirection);
Ich habe das Ganze in eine kleine Function gepackt, diese überprüft mittels IsWin64, ob ein 64-Bit-Windows vorliegt oder nicht und führt das dementsprechend dann aus. Habe leider keine Möglichkeit, das auf Win32 zu testen; vielleicht kann das ja mal jemand machen und hier ein kleines Feedback posten?! :) Wenn jemand was Schöneres für isWin64() hat, möge er es ebenfalls posten...
Delphi-Quellcode:
uses ShellApi, Registry, Windows; Function Wow64DisableWow64FsRedirection(Var Wow64FsEnableRedirection: LongBool): LongBool; StdCall; External 'Kernel32.dll' Name 'Wow64DisableWow64FsRedirection'; Function Wow64EnableWow64FsRedirection(Wow64FsEnableRedirection: LongBool): LongBool; StdCall; External 'Kernel32.dll' Name 'Wow64EnableWow64FsRedirection'; Var Wow64FsEnableRedirection: LongBool; .... Function FileExec(const sDatei: String): Integer; Function IsWin64: Boolean; begin With TRegistry.Create do begin RootKey := HKEY_LOCAL_MACHINE; Result := KeyExists('\SOFTWARE\Wow6432Node'); Free; end; end; begin if isWin64 then begin If Wow64DisableWow64FsRedirection(Wow64FsEnableRedirection) Then Begin Result := ShellExecute(0, nil, PChar(sDatei), nil, nil, 0); Wow64EnableWow64FsRedirection(Wow64FsEnableRedirection); End else Result := ShellExecute(0, nil, PChar(sdatei), nil, nil, 0); end else Result := ShellExecute(0, nil, PChar(sdatei), nil, nil, 0); end; |
Re: Datei ausführen unter Windows 64-Bit
Hallo,
das klappt bei mir irgendwie nicht. Kompilieren kann ich das unter Win32 problemlos, doch beim Ausführen springt der Debugger zum "begin" in der Project.dpr. Spaßeshalber wollte ich dann mit F8 schauen, ob's irgendwie weitergeht, doch dann kommt:
Code:
Anschließend öffnet sich das CPU-Fenster und markiert ist diese Zeile:
---------------------------
Benachrichtigung über Debugger-Problem --------------------------- In Projekt D:\Eigene Dateien\Borland Studio-Projekte\Project1.exe trat ein Problem mit folgender Meldung auf: 'access violation at 0x7c947a50: write of address 0x00030d24'. Prozess angehalten. Mit Einzelne Anweisung oder Start fortsetzen. --------------------------- OK ---------------------------
Code:
OS: Win XP Pro SP2,32 Bit
7C947A50 56 push esi
Benutzerrechte: Sowohl eingeschränkt, als auch Admin. Beides mal der gleiche Fehler. |
Re: Datei ausführen unter Windows 64-Bit
Zitat:
Code:
eigentlich nur der normale ShellExecute() Teil unter Win32 ausgeführt werden sollte ... vielleicht stimmt ja mit ShellExecute was nicht? Oder meint ihr, der Fehler wird durch die Aufrufe
if isWin64 then begin
Code:
verursacht? Jetzt bin ich etwas verwirrt ... :-)
Function Wow64DisableWow64FsRedirection(Var Wow64FsEnableRedirection: LongBool): LongBool; StdCall;
External 'Kernel32.dll' Name 'Wow64DisableWow64FsRedirection'; Function Wow64EnableWow64FsRedirection(Wow64FsEnableRedirection: LongBool): LongBool; StdCall; External 'Kernel32.dll' Name 'Wow64EnableWow64FsRedirection'; Var Wow64FsEnableRedirection: LongBool; |
Re: Datei ausführen unter Windows 64-Bit
So, jetzt bin ich weniger verwirrt. Habe meine VMWare zum Laufen bekommen und konnte das Ganze auf Win32 (XP, SP2) testen. Dabei trat bei mir der Fehler auf, dass schon die Functionen der kernel32.dll einen Fehler beim Starten des Programms verursacht haben, da diese bei WIn32 fehlen. Auch hat die "0" bei ShellExecute (letzt Parameter) dazu geführt, das RegEdit unsichtbar startet - dies war bei Win64 (Vista) komischerweise nicht der Fall, anscheinend dürften hier Applikatione nicht mehr unsichtbar sein oder so.
Fazit: Habe das Ganze also dynamisch eingebunden und dabei ist folgende Function() herausgekommen; bei mir funktionierte alles unter Win XP32 und Vista 64-Bit tadellos.
Delphi-Quellcode:
Der Aufruf erfolgt dann über:uses ShellApi, Windows, Registry; .... Function FileExec(const sDatei, sParam: String; iShowCmd: Integer = sw_Shownormal): Integer; type TWow64DisableWow64FsRedirection = function(Var Wow64FsEnableRedirection: LongBool): LongBool; StdCall; TWow64EnableWow64FsRedirection = function(Wow64FsEnableRedirection: LongBool): LongBool; StdCall; var Wow64FsEnableRedirection: LongBool; Function IsWin64: Boolean; begin With TRegistry.Create do begin RootKey := HKEY_LOCAL_MACHINE; Result := KeyExists('\SOFTWARE\Wow6432Node'); Free; end; end; var hHandle: THandle; // Handle zur DLL Wow64DisableWow64FsRedirection: TWow64DisableWow64FsRedirection; Wow64EnableWow64FsRedirection: TWow64EnableWow64FsRedirection; begin if isWin64 then begin // Win64 hHandle := LoadLibrary(PChar('kernel32.dll')); if hHandle <> 0 then begin @Wow64EnableWow64FsRedirection := GetProcAddress(hHandle, 'Wow64EnableWow64FsRedirection'); @Wow64DisableWow64FsRedirection := GetProcAddress(hHandle, 'Wow64DisableWow64FsRedirection'); if (@Wow64EnableWow64FsRedirection <> nil) AND (@Wow64DisableWow64FsRedirection <> nil) then begin // Alles OK? Dann Datei ausführen! Wow64DisableWow64FsRedirection(Wow64FsEnableRedirection); Result := ShellExecute(0, nil, PChar(sdatei), Pchar(sParam), nil, iShowCmd); Wow64EnableWow64FsRedirection(Wow64FsEnableRedirection); end; FreeLibrary(hHandle); end; end else begin // Normales Win32 Result := ShellExecute(0, nil, PChar(sdatei), Pchar(sParam), nil, iShowCmd); end; end;
Delphi-Quellcode:
Vielleicht kann's ja jemand anders nochmals testen und ggf. Optimierungsmöglichkeiten posten.
Fileexec('C:\Windows\regedit.exe', '');
|
Re: Datei ausführen unter Windows 64-Bit
Da kernel32.dll in deinen Anwendungen eh immer bereits geladen sein wird, brauchst du ssie nicht nochmals zu laden/freizugeben ^^
FreeLibrary(hHandle); entfällt und hHandle := LoadLibrary('kernel32.dll'); wird durch hHandle := GetModuleHandle('kernel32.dll'); ersetzt. Dein IsWin64 kannst du eigentlich auch weglassen, denn du fühst die Anwendung ja so oder so aus, selbst wenn Wow64DisableWow64FsRedirection nicht funkioniert. Außerdem wird Wow64DisableWow64FsRedirection eh nur unter Win64 laufen. ;) Also kann man auch durch Aufrufen 'ner Win64-Funktion gleich mit auf Win64 testen. :angel: Hier mal eine Kurzfassung deines Codes, wobei hier bei einem fehlgeschalgenem Aufruf mit Wow64FsRedirection nochmal es nochmals ohne versucht wird.
Delphi-Quellcode:
Function FileExec(Const sDatei, sParam: String; iShowCmd: Integer = sw_ShowNormal): Integer;
Type TWow64DisableWow64FsRedirection = Function(Var Wow64FsEnableRedirection: LongBool): LongBool; StdCall; TWow64EnableWow64FsRedirection = Function(Wow64FsEnableRedirection: LongBool): LongBool; StdCall; Var hHandle: THandle; Wow64DisableWow64FsRedirection: TWow64DisableWow64FsRedirection; Wow64EnableWow64FsRedirection: TWow64EnableWow64FsRedirection; Wow64FsEnableRedirection: LongBool; Begin hHandle := GetModuleHandle('kernel32.dll'); @Wow64EnableWow64FsRedirection := GetProcAddress(hHandle, 'Wow64EnableWow64FsRedirection'); @Wow64DisableWow64FsRedirection := GetProcAddress(hHandle, 'Wow64DisableWow64FsRedirection'); If (hHandle <> 0) and (@Wow64EnableWow64FsRedirection <> nil) and (@Wow64DisableWow64FsRedirection <> nil) Then Wow64DisableWow64FsRedirection(Wow64FsEnableRedirection); Result := ShellExecute(0, nil, PChar(sDatei), PChar(sParam), nil, iShowCmd); Wow64EnableWow64FsRedirection(Wow64FsEnableRedirection); End Else Result := 0; Result := Result or ShellExecute(0, nil, PChar(sDatei), PChar(sParam), nil, iShowCmd); End; |
Re: Datei ausführen unter Windows 64-Bit
Zitat:
danke mal wieder für Deine Optimierung des Codes. Funktioniert jetzt unter Win64 (Vista) und Win32 (XP, SP2) fast ohne Probleme oder Fehler. Einziges Problem habe ich mit der ![]() ShowMessage(), MessageDlg() funktionieren normal ... Dieser Fehler taucht übrigens nicht auf, wenn ich die Datei direkt über Shellexecute() (also ohne Wow64DisableWow64FsRedirection) ausführe. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:04 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz