2011-08-10 69 views
21

我嘗試使用CreateProcess來運行一個簡單的命令,如hg > test.txt。我嘗試將字符串作爲一個整體運行(而不是將它分離爲應用程序名稱及其參數)。爲什麼CreateProcess(0, "notepad.exe test.txt", ...)能正常工作,CreateProcess(0, "hg > test.txt", ...)不能?如何使用CreateProcess將輸出重定向到文件?

+2

'CreateProcess'不知道重定向。你爲什麼不使用'system(3)'?讓我猜測:你可以做得比系統(3)更好。 – cnicutar

+0

@cnicutar我一直想知道'函數(數字)'符號的含義。 'system(3)'是什麼意思? –

+2

@Seth Carnegie手冊部分。 '人3系統'。 – cnicutar

回答

21

您不能在傳遞給CreateProcess的命令行中使用stdout重定向。要重定向標準輸出,您需要爲STARTUPINFO結構中的輸出指定文件句柄。

你也在犯另一個更微妙的錯誤。第二個參數lpCommandLine必須指向可寫內存,因爲CreateProcess會覆蓋緩衝區。如果你碰巧使用的是ANSI版本的功能,那麼你會擺脫這一點,但不是爲了Unicode版本。

該函數的Unicode版本,CreateProcessW,可以修改這個字符串的內容。因此,此參數不能是指向只讀內存的指針(例如const變量或文字字符串)。如果此參數是一個常量字符串,則該函數可能會導致訪問衝突。

+14

爲什麼你需要傳入一個可寫緩衝區:[爲什麼'CreateProcess'函數修改它的輸入命令行?](http://blogs.msdn.com/b/oldnewthing/archive/2009/06 /01/9673254.aspx) –

+0

他不一定會犯第二個參數指向可寫內存的錯誤。有可能他沒有定義'UNICODE'編譯,在這種情況下'CreateProcess'是'CreateProcessA',它沒有這個要求。 –

+0

@FrerichRaabe這是當前版本Windows的實現細節。如果你看看MSDN文檔,你會看到第二個參數的類型是'LPTSTR'。無論如何,我在第二段中提出了你的觀點。 –

7

CreateProcess()啓動進程,它不是命令行itnerpreter。它不知道「>」是什麼,也不會爲你做流重定向。您需要打開文件test.txt自己和句柄傳遞給它的STARTUPINFO結構內的CreateProcess: CreateProcess STARTUPINFO

7

微軟有一個例子如何重定向標準輸出: http://msdn.microsoft.com/en-us/library/ms682499(VS.85).aspx

+6

是的,這種工作,但請記住,該示例中存在一個可防止「ReadFromPipe」退出的錯誤。在你調用這個函數之前,你需要調用:'CloseHandle(g_hChildStd_OUT_Wr);'。此外,您可能需要等待子進程退出,然後再關閉句柄以使用類似下面的方法進行處理:'WaitForSingleObject(piProcInfo.hProcess,INFINITE);'。 – Nux

18

下面的代碼創建一個無控制檯進程,stdout和stderr重定向到指定的文件。

#include <windows.h> 


int _tmain(int argc, _TCHAR* argv[]) 
{ 
    SECURITY_ATTRIBUTES sa; 
    sa.nLength = sizeof(sa); 
    sa.lpSecurityDescriptor = NULL; 
    sa.bInheritHandle = TRUE;  

    HANDLE h = CreateFile(_T("out.log"), 
     FILE_APPEND_DATA, 
     FILE_SHARE_WRITE | FILE_SHARE_READ, 
     &sa, 
     OPEN_ALWAYS, 
     FILE_ATTRIBUTE_NORMAL, 
     NULL); 

    PROCESS_INFORMATION pi; 
    STARTUPINFO si; 
    BOOL ret = FALSE; 
    DWORD flags = CREATE_NO_WINDOW; 

    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION)); 
    ZeroMemory(&si, sizeof(STARTUPINFO)); 
    si.cb = sizeof(STARTUPINFO); 
    si.dwFlags |= STARTF_USESTDHANDLES; 
    si.hStdInput = NULL; 
    si.hStdError = h; 
    si.hStdOutput = h; 

    TCHAR cmd[]= TEXT("Test.exe 30"); 
    ret = CreateProcess(NULL, cmd, NULL, NULL, TRUE, flags, NULL, NULL, &si, &pi); 

    if (ret) 
    { 
     CloseHandle(pi.hProcess); 
     CloseHandle(pi.hThread); 
     return 0; 
    } 

    return -1; 
} 
+2

旁邊的代碼說明會很方便。至少註釋 –

+0

在子進程產生後文件可能的CloseHandle()被忽略。 – SerG

+0

不應該hStdInput INVALID_HANDLE_VALUE而不是NULL? –

0

你應該用params「/ c命令行」運行進程cmd.exe。 這會將輸出重定向到一個文件或通過CreateProcess組織一個管道。