簡體   English   中英

如何在Windows上的C中從CreateProcess執行Python腳本?

[英]How to execute Python script from CreateProcess in C on Windows?

我已經設法在C代碼中使用PIPES在Unix上快速獲得C代碼調用Python腳本。 我現在需要在Windows上做同樣的事情。

基本上我想在Windows上用不同的腳本語言編寫腳本,如Python / Lua等,並且能夠使用STDIN / STDOUT等執行它們。

我一直在查看“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;
}

相當一部分上面的代碼是“硬編碼”只是為了測試目的...基本上我傳遞一些文本,如“你好,從paren”發送到“child.exe”....

這是child.c的代碼...發送給它的簡單ECHO

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

void main (){
    CHAR szInput[1024];
    ZeroMemory(szInput,1024);   
    gets(szInput);
    puts(szInput);
    fflush(NULL);   
}

要運行應用程序,我發送“CallSubProcess.exe Child.exe”,它100%工作

接下來我想改變“child.c”成為PYTHON SCRIPT ......

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)){

但它永遠不會奏效。

任何想法我怎么能讓這個工作? 任何幫助將不勝感激。

我的應用程序將字符串發布到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

也許

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

CreateProcess很棘手。

從MSDN文檔:

如果lpApplicationNamelpCommandLine都是非NULL,則... lpApplicationName指定要執行的模塊,並且... lpCommandLine指定命令行....用C編寫的控制台進程可以使用argcargv參數來解析命令行。 因為argv[0]是模塊名稱,所以C程序員通常會重復模塊名稱作為命令行中的第一個標記。

為了避免這種怪異,我建議總是為第一個參數傳遞NULL並將第二個完整的命令行傳遞給:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM