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

[winAPI] ShellExecute - co zwraca program?

Ostatnio zmodyfikowano 2016-09-27 18:59
Autor Wiadomość
mikson
Temat założony przez niniejszego użytkownika
[winAPI] ShellExecute - co zwraca program?
» 2016-09-26 17:55:31
Witam,

Jak mogę sprawdzić, co zwraca program wywołany funkcją ShellExecute?

Z góry dziękuję za odpowiedź i pozdrawiam.
P-152049
jankowalski25
» 2016-09-26 18:17:25
[StackOverflow] how to get return value of an exe called by ShellExecute
Z powyższego tematu wynika, że chyba najprościej użyć innej funkcji. W naszej dokumentacji przy opisie » WinAPICreateProcess masz nawet przykład. Zakładam, że chcesz otrzymać coś w stylu
Process returned: 42
.
P-152052
mikson
Temat założony przez niniejszego użytkownika
» 2016-09-26 18:45:49
Roboczo napisałem sobie taki kod:
C/C++
#include <windows.h>
#include <iostream>
using namespace std;

int main() {
    DWORD exitcode;
    SHELLEXECUTEINFO ShExecInfo = { 0 };
    ShExecInfo.cbSize = sizeof( SHELLEXECUTEINFO );
    ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
    ShExecInfo.hwnd = NULL;
    ShExecInfo.lpVerb = NULL;
    ShExecInfo.lpFile = "C:\\Users\\Mikołaj\\Desktop\\bin\\curl.exe";
    ShExecInfo.lpParameters = "--data testGET=test123 http://mojeurl.pl/plik.php";
    ShExecInfo.lpDirectory = NULL;
    ShExecInfo.nShow = SW_SHOW;
    ShExecInfo.hInstApp = NULL;
    ShellExecuteEx( & ShExecInfo );
    WaitForSingleObject( ShExecInfo.hProcess, INFINITE );
    if( !GetExitCodeProcess( ShExecInfo.hProcess, & exitcode ) ) {
        printf( "Could not get process exit code. (%ld)", GetLastError() );
        return 1;
    }
    printf( "Process returned: %ld", exitcode );
}
I problem polega na tym, że... curl.exe zawsze zwraca 0, zamiast tego, co jest wysyłane przez serwer. Gdy natomiast wywołam to samo z cmd, wszystko jest w porządku.
P-152054
jankowalski25
» 2016-09-26 19:02:21
I problem polega na tym, że... curl.exe zawsze zwraca 0, zamiast tego, co jest wysyłane przez serwer.
Czyli nie chcesz pobrać wartości zwracanej przez program, tylko to, co widzisz w konsoli? Pierwszy komentarz pod podanym tematem:
I think what you mean by "return value" is the output from CMD, which this question addresses: Using ShellExecuteEx and capturing standard in/out/err
Jeśli chodzi o przekierowanie wejścia i wyjścia, to przykład znajdziesz w [MSDN] Creating a Child Process with Redirected Input and Output.
P-152059
mikson
Temat założony przez niniejszego użytkownika
» 2016-09-27 18:05:07
Dobra, dzięki, jako tako działa. Teraz jedyny problem polega na tym, że curl.exe kończy działanie i nie zamyka się, przez co mój program cały czas czeka. Kod:
C/C++
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>

#define BUFSIZE 4096

HANDLE g_hChildStd_IN_Rd = NULL;
HANDLE g_hChildStd_IN_Wr = NULL;
HANDLE g_hChildStd_OUT_Rd = NULL;
HANDLE g_hChildStd_OUT_Wr = NULL;

HANDLE g_hInputFile = NULL;

void CreateChildProcess( void );
void WriteToPipe( void );
void ReadFromPipe( void );
void ErrorExit( PTSTR );

int _tmain( int argc, TCHAR * argv[] )
{
    SECURITY_ATTRIBUTES saAttr;
    printf( "\n->Start of parent execution.\n" );
   
    saAttr.nLength = sizeof( SECURITY_ATTRIBUTES );
    saAttr.bInheritHandle = TRUE;
    saAttr.lpSecurityDescriptor = NULL;
   
    if( !CreatePipe( & g_hChildStd_OUT_Rd, & g_hChildStd_OUT_Wr, & saAttr, 0 ) )
         ErrorExit( TEXT( "StdoutRd CreatePipe" ) );
   
    if( !SetHandleInformation( g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0 ) )
         ErrorExit( TEXT( "Stdout SetHandleInformation" ) );
   
    if( !CreatePipe( & g_hChildStd_IN_Rd, & g_hChildStd_IN_Wr, & saAttr, 0 ) )
         ErrorExit( TEXT( "Stdin CreatePipe" ) );
   
    if( !SetHandleInformation( g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0 ) )
         ErrorExit( TEXT( "Stdin SetHandleInformation" ) );
   
    CreateChildProcess();
   
    printf( "\n->Contents of child process STDOUT:\n\n", argv[ 1 ] );
    ReadFromPipe();
   
    printf( "\n->End of parent execution.\n" ); //nigdy nie dochodzi do tego momentu
   
    return 0;
}

void CreateChildProcess()
{
    TCHAR szCmdline[] = TEXT( "child" );
    PROCESS_INFORMATION piProcInfo;
    STARTUPINFO siStartInfo;
    BOOL bSuccess = FALSE;
   
    ZeroMemory( & piProcInfo, sizeof( PROCESS_INFORMATION ) );
   
    ZeroMemory( & siStartInfo, sizeof( STARTUPINFO ) );
    siStartInfo.cb = sizeof( STARTUPINFO );
    siStartInfo.hStdError = g_hChildStd_OUT_Wr;
    siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
    siStartInfo.hStdInput = g_hChildStd_IN_Rd;
    siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
   
    bSuccess = CreateProcess( "C:\\Users\\Mikołaj\\sciezka\\bin\\curl.exe",
    "curl.exe --data \"POSTtest=test\" http://link.pl/strona.php", // 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
   
    //tu się zawiesza i nie idzie dalej, czeka aż curl.exe się zamknie, który pomimo wykonania już POSTa nie zamyka się
   
    if( !bSuccess )
         ErrorExit( TEXT( "CreateProcess" ) );
    else
    {
        CloseHandle( piProcInfo.hProcess );
        CloseHandle( piProcInfo.hThread );
    }
}

void WriteToPipe( void )
{
    DWORD dwRead, dwWritten;
    CHAR chBuf[ BUFSIZE ];
    BOOL bSuccess = FALSE;
   
    for(;; )
    {
        bSuccess = ReadFile( g_hInputFile, chBuf, BUFSIZE, & dwRead, NULL );
        if( !bSuccess || dwRead == 0 ) break;
       
        bSuccess = WriteFile( g_hChildStd_IN_Wr, chBuf, dwRead, & dwWritten, NULL );
        if( !bSuccess ) break;
       
    }
    if( !CloseHandle( g_hChildStd_IN_Wr ) )
         ErrorExit( TEXT( "StdInWr CloseHandle" ) );
   
}

void ReadFromPipe( void )
{
    DWORD dwRead, dwWritten;
    CHAR chBuf[ BUFSIZE ];
    BOOL bSuccess = FALSE;
    HANDLE hParentStdOut = GetStdHandle( STD_OUTPUT_HANDLE );
   
    for(;; )
    {
        bSuccess = ReadFile( g_hChildStd_OUT_Rd, chBuf, BUFSIZE, & dwRead, NULL );
        if( !bSuccess || dwRead == 0 ) break;
       
        bSuccess = WriteFile( hParentStdOut, chBuf,
        dwRead, & dwWritten, NULL );
        if( !bSuccess ) break;
       
    }
}

void ErrorExit( PTSTR lpszFunction )
{
    LPVOID lpMsgBuf;
    LPVOID lpDisplayBuf;
    DWORD dw = GetLastError();
   
    FormatMessage(
    FORMAT_MESSAGE_ALLOCATE_BUFFER |
    FORMAT_MESSAGE_FROM_SYSTEM |
    FORMAT_MESSAGE_IGNORE_INSERTS,
    NULL,
    dw,
    MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
    ( LPTSTR ) & lpMsgBuf,
    0, NULL );
   
    lpDisplayBuf =( LPVOID ) LocalAlloc( LMEM_ZEROINIT,
    ( lstrlen(( LPCTSTR ) lpMsgBuf ) + lstrlen(( LPCTSTR ) lpszFunction ) + 40 ) * sizeof( TCHAR ) );
    StringCchPrintf(( LPTSTR ) lpDisplayBuf,
    LocalSize( lpDisplayBuf ) / sizeof( TCHAR ),
    TEXT( "%s failed with error %d: %s" ),
    lpszFunction, dw, lpMsgBuf );
    MessageBox( NULL,( LPCTSTR ) lpDisplayBuf, TEXT( "Error" ), MB_OK );
   
    LocalFree( lpMsgBuf );
    LocalFree( lpDisplayBuf );
    ExitProcess( 1 );
}
P-152072
mikson
Temat założony przez niniejszego użytkownika
Zamykam
» 2016-09-27 18:59:56
Nieaktualne, użyłem po prostu argumentu --output FILE i działa. Dziękuję za pomoc.
P-152073
« 1 »
  Strona 1 z 1