천객만래 [千客萬來] (It has an interminable succession of visitors)

CreateProcess 함수 예제 소스코드





/*
 * 출처 : 
http://sosal.tistory.com/
 * made by so_Sal
 */


CreateProcess 라는 함수를 이용하여
Notepad를 실행시키는 간단한 소스입니다.
이해가 가지 않는 부분이 있다면
아래 링크를 참조하세요.
LINK_

====================== CreateProcess ======================

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

#define DIR_LEN BUFSIZ
//BUFSIZ는 운영체제마다 다른 크기를 가지고 있습니다.
//한번 크기를 출력해보시는것도 좋겠네요.

int _tmain(int argc, TCHAR* argv[]){
 STARTUPINFO si = {0,};    //구조체 선언, 초기화
 PROCESS_INFORMATION pi;
 
 si.cb = sizeof(si);
 si.dwFlags = STARTF_USEPOSITION | STARTF_USESIZE;
 //Flags 값들이 여러가지가 있습니다.
 //STARTF_USEPOSITION :: dwX, dwY 위치 사용
 //STARTF_USESIZE     :: dwXSize, dwYSize 사용
 //Flags 값이 주어지지 않는 si구조체 값은
 //새로 만들어지는 프로세스에 영향을 주지 않습니다.
 si.dwX = 100;
 si.dwY = 100;
 si.dwXSize = 300;
 si.dwYSize = 300;  //dw ~ 는 사실 잘 쓰이지 않습니다.

 si.lpTitle = _T(" Child process! ");
 
 TCHAR command[] = _T("notepad 10 10");
 //10 10은 argv[]로 들어가겠죠, 아래 결과를 보시면
 //notepad의 이름으로 들어간다는걸 확인하실 수 있습니다.

 BOOL state;

 state = CreateProcess(
  NULL, //여기에 이름을 넣을 수 있습니다.
  command, // 경로를 System에 해줬기 때문에 notepad가 열릴 수 있죠!
  NULL,NULL, 
  TRUE, //부모프로세스중 상속가능한 핸들 상속
  CREATE_NEW_CONSOLE, //dwCreationFlags
  NULL,NULL,
  &si, //STARTUPINFO 구조체 정보를 위에서 만들어줬죠.
  &pi  //이젠 프로세스의 정보를 가져올때 이 구조체를 사용!
 );

 if(state!=0){
  _fputts(_T("Creation OK! \n"), stdout);
 }
 else{
  _fputts(_T("Creation Fail! \n"), stdout);
 }

 return 0;
}


=======================================================================================


프로세스 :: 시스템 자원들을 포함하는 하나의 주소공간

프로세스는 프로그램 코드, 자료, 변수들, 열린 파일들,
그리고 환경으로 구성됩니다.
하드 메모리에 저장되어 있는 프로그램을 시스템 메모리에 끌어와
하드메모리에 존재하는 하나의 복사본만 존재할 수 있도록
프로그램 코드와 시스템 라이브러리들을 여러 프로세스들이 공유하게 합니다.
더 자세한 내용은 이전에 쓴 '04. Windows 프로세스' 글을 참조하시고
여기서는 프로세스 생성 함수에 대해서 설명하겠습니다.
(프로세스가 새로운 프로세스를 실행시키는것)


프로세스의 생성

하나의 프로세스가 새로운 프로세스를 만든다면,(CreateProcess)
원래의 프로세스는 부모 프로세스라고 하고,
새로 만들어진 프로세스는 자식 프로세스라고 합니다.

그렇다면, 이것은 바탕화면에서 프로그램을 더블클릭하여
생성한 프로세스와 다른것인가?
아닙니다. 바탕화면을 보여주는것도 프로세스입니다.
바탕화면 관리자에서 보여지는 프로그램을 실행시킨다면 (더블클릭)
바탕화면 관리자는 부모프로세스, 실행된 프로세스는 자식 프로세스가 됩니다.
ㅇㅋ?



** :: CreateProcess :: **
MSDN :: 
http://msdn.microsoft.com/en-us/library/ms682425(VS.85).aspx ::
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 구조체 변수의 주소값을 받음
);

9번째 인자 LPSTARTUPINFO 에 정보를 저장하여
CreateProcess를 통하여 프로세스를 생성합니다.
그럼 프로세스의 정보를 다시 가져올때는?
LPPROCESS_INFORMATION을 통해 가져오게 됩니다.

아.. 그런데 위에 CreateProcess 함수 하나에 매개변수가 10개고..
미친듯이 외워야 할거같고,.. 답답..합니다.
저거 다 외워서 쓰는사람... 아무도 없습니다.
공부할때 한번쯤 훑어주고..
중요하게 굵게 써놓은거 정도만 자세히 봐주고...
넘어갑시다!!!!
아주 많이 사용되는 함수도 아닐 뿐더러
책을 보던가 인터넷 조금만 뒤져봐도
상당히 자세히 나와있고, 예제도 널려있으니
그거 보고 프로그래밍 하시면 됩니다!

위 함수를 실행하면 새로운 프로세스가 생성되는데..
프로그램이 부모 프로세스가 되고, 프로그램 안에서 함수에 의해 새로 생성된 프로세스는
자식 프로세스라고 말합니다.

CreateProcess의 첫번째로 전달되는 인자를 통해서 실행파일의 이름이 전달하는 경우에는
현재 디렉터리를 기준으로 실행파일을 찾게 된다.
하지만 두번째 인자로 (첫번째에 NULL을 넣고) 전달되는 경우에는
표준 검색경로 순서대로 실행파일을 찾는다.

1.프로세스의 실행파일이 존재하는 풀더
2.실행중인 프로세스의 현재 풀더
3.windows의 시스템 풀더(system Directory)
4.windows풀더 (windows directory)
5.환경변수 PATH


함수 매개변수의 9번째 매개변수를 보면 STARTUPINFO 라는 구조체가 있다고 나오는데,
그 구조체에 대해서 살펴봅시답!
이것은 새롭게 생성할 프로세스에 정보를 입력하기 위한 구조체입니다.

LPSTARTUPINFO의 구조이다.
MSDN :: 
http://msdn.microsoft.com/en-us/library/ms686331(VS.85).aspx ::

typedef struct _STARTUPINFO {
  DWORD  cb;                           //구조체 변수 크기
  LPTSTR lpReserved;
  LPTSTR lpDesktop;
  LPTSTR lpTitle;                      // 타이틀 바 제목
  DWORD  dwX;                        // 시작될 프로세스 윈도우의 x좌표
  DWORD  dwY;                        // 시작될 프로세스 윈도우의 y좌표
  DWORD  dwXSize;                  // 윈도우의 가로길이
  DWORD  dwYSize;                  // 윈도우의 세로길이
  DWORD  dwXCountChars;
  DWORD  dwYCountChars;
  DWORD  dwFillAttribute;
  DWORD  dwFlags;                   // 설정된 멤버의 정보
  WORD   wShowWindow;
  WORD   cbReserved2;
  LPBYTE lpReserved2;
  HANDLE hStdInput;           // 이 글에서는 CreateProcess에 대해서
  HANDLE hStdOutput;         // 적당히 살펴보는 취지라..
  HANDLE hStdError;           // 핸들에 대한 내용은 넘기겠습니다.
} STARTUPINFO, *LPSTARTUPINFO;

첫번째 인자 DWORD cb가 중요한 이유는
CreateProcess 함수에서 9번째에 들어갈 프로세스 정보 구조체에 들어가는 구조체가
혹시나 다음에 바뀔 수도 있고, 다양한 구조체가 들어갈 수 있게 하기 위해서 둔것인데,
즉 정보를 전달하는 구조체가 무엇인지 구분짓겠다는 의도라고 생각하시면 되겠네요.


Posted by SB패밀리

외부 프로세스 실행을 위한 소스
아래 함수는 Windows 7 에서 관리자 권한으로 실행이 가능하게 하는 코드이다.
MFC 개발하시분 분들에게는 많이 유용할 것이다.
쌈꼬쪼려 소백촌닭

=======================================================
사례1

// 프로세스 실행
BOOL SBRICH::ExecuteProcess(CString FilePath, CString Parameter)

 //TCHAR path[1024] = {0,};
 //::GetModuleFileName(NULL, path, 1024);
 BOOL bRes = FALSE;

 if(OSVersionXPOver())
 {
  // 관리자 모드로 실행
  SHELLEXECUTEINFO exeInfo = {0,};

  exeInfo.cbSize = sizeof(SHELLEXECUTEINFO);
  exeInfo.hwnd = NULL;
  exeInfo.fMask = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI;
  exeInfo.lpVerb = _T("runas");
  exeInfo.lpFile = FilePath;
  exeInfo.lpParameters = Parameter;
  exeInfo.nShow = SW_SHOWNORMAL;

  bRes = ::ShellExecuteEx(&exeInfo);

 }
 else
 {
  //xp 이하이므로 그냥 호출.
  if( ::ShellExecute(NULL, _T("open"), FilePath, Parameter, NULL, SW_SHOW) == (HINSTANCE)HINSTANCE_ERROR)
   bRes = FALSE;
  else
   bRes = TRUE;
 }

 return bRes;
}


===================================================================
사례2

// 프로세스 실행
BOOL SBRICH::ExecuteProcess(CString FilePath, CString Parameter)

 //TCHAR path[1024] = {0,};
 //::GetModuleFileName(NULL, path, 1024);
 BOOL bRes = FALSE;

 if(OSVersionXPOver())
 {
  // 관리자 모드로 실행
  CString sRun;
  STARTUPINFO si;
  PROCESS_INFORMATION pi;
  ZeroMemory(&si, sizeof(si));
  si.cb = sizeof(si);
  si.lpDesktop = "winsta0\\default";
  ZeroMemory(&pi, sizeof(pi));

  sRun = FilePath;
  sRun += Parameter;
  // start the child process
  if (!CreateProcess(NULL, // no module name (use command line)
   (LPSTR)(LPCSTR)sRun, // Command line
   NULL, // Process handle not inheritate
   NULL, // Thread handle not inheritate
   FALSE, // Set handle inheritance to FALSE
   0, // No creation flags
   NULL, // Use parent's environment block
   NULL, // Use parent's starting directory
   &si, // Pointer STARTUPINFO structure
   &pi) // Pointer to PROCESS_INFORMATION structure
   )
  {
#ifdef _DEBBUG
   fprintf(Filelog, "CreateProcess Failed (%d)\n", GetLastError());
   Filelog.flush();
#endif
   return FALSE;
  }
  // wait until child process exits
  WaitForSingleObject(pi.hProcess, INFINITE);
  // Close process and thread handles;
  CloseHandle(pi.hProcess);
  CloseHandle(pi.hThread);   


 }
 else
 {
  //xp 이하이므로 그냥 호출.
  if( ::ShellExecute(NULL, _T("open"), FilePath, Parameter, NULL, SW_SHOW) == (HINSTANCE)HINSTANCE_ERROR)
   bRes = FALSE;
  else
   bRes = TRUE;
 }

 return bRes;
}

Posted by SB패밀리

/*
 * 출처 :
http://sosal.tistory.com/
 * made by so_Sal
 */


CreateProcess 라는 함수를 이용하여
Notepad를 실행시키는 간단한 소스입니다.
이해가 가지 않는 부분이 있다면
아래 링크를 참조하세요.
LINK_

====================== CreateProcess ======================

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

#define DIR_LEN BUFSIZ
//BUFSIZ는 운영체제마다 다른 크기를 가지고 있습니다.
//한번 크기를 출력해보시는것도 좋겠네요.

int _tmain(int argc, TCHAR* argv[]){
 STARTUPINFO si = {0,};    //구조체 선언, 초기화
 PROCESS_INFORMATION pi;
 
 si.cb = sizeof(si);
 si.dwFlags = STARTF_USEPOSITION | STARTF_USESIZE;
 //Flags 값들이 여러가지가 있습니다.
 //STARTF_USEPOSITION :: dwX, dwY 위치 사용
 //STARTF_USESIZE     :: dwXSize, dwYSize 사용
 //Flags 값이 주어지지 않는 si구조체 값은
 //새로 만들어지는 프로세스에 영향을 주지 않습니다.
 si.dwX = 100;
 si.dwY = 100;
 si.dwXSize = 300;
 si.dwYSize = 300;  //dw ~ 는 사실 잘 쓰이지 않습니다.

 si.lpTitle = _T(" Child process! ");
 
 TCHAR command[] = _T("notepad 10 10");
 //10 10은 argv[]로 들어가겠죠, 아래 결과를 보시면
 //notepad의 이름으로 들어간다는걸 확인하실 수 있습니다.

 BOOL state;

 state = CreateProcess(
  NULL, //여기에 이름을 넣을 수 있습니다.
  command, // 경로를 System에 해줬기 때문에 notepad가 열릴 수 있죠!
  NULL,NULL,
  TRUE, //부모프로세스중 상속가능한 핸들 상속
  CREATE_NEW_CONSOLE, //dwCreationFlags
  NULL,NULL,
  &si, //STARTUPINFO 구조체 정보를 위에서 만들어줬죠.
  &pi  //이젠 프로세스의 정보를 가져올때 이 구조체를 사용!
 );

 if(state!=0){
  _fputts(_T("Creation OK! \n"), stdout);
 }
 else{
  _fputts(_T("Creation Fail! \n"), stdout);
 }

 return 0;
}


=======================================================================================


프로세스 :: 시스템 자원들을 포함하는 하나의 주소공간

프로세스는 프로그램 코드, 자료, 변수들, 열린 파일들,
그리고 환경으로 구성됩니다.
하드 메모리에 저장되어 있는 프로그램을 시스템 메모리에 끌어와
하드메모리에 존재하는 하나의 복사본만 존재할 수 있도록
프로그램 코드와 시스템 라이브러리들을 여러 프로세스들이 공유하게 합니다.
더 자세한 내용은 이전에 쓴 '04. Windows 프로세스' 글을 참조하시고
여기서는 프로세스 생성 함수에 대해서 설명하겠습니다.
(프로세스가 새로운 프로세스를 실행시키는것)


프로세스의 생성

하나의 프로세스가 새로운 프로세스를 만든다면,(CreateProcess)
원래의 프로세스는 부모 프로세스라고 하고,
새로 만들어진 프로세스는 자식 프로세스라고 합니다.

그렇다면, 이것은 바탕화면에서 프로그램을 더블클릭하여
생성한 프로세스와 다른것인가?
아닙니다. 바탕화면을 보여주는것도 프로세스입니다.
바탕화면 관리자에서 보여지는 프로그램을 실행시킨다면 (더블클릭)
바탕화면 관리자는 부모프로세스, 실행된 프로세스는 자식 프로세스가 됩니다.
ㅇㅋ?



** :: CreateProcess :: **
MSDN ::
http://msdn.microsoft.com/en-us/library/ms682425(VS.85).aspx ::
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 구조체 변수의 주소값을 받음
);

9번째 인자 LPSTARTUPINFO 에 정보를 저장하여
CreateProcess를 통하여 프로세스를 생성합니다.
그럼 프로세스의 정보를 다시 가져올때는?
LPPROCESS_INFORMATION을 통해 가져오게 됩니다.

아.. 그런데 위에 CreateProcess 함수 하나에 매개변수가 10개고..
미친듯이 외워야 할거같고,.. 답답..합니다.
저거 다 외워서 쓰는사람... 아무도 없습니다.
공부할때 한번쯤 훑어주고..
중요하게 굵게 써놓은거 정도만 자세히 봐주고...
넘어갑시다!!!!
아주 많이 사용되는 함수도 아닐 뿐더러
책을 보던가 인터넷 조금만 뒤져봐도
상당히 자세히 나와있고, 예제도 널려있으니
그거 보고 프로그래밍 하시면 됩니다!

위 함수를 실행하면 새로운 프로세스가 생성되는데..
프로그램이 부모 프로세스가 되고, 프로그램 안에서 함수에 의해 새로 생성된 프로세스는
자식 프로세스라고 말합니다.

CreateProcess의 첫번째로 전달되는 인자를 통해서 실행파일의 이름이 전달하는 경우에는
현재 디렉터리를 기준으로 실행파일을 찾게 된다.
하지만 두번째 인자로 (첫번째에 NULL을 넣고) 전달되는 경우에는
표준 검색경로 순서대로 실행파일을 찾는다.

1.프로세스의 실행파일이 존재하는 풀더
2.실행중인 프로세스의 현재 풀더
3.windows의 시스템 풀더(system Directory)
4.windows풀더 (windows directory)
5.환경변수 PATH


함수 매개변수의 9번째 매개변수를 보면 STARTUPINFO 라는 구조체가 있다고 나오는데,
그 구조체에 대해서 살펴봅시답!
이것은 새롭게 생성할 프로세스에 정보를 입력하기 위한 구조체입니다.

LPSTARTUPINFO의 구조이다.
MSDN ::
http://msdn.microsoft.com/en-us/library/ms686331(VS.85).aspx ::

typedef struct _STARTUPINFO {
  DWORD  cb;                           //구조체 변수 크기
  LPTSTR lpReserved;
  LPTSTR lpDesktop;
  LPTSTR lpTitle;                      // 타이틀 바 제목
  DWORD  dwX;                        // 시작될 프로세스 윈도우의 x좌표
  DWORD  dwY;                        // 시작될 프로세스 윈도우의 y좌표
  DWORD  dwXSize;                  // 윈도우의 가로길이
  DWORD  dwYSize;                  // 윈도우의 세로길이
  DWORD  dwXCountChars;
  DWORD  dwYCountChars;
  DWORD  dwFillAttribute;
  DWORD  dwFlags;                   // 설정된 멤버의 정보
  WORD   wShowWindow;
  WORD   cbReserved2;
  LPBYTE lpReserved2;
  HANDLE hStdInput;           // 이 글에서는 CreateProcess에 대해서
  HANDLE hStdOutput;         // 적당히 살펴보는 취지라..
  HANDLE hStdError;           // 핸들에 대한 내용은 넘기겠습니다.
} STARTUPINFO, *LPSTARTUPINFO;

첫번째 인자 DWORD cb가 중요한 이유는
CreateProcess 함수에서 9번째에 들어갈 프로세스 정보 구조체에 들어가는 구조체가
혹시나 다음에 바뀔 수도 있고, 다양한 구조체가 들어갈 수 있게 하기 위해서 둔것인데,
즉 정보를 전달하는 구조체가 무엇인지 구분짓겠다는 의도라고 생각하시면 되겠네요.

Posted by SB패밀리