[英]Delphi 7 32 bits execute and wait 64 bits process
I used to use the function below to start and wait unil the end of a process. 我曾经使用下面的函数启动并等待unil结束进程。
It works fine for starting and waiting for 32 bits process on a 32 bits or 64 bits OS. 它适用于在32位或64位OS上启动和等待32位进程。
But on a 64 bits OS, it returns immediately when i launch a 64 bits process (WaitForSingleObject = WAIT_OBJECT_0). 但是在64位操作系统上,当我启动64位进程(WaitForSingleObject = WAIT_OBJECT_0)时它会立即返回。
For example, if my app (32 bits), launch mstsc.exe on a 32 bits OS it is ok but it don't wait on a 64 bits OS certainly because mstsc.exe is a 64 bits program. 例如,如果我的应用程序(32位),在32位操作系统上启动mstsc.exe就可以,但它不会在64位操作系统上等待,因为mstsc.exe是一个64位程序。
Any solution ? 有解决方案吗
function gShellExecuteAndWait(
vHandle : HWND;
vOperation : string;
vFichier : string;
vParametres : string;
vRepertoire : string;
vAffichage : Integer;
vDuree : DWORD;
var vErreur : string
) : Boolean;
var
vSEInfo : TShellExecuteInfo;
vAttente : DWORD;
begin
// Initialisation
Result := True;
vErreur := '';
vAttente := 0;
// Initialisation de la structure ShellExecuteInfo
ZeroMemory(@vSEInfo, SizeOf(vSEInfo));
// Remplissage de la structure ShellExecuteInfo
vSEInfo.cbSize := SizeOf(vSEInfo);
vSEInfo.fMask := SEE_MASK_NOCLOSEPROCESS;
vSEInfo.Wnd := vHandle;
vSEInfo.lpVerb := PAnsiChar(vOperation);
vSEInfo.lpFile := PAnsiChar(vFichier);
vSEInfo.lpParameters := PAnsiChar(vParametres);
vSEInfo.lpDirectory := PAnsiChar(vRepertoire);
vSEInfo.nShow := vAffichage;
// L'exécution a réussi
if ShellExecuteEx(@vSEInfo) then
begin
// Attendre la fin du process ou une erreur
while True do
begin
case WaitForSingleObject(vSEInfo.hProcess, 250) of
WAIT_ABANDONED :
begin
Result := False;
vErreur := 'L''attente a été annulée.';
Break;
end;
WAIT_OBJECT_0 :
begin
Break;
end;
WAIT_TIMEOUT :
begin
// Initialisation
vAttente := vAttente + 250;
// Le délai d'attente n'a pas été atteint
if vAttente < vDuree then
begin
Application.ProcessMessages();
end
// Le délai d'attente est dépassé
else
begin
Result := False;
vErreur := 'Le délai d''attente a été dépassé.';
Break;
end;
end;
WAIT_FAILED :
begin
Result := False;
vErreur := SysErrorMessage(GetLastError());
Break;
end;
end;
end;
end
// L'exécution a échoué
else
begin
Result := False;
vErreur := SysErrorMessage(GetLastError());
end;
end;
My guess is that the following happens: 我的猜测是发生以下情况:
mstsc.exe
. mstsc.exe
的新进程。 mstsc.exe
then determines that it needs to start the 64 bit version of mstsc.exe
, which it does, passing on any command line arguments, and then immediately terminates. mstsc.exe
确定它需要启动mstsc.exe
的64位版本,它会传递任何命令行参数,然后立即终止。 This would explain why your new process immediately terminates. 这可以解释为什么您的新流程会立即终止。
Some possible solutions: 一些可能的解决方
In the case of launching mstsc.exe from a 32 bits program on a 64 OS, I modified the function like this (it is a first try not the definitive version) ans it works like a charm ! 在从64位OS上的32位程序启动mstsc.exe的情况下,我修改了这样的功能(这是第一次尝试而不是最终版本),它就像一个魅力!
Thank you @DavidHeffernan ! 谢谢@DavidHeffernan!
But be aware that if you don't know what process will be lauched (and its behavio) you need to consider @RemyLebeau global solution. 但请注意,如果您不知道将推出什么流程(及其行为),您需要考虑@RemyLebeau全球解决方案。
Thanks you ! 谢谢 !
function gShellExecuteAndWait(
vHandle : HWND;
vOperation : string;
vFichier : string;
vParametres : string;
vRepertoire : string;
vAffichage : Integer;
vDuree : DWORD;
var vErreur : string
) : Boolean;
var
vSEInfo : TShellExecuteInfo;
vAttente : DWORD;
IsWow64Process :function(aProcess: THandle; var aWow64Process: Bool): Bool; stdcall;
Wow64DisableWow64FsRedirection :function(aOldValue :pointer) :Bool; stdcall;
Wow64RevertWow64FsRedirection :function(aOldValue :pointer) :Bool; stdcall;
Wow64 :Bool;
OldFs :pointer;
begin
// Initialisation
Result := True;
vErreur := '';
vAttente := 0;
OldFS := nil;
IsWow64Process := Windows.GetProcAddress(Windows.GetModuleHandle('kernel32.dll'), 'IsWow64Process');
if Assigned(IsWow64Process) then
begin
IsWow64Process(GetCurrentProcess, Wow64);
end
else
begin
Wow64 := False;
end;
if Wow64 then
begin
Wow64DisableWow64FsRedirection := GetProcAddress(Windows.GetModuleHandle('kernel32.dll'), 'Wow64DisableWow64FsRedirection');
Wow64DisableWow64FsRedirection(OldFS);
end;
// Initialisation de la structure ShellExecuteInfo
ZeroMemory(@vSEInfo, SizeOf(vSEInfo));
// Remplissage de la structure ShellExecuteInfo
vSEInfo.cbSize := SizeOf(vSEInfo);
vSEInfo.fMask := SEE_MASK_NOCLOSEPROCESS;
vSEInfo.Wnd := vHandle;
vSEInfo.lpVerb := PAnsiChar(vOperation);
vSEInfo.lpFile := PAnsiChar(vFichier);
vSEInfo.lpParameters := PAnsiChar(vParametres);
vSEInfo.lpDirectory := PAnsiChar(vRepertoire);
vSEInfo.nShow := vAffichage;
// L'exécution a réussi
if ShellExecuteEx(@vSEInfo) then
begin
// Attendre la fin du process ou une erreur
while True do
begin
case WaitForSingleObject(vSEInfo.hProcess, 250) of
WAIT_ABANDONED :
begin
Result := False;
vErreur := 'L''attente a été annulée.';
Break;
end;
WAIT_OBJECT_0 :
begin
Break;
end;
WAIT_TIMEOUT :
begin
// Initialisation
vAttente := vAttente + 250;
// Le délai d'attente n'a pas été atteint
if vAttente < vDuree then
begin
Application.ProcessMessages();
end
// Le délai d'attente est dépassé
else
begin
Result := False;
vErreur := 'Le délai d''attente a été dépassé.';
Break;
end;
end;
WAIT_FAILED :
begin
Result := False;
vErreur := SysErrorMessage(GetLastError());
Break;
end;
end;
end;
end
// L'exécution a échoué
else
begin
Result := False;
vErreur := SysErrorMessage(GetLastError());
end;
if Wow64 then
begin
Wow64RevertWow64FsRedirection := GetProcAddress(Windows.GetModuleHandle('kernel32.dll'), 'Wow64RevertWow64FsRedirection');
Wow64RevertWow64FsRedirection(OldFs);
end;
end;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.