这是关于netmeeting的第四问贴了。问题是这样的,我用一按钮执行打开netmeeting操作,代码见下:
ShellExecute(0,'open','conf.EXE',nil,nil,SW_HIDE);
sleep(6000);
h:=FindWindow(nil,'NetMeeting - 通話なし');
hnext1:=FindWindow(nil,'NetMeeting');
if (h=0) then
begin
  if (hnext1<>0) then
     SetWindowPos(hnext1,0,0,0,0,0, SWP_NOSIZE +SWP_NOMOVE+ SWP_HIDEWINDOW);
  .......
  ........
else
  SetWindowPos(h,hwnd_topmost,0,0,0,0, SW_SHOWNORMAL+SWP_NOSIZE +SWP_NOMOVE+SWP_SHOWWINDOW);
  //已经注册过netmeeting,即直接启动netmeeting1、shellexecute打开操作需要一段时间,除了设置sleep以外,还有什么方法?(我想不同的计算机或者同一计算机打开程序的多少,决定了程序能获得CPU的占用率,所以考虑复杂一些)
2、因为有可能是第一次运行netmeeting,需要注册、填写用户名等信息,我想隐藏该注册界面,上述方法虽能隐藏,但是总会先显示,一闪即过,再隐藏。有什么办法能解决?
3、再有我要是用Terminateprocess结束进程,例如在没有输入用户信息,我就退出netmeeting,是必须一开始得用cressprocess打开netmeeting吗?期待大家能帮忙!

解决方案 »

  1.   

    while h=0 do
    begin
       h:=FindWindow(nil,'NetMeeting - 通話なし');
    end;这样就可以了
      

  2.   


    谢谢HeroicDragon,因为它涉及到有些人是第一次使用netmeeting,所以弹出的是注册向导,hnext1:=FindWindow(nil,'NetMeeting'); 
    不能单纯的用h:=FindWindow(nil,'NetMeeting - 通話なし'),将陷入死循环
      

  3.   

    问题1:可以“动态分配等待时间+设置超时退出”来完美解决。机器慢的分配的时间多,机器慢的分配的时间多。程序自动判断。问题2:可以用钩子实现彻底隐藏。对外部窗口的的SHOW事件进行子类化。问题3:不是必须。但如果用CreateProcess打开的话,可以直接返回进程ID,杀进程的时候调用即可,非常方便。
      

  4.   

     
    function WinExecAndWait(APath: PChar; ACmdShow: Integer;
      ATimeout: Longword): Integer;
    var
      vStartupInfo: TStartupInfo;
      vProcessInfo: TProcessInformation;
    begin
      FillChar(vStartupInfo, SizeOf(TStartupInfo), 0);
      with vStartupInfo do
      begin
        cb := SizeOf(TStartupInfo);
        dwFlags := STARTF_USESHOWWINDOW or STARTF_FORCEONFEEDBACK;
        wShowWindow := ACmdShow;
      end;
      if CreateProcess(nil, APath, nil, nil, False,
        NORMAL_PRIORITY_CLASS, nil, nil,
        vStartupInfo, vProcessInfo) then
        Result := WaitForSingleObject(vProcessInfo.hProcess, ATimeout)
      else Result := GetLastError;
    end;
      

  5.   

    谢谢liangpei2008,还想麻烦问一下,因为我了解的的createprocess需要绝对路径,但是如我要是调用不确定路径的程序,还有什么办法吗?
    例如有些系统自带的程序,在xp和2000下就不一样,比方说netmeeting,一个好像是在winnt下,一个是在windows目录下。
      

  6.   

    问题一解决办法,以系统自带的“计算器”为例说明:Function pause(cap:string;chao:integer):HWND;
    var t:integer;
    begin
     t:=GetTickCount;
     while (FindWindow(0,pchar(cap))=0) and (GetTickCount-t<chao)
      do Application.ProcessMessages;
     result:=FindWindow(0,pchar(cap));
    end;procedure TForm1.Button1Click(Sender: TObject);
    var h:HWND;
    begin
     WinExec('calc',1);
    //动态分配时间等待程序启动完毕并返回它的窗口句柄。
    //如果启动程序速度非常慢,最长等待10秒后强制返回:
     h:=pause('计算器',10000);
     showmessage('窗口句柄:'+inttostr(h));end;问题三:
    //创建进程并杀掉它
    procedure TForm1.Button2Click(Sender: TObject);
    var
      si:STARTUPINFO;
      pi:PROCESS_INFORMATION;
    begin
    FillChar(si, SizeOf(si),0);
    si.dwFlags := STARTF_USESHOWWINDOW;
    si.cb:=SizeOf(si);
    si.wShowWindow := SW_Show;
    CreateProcess(0,'calc.exe',nil, nil, False,NORMAL_PRIORITY_CLASS, nil, nil,si,pi);
    CloseHandle(pi.hProcess);
    Sleep(3000);//等待3秒后杀掉进程:
    TerminateProcess(OpenProcess(PROCESS_ALL_ACCESS,FALSE,pi.dwProcessId),0);//一行代码杀死成功
    end;你在6楼的新问题:可以用GetSystemDirectory或GetWindowsDirectory获取系统文件夹。
    特殊文件夹比如回收站或者IE临时目录或者程序目录,也有API可以动态获取,不过那是另一个新问题了。
    问题二比较麻烦。暂不予解决!
      

  7.   

    2. 要是conf.exe能够支持silent的参数...
      

  8.   

    不同路径这是操作系统目录发生了变化...
    GetWindowsDirectory() api来获得
      

  9.   

    指conf.exe是不是有一个参数来支持silent模式运行,这样的话,你就可以启动的时候传递这个参数
    当然这个方法就是需要conf.exe本身支持