我没有设法从安装程序成功调用CreateProcess()
。
虽然以下C代码(在Win7上使用MinGW编译)可以正常启动notepad.exe
:
#include <windows.h>
#include <stdio.h>
int main(int argc, char *argv[]){
BOOL result;
STARTUPINFO startupInfo;
PROCESS_INFORMATION processInformation;
memset(&startupInfo,0, sizeof(STARTUPINFO));
startupInfo.cb = sizeof(startupInfo);
memset(&processInformation, 0, sizeof(PROCESS_INFORMATION));
//these 2 values are used for NSIS
printf("sizeof(startupInfo) = %d\n",sizeof(startupInfo));
printf("sizeof(processInformation) = %d\n",sizeof(processInformation));
result = CreateProcess(NULL, "NOTEPAD.exe",
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&startupInfo,
&processInformation
);
if(result == 0)
printf("Could not create process, lasterr = %ld\n", GetLastError());
}
这个等效的NSIS脚本在WinXp和Win7上都失败了:
!include "TextFunc.nsh"
!include "logiclib.nsh"
outfile "process.exe"
!define DEBUG `System::Call kernel32::OutputDebugString(ts)`
Var cmd
Section
StrCpy $cmd "notepad.exe"
;System::Alloc 72 ;// $1 = struct STARTUPINFO
;Pop $1
System::Call "*(i 68, i 0, i 0, i 0, i 0, i 0, i 0, i 0, i 0, i 0, i 0, i 0, &i2 0, &i2 0, i 0, i 0, i 0, i 0) p.r1" ;// StartUp.cb=sizeof(StartUp);
;System::Alloc 16 ;// $2 = struct PROCESS_INFORMATION
;Pop $2
System::Call "*(i 0, i 0, i 0, i 0) p.r2"
;System::Call "*$1(i 68)" ;// StartUp.cb=sizeof(StartUp);
System::Call /NOUNLOAD 'kernel32::CreateProcess(i 0, t $cmd, i 0, i 0, i 0, i 0, i 0, i 0, i r1, i.r2)i.r0 ?e'
Pop $9
${debug} "$0 lasterr=$9"
StrCmp $0 "0" 0 Good
MessageBox MB_OK "CreateProcess failed"
${debug} "CreateProcess failed"
Goto Free
Good:
${debug} "get infos"
System::Call "*$2(i.r3,i.r4,i.r5,i.r6) ?!e"
${debug} "PHND=$3 PID=$5"
System::Call 'kernel32::CloseHandle(i $3)'
System::Call 'kernel32::CloseHandle(i $4)'
Free:
System::Free $1
System::Free $2
SectionEnd
当我替换System::Cal
进行结构分配并改为使用System::Alloc
时,没有崩溃但CreateProcess
失败而GetLastError
返回87(ERROR_INVALID_PARAMETER
)
修复CreateProcess
我错过了什么?我不想使用内置Exec
,因为我想使用无法从nsis脚本访问的CreateProcess
标志。
修改:我收到了错误:在调用CreateProcess
时,最后一个参数i.r2
必须是ir2
:PROCESS_INFORMATION
的内存块已经分配了它,并且它的指针必须传递给CreateProcess
,而i.r2
忽略了调用之前的值,只接受它。感谢Anders的帮助:)
答案 0 :(得分:2)
p
不是有效类型,而且我认为您的STARTUPINFO尺寸错误。
Section
System::Call '*(i,i,i,i)i.r0'
System::Alloc 72
pop $4
System::Call "*$4(i 72)"
StrCpy $1 '"explorer.exe" "$startmenu"'
System::Call 'kernel32::CreateProcess(i0,tr1,i0,i0,i0,i 0,i0,i0,ir4,ir0)i.r3'
DetailPrint RET=$3
System::Free $4
${If} $3 <> 0
System::Call "*$0(i.r3,i.r4)"
System::Call 'kernel32::CloseHandle(i $3)'
System::Call 'kernel32::CloseHandle(i $4)'
${EndIf}
System::Free $0
SectionEnd