2011-08-10 18 views
21

Próbowałem użyć CreateProcess, aby uruchomić proste polecenie, takie jak hg > test.txt. Próbowałem uruchomić ciąg jako całość (w przeciwieństwie do rozdzielenia go na nazwę aplikacji i jej parametry). Dlaczego CreateProcess(0, "notepad.exe test.txt", ...) dziala, ale CreateProcess(0, "hg > test.txt", ...) nie?Jak przekierować dane wyjściowe do pliku za pomocą CreateProcess?

+2

'CreateProcess' nie wie o przekierowaniach. Dlaczego nie używasz 'system (3)'? Niech zgadnę: możesz zrobić to lepiej niż system (3). – cnicutar

+0

@cnicutar Zawsze zastanawiałem się, co oznaczała notacja "funkcja (liczba)". Co oznacza "system (3)"? –

+2

@Seth Carnegie Sekcja podręcznika. 'system man 3'. – cnicutar

Odpowiedz

21

Nie można użyć stdout przekierowanie w wierszu polecenia przekazywane do CreateProcess. Aby przekierować standardowe wyjście, musisz określić uchwyt pliku dla wyjścia w strukturze STARTUPINFO.

Jesteś również dokonywania inny, bardziej subtelny, błąd. Drugi parametr, lpCommandLine, musi wskazywać na pamięć zapisu, ponieważ CreateProcess nadpisuje bufor. Jeśli używasz wersji ANSI tej funkcji, uciekniesz, ale nie dla wersji Unicode.

Wersja Unicode tej funkcji, CreateProcessW, mogą modyfikować zawartość tego łańcucha. Dlatego ten parametr nie może być wskaźnikiem dla pamięci tylko do odczytu (takiej jak const zmienna lub ciąg literowy). Jeśli ten parametr jest stałym ciągiem, funkcja może spowodować naruszenie zasad dostępu.

+14

Dla ciekawskich, dlaczego trzeba przejść w buforze do zapisu: [Dlaczego funkcja 'CreateProcess' zmodyfikować swój wiersz polecenia wejściowe?] (Http://blogs.msdn.com/b/oldnewthing/archive/2009/06 /01/9673254.aspx) –

+0

Niekoniecznie popełnia błąd, nie czyniąc drugiego punktu parametru zapisywalną pamięcią.Możliwe, że nie kompiluje się ze zdefiniowanym 'UNICODE', w którym to przypadku' CreateProcess' to 'CreateProcessA', który nie ma tego wymagania. –

+0

@FrerichRaabe To szczegół implementacji bieżących wersji systemu Windows. Jeśli spojrzysz na dokumentację MSDN, zobaczysz, że typ drugiego parametru to 'LPTSTR'. W każdym razie, właśnie w punkcie drugim podałem tę kwestię. –

7

CreateProcess() uruchamia procesy, nie jest to program itnerpreter wiersza poleceń. Nie wie, co ">" oznacza i nie będzie przekierowywać za Ciebie. Musisz otworzyć plik test.txt siebie i przekazać do niego uchwyt do CreateProccess wewnątrz struktury STARTUPINFO: CreateProcess STARTUPINFO

7

Microsoft ma przykład jak przekierować standardowe wyjście: http://msdn.microsoft.com/en-us/library/ms682499(VS.85).aspx.

+6

Tak, tego rodzaju prace, ale pamiętaj, że w tym przykładzie występuje błąd, który uniemożliwia wyjście 'ReadFromPipe'. Przed wywołaniem tej funkcji należy wywołać: 'CloseHandle (g_hChildStd_OUT_Wr);'. Prawdopodobnie będziesz także chciał poczekać na zakończenie procesu potomnego, zanim zamkniesz uchwyt, aby przetworzyć coś takiego: 'WaitForSingleObject (piProcInfo.hProcess, INFINITE);'. – Nux

18

Poniższy kod tworzy proces konsoli mniej z stdout i stderr przekierowany do określonego pliku.

#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

Opis obok kodu byłby przydatny. Przynajmniej komentarze –

+0

Możliwe CloseHandle() pliku po spłodzonym procesie potomnym jest pominięte. – SerG

+0

Czy hStdInput nie powinien być INVALID_HANDLE_VALUE zamiast NULL? –

0

należy uruchomić proces cmd.exe z parametrami "/ c command line". Spowoduje to przekierowanie danych wyjściowych do pliku lub zorganizowanie potoku przez CreateProcess.

Powiązane problemy