2010-09-09 96 views
1

我已經設法在C代碼中使用PIPES在Unix上高興地獲得C代碼調用Python腳本。我現在需要在Windows上執行相同的操作。如何在Windows上的C中的CreateProcess執行Python腳本?

基本上我想編寫不同的腳本語言就像在Windows中的Python/Lua的腳本等,並能使用執行這些標準輸入/輸出等

我一直在尋找的「CreateProcess的」電話:

http://msdn.microsoft.com/en-us/library/ms682425(VS.85).aspx

,雖然我可以得到它與「C語言編寫的孩子」的工作,我不能讓它調用Python腳本。

下面是在我的Windows中的「父/發送代碼」:

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

#pragma comment(lib, "User32.lib") 
void DisplayError(char *pszAPI); 
void readFromPipe(HANDLE hPipeRead); 
void createChildProcess(char *commandLine, 
         HANDLE hChildStdOut, 
         HANDLE hChildStdIn, 
         HANDLE hChildStdErr); 
DWORD WINAPI writeToPipe(LPVOID lpvThreadParam); 

HANDLE hChildProcess = NULL; 
HANDLE hStdIn = NULL; 
BOOL bRunThread = TRUE; 
char *inputStream; 

int main(int argc, char *argv[]){ 
    HANDLE hOutputReadTmp,hOutputRead,hOutputWrite; 
    HANDLE hInputWriteTmp,hInputRead,hInputWrite; 
    HANDLE hErrorWrite; 
    HANDLE hThread; 
    DWORD ThreadId; 
    SECURITY_ATTRIBUTES sa; 
    int streamLen; 

    sa.nLength= sizeof(SECURITY_ATTRIBUTES); 
    sa.lpSecurityDescriptor = NULL; 
    sa.bInheritHandle = TRUE; 

    if (!CreatePipe(&hOutputReadTmp,&hOutputWrite,&sa,0)) 
    return 1; 

    if (!DuplicateHandle(GetCurrentProcess(),hOutputWrite, 
         GetCurrentProcess(),&hErrorWrite,0, 
         TRUE,DUPLICATE_SAME_ACCESS)) 
    return 1; 

    if (!CreatePipe(&hInputRead,&hInputWriteTmp,&sa,0)) 
    return 1; 

    if (!DuplicateHandle(GetCurrentProcess(),hOutputReadTmp, 
         GetCurrentProcess(), 
         &hOutputRead, 
         0,FALSE, 
         DUPLICATE_SAME_ACCESS)) 
    return 1; 

    if (!DuplicateHandle(GetCurrentProcess(),hInputWriteTmp, 
         GetCurrentProcess(), 
         &hInputWrite, 
         0,FALSE, 
         DUPLICATE_SAME_ACCESS)) 
    return 1; 

    if (!CloseHandle(hOutputReadTmp)) return 1;; 
    if (!CloseHandle(hInputWriteTmp)) return 1;; 

    if ((hStdIn = GetStdHandle(STD_INPUT_HANDLE)) == INVALID_HANDLE_VALUE) 
    return 1; 

    if (argc == 2){ 
    createChildProcess(argv[1], hOutputWrite,hInputRead,hErrorWrite); 
    }else{ 
    puts("No process name/input stream specified\n"); 
    return 1; 
    } 


    if (!CloseHandle(hOutputWrite)) return 1;; 
    if (!CloseHandle(hInputRead)) return 1;; 
    if (!CloseHandle(hErrorWrite)) return 1;; 

    hThread = CreateThread(NULL,0,writeToPipe, 
          (LPVOID)hInputWrite,0,&ThreadId); 
    if (hThread == NULL) 
    return 1;; 

    readFromPipe(hOutputRead); 

    if (!CloseHandle(hStdIn)) 
    return 1; 
    bRunThread = FALSE; 

    if (WaitForSingleObject(hThread,INFINITE) == WAIT_FAILED) 
    return 1;; 

    if (!CloseHandle(hOutputRead)) return 1;; 
    if (!CloseHandle(hInputWrite)) return 1;; 
} 

void createChildProcess(char *commandLine, 
         HANDLE hChildStdOut, 
         HANDLE hChildStdIn, 
         HANDLE hChildStdErr){ 
    PROCESS_INFORMATION pi; 
    STARTUPINFO si; 

    ZeroMemory(&si,sizeof(STARTUPINFO)); 
    si.cb = sizeof(STARTUPINFO); 
    si.dwFlags = STARTF_USESTDHANDLES; 
    si.hStdOutput = hChildStdOut; 
    si.hStdInput = hChildStdIn; 
    si.hStdError = hChildStdErr; 

    if (!CreateProcess(NULL,commandLine,NULL,NULL,TRUE, 
        NULL,NULL,NULL,&si,&pi)) 
    hChildProcess = pi.hProcess; 
    if (!CloseHandle(pi.hThread)) return 1;; 
} 

void readFromPipe(HANDLE hPipeRead) 
{ 
    CHAR lpBuffer[256]; 
    DWORD nBytesRead; 
    DWORD nCharsWritten; 

    while(TRUE) 
    { 
    if (!ReadFile(hPipeRead,lpBuffer,sizeof(lpBuffer), 
             &nBytesRead,NULL) || !nBytesRead) 
    { 
     if (GetLastError() == ERROR_BROKEN_PIPE) 
      break; // pipe done - normal exit path. 
     else 
      return 1; // Something bad happened. 
    } 
    if (!WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE),lpBuffer, 
         nBytesRead,&nCharsWritten,NULL)) 
     return 1;; 
    } 
} 

DWORD WINAPI writeToPipe(LPVOID lpvThreadParam) 
{ 
    CHAR read_buff[256]; 
    DWORD nBytesRead,nBytesWrote; 
    HANDLE hPipeWrite = (HANDLE)lpvThreadParam; 

    while (bRunThread){ 
    nBytesRead = 21; 
    strncpy(read_buff, "hello from the paren\n",21); 
    read_buff[nBytesRead] = '\0'; 

    if (!WriteFile(hPipeWrite,read_buff,nBytesRead,&nBytesWrote,NULL)){ 
     if (GetLastError() == ERROR_NO_DATA) 
      break; //Pipe was closed (normal exit path). 
     else 
     return 1;; 
    } 
    } 
    return 1; 
} 

頗有幾分上面的代碼只是爲了測試目的「硬編碼」 ......基本上我傳遞一些文字,如「你好從括號」發送到‘child.exe’......

下面是child.c代碼...什麼是發送給它

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

void main(){ 
    CHAR szInput[1024]; 
    ZeroMemory(szInput,1024); 
    gets(szInput); 
    puts(szInput); 
    fflush(NULL); 
} 
一個簡單的ECHO

要運行該應用程序,我發送「CallSubPr ocess.exe Child.exe」和它的作品100%

接下來我要改變‘child.c’是一個Python腳本...

import sys 

if __name__ == "__main__": 
    inStream = sys.stdin.read() 
    outStream = inStream 
    sys.stdout.write(outStream) 
    sys.stdout.flush() 

所以,我怎麼可以改變的CreateProcess調用執行這個腳本?

if (!CreateProcess("C:\\Python26\\python.exe", "echo.py",NULL, NULL,FALSE, 0,NULL,NULL,&si,&pi)){ 

但它從來沒有工作。

任何想法,我可以得到這個工作?任何幫助將不勝感激。

+2

哦!永遠不要使用'gets()'! – pmg 2010-09-09 09:25:58

+0

我知道這是一個六年的問題,但是你有沒有發現任何有效的東西?沒有被接受的答案。 – rstackhouse 2017-07-26 19:50:12

回答

1

也許

if (!CreateProcess("C:\\Python26\\python.exe", 
      "echo.py 'hello from parent'", 
      NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { 
+0

您好,謝謝您的建議,但我想發送流到PIPE而不是作爲參數傳遞給Python腳本?我在Unix上也有同樣的事情......只是這個CreateProcess似乎給了我很大的幫助;-(其他建議? – 2010-09-10 11:32:48

0

CreateProcess是棘手的一種使用。

從MSDN文檔:

如果兩個lpApplicationNamelpCommandLine是非NULL,... lpApplicationName指定執行所述模塊,和... lpCommandLine指定命令行....控制檯流程用C編寫可以使用argcargv參數來解析命令行。因爲argv[0]是模塊名稱,所以C程序員通常會重複模塊名稱作爲命令行中的第一個標記。

爲了避免古怪,我建議始終傳遞NULL的第一個參數,並通過完整的命令行作爲第二:

CreateProcess(NULL, "\"C:\\Python26\\python.exe\" echo.py", ...); 
+0

您好,我試過了您的建議,但仍然沒有運氣;-(任何其他想法? – 2010-09-10 11:30:44

+0

@lyntongrice:我想我可能誤解了你的問題,難道你不能讓腳本執行,或者你不能讀取它的輸出嗎? – jamesdlin 2010-09-10 19:05:28

3

我的應用程序發送一個字符串到Python腳本,和python腳本將該字符串發回給c 應用程序。它運作良好。

//c code 
#pragma comment(lib, "json_vc71_libmtd.lib") 
#include <windows.h> 
#include <iostream> 
#include <io.h> 
#include "./json/json.h" 

using namespace std; 

DWORD WINAPI threadproc(PVOID pParam); 
HANDLE hRead, hWrite, hRead1, hWrite1; 
int main() 
{ 
    SECURITY_ATTRIBUTES sa; 
    sa.nLength = sizeof(SECURITY_ATTRIBUTES); 
    sa.lpSecurityDescriptor = NULL; 
    sa.bInheritHandle = TRUE; 
    if (!CreatePipe(&hRead, &hWrite, &sa, 0)){ 
     ::MessageBox(NULL, L"can't create pipe", L"error", MB_OK); 
     return -1; 
    } 
    if (!CreatePipe(&hRead1, &hWrite1, &sa, 0)){ 
     ::MessageBox(NULL, L"can't create pipe1", L"error", MB_OK); 
     return -1; 
    } 
    STARTUPINFO si; 
    PROCESS_INFORMATION pi; 
    GetStartupInfo(&si); 
    si.cb = sizeof(STARTUPINFO); 
    si.hStdError = hWrite; 
    si.hStdOutput = hWrite; 
    si.hStdInput = hRead1; 
    si.wShowWindow = SW_SHOW; 
    si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; 
    WCHAR szCmdLine[] = L"\"D:\\tools\\python\\python.exe\" D:\\code\\test\\pipeCallCore\\pipeCallCore\\json_wraper.py"; 
    if (!CreateProcess(NULL, szCmdLine, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)){ 
     ::MessageBox(NULL, L"can't create process", L"error", MB_OK); 
     return -1; 
    } 
    CloseHandle(hWrite); 
    CloseHandle(hRead1); 
    const int cBufferSize = 4096; 
    char buffer[cBufferSize] = {0}; 
    DWORD bytes; 
    int i = 0; 
    while (true){ 
     cout << "come !" << endl; 
     ZeroMemory(buffer, sizeof(buffer)); 
     sprintf(buffer, "{\"write\":%d}\n", i ++); 
     if (NULL == WriteFile(hWrite1, buffer, strlen(buffer), &bytes, NULL)){ 
      ::MessageBox(NULL, L"write file failed!", L"error", MB_OK); 
      break; 
     } 
     ZeroMemory(buffer, sizeof(buffer)); 
     if (NULL == ReadFile(hRead, buffer, cBufferSize - 1, &bytes, NULL)){ 
      ::MessageBox(NULL, L"readfile failed", L"error", MB_OK); 
      return -1; 
     } 
     cout <<"yes " << buffer << endl; 
     Sleep(2000); 
    } 
    return 0; 
} 


//python code 
#!/usr/bin/env python 
# -*- coding: utf-8 -*- 

import sys 

while True: 
    try: 
     s = sys.stdin.readline() 
     sys.stdout.write(s) 
     sys.stdout.flush() 
    except EOFError, KeyboardInterrupt: 
     break 
+0

你必須從你稱之爲Python腳本的文件寫入文件方式?認爲我有一些權限問題。 – rstackhouse 2017-07-26 19:50:56