2011-08-10 40 views
21

Tôi đã thử sử dụng CreateProcess để chạy một lệnh đơn giản như hg > test.txt. Tôi đã thử chạy chuỗi như một toàn thể (như trái ngược với việc tách nó thành một tên ứng dụng và các tham số của nó). Tại sao CreateProcess(0, "notepad.exe test.txt", ...) hoạt động nhưng CreateProcess(0, "hg > test.txt", ...) thì không?Làm cách nào để chuyển hướng đầu ra tới tệp bằng CreateProcess?

+2

'CreateProcess' không biết về chuyển hướng. Tại sao bạn không sử dụng 'hệ thống (3)'? Hãy để tôi đoán: bạn có thể làm điều đó tốt hơn so với hệ thống (3). – cnicutar

+0

@cnicutar Tôi luôn tự hỏi ý nghĩa của ký hiệu 'hàm (số) '. 'System (3)' nghĩa là gì? –

+2

@Seth Carnegie Phần hướng dẫn sử dụng. 'man 3 system'. – cnicutar

Trả lời

21

Bạn không thể sử dụng chuyển hướng stdout trong dòng lệnh được chuyển đến CreateProcess. Để chuyển hướng stdout, bạn cần chỉ định một tập tin xử lý cho đầu ra trong cấu trúc STARTUPINFO.

Bạn cũng đang mắc lỗi khác, tinh tế hơn. Tham số thứ hai, lpCommandLine phải trỏ đến bộ nhớ có thể ghi bởi vì CreateProcess ghi đè bộ đệm. Nếu bạn tình cờ sử dụng phiên bản ANSI của hàm thì bạn sẽ thoát khỏi điều này, nhưng không phải với phiên bản Unicode.

Phiên bản Unicode của chức năng này, CreateProcessW, có thể sửa đổi các nội dung của chuỗi này. Do đó, tham số này không thể là con trỏ tới bộ nhớ chỉ đọc (chẳng hạn như một biến số const hoặc chuỗi chữ). Nếu tham số này là một chuỗi không đổi, hàm có thể gây ra sự vi phạm truy cập.

+14

Đối với những người tò mò về lý do tại sao bạn cần phải vượt qua trong một bộ đệm ghi: [Tại sao chức năng 'CreateProcess' sửa đổi dòng lệnh đầu vào của nó?] (Http://blogs.msdn.com/b/oldnewthing/archive/2009/06 /01/9673254.aspx) –

+0

Anh ấy không nhất thiết mắc lỗi bằng cách không đặt điểm tham số thứ hai thành bộ nhớ ghi được.Có thể anh ta không biên dịch với 'UNICODE' được định nghĩa, trong trường hợp đó' CreateProcess' là 'CreateProcessA', mà không có yêu cầu này. –

+0

@ FrerichRaabe Đó là một chi tiết thực hiện của các phiên bản Windows hiện tại. Nếu bạn nhìn vào tài liệu MSDN, bạn sẽ thấy rằng kiểu tham số thứ hai là 'LPTSTR'. Trong mọi trường hợp, tôi đã thực hiện chính điểm mà bạn đưa ra trong đoạn thứ hai của tôi. –

7

CreateProcess() khởi chạy quá trình, nó không phải là dòng lệnh itnerpreter. Nó không biết ">" là gì và sẽ không thực hiện chuyển hướng luồng cho bạn. Bạn cần phải mở tập tin test.txt bản thân và vượt qua tay cầm vào nó để CreateProcess bên trong cấu trúc STARTUPINFO: CreateProcess STARTUPINFO

7

Microsoft có một ví dụ làm thế nào để chuyển hướng đầu ra tiêu chuẩn: http://msdn.microsoft.com/en-us/library/ms682499(VS.85).aspx.

+6

Vâng, đó là loại công việc, nhưng hãy nhớ có một lỗi trong ví dụ đó ngăn chặn 'ReadFromPipe' từ thoát. Trước khi bạn gọi hàm đó, bạn cần gọi: 'CloseHandle (g_hChildStd_OUT_Wr);'. Cũng có thể bạn sẽ muốn đợi cho quá trình con thoát ra trước khi bạn đóng xử lý để xử lý với một cái gì đó như: 'WaitForSingleObject (piProcInfo.hProcess, INFINITE);'. – Nux

18

Đoạn mã dưới đây tạo quy trình không có bàn điều khiển với stdout và stderr được chuyển hướng đến tệp được chỉ định.

#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

Mô tả cùng với mã sẽ có ích. Ít nhất ý kiến ​​ –

+0

Có thể ĐóngHandle() của tệp sau khi quá trình con sinh ra bị bỏ qua. – SerG

+0

Không nên hStdInput được INVALID_HANDLE_VALUE thay vì NULL? –

0

bạn nên chạy quy trình cmd.exe với thông số "/ c dòng lệnh". Điều này sẽ chuyển hướng đầu ra đến một tệp hoặc tổ chức một đường dẫn thông qua CreateProcess.

Các vấn đề liên quan