2013-09-22 74 views
1

我需要幫助創建子進程繼承新的臨時Path環境變量,然後使用子進程,它將在路徑中指定的新文件夾內運行進程。C++ WinApi CreateProcess無法創建子進程與環境塊

例子,我加C:\測試到Path環境變量,然後我wan't使用CMD.EXE作爲

我有問題,通過創建過程中的子進程來運行程序線下,它會彈出消息無法運行子進程

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"); 

如果我通過NULL作爲我的環境塊,我就可以執行我的孩子的過程,但它不會繼承新路徑環境變量,因此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/en-us/library/ms679360(v = vs.85).aspx)return?沒有這個,你只是猜測新的環境是問題。 – Richard

+1

另外['StringCchCat'](http://msdn.microsoft.com/en-us/library/ms647518%28v=vs.85%29.aspx)不適合操作帶有嵌入式空值的字符緩衝區:下一次調用將把它發現的第一個'\ 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