怎样得知一个应用程序已经关闭?(50分)

  • 主题发起人 主题发起人 pandaxj
  • 开始时间 开始时间
P

pandaxj

Unregistered / Unconfirmed
GUEST, unregistred user!
各位兄台!我现在遇到的问题是:我用shellexecute执行一个带参数人可执行文件,这个可执行文件是按参数执行完<br>后自动结束!当这个文件执行完后我还要执行一个文件(这个文件想要在上一个文件执行完后再执行),怎么<br>才能知道上一个文件已经执行完毕?还望各位兄台多多指点!
 
ShellExecute 因为无法获取创建的进程句柄,所以只能是不断循环等待处理<br>这个函数在RxLib 的 RXShell.pas 的FileExecuteWait函数解释的非常清楚的。<br>Win32环境可以使用ShellExecuteEx或是CreateProcess函数,Win16环境就使用<br>FileExecute<br><br>-----摘抄自 RxLib 2.75 RXShell.pas<br><br>function FileExecute(const FileName, Params, StartDir: string;<br>&nbsp; InitialState: TExecState): THandle;<br>{$IFDEF WIN32}<br>begin<br>&nbsp; Result := ShellExecute(Application.Handle, nil, PChar(FileName),<br>&nbsp; &nbsp; PChar(Params), PChar(StartDir), ShowCommands[InitialState]);<br>end;<br>{$ELSE}<br>var<br>&nbsp; cFileName, cParams, cPath: array [0..80] of Char;<br>begin<br>&nbsp; Result := ShellExecute(Application.Handle, nil, StrPCopy(cFileName,<br>&nbsp; &nbsp; FileName), StrPCopy(cParams, Params), StrPCopy(cPath, StartDir),<br>&nbsp; &nbsp; ShowCommands[InitialState]);<br>end;<br>{$ENDIF}<br><br>function FileExecuteWait(const FileName, Params, StartDir: string;<br>&nbsp; InitialState: TExecState): Integer;<br>{$IFDEF WIN32}<br>var<br>&nbsp; Info: TShellExecuteInfo;<br>&nbsp; ExitCode: DWORD;<br>begin<br>&nbsp; FillChar(Info, SizeOf(Info), 0);<br>&nbsp; Info.cbSize := SizeOf(TShellExecuteInfo);<br>&nbsp; with Info do begin<br>&nbsp; &nbsp; fMask := SEE_MASK_NOCLOSEPROCESS;<br>&nbsp; &nbsp; Wnd := Application.Handle;<br>&nbsp; &nbsp; lpFile := PChar(FileName);<br>&nbsp; &nbsp; lpParameters := PChar(Params);<br>&nbsp; &nbsp; lpDirectory := PChar(StartDir);<br>&nbsp; &nbsp; nShow := ShowCommands[InitialState];<br>&nbsp; end;<br>&nbsp; if ShellExecuteEx(@Info) then begin<br>&nbsp; &nbsp; repeat<br>&nbsp; &nbsp; &nbsp; Application.ProcessMessages;<br>&nbsp; &nbsp; &nbsp; GetExitCodeProcess(Info.hProcess, ExitCode);<br>&nbsp; &nbsp; until (ExitCode &lt;&gt; STILL_ACTIVE) or Application.Terminated;<br>&nbsp; &nbsp; Result := ExitCode;<br>&nbsp; end<br>&nbsp; else Result := -1;<br>end;<br>{$ELSE}<br>var<br>&nbsp; Task: THandle;<br>begin<br>&nbsp; Result := 0;<br>&nbsp; Task := FileExecute(FileName, Params, StartDir, InitialState);<br>&nbsp; if Task &gt;= HINSTANCE_ERROR then begin<br>&nbsp; &nbsp; repeat<br>&nbsp; &nbsp; &nbsp; Application.ProcessMessages;<br>&nbsp; &nbsp; until (GetModuleUsage(Task) = 0) or Application.Terminated;<br>&nbsp; end<br>&nbsp; else Result := -1;<br>end;<br>{$ENDIF}
 
假如我知道程序的名字呢?<br>
 
var Myhandle:HWND;<br>begin<br>&nbsp; &nbsp;Myhandle:= FindWindow(nil, 'xx');<br>&nbsp;if MyHandle &lt;&gt; 0 then<br>&nbsp; <br>获得句柄,说明还没完。<br>或<br>//循环枚举出系统开启的所有进程,找出“xxx”<br>&nbsp; &nbsp; &nbsp; &nbsp;<br>
 
用CreateProcess 配合 WaitForSingleObject<br><br>抄了一段网上的tips过来:<br><br>var<br>&nbsp; &nbsp;sCommandLine: string;<br>&nbsp; &nbsp;bCreateProcess: boolean;<br>&nbsp; &nbsp;lpStartupInfo: TStartupInfo;<br>&nbsp; &nbsp;lpProcessInformation: TProcessInformation;<br>begin<br>&nbsp; &nbsp;// sCommandLine 的内容请视您的情况修改<br>&nbsp; &nbsp;sCommandLine :='Xcopy d:/temp/temp1/*.* d:/temp/temp2 <br>/v/y';<br>&nbsp; &nbsp;lpStartupInfo.dwFlags := STARTF_USESHOWWINDOW;<br>&nbsp; &nbsp;lpStartupInfo.wShowWindow := SW_HIDE;<br>&nbsp; &nbsp;bCreateProcess := CreateProcess(nil, <br>PChar(sCommandLine),nil,nil,True,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; HIGH_PRIORITY_CLASS, nil, <br>nil,lpStartupInfo, lpProcessInformation);<br>&nbsp; &nbsp;if bCreateProcess then<br>&nbsp; &nbsp; &nbsp; &nbsp; WaitForSingleObject(lpProcessInformation.hProcess, <br>INFINITE);<br>end;<br>
 
用API,以下是一段VB程序,应该可以看得懂的。<br>'执行<br>Dim pId As Long, pHnd As Long<br>pId = Shell("cmd.exe", vbNormalFocus)<br>pHnd = OpenProcess(SYNCHRONIZE, 0, pId) ' 取得 Process Handle<br>If pHnd &lt;&gt; 0 Then<br>Call WaitForSingleObject(pHnd, INFINITE) ' 等待程序结束<br>Call CloseHandle(pHnd)<br>End If<br>'执行结束<br><br>
 
想简单的话,就用FINDWINDOW吧;<br>VAR<br>&nbsp; HW:HWND;<br>BEGIN<br>&nbsp; &nbsp;HW:=FINDWINDOW(NIL,你的程序的窗体名称);<br>&nbsp; &nbsp;IF HW&lt;&gt;0 THEN<br>&nbsp; &nbsp; &nbsp; 未关闭;<br>END;<br>
 
// WinExecAndWait32能满足你的要求,要是只是想判断,可以用第二个函数.适当修改一下就可以了.<br><br>FUNCTION WinExecAndWait32(FileName: STRING; Visibility: integer): longint;<br>VAR<br>&nbsp; zAppName: ARRAY[0..512] OF char;<br>&nbsp; zCurDir: ARRAY[0..255] OF char;<br>&nbsp; WorkDir: STRING;<br>&nbsp; StartupInfo: TStartupInfo;<br>&nbsp; ProcessInfo: TProcessInformation;<br>// &nbsp;LPDWORD: lpExitCode;<br>BEGIN<br>&nbsp; StrPCopy(zAppName, FileName);<br>&nbsp; GetDir(0, WorkDir);<br>&nbsp; StrPCopy(zCurDir, WorkDir);<br>&nbsp; FillChar(StartupInfo, Sizeof(StartupInfo), #0);<br>&nbsp; StartupInfo.cb := Sizeof(StartupInfo);<br>&nbsp; StartupInfo.dwFlags := STARTF_USESHOWWINDOW;<br>&nbsp; StartupInfo.wShowWindow := Visibility;<br>&nbsp; IF NOT CreateProcess(NIL,<br>&nbsp; &nbsp; zAppName, { pointer to command line string }<br>&nbsp; &nbsp; NIL, { pointer to process security attributes}<br>&nbsp; &nbsp; NIL, { pointer to thread security attributes }<br>&nbsp; &nbsp; false, { handle inheritance flag }<br>&nbsp; &nbsp; CREATE_NEW_CONSOLE OR { creation flags }<br>&nbsp; &nbsp; NORMAL_PRIORITY_CLASS,<br>&nbsp; &nbsp; NIL, { pointer to new environment block }<br>&nbsp; &nbsp; NIL, { pointer to current directory name }<br>&nbsp; &nbsp; StartupInfo, { pointer to STARTUPINFO }<br>&nbsp; &nbsp; ProcessInfo) THEN<br>&nbsp; &nbsp; Result := -1 { pointer to PROCESS_INF }<br>&nbsp; ELSE<br>&nbsp; BEGIN<br>&nbsp; &nbsp; WaitforSingleObject(ProcessInfo.hProcess, INFINITE);<br>&nbsp; // &nbsp;GetExitCodeProcess(ProcessInfo.hProcess, nil);<br>&nbsp; END;<br>END;<br><br>function TfrmMain.Execute(ComLine: string): boolean;<br>var<br>&nbsp; lpAppName: pchar;<br>&nbsp; lpTitle: Pchar;<br>&nbsp; StartInfo: TStartupInfo;<br>&nbsp; FProcessInfo: TProcessInformation;<br>&nbsp; Maxpath: integer;<br>begin<br>&nbsp; if (Length(ComLine) + 2) &gt; 255 then<br>&nbsp; begin<br>&nbsp; &nbsp;// SetError(-1, 'Command Line Too Long!');<br>&nbsp; &nbsp; Result := false;<br>&nbsp; &nbsp; exit;<br>&nbsp; end;<br>// &nbsp;Size := FileSize(F);<br>// &nbsp;MaxPath:=sizeof(lpAppName);<br>&nbsp; GetMem(lpAppName, MaxPath);<br>&nbsp; GetMem(lpTitle, MaxPath);<br><br>&nbsp; StrPCopy(lpAppName, ComLine);<br>&nbsp; StrPCopy(lpTitle, ComLine);<br>&nbsp; //init StartInformation<br>&nbsp; StartInfo.cb := sizeof(TStartupInfo);<br>&nbsp; StartInfo.lpReserved := nil;<br>&nbsp; StartInfo.lpDesktop := nil;<br>&nbsp; StartInfo.lpTitle := lpTitle;<br>&nbsp; StartInfo.dwFillAttribute := 0;<br>&nbsp; StartInfo.cbReserved2 := 0;<br>&nbsp; StartInfo.lpReserved2 := nil;<br>&nbsp; //这个参数控制Create Window形态<br>&nbsp; //STARTF_USESHOWWINDOW 指定这个标志位,指示用ShowWindow的参数建立窗口<br>&nbsp; StartInfo.dwFlags := STARTF_USESHOWWINDOW;<br>&nbsp;// StartInfo.wShowWindow := FWinStyle;<br><br>&nbsp; //CreateProcess 在Windows.pas中的一个原形<br>&nbsp; //function CreateProcessA(lpApplicationName: PAnsiChar; lpCommandLine: PAnsiChar;<br>&nbsp; //lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;<br>&nbsp; //bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;<br>&nbsp; //lpCurrentDirectory: PAnsiChar; const lpStartupInfo: TStartupInfo;<br>&nbsp; //var lpProcessInformation: TProcessInformation): BOOL; stdcall;<br><br>&nbsp; //Clear ProcessInfo Structure<br>&nbsp; FProcessInfo.hProcess := 0;<br>&nbsp; FProcessInfo.hThread := 0;<br>&nbsp; FProcessInfo.dwProcessId := 0;<br>&nbsp; FProcessInfo.dwThreadId := 0;<br><br>&nbsp; //Create process<br>&nbsp; if CreateProcess(nil,<br>&nbsp; &nbsp; lpAppName,<br>&nbsp; &nbsp; nil,<br>&nbsp; &nbsp; nil,<br>&nbsp; &nbsp; False,<br>&nbsp; &nbsp; 0,<br>&nbsp; &nbsp; nil,<br>&nbsp; &nbsp; nil,<br>&nbsp; &nbsp; StartInfo,<br>&nbsp; &nbsp; FProcessInfo) then<br>&nbsp; begin //Command Executed<br>&nbsp; &nbsp; //为进程建立可查询的属性。<br>&nbsp; &nbsp; FAppHandle := OpenProcess(PROCESS_QUERY_INFORMATION, False, FProcessInfo.dwProcessId);<br>&nbsp; &nbsp; //建立可查询的属性后可用于GetExitCodeProcess,在Delphi中查询外部程序是<br>&nbsp; &nbsp; //否还在运行,这个函数在W95,W98,NT40下均可用.<br>&nbsp; &nbsp; //注意:FAppHandle要改成Form的变量,以便其它函数可以使用.<br>&nbsp; &nbsp;// &nbsp;GetExitCodeProcess(FAppHandle,FAppState);<br>&nbsp; &nbsp;// &nbsp;if FAppState&lt;&gt;STILL_ACTIVE then<br>&nbsp; &nbsp; &nbsp;// &nbsp; &nbsp;外部程序已结束<br>&nbsp; &nbsp; &nbsp;// &nbsp;else<br>&nbsp; &nbsp; &nbsp; // &nbsp;外部程序还在运行<br>&nbsp; end<br>&nbsp; else //false Create Process;<br>&nbsp; begin<br>&nbsp; &nbsp;// SetError(-2, 'Can not create process!');<br>&nbsp; &nbsp; Result := false;<br>&nbsp; end;<br><br>&nbsp; FreeMem(lpAppName);<br>&nbsp; FreeMem(lpTitle);<br>end;<br><br><br>procedure TfrmMain.Button3Click(Sender: TObject);<br>var<br>&nbsp; FAppState: DWORD;<br>begin<br>&nbsp; GetExitCodeProcess(FAppHandle, FAppState);<br>&nbsp; if FAppState &lt;&gt; STILL_ACTIVE then<br>&nbsp; &nbsp; caption := ' 外部程序已结束'<br>&nbsp; else<br>&nbsp; &nbsp; caption := ' &nbsp;外部程序还在运行';<br>&nbsp; showmessage(inttostr(FAppHandle));<br>end;<br>
 
多人接受答案了。
 
后退
顶部