Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[WinAPI] Przekazywanie poleceń do programu uruchomionego przez CreateProcess

Ostatnio zmodyfikowano 2017-02-17 23:10
Autor Wiadomość
Vister26
Temat założony przez niniejszego użytkownika
[WinAPI] Przekazywanie poleceń do programu uruchomionego przez CreateProcess
» 2017-02-16 00:35:07
Mój program w oddzielnym procesie ma uruchomić cmd i przekazywać do niego polecenia.
C/C++
PROCESS_INFORMATION pi;
STARTUPINFO si;

ZeroMemory( & pi, sizeof( pi ) );
ZeroMemory( & si, sizeof( si ) );
si.cb = sizeof( si );

if( !CreateProcess(
NULL,
( LPSTR ) "cmd.exe",
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
& si,
& pi )
)

     WaitForSingleObject( pi.hProcess, INFINITE );


W jaki sposób mam obsługiwać input i output wewnątrz programu?
P-157797
j23
» 2017-02-16 11:19:52
Do jednego z wątków napisałem funkcję, która odpala cmd z przekierowanym i/o. Poszukaj, może coś tam znajdziesz dla siebie.
P-157818
Vister26
Temat założony przez niniejszego użytkownika
» 2017-02-16 21:19:28
Niestety wyszukiwanie postów danego użytkownika działa niezbyt sprawnie. Z poniższych źródeł udało mi się zmontować trochę kodu.
launch an exe/process with stdin stdout and stderr?
Creating a Child Process with Redirected Input and Output

Zmieniłem tez koncepcję - zamiast do cmd input ma być przekierowany do program.exe
Próbuję do tego użyć windows pipe'ów. Proces działa, odbiera komendy wpisane z klawiatury ale te wysłane przez printf są ignorowane
C/C++
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <process.h>
#include <iostream>

#define BUFSIZE 4096

CHAR chBuf[ BUFSIZE ];
DWORD dwRead, dwWritten;
HANDLE hStdin, hStdout;
BOOL bSuccess;

using namespace std;

STARTUPINFO siEngine;
PROCESS_INFORMATION piEngine;

void WriteToPipe( void );
void CreateEngineProcess();

int main()
{
   
    hStdout = GetStdHandle( STD_OUTPUT_HANDLE );
    hStdin = GetStdHandle( STD_INPUT_HANDLE );
    if(
    ( hStdout == INVALID_HANDLE_VALUE ) ||
    ( hStdin == INVALID_HANDLE_VALUE )
    )
         ExitProcess( 1 );
   
    // Nowy child process
    CreateEngineProcess();
   
    // Proba wyslania komendy na wejscie nowego procesu
    printf( "START 15\r\n" );
    WriteToPipe();
   
    // Czekanie na proces
    WaitForSingleObject( piEngine.hThread, INFINITE );
   
    CloseHandle( piEngine.hProcess );
    CloseHandle( piEngine.hThread );
    return 0;
}

void CreateEngineProcess()
{
    BOOL bSuccess = FALSE;
    ZeroMemory( & siEngine, sizeof( siEngine ) );
    siEngine.cb = sizeof( siEngine );
    ZeroMemory( & piEngine, sizeof( piEngine ) );
   
    // Uzupelnianie struktury STARTUPINFO
    siEngine.cb = sizeof( STARTUPINFO );
    siEngine.hStdOutput = hStdout;
    siEngine.hStdInput = hStdin;
    siEngine.dwFlags |= STARTF_USESTDHANDLES;
   
    if( !CreateProcess( "program.exe",
    NULL, // Command line
    NULL, // Process handle not inheritable
    NULL, // Thread handle not inheritable
    TRUE, // Set handle inheritance to FALSE
    0, // No creation flags
    NULL, // Use parent's environment block
    NULL, // Use parent's starting directory
    & siEngine, // Pointer to STARTUPINFO structure
    & piEngine ) // Pointer to PROCESS_INFORMATION structure
    )
         return;
   
}

void WriteToPipe( void )
{
   
    // Read from standard input
    bSuccess = ReadFile( hStdin, chBuf, BUFSIZE, & dwRead, NULL );
   
    if( !bSuccess || dwRead == 0 )
         cout << "-1" << endl;
   
    // Write to standard output
    bSuccess = WriteFile( hStdout, chBuf, dwRead, & dwWritten, NULL );
   
    if( !bSuccess )
         cout << "-2" << endl;
   
}
P-157854
jankowalski25
» 2017-02-16 21:36:55
@j23: Chodzi o temat system(polecenia)?
P-157855
Vister26
Temat założony przez niniejszego użytkownika
» 2017-02-16 21:53:51
Dziękuję!
@j23: Proszę jeszcze o jakieś wskazówki jak przerobić tą funkcję aby przekazywała ten argument do innego programu i żeby po wykonaniu polecenia nie był on natychmiast zamykany tylko dalej czekał w procesie na kolejne polecenia. Trochę mnie przerasta konstrukcja tej funkcji i sam nie podołam
P-157858
j23
» 2017-02-17 11:41:55
@jankowalski25, tak, o ten temat mi chodziło.

@Vister26, nie jestem pewien, czy cmd jest w stanie przyjmować komendy strumieniowo przez standardowe wejście. O ile dobrze pamiętam, podczas pisania tamtej funkcji próbowałem wysyłać komendy na wejście, ale to nie działało. Być może trzeba użyć jakiejś dodatkowej opcji przy uruchomieniu cmd.exe.
P-157894
Vister26
Temat założony przez niniejszego użytkownika
» 2017-02-17 23:10:05
Przeszukałem większość tematów na Stackoverflow odnośnie tego problemu i mam działający program
C/C++
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <iostream>
#include <string>

#define BUFSIZE 4096

HANDLE hEngineStd_IN_Rd = NULL;
HANDLE hEngineStd_IN_Wr = NULL;
HANDLE hEngineStd_OUT_Rd = NULL;
HANDLE hEngineStd_OUT_Wr = NULL;

using namespace std;

void CreateEngineProcess( void );
void WriteToPipe( string msg );
void ReadFromPipe( void );


int main()
{
    SECURITY_ATTRIBUTES saAttr;
   
    printf( "\n->Start of parent execution.\n" );
   
    // Set the bInheritHandle flag so pipe handles are inherited.
   
    saAttr.nLength = sizeof( SECURITY_ATTRIBUTES );
    saAttr.bInheritHandle = TRUE;
    saAttr.lpSecurityDescriptor = NULL;
   
    // Create pipes for the child process's STDOUT and STDIN,
    // ensures both handle are not inherited
   
    if( !CreatePipe( & hEngineStd_OUT_Rd, & hEngineStd_OUT_Wr, & saAttr, 0 ) );
   
    if( !SetHandleInformation( hEngineStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0 ) );
   
    if( !CreatePipe( & hEngineStd_IN_Rd, & hEngineStd_IN_Wr, & saAttr, 0 ) );
   
    if( !SetHandleInformation( hEngineStd_IN_Wr, HANDLE_FLAG_INHERIT, 0 ) );
   
    // Create the child process.
    CreateEngineProcess();
   
    // Write to the pipe that is the standard input for a child process.
   
    WriteToPipe( "START 15\r\n" );
   
    // Read from pipe that is the standard output for child process.
   
    ReadFromPipe();
   
    WriteToPipe( "BEGIN\r\n" );
    ReadFromPipe();
   
    printf( "\n->End of parent execution.\n" );
   
    // The remaining open handles are cleaned up when this process terminates.
    // To avoid resource leaks in a larger application, close handles explicitly.
   
    return 0;
}

void CreateEngineProcess()
// Create a child process that uses the previously created pipes for STDIN and STDOUT.
{
    TCHAR szCmdline[] = TEXT( "program.exe" );
    PROCESS_INFORMATION piProcInfo;
    STARTUPINFO siStartInfo;
    BOOL bSuccess = FALSE;
   
    // Set up members of the PROCESS_INFORMATION structure.
   
    ZeroMemory( & piProcInfo, sizeof( PROCESS_INFORMATION ) );
   
    // Set up members of the STARTUPINFO structure.
    // This structure specifies the STDIN and STDOUT handles for redirection.
   
    ZeroMemory( & siStartInfo, sizeof( STARTUPINFO ) );
    siStartInfo.cb = sizeof( STARTUPINFO );
    siStartInfo.hStdError = hEngineStd_OUT_Wr;
    siStartInfo.hStdOutput = hEngineStd_OUT_Wr;
    siStartInfo.hStdInput = hEngineStd_IN_Rd;
    siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
   
    // Create the child process.
   
    bSuccess = CreateProcess( NULL,
    szCmdline, // command line
    NULL, // process security attributes
    NULL, // primary thread security attributes
    TRUE, // handles are inherited
    0, // creation flags
    NULL, // use parent's environment
    NULL, // use parent's current directory
    & siStartInfo, // STARTUPINFO pointer
    & piProcInfo ); // receives PROCESS_INFORMATION
   
    // If an error occurs, exit the application.
    if( !bSuccess );
    else
    {
        // Close handles to the child process and its primary thread.
        // Some applications might keep these handles to monitor the status
        // of the child process, for example.
       
        CloseHandle( hEngineStd_OUT_Wr );
        CloseHandle( hEngineStd_IN_Rd );
        CloseHandle( piProcInfo.hProcess );
        CloseHandle( piProcInfo.hThread );
    }
}

void WriteToPipe( string msg )
{
    BOOL bSuccess;
    bSuccess = WriteFile( hEngineStd_IN_Wr, msg.c_str(), msg.size(), NULL, NULL );
}

void ReadFromPipe( void )
{
    DWORD dwRead, dwWritten, dwAvailableBytes, dwBytesLeft;
    CHAR chBuf[ BUFSIZE ];
    BOOL bSuccess = FALSE;
    HANDLE hParentStdOut = GetStdHandle( STD_OUTPUT_HANDLE );
   
    //  How much data in the program output. How much to read without blocking
    bSuccess = PeekNamedPipe( hEngineStd_OUT_Rd, chBuf, BUFSIZE, & dwRead, & dwAvailableBytes, & dwBytesLeft );
   
    bSuccess = ReadFile( hEngineStd_OUT_Rd, chBuf, dwAvailableBytes, & dwRead, NULL );
    //if( ! bSuccess || dwRead == 0 ) ;
   
    bSuccess = WriteFile( hParentStdOut, chBuf, dwRead, & dwWritten, NULL );
    // if (! bSuccess ) ;
}

Może ktoś kiedyś skorzysta z tego kodu ;)
Temat zamykam.
P-157926
« 1 »
  Strona 1 z 1