Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Delphi中调用CreateProcess?_Delphi_Winapi_Delphi Xe6 - Fatal编程技术网

如何在Delphi中调用CreateProcess?

如何在Delphi中调用CreateProcess?,delphi,winapi,delphi-xe6,Delphi,Winapi,Delphi Xe6,根据和的文档,我正在尝试呼叫: 呼叫因访问冲突而崩溃: 0003B77B模块kernel32.dll中的异常EAccessViolation。 模块“kernel32.dll”中地址7671B77B处的访问冲突。写入地址00B47EA6 现在我明白了为什么它会让我崩溃,但我不明白为什么,我也不明白 CreateProcess的文档说明,如果第一个参数是null(在我的示例、MSDN示例和其他示例中都是如此),则CreateProcess将修改命令行参数: lpCommandLine[输入、输出、

根据和的文档,我正在尝试呼叫:

呼叫因访问冲突而崩溃:

0003B77B模块kernel32.dll中的异常EAccessViolation。
模块“kernel32.dll”中地址7671B77B处的访问冲突。写入地址00B47EA6

现在我明白了为什么它会让我崩溃,但我不明白为什么,我也不明白

CreateProcess
的文档说明,如果第一个参数是null(在我的示例、MSDN示例和其他示例中都是如此),则
CreateProcess
修改
命令行
参数:

lpCommandLine[输入、输出、可选]

此函数的Unicode版本,CreateProcessW,可以修改此字符串的内容。因此,此参数不能是指向只读内存(例如常量变量或文字字符串)的指针。如果此参数是常量字符串,则函数可能会导致访问冲突

当我查看访问冲突时,它试图写入地址
0x00B47EA6

所以,
CreateProcess
试图在我的unicode字符串的空终止符上涂鸦。如果
CreateProcess
试图修改命令行而不是使其变长,则在
CreateProcess
页面注释中存在一些争议

完全有可能我的绳子

C:\Windows\System32\cmd.exe

位于只读数据节中。字符串本身的引用计数为
-1

当常量字符串来自常量时会发生这种情况

我可以通过将字符串复制到缓冲区来测试这一点:

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
);
这是成功的

因此,在创作了我的问题并进行了研究之后,我回答了我自己的问题。但我还是想知道处理这件事的好方法是什么

如何在Delphi中调用CreateProcess

其他人怎么称呼它?其他人是否正在将字符串复制到字节缓冲区

奖金
ShellExecute
他是你如何使用
ShellExecute

var
   shi: TShellExecuteInfo;

shi := Default(TShellExecuteInfo);
shi.cbSize := SizeOf(TShellExecuteInfo);
shi.lpFile := PChar(commandLine); 
shi.nShow := SW_SHOWNORMAL;

ShellExecuteEx(@shi);
您可以将PChar(命令行)替换为PChar(宽字符串(命令行))。这在Delphi XE6中对我有效


我想他们破坏了字符串类型转换中的某些内容,因为我在Delphi XE中的旧代码在没有严格转换的情况下工作。

另请参见完整示例使用单独的缓冲区正是MSDN代码和David的代码所做的。在C和C++中,<>代码> ARGV 是可写字符数组指针的可写数组。在Delphi中,动态构造的字符串是可写的。不过,您不需要字节缓冲区;在我看来,调用UniqueString是确保字符串缓冲区可写的惯用方法,而不需要WideString。我们可以用UniqueString创建一个可写的UniqueString。
var
   shi: TShellExecuteInfo;

shi := Default(TShellExecuteInfo);
shi.cbSize := SizeOf(TShellExecuteInfo);
shi.lpFile := PChar(commandLine); 
shi.nShow := SW_SHOWNORMAL;

ShellExecuteEx(@shi);