2013-09-22 2 views
1

새 임시 Path 환경 변수를 상속 한 자식 프로세스 생성에 도움이 필요합니다. 하위 프로세스를 사용하면 경로에 지정된 새 폴더 내에서 프로세스가 실행됩니다. Path 환경 변수에 \ 테스트를하고 난 사용하여 프로세스를 생성하는 데 문제가C++ WinApi CreateProcess 환경 블록을 사용하여 자식 프로세스를 만들 수 없습니다.

자식 프로세스로 cmd.exe를 사용하여 프로그램을 실행 wan't :

예, 나는 C를 추가 아래의 라인, 그것은

난 내 환경 블록으로 NULL 전달하면
Utilities::createProcess(_T("C:\\Windows\\system32\\cmd.exe"),_T(""),txtbuff); 
// txtbuff is a WCHAR with size of 4096 
// it contains the concatenation of _T("Path=C:\\Test;\0"); and pszOldPath 
// pszOldPath get its value from GetEnvironmentVariable(_T("PATH"), pszOldPath,4096); 
// The concantenated string will have the form of _T("Path=path1\0path2\0....\0\0"); 

, 내 자식 프로세스를 실행 할 수 있습니다 자식 프로세스를 실행할 수없는 메시지가 나타납니다하지만 새로운 길을 상속하지 않습니다 cmd.exe는 현재 경로 환경에서 지정되지 않은 프로그램을 실행할 수 없습니다.

Utilities::createProcess(_T("C:\\Windows\\system32\\cmd.exe"),_T(""),NULL); 

이 내 코드입니다 :

// Utilities.h 
namespace Utilities 
{ 
    bool createProcess(LPCWSTR filename,LPWSTR arg,LPTSTR envpath) 
    { 
     DWORD dwRet; 
     LPTSTR pszOldVal; 
     TCHAR pszDest[BUFSIZE] = _T(""); 
     pszOldVal = (LPTSTR) malloc(BUFSIZE*sizeof(TCHAR)); 
     if(envpath != NULL) 
     { 
      dwRet = GetEnvironmentVariable(_T("PATH"), pszOldVal, BUFSIZE); 
      if(!dwRet) 
      { 
       MessageBox(NULL,_T("Get environment variables failed."),_T("Error"),MB_OK); 
       return false; 
      } 
      else 
      { 
       StringCchCat(pszDest,BUFSIZE,_T("Path=")); 
       StringCchCat(pszDest,BUFSIZE,envpath); 
       StringCchCat(pszDest,BUFSIZE,_T(";\0")); 
       StringCchCat(pszDest,BUFSIZE,pszOldVal); 
       //MessageBox(NULL,pszDest,_T("Environtment Variables"),MB_OK); 
      } 
     } 
     STARTUPINFO si; 
     PROCESS_INFORMATION pi; 
     ZeroMemory(&si, sizeof(si)); 
     si.cb= sizeof(si); 
     ZeroMemory(&pi, sizeof(pi)); 
     if(!CreateProcess(filename,arg,NULL,NULL,NULL,NULL,pszDest,NULL,&si,&pi)) 
     { 
      MessageBox(NULL,_T("Unable to create process."),_T("Error"),MB_OK); 
      return false; 
     } 
     //WaitForSingleObject(pi.hProcess, INFINITE); 
     CloseHandle(pi.hProcess); 
     CloseHandle(pi.hThread); 
     free(pszOldVal); 
     return true; 
    } 
} 
// Main.cpp 
// At Wnd Proc 
LRESULT CALLBACK(......) 
{ 
case WM_COMMAND: 
    switch(wParam) 
    { 
     case ID_TEST: 
      Utilities::getDlgText(hWnd,ID_INPUT_CPP,txtbuff); 
      if(_tcscmp(txtbuff, _T("")) == 0) 
      { 
       MessageBox(NULL,_T("Please make sure you select folder."),_T("Error"),MB_OK); 
       break; 
      } 
      // Environtment variable"MyVar=MyValue\0MyOtheVar=MyOtherValue\0\0" 

// This is where Im having problem right now 
      Utilities::createProcess(_T("C:\\Windows\\system32\\cmd.exe"),_T(""),txtbuff,NULL); 
      break; 
    } 
    return true; 
} 

정말 대답하지 어떤 오류 코드

+0

로 가르치 려하는 사람이 필요 ['GetLastError'] (http://msdn.microsoft. com/ko-ko/library/ms679360 (v = vs.85) .aspx) return? 이것이 없다면 새로운 환경이 문제라고 추측 할 수 있습니다. – Richard

+1

또한 ['StringCchCat'] (http://msdn.microsoft.com/en-us/library/ms647518%28v=vs.85%29.aspx)는 null이 포함 된 문자 버퍼를 처리하는 데 적합하지 않습니다. 다음 호출 새로운 문자를 쓰기 시작할 지점으로 찾은 첫 번째 '\ 0'을 처리합니다. – Richard

+0

GetLastError는 0을 반환합니다. StringCch를 다른 것으로 변경해 보겠습니다. – D13

답변

1
// Utilities.h 
namespace Utilities 
{ 
    bool createProcess(LPCWSTR filename, LPWSTR arg, LPWSTR envpath) 
    { 
     std::vector<WCHAR> oldPath; 
     std::vector<WCHAR> newPath; 
     DWORD dwOldLen = 0; 

     if(envpath != NULL) 
     { 
      DWORD dwLen = GetEnvironmentVariable(L"PATH", NULL, 0); 
      if (dwLen) { 
       oldPath.resize(dwLen); 
       dwOldLen = GetEnvironmentVariable(L"PATH", oldPath.data(), dwLen); 
       if(dwOldLen + 1 != dwLen) 
       { 
        MessageBox(NULL,_T("Get environment variables failed."),_T("Error"),MB_OK); 
        return false; 
       } 
      } 
      size_t newLen = dwOldLen + wcslen(envpath) + 8; //8 for "path=" ";" and double null terminating 
      newPath.resize(newLen); 
      std::fill(newPath.begin(), newPath.end(), 0); 
      memcpy(newPath.data(), L"Path=", 5 * 2); 
      memcpy(newPath.data() + 5, oldPath.data(), dwOldLen * 2); 
      memcpy(newPath.data() + 5 + dwOldLen, L";", 2); 
      memcpy(newPath.data() + 6 + dwOldLen, envpath, wcslen(envpath) * 2); 
     } 
     STARTUPINFO si; 
     PROCESS_INFORMATION pi; 
     ZeroMemory(&si, sizeof(si)); 
     si.cb= sizeof(si); 
     ZeroMemory(&pi, sizeof(pi)); 
     if(!CreateProcess(filename,arg,NULL,NULL,NULL,CREATE_UNICODE_ENVIRONMENT,newPath.data(),NULL,&si,&pi)) 
     { 
      MessageBox(NULL,_T("Unable to create process."),_T("Error"),MB_OK); 
      return false; 
     } 
     //WaitForSingleObject(pi.hProcess, INFINITE); 
     CloseHandle(pi.hProcess); 
     CloseHandle(pi.hThread); 
     return true; 
    } 
} 
+0

wchar에 대한 memcpy 크기를 2로 곱해야하는 이유는 wchar이 각 바이트에 대해 2 바이트를 보유하기 때문입니다. 일주일 후에 바이트 수업을 배우기 시작할 것입니다. – D13

+0

또한 해결책 주셔서 감사합니다 – D13

+0

@ D13 : 예, wchar은 2 바이트입니다. – Jichao