调用外部程序的问题 ( 积分: 100 )

  • 主题发起人 主题发起人 shipper123
  • 开始时间 开始时间
S

shipper123

Unregistered / Unconfirmed
GUEST, unregistred user!
做了一个菜单,菜单里的每一项都对应一个外部的程序.我要控制同时只能打开一个外部的程序,只有当一个程序关闭的时候才可以打开第二个程序.请高手提供统计线程的函数,最好能统计当前窗口数量的函数.因为我一开机只运行一个窗口,然后调用的程序也只存在一个窗口.更希望高手能提供更好的解决办法.因为我想控制只能打开二个外部程序,或三个...可以人为的控制.
 
做了一个菜单,菜单里的每一项都对应一个外部的程序.我要控制同时只能打开一个外部的程序,只有当一个程序关闭的时候才可以打开第二个程序.请高手提供统计线程的函数,最好能统计当前窗口数量的函数.因为我一开机只运行一个窗口,然后调用的程序也只存在一个窗口.更希望高手能提供更好的解决办法.因为我想控制只能打开二个外部程序,或三个...可以人为的控制.
 
参照此贴:http://www.delphibbs.com/delphibbs/dispq.asp?lid=2648444<br>关键字:进程阻塞
 
看了链接,还是感觉用不起来,请继续指点
 
可以这样,使用SHELLEXECUTEEX打开进程,搜索此进程的PROCESSID(使用toolhelpapi),使用enumwindows枚举所有窗口,使用GetWindowThreadProcessId检查指定窗口句柄是否为此要管理的进程ID,如是就记数加1。
 
appfirst 能不能附上完整的的代码呀?!其实我不需要对特定的窗口进行管理的,只要控制打开的程序数量不超过某个常量值就行了.
 
关键的几个API我都告诉你了,自己做一下吧,可以练习并熟悉使用这些API。
 
CreateProcess + CreateEvent,这样效率比较高。
 
江南草,能不能具体谈谈呀?!我也觉得上面的方法效率不是太高
 
可以CreateProcess <br>然后WaitForSingleObject(使用infinite参数)<br><br>参看下面这个<br>http://www.delphibbs.com/delphibbs/dispq.asp?lid=3058225
 
我还是没解决呀!哪位朋友帮我解决了。我把分都给他!
 
你是不是想控制用户同时只能运行一个程序??或者指定数量的程序?<br>如果这样的化我可能有办法。
 
unit ProcessUnit;<br><br>interface<br><br>Uses Windows,tlhelp32,Classes,SysUtils,ComCtrls,Dialogs;<br><br><br>function ExecProcess(FileName:String; Var hProcess,ProcessID:THandle):Boolean;<br><br>procedure AddProcess(FileName:String; hProcess,ProcessID:THandle);<br>Function StatWindows:Integer;<br>Function StatProcess:Integer;<br><br>implementation<br><br>Type<br> &nbsp; &nbsp;PProcessInfo=^TProcessInfo;<br> &nbsp; &nbsp;TProcessInfo=Record<br> &nbsp; &nbsp; &nbsp; &nbsp;Name:String;<br> &nbsp; &nbsp; &nbsp; &nbsp;Path:String;<br> &nbsp; &nbsp; &nbsp; &nbsp;hProcess, ProcessID:THandle;<br> &nbsp; &nbsp;end;<br><br>Var<br> &nbsp; &nbsp;List:TList;<br>function ExecProcess(FileName:String; Var hProcess,ProcessID:THandle):Boolean;<br>var<br> &nbsp; &nbsp;sInfo:TStartUpInfo;<br> &nbsp; &nbsp;pInfo:TProcessInformation;<br>begin<br> &nbsp; &nbsp;Result:=False;<br> &nbsp; &nbsp;FillChar(sInfo,sizeof(sInfo),#0);<br> &nbsp; &nbsp;with sInfo do<br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp;cb:=sizeof(sInfo);<br> &nbsp; &nbsp; &nbsp;dwFlags:=STARTF_USESHOWWINDOW;<br> &nbsp; &nbsp; &nbsp;lptitle:=nil;<br> &nbsp; &nbsp; &nbsp;wShowWindow:=SW_SHOW;<br> &nbsp; &nbsp;end;<br> &nbsp; &nbsp;if CreateProcess(PChar(FileName),<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;nil,nil,nil,true,NORMAL_PRIORITY_CLASS,nil,nil,sInfo,pInfo) then<br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp; &nbsp;hProcess:=pInfo.hProcess;<br> &nbsp; &nbsp; &nbsp; &nbsp;ProcessID:=pInfo.dwProcessId;<br> &nbsp; &nbsp; &nbsp; &nbsp;Result:=true;<br> &nbsp; &nbsp;end;<br>end;<br><br>procedure AddProcess(FileName:String; hProcess,ProcessID:THandle);<br>Var<br> &nbsp; &nbsp;Info:PProcessInfo;<br>begin<br> &nbsp; &nbsp;New(Info);<br> &nbsp; &nbsp;Info.hProcess:=hProcess;<br> &nbsp; &nbsp;Info.ProcessID:=ProcessID;<br> &nbsp; &nbsp;Info.Name:=ExtractFileName(FileName);<br> &nbsp; &nbsp;Info.Path:=ExtractFilePath(FileName);<br> &nbsp; &nbsp;List.Add(Info);<br>end;<br><br>Function StatProcess:Integer;<br>Var<br> &nbsp; &nbsp;Hd,Hs:THandle;<br> &nbsp; &nbsp;Lps:TModuleEntry32;<br> &nbsp; &nbsp;Lp:TProcessEntry32;<br> &nbsp; &nbsp;Function CheckProcess(ProcessID:THandle):Boolean;<br> &nbsp; &nbsp;Var<br> &nbsp; &nbsp; &nbsp; &nbsp;i:Integer;<br> &nbsp; &nbsp; &nbsp; &nbsp;Info:PProcessInfo;<br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp; &nbsp;Result:=false;<br> &nbsp; &nbsp; &nbsp; &nbsp;For i:=0 to List.Count-1 do<br> &nbsp; &nbsp; &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Info:=List.Items;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Result:=Info.ProcessID=ProcessID;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if Result then<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break;<br> &nbsp; &nbsp; &nbsp; &nbsp;end;<br> &nbsp; &nbsp;end;<br>begin<br> &nbsp; &nbsp;Result:=0;<br> &nbsp; &nbsp;Lp.dwSize:=sizeof(TProcessEntry32);<br> &nbsp; &nbsp;Hd:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);<br> &nbsp; &nbsp;Try<br> &nbsp; &nbsp; &nbsp; &nbsp;if Process32First(Hd,Lp) then<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Repeat<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if CheckProcess(LP.th32ProcessID) then<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Inc(Result);<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Until Process32Next(Hd,Lp)=False;<br> &nbsp; &nbsp;Finally<br> &nbsp; &nbsp; &nbsp; &nbsp;CloseHandle(Hd);<br> &nbsp; &nbsp;end;<br>end;<br><br>Type<br> &nbsp; &nbsp;PResultInfo=^TResultInfo;<br> &nbsp; &nbsp;TResultInfo=record<br> &nbsp; &nbsp; &nbsp; &nbsp;ProcessID:Integer;<br> &nbsp; &nbsp; &nbsp; &nbsp;Result:Integer;<br> &nbsp; &nbsp;end;<br><br>Function EnumWindowsProc(hwnd:HWND; lParam:LPARAM):Bool; stdcall;<br>Var<br> &nbsp; &nbsp;ProcessID:THandle;<br> &nbsp; &nbsp;Value:PInteger;<br><br> &nbsp; &nbsp;Function CheckProcess(ProcessID:THandle):Boolean;<br> &nbsp; &nbsp;Var<br> &nbsp; &nbsp; &nbsp; &nbsp;i:Integer;<br> &nbsp; &nbsp; &nbsp; &nbsp;Info:PProcessInfo;<br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp; &nbsp;Result:=false;<br> &nbsp; &nbsp; &nbsp; &nbsp;For i:=0 to List.Count-1 do<br> &nbsp; &nbsp; &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Info:=List.Items;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Result:=Info.ProcessID=ProcessID;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if Result then<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break;<br> &nbsp; &nbsp; &nbsp; &nbsp;end;<br> &nbsp; &nbsp;end;<br>begin<br> &nbsp; &nbsp;Result:=true;<br> &nbsp; &nbsp;Value:=Ptr(LParam);<br> &nbsp; &nbsp;GetWindowThreadProcessId(hwnd,ProcessID);<br> &nbsp; &nbsp;if CheckProcess(ProcessID) then<br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp; &nbsp;Inc(Value^);<br> &nbsp; &nbsp;end;<br>end;<br><br>Function StatWindows:Integer;<br>Var<br> &nbsp; &nbsp;ResultInfo:TResultInfo;<br>begin<br> &nbsp; &nbsp;Result:=0;<br> &nbsp; &nbsp;EnumWindows(@EnumWindowsProc,Integer(@Result));<br>end;<br><br>Var<br> &nbsp; &nbsp;i:Integer;<br>Initialization<br> &nbsp; &nbsp;List:=TList.Create;<br><br>Finalization<br> &nbsp; &nbsp;For i:=0 to List.Count-1 do<br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp; &nbsp;Dispose(List.Items);<br> &nbsp; &nbsp;end;<br> &nbsp; &nbsp;List.Free;<br>end.
 
unit Unit1;<br><br>interface<br><br>uses<br> &nbsp;Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,<br> &nbsp;Dialogs, StdCtrls, ShellAPI;<br><br>type<br> &nbsp;TForm1 = class(TForm)<br> &nbsp; &nbsp;Memo1: TMemo;<br> &nbsp; &nbsp;Button1: TButton;<br> &nbsp; &nbsp;Button2: TButton;<br> &nbsp; &nbsp;OpenDialog1: TOpenDialog;<br> &nbsp; &nbsp;Button3: TButton;<br> &nbsp; &nbsp;procedure Button3Click(Sender: TObject);<br> &nbsp; &nbsp;procedure Button1Click(Sender: TObject);<br> &nbsp; &nbsp;procedure Button2Click(Sender: TObject);<br> &nbsp;private<br> &nbsp; &nbsp;{ Private declarations }<br> &nbsp;public<br> &nbsp; &nbsp;{ Public declarations }<br> &nbsp;end;<br><br>var<br> &nbsp;Form1: TForm1;<br><br>implementation<br><br>uses ProcessUnit;<br><br>{$R *.dfm}<br><br>procedure TForm1.Button3Click(Sender: TObject);<br>Var<br> &nbsp; &nbsp;hProcess,ProcessID:THandle;<br>begin<br> &nbsp; &nbsp;if Not OpenDialog1.Execute then<br> &nbsp; &nbsp; &nbsp; &nbsp;Exit;<br><br> &nbsp; &nbsp;if Not ExecProcess(OpenDialog1.FileName,hProcess,ProcessID) then<br> &nbsp; &nbsp; &nbsp; &nbsp;Exit;<br> &nbsp; &nbsp;AddProcess(OpenDialog1.FileName,hProcess,ProcessID);<br> &nbsp; &nbsp;Memo1.Lines.Add(OpenDialog1.FileName);<br>end;<br><br>procedure TForm1.Button1Click(Sender: TObject);<br>begin<br> &nbsp; &nbsp;ShowMessage('本程序打开的进程所打开的窗口数量:'+IntToStr(StatWindows));<br>end;<br><br>procedure TForm1.Button2Click(Sender: TObject);<br>begin<br> &nbsp; &nbsp;ShowMessage('本程序打开的进程数量:'+IntToStr(StatProcess));<br><br>end;<br><br>end.
 
给你做了,不过还是应该自己多做。:)
 
unit1 是调用单元,ProcessUnit是实现单元,已经调试通过,可以直接用<br>StatProcess返回打开了多少个进程<br>StatWindows返回本程序打开进程所打开的窗口数量(有点饶舌)
 
to mosker<br>指定数量的程序
 
to appfirst 谢谢你的帮助,我测试通过,但是里面有个BUG,希望依旧得到你的帮助,就是调用的程序,在主程序之前有个更新的界面,当关闭更新界面后,线程就捕捉不到了。显示都为0了。麻烦appfirst 继续再指点一下!
 
这个就好办了.给你几个函数可以控制任意用户的执行数量<br><br>function GetUserAndDomainFromPID(ProcessId: DWORD; var User: string): Boolean; &nbsp; &nbsp;{获取进程的用户名函数}<br>var<br> &nbsp;hToken: THandle;<br> &nbsp;cbBuf: Cardinal;<br> &nbsp;ptiUser: PSIDAndAttributes;<br> &nbsp;snu: SID_NAME_USE;<br> &nbsp;ProcessHandle: THandle;<br> &nbsp;UserSize, DomainSize: DWORD;<br> &nbsp;bSuccess: Boolean;<br> &nbsp;Domain: string;<br>begin<br> &nbsp;Result := False;<br> &nbsp;ProcessHandle := OpenProcess(PROCESS_QUERY_INFORMATION, False, ProcessId);<br> &nbsp;if ProcessHandle &lt;&gt; 0 then<br> &nbsp;begin<br> &nbsp; &nbsp;if OpenProcessToken(ProcessHandle, TOKEN_QUERY, hToken) then<br> &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp;bSuccess := GetTokenInformation(hToken, TokenUser, nil, 0, cbBuf);<br> &nbsp; &nbsp; &nbsp;ptiUser &nbsp;:= nil;<br> &nbsp; &nbsp; &nbsp;while (not bSuccess) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) do<br> &nbsp; &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp; &nbsp;ReallocMem(ptiUser, cbBuf);<br> &nbsp; &nbsp; &nbsp; &nbsp;bSuccess := GetTokenInformation(hToken, TokenUser, ptiUser, cbBuf, cbBuf);<br> &nbsp; &nbsp; &nbsp;end;<br> &nbsp; &nbsp; &nbsp;CloseHandle(hToken);<br><br> &nbsp; &nbsp; &nbsp;if not bSuccess then Exit;<br> &nbsp; &nbsp; &nbsp;UserSize := 0;<br> &nbsp; &nbsp; &nbsp;DomainSize := 0;<br> &nbsp; &nbsp; &nbsp;LookupAccountSid(nil, ptiUser.Sid, nil, UserSize, nil, DomainSize, snu);<br> &nbsp; &nbsp; &nbsp;if (UserSize &lt;&gt; 0) and (DomainSize &lt;&gt; 0) then<br> &nbsp; &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp; &nbsp;SetLength(User, UserSize);<br> &nbsp; &nbsp; &nbsp; &nbsp;SetLength(Domain, DomainSize);<br> &nbsp; &nbsp; &nbsp; &nbsp;if LookupAccountSid(nil, ptiUser.Sid, PChar(User), UserSize,<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;PChar(Domain), DomainSize, snu) then<br> &nbsp; &nbsp; &nbsp; &nbsp;begin<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Result := True;<br> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;User := StrPas(PChar(User));<br> &nbsp; &nbsp; &nbsp; &nbsp;end;<br> &nbsp; &nbsp; &nbsp;end;<br> &nbsp; &nbsp; &nbsp;FreeMem(ptiUser);<br> &nbsp; &nbsp;end;<br> &nbsp; &nbsp;CloseHandle(ProcessHandle);<br> &nbsp;end;<br>end;<br><br>function GetUserName:String; {获取当前登陆用户名函数}<br>var<br> &nbsp;pcUser:PChar;<br> &nbsp;dwUSize:DWORD;<br>begin<br> &nbsp;dwUSize:=40; &nbsp; //用户名长度不大于20个字符<br> &nbsp;Result:='';<br> &nbsp;GetMem(pcUser,dwUSize);<br> &nbsp;try<br> &nbsp; &nbsp;if Windows.GetUserName(pcUser,dwUSize) then<br> &nbsp; &nbsp; &nbsp;Result:=pcUser<br> &nbsp;finally<br> &nbsp; &nbsp;FreeMem(pcUser);<br> &nbsp;end;<br>end;<br><br>function CheckAppNum(Username:String):Integer; &nbsp; &nbsp; &nbsp;{检测当前用户程序运行数量函数}<br>var<br> &nbsp;ProcessListHandle: THandle;<br> &nbsp;ProcessStruct: TProcessEntry32;<br> &nbsp;ContinueLoop:bool;<br> &nbsp;users,dom:string;<br> &nbsp;Num:integer;<br>begin<br>Num:=0;<br>users:='';<br>ProcessListHandle:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);<br>ProcessStruct.dwSize:=Sizeof(ProcessStruct);<br>ContinueLoop:=Process32First(ProcessListHandle,ProcessStruct);<br>while ContinueLoop &nbsp;do<br>begin<br>GetUserAndDomainFromPID(ProcessStruct.th32ProcessID,users);<br>if users=Username then Num:=Num+1;<br>ContinueLoop:=Process32Next(ProcessListHandle,ProcessStruct);<br>end;<br>Result:=Num;<br>end;<br>通过以上函数就可以知道任意用户名的当前运行进程,就可以控制他运行的程序数量了,以上的绝对可以用.给分吧.:)
 
谢谢,APPFIRST兄弟~
 
后退
顶部