2012-07-19 40 views
10

Tôi đang gặp vấn đề nghiêm trọng ở đây. Tôi cần phải thực hiện một dòng lệnh CMD thông qua C + + mà không có cửa sổ giao diện điều khiển hiển thị. Do đó tôi không thể sử dụng system(cmd), vì cửa sổ sẽ hiển thị.C++ Thực hiện các lệnh CMD

Tôi đã thử winExec(cmd, SW_HIDE), nhưng điều này không hoạt động. CreateProcess là một số khác mà tôi đã thử. Tuy nhiên, điều này là để chạy chương trình hoặc tập tin thực thi.

Tôi đã kết thúc cố gắng ShellExecute:

ShellExecute(NULL, "open", 
    "cmd.exe", 
    "ipconfig > myfile.txt", 
    "c:\projects\b", 
    SW_SHOWNORMAL 
); 

bất cứ ai có thể nhìn thấy bất cứ điều gì sai trái với mã trên? Tôi đã sử dụng SW_SHOWNORMAL cho đến khi tôi biết công trình này hoạt động.

Tôi thực sự cần trợ giúp về vấn đề này. Không có gì đến với ánh sáng, và tôi đã cố gắng khá lâu rồi. Bất kỳ lời khuyên nào mà mọi người có thể đưa ra đều tuyệt vời :)

+0

Bạn đã kiểm tra mã trả lại chưa? – Collin

+1

Tôi biết bạn đã có câu trả lời, nhưng thường là một ý kiến ​​hay để nói nó không hoạt động như thế nào. – Deanna

+0

Tại sao không gọi hàm WMI_ và ghi kết quả vào tệp. Không có cửa sổ và chỉ là dữ liệu bạn cần. –

Trả lời

6

Chuyển hướng đầu ra để ống của riêng bạn là một giải pháp ngăn nắp vì nó tránh được việc tạo ra các tập tin đầu ra, nhưng điều này hoạt động tốt:

ShellExecute(0, "open", "cmd.exe", "/C ipconfig > out.txt", 0, SW_HIDE); 

Bạn không thấy cửa sổ cmd và sản lượng được chuyển hướng như mong đợi .

Mã của bạn có thể không thành công (ngoài điều /C) vì bạn chỉ định đường dẫn là "c:\projects\b" thay vì "c:\\projects\\b".

4

Bạn nên sử dụng CreateProcess trên cmd.exe với tham số /C để tunnel lệnh ipconfig. Các> không hoạt động trên mỗi dòng lệnh. Bạn phải redirect programmatically the stdout.

+0

Nếu đó là dòng lệnh 'cmd/c', thì dĩ nhiên'> 'chuyển hướng sẽ hoạt động. – eryksun

3

Dưới đây là triển khai thực hiện hàm DosExec cho phép (âm thầm) thực thi bất kỳ lệnh DOS nào và truy xuất kết quả được tạo dưới dạng chuỗi unicode.

// Convert an OEM string (8-bit) to a UTF-16 string (16-bit) 
#define OEMtoUNICODE(str) CHARtoWCHAR(str, CP_OEMCP) 

/* Convert a single/multi-byte string to a UTF-16 string (16-bit). 
We take advantage of the MultiByteToWideChar function that allows to specify the charset of the input string. 
*/ 
LPWSTR CHARtoWCHAR(LPSTR str, UINT codePage) { 
    size_t len = strlen(str) + 1; 
    int size_needed = MultiByteToWideChar(codePage, 0, str, len, NULL, 0); 
    LPWSTR wstr = (LPWSTR) LocalAlloc(LPTR, sizeof(WCHAR) * size_needed); 
    MultiByteToWideChar(codePage, 0, str, len, wstr, size_needed); 
    return wstr; 
} 

/* Execute a DOS command. 

If the function succeeds, the return value is a non-NULL pointer to the output of the invoked command. 
Command will produce a 8-bit characters stream using OEM code-page. 

As charset depends on OS config (ex: CP437 [OEM-US/latin-US], CP850 [OEM 850/latin-1]), 
before being returned, output is converted to a wide-char string with function OEMtoUNICODE. 

Resulting buffer is allocated with LocalAlloc. 
It is the caller's responsibility to free the memory used by the argument list when it is no longer needed. 
To free the memory, use a single call to LocalFree function. 
*/ 
LPWSTR DosExec(LPWSTR command){ 
    // Allocate 1Mo to store the output (final buffer will be sized to actual output) 
    // If output exceeds that size, it will be truncated 
    const SIZE_T RESULT_SIZE = sizeof(char)*1024*1024; 
    char* output = (char*) LocalAlloc(LPTR, RESULT_SIZE); 

    HANDLE readPipe, writePipe; 
    SECURITY_ATTRIBUTES security; 
    STARTUPINFOA  start; 
    PROCESS_INFORMATION processInfo; 

    security.nLength = sizeof(SECURITY_ATTRIBUTES); 
    security.bInheritHandle = true; 
    security.lpSecurityDescriptor = NULL; 

    if (CreatePipe(
        &readPipe, // address of variable for read handle 
        &writePipe, // address of variable for write handle 
        &security, // pointer to security attributes 
        0   // number of bytes reserved for pipe 
        )){ 


     GetStartupInfoA(&start); 
     start.hStdOutput = writePipe; 
     start.hStdError = writePipe; 
     start.hStdInput = readPipe; 
     start.dwFlags  = STARTF_USESTDHANDLES + STARTF_USESHOWWINDOW; 
     start.wShowWindow = SW_HIDE; 

// We have to start the DOS app the same way cmd.exe does (using the current Win32 ANSI code-page). 
// So, we use the "ANSI" version of createProcess, to be able to pass a LPSTR (single/multi-byte character string) 
// instead of a LPWSTR (wide-character string) and we use the UNICODEtoANSI function to convert the given command 
     if (CreateProcessA(NULL,     // pointer to name of executable module 
          UNICODEtoANSI(command), // pointer to command line string 
          &security,    // pointer to process security attributes 
          &security,    // pointer to thread security attributes 
          TRUE,     // handle inheritance flag 
          NORMAL_PRIORITY_CLASS, // creation flags 
          NULL,     // pointer to new environment block 
          NULL,     // pointer to current directory name 
          &start,     // pointer to STARTUPINFO 
          &processInfo    // pointer to PROCESS_INFORMATION 
         )){ 

      // wait for the child process to start 
      for(UINT state = WAIT_TIMEOUT; state == WAIT_TIMEOUT; state = WaitForSingleObject(processInfo.hProcess, 100)); 

      DWORD bytesRead = 0, count = 0; 
      const int BUFF_SIZE = 1024; 
      char* buffer = (char*) malloc(sizeof(char)*BUFF_SIZE+1); 
      strcpy(output, ""); 
      do {     
       DWORD dwAvail = 0; 
       if (!PeekNamedPipe(readPipe, NULL, 0, NULL, &dwAvail, NULL)) { 
        // error, the child process might have ended 
        break; 
       } 
       if (!dwAvail) { 
        // no data available in the pipe 
        break; 
       } 
       ReadFile(readPipe, buffer, BUFF_SIZE, &bytesRead, NULL); 
       buffer[bytesRead] = '\0'; 
       if((count+bytesRead) > RESULT_SIZE) break; 
       strcat(output, buffer); 
       count += bytesRead; 
      } while (bytesRead >= BUFF_SIZE); 
      free(buffer); 
     } 

    } 

    CloseHandle(processInfo.hThread); 
    CloseHandle(processInfo.hProcess); 
    CloseHandle(writePipe); 
    CloseHandle(readPipe); 

    // convert result buffer to a wide-character string 
    LPWSTR result = OEMtoUNICODE(output); 
    LocalFree(output); 
    return result; 
} 
+0

Cảm ơn bạn đã nhập mã mẫu! –

0

Tôi có một chương trình tương tự [windows7 và 10 thử nghiệm] trên github

https://github.com/vlsireddy/remwin/tree/master/remwin

Đây là chương trình máy chủ mà

  1. lắng nghe trên "Local Area Connection" tên giao diện trong cửa sổ cho cổng UDP (5555) và nhận gói udp.
  2. nội dung gói udp đã nhận được thực hiện trên cmd.exe [vui lòng không cmd.exe KHÔNG đóng sau khi chạy lệnh và chuỗi đầu ra [đầu ra của lệnh đã thực hiện] được fedback cho chương trình khách trên cùng một cổng udp].
  3. Nói cách khác, lệnh nhận được trong udp packet -> phân tích cú pháp gói udp -> thực hiện trên cmd.exe -> đầu ra đưa trở lại trên cùng một cổng vào chương trình khách hàng

này không hiển thị "giao diện điều khiển cửa sổ" Không cần ai đó thực hiện lệnh bằng tay trên cmd.exe remwin.exe có thể chạy trong nền và chương trình máy chủ mỏng của nó

+0

Xin chào, có vẻ như quá nhiều việc kiểm soát, tôi đặt một liên kết được kiểm tra hợp lệ và nó trả lời câu hỏi cụ thể bằng câu trả lời cụ thể với mã được kiểm tra, không hiểu đề xuất đánh giá xóa của bạn. Bạn chạy mã [MSVC], kiểm tra đầu ra của nó, kiểm tra nó và nếu nó không phù hợp, hãy xóa nó. – particlereddy

+0

Xin lỗi, tôi đã xóa nhận xét của mình. Tôi đã quá nhanh về kích hoạt ... – Jolta

+0

Đọc câu trả lời của bạn, có vẻ như tôi đã giải quyết được vấn đề. Tuy nhiên, Stack Overflow không khuyến khích các câu trả lời cung cấp các giải pháp dưới dạng các liên kết bên ngoài. – Jolta

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