2016-11-27 177 views
0

所以,我不能改變調用一個可執行文件,我需要給它不同的命令行參數比黑盒代碼調用。我在想我可以製作一個可執行文件作爲代理。 proc.exe位於黑盒部分所期望的位置,接受命令行參數,修改它們,然後調用原始文件procReal.exeCreateProcess失敗 - 錯誤183

不幸的是,CreateProcess似乎無法啓動,返回狀態183。我查了一切,我無法找到這個。已經嘗試翻轉事物,將句柄繼承設置爲true,手動指定工作目錄,而不是執行其中任何一項。沒有運氣。我以爲有一些事情在這裏的繼承調用應用,使得包裝作品適當直通的適當的安全上下文,但我想不出該怎麼辦呢?下面

代碼,不相關的部分修剪。

編輯將請求後的完整代碼放在這裏。這沒有任何意義了。它現在將部分工作,但僅限traceFilefopen部分不存在。甚至沒有刪除fprintfs,特別是整個部分不得不被刪除。

我試着回覆所有人的評論,我認爲我已經排除了大部分這些問題,但是我留下了當前的異常行爲。我可以從這個角度再讀一點,就是說某些形式的字符串複製可能導致內存溢出,這可能嗎?

#include <iostream> 
#include <fstream> 
#include <windows.h> 
#include <string> 
#include <vector> 
#include <stdio.h> 
#include <tchar.h> 
#include <algorithm> 
#include <string> 

using namespace std; 

bool caseInsensitiveStringCompare(const std::string& str1, const std::string& str2); 

int main(int argc, char* argv[]) { 

    const string path = "E:\\util\\bin\\"; 
    const string procName = "procReal.exe"; 
    const string argToFilter = "-t"; 


    string origValue; 
    string passedValue; 

    for(int i = 1; i < argc; i++) 
    { 
     origValue.append(" ").append(argv[i]); 
    } 

    for(int i = 1; i < argc; i++) 
    { 
     if (!caseInsensitiveStringCompare(argv[i],argToFilter)) 
     { 
      passedValue.append(" ").append(argv[i]); 
     } 
     else 
     { 
      i++; // skip over argument and it's value 
     } 

    } 

    const LPCTSTR exeModule = (path+procName).c_str(); 

    std::vector<char> chars(passedValue.c_str(), passedValue.c_str() + passedValue.size() + 1u); 
    LPTSTR exeArgs = &chars[0]; 


    STARTUPINFO si; 
    PROCESS_INFORMATION pi; 

    ZeroMemory(&si, sizeof(si)); 
    si.cb = sizeof(si); 
    ZeroMemory(&pi, sizeof(pi)); 

    GetStartupInfo(&si); 

    FILE* traceFile; 
    traceFile = fopen ((path+"lastRun.txt").c_str(), "w"); // This causes exeModule to change value for unknown reasons??? 
    fprintf(traceFile, "orig: %s%s\n", exeModule, origValue.c_str()); 
    fprintf(traceFile, "%s%s\n", exeModule, exeArgs); 

    SetLastError(0); 

    // Start the child process. 
    if(!CreateProcess(exeModule, // use module name with args for exeArgs 
     exeArgs,  // Command line 
     NULL,   // Process handle not inheritable 
     NULL,   // Thread handle not inheritable 
     TRUE,   // Set handle inheritance to FALSE 
     0,    // No creation flags 
     NULL,   // Use parent's environment block 
     NULL, // use parent's starting directory 
     &si,   // Pointer to STARTUPINFO structure 
     &pi)   // Pointer to PROCESS_INFORMATION structure 
    ) 
    { 
     FILE* myfile; 
     myfile = fopen ((path+"error.txt").c_str(), "w"); 
     fprintf(myfile, "CreateProcess failed (%d).\n", int(GetLastError())); 
     fclose(myfile); 
    } 

    // Wait until child process exits. 
    WaitForSingleObject(pi.hProcess, INFINITE); 

    DWORD exit_code; 
    GetExitCodeProcess(pi.hProcess, &exit_code); 

    fprintf(traceFile, "Exit Code: %d\n", int(exit_code)); 
    fclose(traceFile); 

    // Close process and thread handles. 
    CloseHandle(pi.hProcess); 
    CloseHandle(pi.hThread); 

    return exit_code; 
} 

bool caseInsensitiveStringCompare(const std::string& str1, const std::string& str2) { 
    std::string str1Cpy(str1); 
    std::string str2Cpy(str2); 
    std::transform(str1Cpy.begin(), str1Cpy.end(), str1Cpy.begin(), ::tolower); 
    std::transform(str2Cpy.begin(), str2Cpy.end(), str2Cpy.begin(), ::tolower); 
    return (str1Cpy == str2Cpy); 
} 
+0

錯誤代碼183名的意思是「ERROR_ALREADY_EXISTS」 –

+0

是您的計算機上啓用UAC?難道procReal.exe需要管理員權限?是否proc.exe有呢?你有沒有嘗試運行它UAC禁用? – z32a7ul

+0

基本過程可以直接運行而不需要管理員權限leges,是的。 – Vigilant

回答

2

最明顯的問題是,你不能說(path+procName).c_str()因爲它建立了臨時字符串對象被立即丟棄,返回指針無效。 我也很懷疑假設 vector的元素必然是連續的。

修正字符串處理的代碼應該是這個樣子:

string passedValue(procName); // First element of command line MUST be module name 

    ... 

    const string exeModuleString(path + procName); 
    const LPCTSTR exeModule = exeModuleString.c_str(); 

    LPTSTR exeArgs = new char[passedValue.size() + 1]; 
    passedValue.copy(exeArgs, passedValue.size()); 
    exeArgs[passedValue.size()] = '\0'; 

(這也許不是做到這最好的方式,我不使用C++常常但它應該正常工作。 。)

修正錯誤處理代碼,以確保最後一個錯誤代碼讀取立即,應該是這個樣子:

{ 
     DWORD err = GetLastError(); 
     FILE* myfile; 
     myfile = fopen ((path+"error.txt").c_str(), "w"); 
     fprintf(myfile, "CreateProcess failed (%d).\n", int(err)); 
     fclose(myfile); 
    } 

您的代碼報告錯誤的錯誤代碼,因爲調用fopen()會更改它。 (創建覆蓋現有文件的新文件時,最後的錯誤代碼設置爲ERROR_ALREADY_EXISTS。)

存在兩個更廣泛的問題,這些問題在您的上下文中可能相關,也可能不重要。首先,您正在使用argv []爲新進程構建命令行;這意味着命令行解析(如Parsing C Command-Line Arguments中所述)將被應用兩次(一次通過您的進程並且一次通過子進程),如果命令行包含任何特殊字符(例如引號或反斜槓),則可能會造成麻煩。理想情況下,在一般情況下,您可以調用GetCommandLine()。 (當然,這使得解析字符串以去除額外的參數要困難得多。)

其次,你顯然在ANSI模式下構建代碼。如果命令行中包含任何寬字符(「Unicode」),則這可能會導致問題。通常認爲最佳實踐是始終以Unicode模式構建。您需要對代碼進行的唯一重大更改是將string替換爲wstring,因此它應該足夠簡單。

+1

從C++ 11開始,向量的元素保證是連續的。 – Buster

+0

@Buster:謝謝。據我瞭解,最新版本的Visual Studio *主要是* C++ 11兼容,所以部分原始代碼可能是好的。 –

+0

這整理了我的所有或大部分問題,特別是GetCommandLine()部分,謝謝! – Vigilant

0

我有同樣的問題。 問題似乎在那裏,當我打電話可執行文件沒有窗口。 我發現2個解決方案:

1. 創建泰德exe文件名的bat文件,其次是參數, 然後執行批處理文件: 的CreateProcess( 「temp.bat」,NULL,.. ..等

2. 使用_spawnl

相關問題