Windows :: 프로세스들을 실행하는 함수들
/*
* 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() 함수는..
이번 포스트에 함께 정리하는건 너무 버거울것 같네요..
어영부영 포스트 마치네요.. 나중에 수정이라도 해야겠습니다. ㅠㅠ