我用ShellExecuteEx() 执行一个外部程序, 希望的到这个程序进程句柄, 然后WaitForSingleObject等待它退出, 我执行的程序是用 "Open"方式打开一个文件, 即由系统根据文件扩展名来自动启动与该扩展名关联的程序(打开方式中设定的程序), 但如果我打开的文档是一个已经启动的多文档程序打开的话, 我得不到那个进程得句柄, 我就没办法知道那个进程什么时候退出, 我该怎么做, 请高手指点.

解决方案 »

  1.   

    例如, 我Open 一个 txt文件, 系统指定的打开方式是UltraEdit, 我的UltraEdit已经打开, 执行ShellExecuteEx后 UltraEdit确实把txt文件打开了. 可是我得不到它得句柄. how can i do?
      

  2.   

    http://www.vckbase.com/document/viewdoc.asp?id=416Q: 如何启动一个程序,直到它运行结束? 
    SHELLEXECUTEINFO ShExecInfo = {0};
    ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
    ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
    ShExecInfo.hwnd = NULL;
    ShExecInfo.lpVerb = NULL;
    ShExecInfo.lpFile = "c:\\MyProgram.exe";
    ShExecInfo.lpParameters = "";
    ShExecInfo.lpDirectory = NULL;
    ShExecInfo.nShow = SW_SHOW;
    ShExecInfo.hInstApp = NULL;
    ShellExecuteEx(&ShExecInfo);
    WaitForSingleObject(ShExecInfo.hProcess,INFINITE);
      

  3.   

    可以用CreateProcess,下面是一个MSDN中的小例子,希望能对您有所帮助。void main( VOID )
    {
        STARTUPINFO si;
        PROCESS_INFORMATION pi;    ZeroMemory( &si, sizeof(si) );
        si.cb = sizeof(si);
        ZeroMemory( &pi, sizeof(pi) );    // 创建子进程
        if( !CreateProcess( NULL, // No module name (use command line). 
            "MyChildProcess", // Command line. 
            NULL,             // Process handle not inheritable. 
            NULL,             // Thread handle not inheritable. 
            FALSE,            // Set handle inheritance to FALSE. 
            0,                // No creation flags. 
            NULL,             // Use parent's environment block. 
            NULL,             // Use parent's starting directory. 
            &si,              // Pointer to STARTUPINFO structure.
            &pi )             // Pointer to PROCESS_INFORMATION structure.
        ) 
        {
            ErrorExit( "CreateProcess failed." );
        }    // 等待子进程退出
        WaitForSingleObject( pi.hProcess, INFINITE );    // 关闭句柄
        CloseHandle( pi.hProcess );
        CloseHandle( pi.hThread );
    }
      

  4.   

    CreateProcess,ShellExecuteEx都可以获得句柄的
      

  5.   

    楼上说得都对,可是当那个程序是只允许一个实例运行,而且是个多文档的程序,我可以ShellExecuteEx打开这个文档,但此时得到的进程句柄为0, 我就没办法 wait For it exit了。
      

  6.   

    使用
    CreateToolhelp32Snapshot和它的相关函数,可以枚举WIN32进程表里的所有进程,应该够用了吧.class JProcessInfo  
    {
    public:
    JProcessInfo();
    virtual ~JProcessInfo();
    BOOL FindProcessInfo(const CString& cstrProcessName);
    BOOL NeedTerminateProcess();
    void GetUpdateSystemName(const CString&);
    void ClearProcessInfo();
    private:
    HANDLE m_hProcessSnap;
    PROCESSENTRY32 m_pe32; 
    HANDLE m_hProcess;
    HANDLE m_hRealProcess;
    CString m_cstrSystemName;
    };JProcessInfo::JProcessInfo():m_hProcessSnap(NULL),m_hProcess(NULL),m_hRealProcess(NULL)
    {
    memset(&m_pe32,0,sizeof(m_pe32));
    m_pe32.dwSize = sizeof(PROCESSENTRY32);
    m_hProcessSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    }JProcessInfo::~JProcessInfo()
    {
    try
    {
    if (m_hRealProcess)
    ::CloseHandle(m_hRealProcess);
    ::CloseHandle(m_hProcessSnap);
    }
    catch (...) 
    {
    0;
    }
    }BOOL JProcessInfo::FindProcessInfo(const CString& cstrProcessName)
    {
    if (m_hProcessSnap != INVALID_HANDLE_VALUE)
    {
    if (::Process32First(m_hProcessSnap,&m_pe32)) 
    {
    do 
    {
    HANDLE m_hProcess = ::OpenProcess(PROCESS_ALL_ACCESS,FALSE,m_pe32.th32ProcessID);
    CString cstrAppName(m_pe32.szExeFile);
    if (cstrAppName == cstrProcessName)
    {if (m_pe32.th32ProcessID != ::GetCurrentProcessId() && m_cstrSystemName != cstrProcessName)
    {
    ::TerminateProcess(m_hProcess,0);
    if (::WaitForSingleObject(m_hProcess,INFINITE) == WAIT_OBJECT_0)
    {
    return TRUE;
    }
    }
    else
    m_hRealProcess = ::OpenProcess(PROCESS_ALL_ACCESS,FALSE,m_pe32.th32ProcessID);
    }

    while (::Process32Next(m_hProcessSnap,&m_pe32));
    if (m_hRealProcess)
    return TRUE;
    return FALSE;
    }
        }
    return FALSE;
    }BOOL JProcessInfo::NeedTerminateProcess()
    {
    if (!m_hRealProcess)
    return FALSE;
    return ::TerminateProcess(m_hRealProcess,0);
    }void JProcessInfo::GetUpdateSystemName(const CString& pm)
    {
    m_cstrSystemName = pm;
    }void JProcessInfo::ClearProcessInfo()
    {
    m_cstrSystemName.Empty();
    }