我写了一个小安装程序,我想写下这里写的东西:Waiting for grandchild processes in windows (我想等到另一个卸载程序完成)
我定义了必要的类型和std调用。
这是我的代码:
procedure UninstallPreviousVersion;
var
UninstallString: String;
ErrorCode: Integer;
UninstallJob : THandle;
UninstallStartUpInfo : LPSTARTUPINFO;
UninstallProcessInfo : LPPROCESS_INFORMATION;
begin
UninstallJob := CreateJobObject( '' , '' );
CreateProcess(
'',
'C:\Program Files (x86)\InstallShield Installation Information\{2FEAF140-139A-11D5-8925-0050DAE02BFF}\Setup.exe',
null,
null,
false,
4, //CREATE_SUSPENDED 0x00000004
null,
null,
UninstallStartUpInfo,
UninstallProcessInfo
);
AssignProcessToJobObject( UninstallJob , UninstallProcessInfo.hProcess );
ResumeThread( UninstallProcessInfo.hThread );
WaitForSingleObject( UninstallJob , $FFFFFFFF );
MsgBox('Uninstall returned! Wohohohooo yeah!', mbInformation, MB_OK);
end;
它编译,并根据调试器在CreateProcess函数期间失败。当我运行安装程序时出现以下错误: 无法将类型(Null)的变体转换为类型(OleStr)。
定义的类型:
type
LPSTARTUPINFO = record
cb : DWORD;
lpReserved : String;
lpDesktop : String;
lpTitle : String;
dwX:DWORD;
dwY:DWORD;
dwXSize:DWORD;
dwYSize:DWORD;
dwXCountChars : DWORD;
dwYCountChars : DWORD;
dwFillAttribute : DWORD;
dwFlags : DWORD;
wShowWindow : WORD;
cbReserved2 : WORD;
lpReserved2 : BYTE;
hStdInput : Thandle;
hStdOutput : Thandle;
hStdError : Thandle;
end;
type
LPPROCESS_INFORMATION = record
hProcess:THandle;
hThread:THandle;
dwProcessId:DWORD;
dwThreadId:DWORD;
end;
如有必要,我可以上传更多类型。
修改
此版本编译并启动所需的.exe。 编译器:Inno Setup 5.5 类型未定义,您必须自己定义!在windows dev网站上查找它们。 (上面有两个例子)。
procedure UninstallPreviousVersion;
var
UninstallString: String;
ErrorCode: Integer;
UninstallJob : THandle;
UninstallStartUpInfo : LPSTARTUPINFO;
UninstallProcessInfo : LPPROCESS_INFORMATION;
Info : LPVOID;
procAtt : LPSECURITY_ATTRIBUTES;
threadAtt : LPSECURITY_ATTRIBUTES;
begin
UninstallStartUpInfo.lpReserved := '';
UninstallStartUpInfo.lpDesktop := '';
UninstallStartUpInfo.lpTitle := '';
UninstallStartUpInfo.dwX := 0;
UninstallStartUpInfo.dwY := 0;
UninstallStartUpInfo.dwXSize := 0;
UninstallStartUpInfo.dwYSize := 0;
UninstallStartUpInfo.dwXCountChars := 0;
UninstallStartUpInfo.dwYCountChars := 0;
UninstallStartUpInfo.dwFillAttribute := 0;
UninstallStartUpInfo.dwFlags := ( $00000001 ) or ( $00000200 ); //STARTF_USESHOWWINDOW
UninstallStartUpInfo.wShowWindow := SW_SHOW;
UninstallStartUpInfo.cbReserved2 := 0;
UninstallStartUpInfo.lpReserved2 := 0;
UninstallStartUpInfo.cb := sizeof(UninstallStartUpInfo);
UninstallJob := CreateJobObject( '' , '' );
CreateProcess(
'C:\Program Files (x86)\\InstallShield Installation Information\{2FEAF140-139A-11D5-8925-0050DAE02BFF}\Setup.exe',
'UNINSTALL',
procAtt,
threadAtt,
false,
4, //CREATE_SUSPENDED 0x00000004
Info,
'',
UninstallStartUpInfo,
UninstallProcessInfo
);
AssignProcessToJobObject( UninstallJob , UninstallProcessInfo.hProcess );
ResumeThread( UninstallProcessInfo.hThread );
WaitForSingleObject( UninstallJob , $FFFFFFFF );
end;
答案 0 :(得分:3)
您的代码中存在多个问题。
首先,除了引用NULL
类型时,Pascal(包括Inno Setup的Pascal脚本)不使用Variant
。将null
的使用转换为调用nil
中的CreateProcess
,开始。
CreateProcess(
'',
'C:\Program Files (x86)\InstallShield Installation Information\{2FEAF140-139A-11D5-8925-0050DAE02BFF}\Setup.exe',
nil,
nil,
false,
4, //CREATE_SUSPENDED 0x00000004
nil,
nil,
UninstallStartUpInfo,
UninstallProcessInfo
);
接下来,您需要在CreateProcess调用中使用它之前填充lpStartupInfo
参数,因为它在STARTUPINFO结构的文档中解释(记录,以Pascal语言表示),从初始化开始它为空值并将cb
成员设置为结构的大小。
var
si: UninstallStartupInfo;
pi: UninstallProcessInfo;
begin
FillChar(si, sizeof(si), 0);
FillChar(pi, sizeof(pi), 0);
si.cb := sizeof(si);
si.dwFlags := STARTF_USESHOWWINDOW;
si.wShowWindow := SW_HIDE;
if not CreateProcess(...) then
// Use GetLastError() here to find out why it failed.
最后,您还应该检查返回值; CreateProcess文档告诉您对成功的期望,以及如果它没有返回成功代码该怎么办。
(并且,作为一个注释:InnoSetup的Pascal脚本有一个内置的包装器,用于执行外部文件ShellExec,它有一个参数,告诉它在返回之前等待进程执行。使用它可以使您更容易,除非有特定原因它不能满足您的需求。)