我想用CreateProcess()实现以下功能 – 调用:
>更改为svn工作副本
>执行svn命令
>将输出管道传输到文件
我尝试使用以下功能
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,false,CREATE_NEW_PROCESS_GROUP + NORMAL_PRIORITY_CLASS,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,#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(path),INFINITE); end;
调用CreateProcess时需要提供可执行文件.我猜你习惯调用ShellExecute,这更松懈.
您显然希望调用cmd.exe,因此您应该将其添加到命令行.而不是在cmd.exe启动后更改工作目录,而是使用CreateProcess的lpCurrentDirectory参数来执行此操作.您还需要将/ C选项传递给cmd.exe,以便在命令完成后将其关闭.
所以你需要改变输入是这样的:
input := GetEnvironmentVariable('COMSPEC') + ' /C ' + SVN_PATH + ' log > C:\users\PhilippKober\UNIQUE_NAME_BLUB.txt';
我使用GetEnvironmentVariable(‘COMSPEC’)作为获取命令解释器路径的方法.
然后像这样调用CreateProcess:
CreateProcess( nil,False,CREATE_NEW_PROCESS_GROUP or NORMAL_PRIORITY_CLASS,'D:\Qport\trunk\Qport',ProcInfo );
使用或组合标志在语义上比较清晰,尽管它对这些标志具有相同的效果.
需要注意的是,第二个参数必须指向可写内存.那是因为CreateProcess可能会修改该参数.碰巧,您的输入设置将满足该要求.在任何情况下,我都建议在我的视图中调用UniqueString,以明确表示您满足该要求.
我看到的另一件事是缺少关闭CreateProcess返回的句柄的代码.最后通过执行此操作来关闭这些句柄:
//WaitForSingleObject(ProcInfo.hProcess,INFINITE); //in case you want to wait for Process to terminate CloseHandle(ProcInfo.hProcess); CloseHandle(ProcInfo.hThread);