/*

 * http://sosal.kr/

 * made by so_Sal

 */




이번장에서 살펴볼 함수들
1.WinExec()
   CreateProcess()
2.ShellExecute()
   ShellExecuteEx()

================= 1. WinExec(), CreateProcess() =================
아래는 WinExec() 와 CreateProcess()를 살펴보겠습니다.

WinExec() 함수는 Windows 3.x 버전에서
새로운 프로세스 (프로그램)을 실행시키는 유일한 함수였습니다.
상당히 간결하게 사용할 수 있는 함수입니다.

WinExec의 문제점은? ::
프로그램이 실행되고 나면 이전의 프로세스가 새로이 생성된
프로세스에게 간섭할 수 없다. (접근 불가)
(프로그램이 제대로 작동하는지, 종료시 리턴값 등)
아래 첫번째 인자에 대한 보안 위험성도 문제점중 하나이다.
결론 :: 아주 간단하게 프로그램을 실행시키기 위한 경우에만 쓰자!
     :: 그외에는 CreateProcess 함수 호출!!
     :: 아래에서 배울 ShellExecute() 함수는 내부적으로 CreateProcess()를 호출


UINT
WinExec(
     LPCSTR lpCmdLine,
     UINT uCmdShow);

LPCSTR lpCmdLine // 실행될 프로그램의 경로를 입력받습니다.

절대 경로를 입력시에 절대경로에 맞춰서 실행됩니다.
그 외에 상대경로를 입력시
1. 함수를 실행하는 프로그램이 존재하는 디렉토리
2. Windows System 디렉토리
3. Windows 디렉토리
4. :: PATH :: 환경변수에 등록된 디렉토리
를 순서로 검색하여 실행합니다.

* lpCmdLine 입력시 보안상 문제가 발생한다.
WinExec( "C:\\Program Files\\Games.... " , ...);
이렇게 입력했다고 가정했을때, lpCmdLine으로 넘어가는 인자의 값은
c: -> Program Files -> Games -> 로 검색해서 파일을 찾는다.
하지만 중간에 누군가 악의적으로 "Program.exe"라는 파일을 만들어 놓는다면
위처럼 Program Files를 호출하는 모든 프로세스가 Program.exe 파일을
실행하게 된다. 따라서 인자를 넘길때 " (\" ) 따옴표로 묶는걸 권장한다.
ex)
WinExec( " \"C:\\Program Files\\Games.... \" " , ...);

UINT uCmdShow // 실행되어질 프로그램의 상태 Flag를 나타냄
INT nShowCmd                 // 윈도우 상태 옵션
SW_HIDE                           // 숨긴다
SW_SHOWNORMAL            // Normal 크기로 활성화
SW_SHOWMINIMIZED         // 최소화 크기로 활성화
SW_SHOWMAXIMIZED        // 최대화 크기로 활성화
SW_SHOWNOACTIVATE      // 최근의 위치와 크기로 활성화
SW_SHOW                         // 조건 없이 활성화
SW_MINIMIZE                    // 최소화 상태로 활성화
SW_MAXIMIZE                   // 최대화 상태로 활성화
SW_SHOWDEFAULT            // 초기에 윈도우 생성시의 Flag값에 따라 결정
SW_SHOWMINNOACTIVE    // 최소화 상태로 표시, 이미 활성화되어 있다면 내버려둔다
SW_SHOWNA                     // 현상태 유지

프로그램의 실행이 성공시 리턴값은 31보다 크며,
실패시 아래 에러값들이 리턴됩니다.

Error Code                         :: Description
0                                       :: out of memory, out of resource
ERROR_BAD_FORMAT         :: 실행할 수 있는 파일이 아니다.
ERROR_FILE_NOT_FOUND   :: 정해진 경로에 파일이 없다.
ERROR_PATH_NOT_FOUND :: 정해진 경로가 존재하지 않는다.


아래는 CreateProcess 함수입니다.

BOOL CreateProcess(
    LPCTSTR lpApplicationName,
             //생성될 프로세스의 이름 (NULL을 넣고 IpCommandLine로 전달 가능)
     LPTSTR lpCommandLine,
        
   //argc. argv[] 인자로 전달할 문자 매개변수. 표준 검색 경로를 기준으로 찾는다.
     LPSECURITY_ATTRIBUTES lpProcessAttributes, //보안 속성을 지정하는 인자. 보통 NULL
     LPSECURITY_ATTRIBUTES lpThreadAttributes,
                           //쓰레드의 보안 속성 지정. NULL 입력시 기본 보안 속성지정
     BOOL bInheritHandles, // TRUE ::부모 프로세스가 소유하는 상속 가능한 핸들을 상속한다.
     DWORD dwCreationFlags, // 프로세스의 특성을 결정짓는 옵션. 사용 안할경우 0 입력
     LPVOID lpEnvironment, //환경변수 지정. NULL 전달시 부모는 자식에게 환경변수 복사
     LPCTSTR lpCurrentDirectory, //생성하는 프로세스의 현재 디렉터리 NULL시 자식위치 = 부모위치
     LPSTARTUPINFO lpStartupInfo, //STARTUPINFO 구조체 변수 초기화후 변수의 포인터를
               //매개변수 로 전달. STARTUPINFO 구조체 변수들은 프로세스의 속성 정보를 전달한다.
     LPPROCESS_INFORMATION lpProcessInformation
           
//생성하는 프로세스의 정보를 얻기 위한 매개변수.
               //PROCESS_INFORMATION 구조체 변수의 주소값을 받음
);
다들 잘 알고있을거란 생각에..
자세한 내용은 링크로 대신합니다.
LINK_




================= 2. ShellExecute(), ShellExecuteEx() =================

ShellExecute()함수에 대해서 먼저 설명한다.

HINSTANCE ShellExecute(
     HWND hwnd,                  // 부모가 될 윈도우 핸들
     LPCTSTR lpVerb,           // 실행시 행동
     LPCTSTR lpFile,             // 실행 대상 문서
     LPCTSTR lpParameters,  // argv[] 인자
     LPCTSTR lpDirectory,      // 현재 디렉토리
     INT nShowCmd              // 윈도우 상태 옵션
);

HWND hwnd ::
CreateProcess()는 함수를 실행하는 프로세스가 부모 프로세스가 되지만
ShellExecute() 함수는 부모프로세스를 임의로 지정할 수 있습니다.

HWND
hwnd = GetDesktopProcess(); (바탕화면 HWND 리턴. NULL을 집어넣은것과 같음)
HWND hwnd = GetForegroundProcess(); (화면에서 가장 앞에 떠있는 프로세스)

다른 HWND 값을 얻어와서 넣든 간에 IPC 프로그래밍이 아닌 이상
비중있는 인자는 아닙니다. (물론 상황에 따라서.. 중요할수도)

LPCTSTR lpVerb :: <대소문자 관계 없음>
open    // 실제 프로그램을 실행시킨다.
explore // 디렉토리를 lpFile 인자로 전달시에 탐색기로 실행한다.
           // open으로 디렉토리를 실행시키면 단순 풀더만 연다.
           // 실행파일 (.exe 등)을 넣을경우 아무런 반응 없다.
print     // lpFile 매개변수로 들어온 파일을 인쇄한다.
           // 파일의 확장자에 따른 프로그램의 인쇄명령어를 검색하여 실행한다.
           // 프린터나 출력될 포트를 설정하고 싶으면 printto를 사용
find      // lpFile 매개변수로 들어온 디렉토리에 검색창을 띄운다.
           // 디렉토리를 실행할 경우 반응無

LPCTSTR lpParameters,  // argv[] 인자를 넣어준다.
LPCTSTR lpDirectory
     // 현재 디렉토리를 직접 지정할 수 있다.
     // NULL 입력시 프로그램이 실행되는 위치의 Directory가 설정된다.


INT nShowCmd                 // 윈도우 상태 옵션
SW_HIDE                           // 숨긴다
SW_SHOWNORMAL            // Normal 크기로 활성화
SW_SHOWMINIMIZED         // 최소화 크기로 활성화
SW_SHOWMAXIMIZED        // 최대화 크기로 활성화
SW_SHOWNOACTIVATE      // 최근의 위치와 크기로 활성화
SW_SHOW                         // 조건 없이 활성화
SW_MINIMIZE                    // 최소화 상태로 활성화
SW_MAXIMIZE                   // 최대화 상태로 활성화
SW_SHOWDEFAULT            // 초기에 윈도우 생성시의 Flag값에 따라 결정
SW_SHOWMINNOACTIVE    // 최소화 상태로 표시, 이미 활성화되어 있다면 내버려둔다
SW_SHOWNA                     // 현상태 유지

ex)
#include<stdio.h>
#include<tchar.h>
#include<windows.h>

int _tmain(int argc, TCHAR *argv[]){

 HWND hwnd = GetForegroundWindow();
 ShellExecute(hwnd,_T("open"),_T("notepad"),_T("Sosal"),,SW_SHOW);
 ShellExecute(hwnd,_T("find"),_T("c:\\"),NULL,,SW_SHOWMAXIMIZED);
 ShellExecute(hwnd,_T("explore"),_T("c:\\"),NULL,,SW_SHOW);
 //프린트는 제가..;; 없는관계로 ㅇ_ㅇ ;;
Sleep(2000);

 return 0;
}

=== ShellExecuteEx() 함수 설명

BOOL ShellExecuteEx(LPSHELLEXECUTEINFO lpExexInfo);
ShellExecute() 함수에서는, 매개변수로 모든 정보를 넘기는 반면
ShellExecuteEx() 함수는 구조체로 원하는 프로세스의 정보를 모두 담아서
프로세스를 실행시킵니다.

SHELLEXECUTEINFO 구조체의 정의

typedef struct _SHELLEXECUTEINFO {
    DWORD     cbSize;              // 구조체 사이즈(=60)
    ULONG     fMask;               // 옵션
    HWND      hwnd;                // 친 윈도우
    LPCTSTR   lpVerb;             // 동작명
    LPCTSTR   lpFile;              // 파일명
    LPCTSTR   lpParameters;   // 커멘드 라인 파라미터
    LPCTSTR   lpDirectory;       // 기동시 디렉토리
    int       nShow;                   // 표시 형식
    HINSTANCE hInstApp;        // 결과치
    LPVOID    lpIDList;              // 아이템ID리스트
    LPCTSTR   lpClass;           // 클래스명
    HKEY      hkeyClass;          // 파일 클래스의 레지스트리 키
    DWORD     dwHotKey;         // hot key
    union {
        HANDLE  hIcon;             // 파일 클래스의 아이콘
        HANDLE  hMonitor;        // 모니터
    } DUMMYUNIONNAME;
    HANDLE    hProcess;         // 프로세스 핸들
} SHELLEXECUTEINFO, FAR *LPSHELLEXECUTEINFO;

구조체에 대한 자세한 설명은 설명이 잘 되어있는 링크로 넘기겠습니다.
LINK_

cbSize는 전달하는 구조체가 무엇인지 분명히 하기 위한
인자이기 때문에, 꼭 정의해주셔야 합니다.

SHELLEXECUTEINFO sci = {0,};
sci.cbSize = sizeof(SHELLEXECUTEINFO);  // == sizeof(sci);

sci.lpFile = __T("notepad");                // lpFile 역할
sci.nShow = SW_SHOWMAXIMIZED;   // nShowCmd 역할
sci.lpVerb = _T("open");                    // lpVerb 역할

여기까지만 정의해주고 ShellExecuteEx(&sci); 로
함수를 실행해줘도 ShellExecute() 함수와 비슷하게 사용이 가능합니다.


이것 외에 SHELLEXECUTEINFO 구조체를 이용해서
PIDL을 호출하여 더욱 많은 기능을 활용할 수 있다.

//#include<shlobj.h>

LPITEMIDLIST pidl;
SHGetSpecialFolderLocation(NULL, CSIDL_PRINTER, &pidl);

sci.lpIDList = pidl;
sci.fMask = SEE_MASK_INVOKEIDLIST;

ShellExecuteEx(&sci);

fMask에 SEE_MASK_NOCLOSEPROCESS 인자가 들어가있다면
sci 구조체 안에 hProcesss 멤버변수러
새로 생설되어질 프로세스의 핸들을 반환받아
핸들값을 사용할 수 있습니다.
ShellExecute, ShellExecuteEx()
lpverb, lpFile 모두 동적으로 매개변수를 지정할 수 있습니다.


LPITEMIDLIST 구조체와
SHGetSpecialFolderLocation() 함수는..
이번 포스트에 함께 정리하는건 너무 버거울것 같네요..
어영부영 포스트 마치네요.. 나중에 수정이라도 해야겠습니다. ㅠㅠ

Posted by sosal sosal

댓글을 달아 주세요

  1. 2016.09.30 23:09 신고

    어떻게 쓰냐고!!!!!