본문 바로가기
C & C++/C & C++

ShellExecuteEx로 실행한 어플 찾기

by izen8 2011. 11. 2.
반응형

ShellExecute 또는 CreateProcess로 application을 실행하고

FindWindow로 해당 프로그램을 찾아서 써야 할경우가 종종 있다.

 

그런데 혹시 같은 프로그램이 이미  여러개 떠있어서

ClassName이나 Caption이 같은 윈도우가 여러개 있다면

단지 FindWindow로서 정확히 해당 윈도우를 찾지 못하는경우가 발생하기도 한다.

 

대개의 경우는 제대로 찾아지는데 이는

방금실행한 폼이 Desktop에 맨앞으로 오기 때문이다.

 

 

그렇다면 내가 실행한 application의 윈도우를 정확히 찾으려면 어떻게 해야할까?

 

방법은?

processid를 이용해서 EnumWindow 프로세서로 넘오오는 HWND의 prossesid와 비교해서 찾을수있다.

 

아래와 같이

 

// 참조  http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_qna&no=53233

  


typedef struct _PIDANDHWND{
   DWORD  pID;
   HWND   hWindow;
   String clsname;
} PIDANDHWND;


BOOL CALLBACK EnumWindowsProc(HWND hWindow, PIDANDHWND *lParam)
{
    char sClass[513] = { 0, };
    char sCaption[1025] = { 0, };

    DWORD pId;

    GetClassName( hWindow, sClass, 512 );
    if( strcmp( sClass, lParam->clsname.c_str() ) == 0 ) //class이름이 같은지 확인
    {
        GetWindowThreadProcessId(hWindow,&pId);
        if(pId==lParam->pID)                            // 같은 process인지 확인
        {
            lParam->hWindow = hWindow;
            return FALSE;
        }
    }

    return true;

}
HWND WindowFromProcessID(DWORD pID,String sClsname)
{
    PIDANDHWND Param;
    Param.pID     = pID;
    Param.hWindow = 0;
    Param.clsname=sClsname;
    EnumWindows((WNDENUMPROC)EnumWindowsProc, (LPARAM)&Param);
    return Param.hWindow;

}

     

 

그럼 이제 실행한 프로그램의 prossesId와 classname을  가지고

 

WindwoFormProcessId 함수를 호출해주면 된다.

 

방법 1. CreateProcess 이용

 

  


void __fastcall TForm1::Button1Click(TObject *Sender)
{
    String str="notepad.exe";
    STARTUPINFO si;
    PROCESS_INFORMATION m_pi;

    GetStartupInfo(&si); 

    si.cb            = sizeof(STARTUPINFO); 
    si.dwFlags       = STARTF_USESHOWWINDOW; 
    si.wShowWindow   = SW_SHOW; 

    BOOL bRet = CreateProcess (NULL, str.c_str(), NULL, NULL, true, NORMAL_PRIORITY_CLASS
                                                         , NULL, NULL, &si, &m_pi);
    if(bRet == TRUE)
    {
        WaitForInputIdle(m_pi.hProcess, INFINITE);

        if(m_pi.dwProcessId != 0)
        {             
            HWND hwnd = WindowFromProcessID(m_pi.dwProcessId,"Notepad");


            if(hwnd)
            {
                SetPage(hwnd,"Notepad"); //그냥 무슨 작업을  하는 함수

            }
        }
    }
}

     

 

 

 방법2.   ShellExecute 를 이용하여..

  CreateProcess 함수를 이용하면 실행한 program의 processid를 쉽게 알수 있지만

  ShellExecute함수를 이용하여서는 processid를 쉽게 알수 없다.

  

   하지만 WinXP 이상에서는 kernel32.dll 에서  GetProcessId 라는 함수가 제공된다.

   

   GetProcessId 함수를 이용하여 ShellExecuteEx 를 이용해서도 processid를 확인할수 있고

   정확히 실행한 프로그램의 handle을 확인할수 있다.

 

   예제

 

//   GetProcessId에 대해
//   winxp  sp1 이상에서 지원   -  http://msdn.microsoft.com/en-us/library/aa383886(VS.85).aspx
//   GetProcessId함수 설명      -  http://msdn.microsoft.com/en-us/library/ms683215(VS.85).aspx

 

  
void __fastcall TForm1::Button3Click(TObject *Sender)

    String str="calc.exe"; 
    PROCESS_INFORMATION m_pi;

    SHELLEXECUTEINFO si; 

    ZeroMemory(&si, sizeof(SHELLEXECUTEINFO));

    si.cbSize = sizeof(SHELLEXECUTEINFO);
    si.lpVerb = __TEXT("open");                 //mode : print, write
    si.lpFile = __TEXT("calc.exe");           //실행파일
    // si.lpParameters = PathIP; //실행파일 인자값.
    // shellIP.lpDirectory = //실핼파일 디렉토리.
    si.nShow = SW_SHOW;                    //SW_HIDE
    si.fMask = SEE_MASK_NOCLOSEPROCESS|SEE_MASK_FLAG_DDEWAIT;

     BOOL bRet = ShellExecuteEx(&si);             //성공시 true

    if(bRet == TRUE)
    {
        WaitForInputIdle(si.hProcess, INFINITE);

        typedef DWORD WINAPI (*TFuncProc)(HANDLE hProcess);

        TFuncProc GetProcessId;

        HINSTANCE lib=LoadLibraryA("kernel32.dll");
        GetProcessId=(TFuncProc)GetProcAddress(lib,"GetProcessId");
        if(GetProcessId)
        {
            DWORD pid=GetProcessId(si.hProcess);

            if(pid != 0)
            { 
                HWND hwnd = WindowFromProcessID(pid,"SciCalc"); 
                if(si.hwnd==hwnd)
                    ShowMessage("같다");
                if(hwnd)
                {
                    SetPage(hwnd,"SciCalc"); //그냥 무슨 작업을  하는 함수
                }
            }
        }
        FreeLibrary(lib);
    }
}
     

 

 

그럼..

반응형

댓글