How to call CreateProcess in Delphi?
按照
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | var commandLine: string; si: TStartupInfo; pi: TProcessInformation; begin commandLine := 'C:\\Windows\\System32\\cmd.exe'; si := Default(TStartupInfo); si.cb := sizeof(si); CreateProcess( PChar(nil), //no module name (use command line) PChar(commandLine), //Command Line nil, //Process handle not inheritable nil, //Thread handle not inheritable False, //Don't inherit handles 0, //No creation flags nil, //Use parent's environment block PChar(nil), //Use parent's starting directory si, //Startup Info pi //Process Info ); |
呼叫因访问冲突而崩溃:
Exception EAccessViolation in module kernel32.dll at 0003B77B.
Access violation at address 7671B77B in module 'kernel32.dll'. Write of address 00B47EA6.
现在我明白了为什么它崩溃了,但是我不明白为什么它没有因为MSDN上的示例代码而崩溃,我也不明白为什么它没有为您失败David 。
lpCommandLine [in, out, optional]
...
The Unicode version of this function, CreateProcessW, can modify the contents of this string. Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). If this parameter is a constant string, the function may cause an access violation.
当我看到访问冲突时,它正在尝试写地址
所以
我的字符串完全有可能是
C:\\Windows\\System32\\cmd.exe
位于只读数据节中。字符串本身的引用计数为
当常量字符串来自常量时发生。
我可以通过将字符串复制到缓冲区中来对此进行测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | var commandLine: string; si: TStartupInfo; pi: TProcessInformation; l: Integer; buffer: TByteDynArray; commandLine := 'C:\\Windows\\System32\\cmd.exe'; //Copy to writable buffer (including null terminator) l := (Length(commandLine)+1)*sizeof(Char); SetLength(buffer, l); Move(commandLine[1], buffer[0], l); si := Default(TStartupInfo); si.cb := sizeof(si); if not CreateProcess( PChar(nil), //no module name (use command line) // PChar(commandLine), //Command Line @buffer[0], nil, //Process handle not inheritable nil, //Thread handle not inheritable False, //Don't inherit handles 0, //No creation flags nil, //Use parent's environment block PChar(nil), //Use parent's starting directory si, //Startup Info {var}pi //Process Info ); |
那成功地工作了。
因此,在写完我的问题并进行研究之后,我已经回答了我自己的问题。但是我仍然想知道解决这个问题的一种体面的方法是
How to call CreateProcess in Delphi?
其他人怎么称呼它?其他所有人是否都将字符串复制到字节缓冲区?
奖励
他是您使用
1 2 3 4 5 6 7 8 9 | var shi: TShellExecuteInfo; shi := Default(TShellExecuteInfo); shi.cbSize := SizeOf(TShellExecuteInfo); shi.lpFile := PChar(commandLine); shi.nShow := SW_SHOWNORMAL; ShellExecuteEx(@shi); |
您可以将PChar(commandLine)替换为PChar(WideString(commandLine))。这在Delphi XE6中对我有用。
我想他们已经破坏了字符串强制转换,因为我在Delphi XE中的旧代码无需进行严格的转换即可工作。