3

我想通过 CreateProcess() 来实现以下目标 - 调用:

  1. 更改为 svn 工作副本
  2. 执行svn命令
  3. 将输出通过管道传输到文件

我尝试使用以下功能

procedure TQPortMainForm.CmdMigrationClick(Sender: TObject);
var
  StartInfo: TStartupInfo;
  ProcInfo: TProcessInformation;
  CreateOk: boolean;
  input: String;
begin
  { fill with known state }
  FillChar(StartInfo, SizeOf(TStartupInfo), #0);
  FillChar(ProcInfo, SizeOf(TProcessInformation), #0);
  StartInfo.cb := SizeOf(TStartupInfo);

  //debug
  input := 'D: && cd D:\Qport\trunk\Qport\ && ' + SVN_PATH + ' log > C:\users\PhilippKober\UNIQUE_NAME_BLUB.txt';

  CreateOk := CreateProcess(nil, PChar(input), nil, nil, false, CREATE_NEW_PROCESS_GROUP + NORMAL_PRIORITY_CLASS, nil,
    nil , StartInfo, ProcInfo);
  { check to see if successful }
  if CreateOk then
    // may or may not be needed. Usually wait for child processes
    WaitForSingleObject(ProcInfo.hProcess, INFINITE);
end;

根本没有任何反应。有没有人知道如何实现这一目标?

谢谢,

菲利普

编辑 1:我正在使用 Delphi XE - Build 7601:Service Pack 1

编辑2:这是解决方案:

var
  StartInfo: TStartupInfo;
  ProcInfo: TProcessInformation;
  CreateOk: boolean;
  input: String;
  path : String;
  cmd : String;
begin
  { fill with known state }
  FillChar(StartInfo, SizeOf(TStartupInfo), #0);
  FillChar(ProcInfo, SizeOf(TProcessInformation), #0);
  StartInfo.cb := SizeOf(TStartupInfo);

  path := 'D:\Qport\trunk\Qport\';
  cmd := 'C:\Windows\System32\cmd.exe';
  //debug
  input := '/C' + SVN_PATH + ' help > C:\users\PhilippKober\UNIQUE_NAME_BLUB.txt';

  CreateOk := CreateProcess(PChar(cmd), PChar(input), nil, nil, false, CREATE_NEW_PROCESS_GROUP + NORMAL_PRIORITY_CLASS, nil,
     Pchar(path), StartInfo, ProcInfo);
  { check to see if successful }
  if CreateOk then
    // may or may not be needed. Usually wait for child processes
    WaitForSingleObject(ProcInfo.hProcess, INFINITE);
end;
4

1 回答 1

4

调用时需要提供一个可执行文件CreateProcess。我猜你习惯叫ShellExecute哪个更宽松。

您显然希望调用cmd.exe,因此您应该将其添加到命令行。与其在启动后更改工作目录,不如cmd.exe使用lpCurrentDirectory参数 ofCreateProcess来执行此操作。命令完成后,您还需要传递/C选项以cmd.exe使其关闭。

所以你需要改变input成这样:

input := GetEnvironmentVariable('COMSPEC') + ' /C ' + SVN_PATH + 
  ' log > C:\users\PhilippKober\UNIQUE_NAME_BLUB.txt';

GetEnvironmentVariable('COMSPEC')用作获取命令解释器路径的一种方式。

然后CreateProcess像这样调用:

CreateProcess(
  nil, 
  PChar(input), 
  nil, 
  nil, 
  False, 
  CREATE_NEW_PROCESS_GROUP or NORMAL_PRIORITY_CLASS, 
  nil,
  'D:\Qport\trunk\Qport', 
  StartInfo, 
  ProcInfo
);

它在语义上or比用于组合标志更清晰+,尽管它对这些标志具有相同的效果。

需要注意的一件事是第二个参数必须指向可写内存。那是因为CreateProcess可能会修改该参数。碰巧的是,您的设置input将满足该要求。无论如何,UniqueString在我看来,建议您致电以明确表明您正在满足该要求。

我看到的另一件事是关闭由返回的句柄的代码CreateProcess。最后通过执行以下操作关闭这些句柄:

//WaitForSingleObject(ProcInfo.hProcess, INFINITE); //in case you want to wait for Process to terminate
CloseHandle(ProcInfo.hProcess);
CloseHandle(ProcInfo.hThread);
于 2013-08-02T09:30:04.133 回答