2012-07-05 78 views
12

我的目標是在我的程序中執行外部可執行文件。首先,我使用了system()函數,但我不希望用戶看到控制檯。於是,我搜索了一下,發現了CreateProcess()的功能。但是,當我嘗試將參數傳遞給它時,我不知道爲什麼,它失敗了。我從MSDN拿了這段代碼,並且改了一點:CreateProcess()失敗並出現訪問衝突

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

void _tmain(int argc, TCHAR *argv[]) 
{ 
    STARTUPINFO si; 
    PROCESS_INFORMATION pi; 

    ZeroMemory(&si, sizeof(si)); 
    si.cb = sizeof(si); 
    ZeroMemory(&pi, sizeof(pi)); 
    /* 
    if(argc != 2) 
    { 
     printf("Usage: %s [cmdline]\n", argv[0]); 
     return; 
    } 
    */ 
    // Start the child process. 
    if(!CreateProcess(NULL, // No module name (use command line) 
     L"c:\\users\\e\\desktop\\mspaint.exe",  // Command line 
     NULL,   // Process handle not inheritable 
     NULL,   // Thread handle not inheritable 
     FALSE,   // 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 
    ) 
    { 
     printf("CreateProcess failed (%d).\n", GetLastError()); 
     return; 
    } 

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

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

但是,這個代碼以某種方式創建了訪問衝突。我可以在不顯示用戶控制檯的情況下執行mspaint嗎?

非常感謝。

+2

一方面,'CreateProcess'要求(如果有的話)的第二個參數是一個非常量字符串。我不確定這在實踐中是否存在問題,但我想完整地提及它。 – reuben

+0

...否則,AV在哪裏發生?你有一個調用堆棧嗎? – reuben

+0

@reuben呃...我不太確定,但我想這是調用堆棧的輸出:'kernel32.dll!76da70ac()\t \t [下面的幀可能不正確和/或丟失,沒有加載符號爲KERNEL32.DLL] \t > \t msvcr100d.dll!_nh_malloc_dbg(無符號整數n大小,INT nhFlag,INT nBlockUse,常量字符* szFileName,INT n線段)線302 + 0x1d字節\t C++' –

回答

7

試試這個,它應該工作。

TCHAR lpszClientPath[500]= TEXT("c:\\users\\e\\desktop\\mspaint.exe"); 
if(!CreateProcess(NULL, lpszClientPath, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE|CREATE_UNICODE_ENVIRONMENT,NULL, NULL, &si, &pi)) 
      { 
    printf("CreateProcess failed (%d).\n", GetLastError()); 
     return; 
      } 
... 
... 
18

第二個參數是LPTSTR,即指向非const char數組的指針。所述docs具體說:

此參數不能是指向只讀(諸如 常量變量或一個文本字符串)

原因傳遞一個字符串文字是一個問題存儲器:

系統向命令行 字符串添加終止空字符,以將文件名與參數分隔開。這將 原始字符串分成兩個字符串用於內部處理。

這意味着在你的情況下,它試圖修改只讀內存,從而導致崩潰。

+0

我也不能分配一個LPTSTR 。如果我可能會問,我的第二個參數必須執行位於「c:\ users \ e \ desktop \」的mspaint嗎?非常感謝你。 –

+2

@JohnDoe:'wchar_t path [] = L「C:\\ users \\ e \\ desktop \\」' – hmjd

+0

'wchar_t path [] = L「C:\\ blahblah」與LPWSTR不一樣path = L「C:\\ blahblah」'但與'wchar_t * path = L「C:\\ blahblah」'相同。你應該使用@hmjd提出的內容,或者你應該定義'LPWSTR path',然後爲這個變量分配內存並複製它的路徑。 –

0

更改您的代碼如下:

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

void _tmain(int argc, TCHAR *argv[]) 
{ 
    TCHAR ProcessName[256]; 
    STARTUPINFO si; 
    PROCESS_INFORMATION pi; 

    wcscpy(ProcessName,L"c:\\users\\e\\desktop\\mspaint.exe"); 
    ZeroMemory(&si, sizeof(si)); 
    si.cb = sizeof(si); 
    ZeroMemory(&pi, sizeof(pi)); 
    /* 
    if(argc != 2) 
    { 
     printf("Usage: %s [cmdline]\n", argv[0]); 
     return; 
    } 
    */ 
    // Start the child process. 
    if(!CreateProcess(NULL, // No module name (use command line) 
     ProcessName,  // Command line 
     NULL,   // Process handle not inheritable 
     NULL,   // Thread handle not inheritable 
     FALSE,   // 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 
    ) 
    { 
     printf("CreateProcess failed (%d).\n", GetLastError()); 
     return; 
    } 

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

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