Hilfe bei der Umleitung der Konsolenausgabe...

partitionist

Erfahrenes Mitglied
Hallo Leute,

ich habe eine Art RPC Projekt (Konsole) erstellt, d.h. man kann im Netzwerk/LAN von einem Client Befehle zum Server senden, der diese dann ausführt. In dem Projekt sind mehrere System Tools in Form von *.exe Dateien wie z.B. kill.exe (Schließt Prozesse), info.exe (Ausgabe von System Infos), proc.exe (Ausgabe von Prozessen), user.exe, ...
Diese Tools und der Client/Server befinden sich im gleichen Ordner.

Beispiel:
Auf dem PC1 läuft der Client.
Auf dem PC2 läuft der Server.

Ablauf:
Jetzt baue ich eine Verbindung mit dem Client zum Server auf. Soabald dies geschehen ist, kann ich in der Konsole des Clients Befehle wie kill, info, proc,... übergeben/senden. Der Server startet mit system(BEFEHL) alle übegebenen Befehle die in dem gleichen Ordner sind.
Beispiel: Soabald der Befehl info übegeben wird, startet der Server die info.exe im gleichen Ordner und führt sie aus, und es erscheint beim Server die Ausgabe von info.

Problem:
Wie bekommt man die Ausgabe vom Server übers Netzwerk umgeleitet?
Also wie in dem obigen Beispiel mit info, die Ausgabe von info.exe möchte ich nur im Client sehen.

Hab mich hier im Forum umgeschaut und es gab ein ähnliches Thema aber keine Lösung: http://www.tutorials.de/forum/c-c/244182-cmd-steuern.html?highlight=pipes


Hier mein Client/Server

Client:
Code:
#include <stdlib.h> 
#include <stdio.h> 
#include <windows.h> 
#include <winsock.h> 
#include <conio.h> 
#include <string>
#include <iostream>
#include <sstream>
#include <cstdio> 
#include <vector>

using namespace std;

#pragma comment(lib,"wsock32.lib")


// Startet Winsock und gibt einige Infos zur Version aus 
// Starts winsock and dumps some infos about the version 
int startWinsock() 
{ 
   int rc; 
   WSADATA wsaData; 
   rc=WSAStartup(MAKEWORD(2,0),&wsaData); 
   
   if(rc==SOCKET_ERROR) 
   { 
      printf("Error, exiting!\n"); 
      return rc; 
   }  
   printf("System Status: %s\n",wsaData.szSystemStatus); 
   return 0; 
} 

// Sucht eine IP anhand eines Strings, der entweder die IP als String 
// oder einen Hostname enthalten kann 
long getAddrFromString(char* hostnameOrIp, SOCKADDR_IN* addr) 
{ 
   long rc; 
   unsigned long ip; 

   HOSTENT* he; 

   if(hostnameOrIp==NULL || addr==NULL) 
      return SOCKET_ERROR; 
   ip=inet_addr(hostnameOrIp); 

   if(ip!=INADDR_NONE)
   { 
      addr->sin_addr.s_addr=ip; 
      return 0; 
   } 
   else 
   { 
      he=gethostbyname(hostnameOrIp); 
      if(he==NULL) 
      { 
         return SOCKET_ERROR; 
      } 
      else 
      { 
         memcpy(&(addr->sin_addr),he->h_addr_list[0],4); 
      } 
      return 0; 
   } 
} 

int main(int argc, char* argv[]) 
{ 
    if(argc > 2)
    {
        char* HOST = argv[1];
        int PORT = atoi(argv[2]);

        SOCKET s; 
        SOCKADDR_IN addr; 
        char c; 
        char buf[1024]; 
        char inpBuf[1024]; 
        int inpBufPos=0; 
        fd_set fdSetRead; 
        TIMEVAL timeout; 
        int rc; 


        // start winsock 
        rc=startWinsock(); 
        if(rc==SOCKET_ERROR) 
        return 1; 

        // addr vorbereiten, hostname auflösen 
        // prepare addr, resolve hostname 
        memset(&addr,0,sizeof(SOCKADDR_IN)); 
        addr.sin_family=AF_INET; 
        addr.sin_port=htons(PORT); 
        rc=getAddrFromString(HOST, &addr); 
        if(rc==SOCKET_ERROR) 
        { 
        printf("Error: Cannot resolve Host %s\n", HOST); 
        return 1; 
        } 

        // socket erstellen 
        // create socket 
        s=socket(PF_INET,SOCK_STREAM,0); 
        if(s==INVALID_SOCKET) 
        { 
        printf("Error, cannot create socket: %d\n",WSAGetLastError()); 
        return 1; 
        } 

        // verbinden.. 
        // connect.. 
        printf("Connecting...\n"); 
        rc=connect(s,(SOCKADDR*)&addr,sizeof(SOCKADDR)); 
        if(rc==SOCKET_ERROR) 
        { 
        printf("Error: connect failed: %d\n",WSAGetLastError()); 
        return 1; 
        } 

        printf("\n"); 
        
        string str; //Eingabe String

        do
        {
            cout << "Eingabe:";
            getline(cin, str);

            if(str == "exit")
            {
                closesocket(s); 
                WSACleanup(); 
                return 0;
            }

            else if(str == "close")
            {
                rc=send(s,str.c_str(),strlen(str.c_str()),0); 
                closesocket(s); 
                WSACleanup(); 
                return 0;
            }

        
            //cout << "send->" << str << endl;
            rc=send(s,str.c_str(),strlen(str.c_str()),0); 

            
            // fd_set und timeout vorbereiten 
            // prepare fd_set and timeout 
            FD_ZERO(&fdSetRead); 
            FD_SET(s,&fdSetRead); 
            timeout.tv_sec=0; 
            timeout.tv_usec=0; 

            // prüfen ob ein socket bereit ist, da timeout=0 kehrt die funktion 
            // sofort wieder zurück nach dem aufruf. 
            // achtung: das timeout auf 0 setzen oder als paremeter NULL mitgeben 
            // ist NICHT das gleiche. auf 0 gesetzt kehrt sofort zurück, während 
            // NULL blockt. 
            // check if any socket is ready (timeout=0, the function returns without delay) 
            while((rc=select(0,&fdSetRead,NULL,NULL,&timeout))>0) 
            { 
                rc=recv(s,buf,1023,0); 
                // server hat die verbindung beendet ? 
                // server closed connection ? 
                if(rc==0) 
                { 
                    printf("Server closed connection!\n"); 
                    return 1; 
                // fehler: beenden! 
                // error: abort! 
                } else if(rc==SOCKET_ERROR) 
                { 
                    printf("Error: recv failed: %d\n",WSAGetLastError()); 
                    return 1; 
                } 
                // empfangene daten ausgeben 
                // print received data 
                buf[rc]='\0'; 
                printf("%s\n",buf); 
            } 
    

        }while(rc!=SOCKET_ERROR);//Ende do-while

        // aufräumen 
        // cleanup.. 
        closesocket(s); 
        WSACleanup(); 
        printf("Client shutdown, press any key to exit\n"); 
        getch(); 

       }
       else    
       {
           cout << "Client HOST PORT" << endl;
       }
       return 0; 

}


Server:
Code:
// max. Anzahl Clients 
// Max. number of clients 
#define MAX_CLIENTS 100 


// Der Standartwert für FD_SETSIZE ist 64, dieser kann aber verändert 
// werden indem man FD_SETSIZE auf einen anderen Wert setzt bevor man 
// winsock2.h includiert. 
// FD_SETSIZE auf die max. Anzahl Clients setzten 
#define FD_SETSIZE   MAX_CLIENTS 

// includes... 
#include <stdlib.h> 
#include <stdio.h> 
#include <windows.h> 
#include <winsock.h> 
#include <conio.h> 
#include <string>
#include <iostream>
#include "convert.h"
#include "registry.h"

#pragma comment(lib, "wsock32.lib")
#pragma comment(lib, "advapi32.lib") 

using namespace std;

// Stellt eine Verbindung mit einem Client dar 
// Represents a connection with a Client 
struct Connection 
{ 
   Connection() 
   { 
      used=false; 
      socket=INVALID_SOCKET; 
   } 
   void set(SOCKET s, SOCKADDR_IN addr) 
   { 
      this->socket=s; 
      this->addr=addr; 
      this->used=true; 
   } 
   void erase() 
   { 
      this->used=false; 
      this->socket=INVALID_SOCKET; 
   } 
   bool used;   // connection benutzt ? / connection slot used ? 
   SOCKET socket; // socket 
   SOCKADDR_IN addr; // client addr 
}; 

// clients 
Connection clients[MAX_CLIENTS]; 

// Sucht den nächsten freien Platz im clients Array 
// -1 = kein platz frei 
// Searches the next free slot in the clients array 
// -1 = no free slot 
int getFreeClientSlot() 
{ 
   for(int i=0;i<MAX_CLIENTS;i++) 
   { 
      if(clients[i].used==false) 
         return i; 
   } 
   return -1; 
} 

// Sendet eine Nachricht an alle Clients 
// Send's a Message to all clients 
int sendToAllClients(char* msg) 
{ 
   int rc,i; 
   for(i=0;i<MAX_CLIENTS;i++) 
   { 
      if(!clients[i].used) 
         continue; 
      rc=send(clients[i].socket,msg,strlen(msg),0); 
      if(rc==SOCKET_ERROR) 
      { 
         printf("Error: Sending to Client %d failed: %d\n",i,WSAGetLastError()); 
      } 
   } 
   return 0; 
} 

// Startet Winsock und gibt einige Infos zur Version aus 
// Starts winsock and dumps some infos about the version 
int startWinsock() 
{ 
   int rc; 
   WSADATA wsaData; 
   rc=WSAStartup(MAKEWORD(2,0),&wsaData); 
   
   if(rc==SOCKET_ERROR) { 
      printf("Error, exiting!\n"); 
      return rc; 
   }   
   printf("System Status: %s\n",wsaData.szSystemStatus); 
   return 0; 
} 

int main(int argc, char* argv[]) 
{ 
    if(argc > 1)
    {
        //Startet auf dem übergebenem PORT
        int PORT = atoi(argv[1]);
    
       // SOCKET welcher neue Verbindungen annimmt 
       // SOCKET which accepts new connections 
       SOCKET acceptSocket; 
       SOCKADDR_IN addr; 
       int rc,addrsize=sizeof(SOCKADDR_IN); 
       unsigned int i,j; 
       // fd_set 
       fd_set fdSetRead; 
       // timout für select() / timeout for select() 
       timeval selectTimeout; 
       // temporär benutz für neue verbindungen 
       // temporary used for new connections 
       Connection newConnection; 
       // buffer 
       char buf[1024]; 

       // clients array leeren / clear clients array 
       memset(clients,0x0,sizeof(Connection)*MAX_CLIENTS); 

       // start winsock 
       rc=startWinsock(); 
       if(rc==SOCKET_ERROR) 
          return 1; 

       // socket erstellen / create socket 
       acceptSocket=socket(PF_INET,SOCK_STREAM,0); 
       if(acceptSocket==INVALID_SOCKET) 
       { 
          printf("Error, cannot create socket: %d\n",WSAGetLastError()); 
          return 1; 
       } 

       // sockt an port 1234 binden / bind socket to port 1234 
       memset(&addr,0,sizeof(SOCKADDR_IN)); 
       addr.sin_family=AF_INET; 
       addr.sin_port=htons(PORT); 
       addr.sin_addr.s_addr=INADDR_ANY; 
       rc=bind(acceptSocket,(SOCKADDR*)&addr,sizeof(SOCKADDR_IN)); 
        if(rc==SOCKET_ERROR) 
        { 
          printf("Error, bind() failed: %d\n",WSAGetLastError()); 
          return 1; 
       } 

       // auf verbindungen warten / listen for connections 
       rc=listen(acceptSocket,10); 
       if(rc==SOCKET_ERROR) 
       { 
          printf("Error,listen() failed: %d\n",WSAGetLastError()); 
          return 1; 
       } 


       // The parameter readfds identifies the sockets that are to be checked for readability. 
       // If the socket is currently in the listen state, it will be marked as readable if an 
       // incoming connection request has been received such that an accept is guaranteed to 
       // complete without blocking. 
        
       while(1) 
       { 

          // fd_set leeren / clear fd_set 
          FD_ZERO(&fdSetRead); 
           
          // den socket welcher verbindungen annimmt hinzufügen 
          // add the SOCKET which accepts new connections 
           
          FD_SET(acceptSocket,&fdSetRead); 
          // alle clients hinzufügen 
          // add all clients 
          for(i=0;i<MAX_CLIENTS;i++) 
          { 
             if(clients[i].used) 
                FD_SET(clients[i].socket,&fdSetRead); 
          } 

          // warten bis irgend ein socket bereit ist, wenn timout NULL ist kehrt select() 
          // erst zurück wenn ein socket bereit ist, select() blockt also in diesem falle 
          // wait until any socket is ready (timeout = NULL, block until one socket is ready) 
          rc=select(0,&fdSetRead,NULL,NULL,NULL); 

          // abbrechen bei einem fehler 
          // break on error 
          if(rc<1) 
             break; 

          printf("select() returned %d ready sockets\n",rc); 
           
          for(i=0;i<fdSetRead.fd_count;i++) 
          { 
           
             // acceptSocket ? 
             if(fdSetRead.fd_array[i]==acceptSocket) 
             { 
                // verbindung annehmen / accept new connection 
                newConnection.socket=accept(acceptSocket,(SOCKADDR*)&newConnection.addr,&addrsize); 
                rc=getFreeClientSlot(); 
                if(rc==-1) 
                { 
                   printf("Cannot accept new clients\n"); 
                   continue; 
                } 
                // zu den clients hinzufügen 
                // add to clients 
                clients[rc]=newConnection; 
                clients[rc].used=true; 
                printf("New Client accepted from %s\n",inet_ntoa(newConnection.addr.sin_addr)); 
                continue; 
             } 
              
             // ein client ? 
             // a client ? 
             for(j=0;j<MAX_CLIENTS;j++) 
             { 
                if(!clients[j].used) 
                   continue; 

                if(clients[j].socket==fdSetRead.fd_array[i]) 
                { 
                   rc=recv(clients[j].socket,buf,1023,0); 
                   buf[rc]='\0'; 
                   // rc==0 => client hat die verbindung beendet 
                   // rc==0 => client closed connection 
                   if(rc==0) { 
                      printf("Client %d (%s): closed connection\n",j,inet_ntoa(clients[j].addr.sin_addr)); 
                      closesocket(clients[j].socket); 
                      clients[j].erase(); 
                      continue; 
                   // rc==SOCKET_ERROR => fehler, verbindung beenden! 
                   // rc==SOCKET_ERROR => error, close connection! 
                   } 
                   else if(rc==SOCKET_ERROR) 
                   { 
                      printf("Client %d (%s): Error %d\n",j,inet_ntoa(clients[j].addr.sin_addr),WSAGetLastError()); 
                        printf("Client %d (%s): Server aborts connection\n",j,inet_ntoa(clients[j].addr.sin_addr)); 
                      closesocket(clients[j].socket); 
                      clients[j].erase(); 
                      continue; 
                   // daten empfangen und an alle clients senden 
                   // receive data and send it to all clients 
                   } 
                   else 
                   { 
                      printf("Client %d (%s): received '%s' \n",j,inet_ntoa(clients[j].addr.sin_addr),buf); 
                      //sendToAllClients(buf); 
                      
                      string command = buf;
                      int pos = command.find(' ');   
                      int lang = command.length();
                        string task = command.substr(0,pos);
                      string para = command.substr(pos+1,lang);
                

                      if(task == "close")
                      {
                          //rc=send(clients[i].socket,msg,strlen(msg),0); 
                          rc=send(clients[j].socket,task.c_str(),strlen(task.c_str()),0); 
                            closesocket(acceptSocket); 
                            WSACleanup(); 
                      }    
                      else
                      {
                          string str;
                          str += '"';
                          str += reg.xmd_GetValue("bin");
                          str += "\\";
                          str += task;
                          str += '"';
                          str += " ";
                          str += para;

                          cout << "exec:" << str << endl;
                          system(str.c_str());  //  <<--------- Hier werden die Befehle ausgeführt.
                      }
                      
                   } 
                } 
             } 
          }
          cout << "-----------------------------------" << endl;
       }//Ende while

       // aufräumen 
       // cleanup 
       closesocket(acceptSocket); 
       WSACleanup();        
    }
    else 
    {
        cout << "server PORT" << endl;
    }
        return 0;
   
}
 
Dazu solltest Du das Dienstprogramm nicht mit 'system' sondern mit 'CreateProcess' starten. Damit hast Du die Möglichkeit, die Ausgabe mittels einer Pipe umzuleiten. Diese verhalten sich dann wie Dateien, Du kannst also aus ihnen lesen bzw. in sie schreiben. Diese gelesenen Daten kannst Du dann wieder an den Client schicken.
 
Vielen Dank für den Tipp

Hab auf die schnelle im Server statt system() jetzt CreateProcess() eingefügt:
//Befehle einlesen...

STARTUPINFO siStartupInfo;
PROCESS_INFORMATION piProcessInfo;


CreateProcess(task.c_str(), cvt.StringToChar(para), 0, 0, false, 0, 0, 0, &siStartupInfo, &piProcessInfo);

Doch wie mache ich jetzt weiter?
Wie oder woher bekomme ich jetzt die Daten
Wie sende ich die Daten mit send()?
 
Hab ein Code gefunden mit CreateProcess() + Pipes():
Code:
CString ExecuteExternalFile(CString csExeName, CString csArguments)
{
  CString csExecute;
  csExecute=csExeName + " " + csArguments;
  
  SECURITY_ATTRIBUTES secattr; 
  ZeroMemory(&secattr,sizeof(secattr));
  secattr.nLength = sizeof(secattr);
  secattr.bInheritHandle = TRUE;

  HANDLE rPipe, wPipe;

  //Create pipes to write and read data
  CreatePipe(&rPipe,&wPipe,&secattr,0);
  //
  STARTUPINFO sInfo; 
  ZeroMemory(&sInfo,sizeof(sInfo));
  PROCESS_INFORMATION pInfo; 
  ZeroMemory(&pInfo,sizeof(pInfo));
  sInfo.cb=sizeof(sInfo);
  sInfo.dwFlags=STARTF_USESTDHANDLES;
  sInfo.hStdInput=NULL; 
  sInfo.hStdOutput=wPipe; 
  sInfo.hStdError=wPipe;
  char command[1024]; strcpy(command,  
          csExecute.GetBuffer(csExecute.GetLength()));

  //Create the process here.
  CreateProcess(0 command,0,0,TRUE,
          NORMAL_PRIORITY_CLASS|CREATE_NO_WINDOW,0,0,&sInfo,&pInfo);
  CloseHandle(wPipe);

  //now read the output pipe here.
  char buf[100];
  DWORD reDword; 
  CString m_csOutput,csTemp;
  BOOL res;
  do
  {
                  res=::ReadFile(rPipe,buf,100,&reDword,0);
                  csTemp=buf;
                  m_csOutput+=csTemp.Left(reDword);
  }while(res);
  return m_csOutput;
}

Ist der Code das Richtige für die Lösung meines Problems ?
 
Hier habe ich eion Beispiel, wie ich das mal gemacht habe. Es gibt da bestimmt noch elegentere Lösungen (z.B. mit Exceptions statt der goto's. Das ist tatsächlich der einzige Fall, wo ich goto überhaupt verwendet habe.), aber es zeigt die grundsätzliche Vorgehensweise mit CreateProcess und Pipes.

Code:
BOOL CProcessingClass::ProcessCommandLine(char * pcCommandLine)
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    SECURITY_ATTRIBUTES sa;
    HANDLE hReadPipe, hWritePipe;
    DWORD dwWaitResult = WAIT_TIMEOUT, dwBytesRead, dwExitCode, dwSizeLow, dwSizeHigh, dwError;
    char cReadLine[MAX_LINE_LENGTH];
    BOOL bDoRead = TRUE, bOK = TRUE;
    MSG AppMsg;

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


    //Pipes erzeugen
    sa.nLength=sizeof(sa);
    sa.bInheritHandle=TRUE;
    sa.lpSecurityDescriptor=NULL;
    bOK = CreatePipe(&hReadPipe, &hWritePipe, &sa, 1048576);
    if(!bOK)
    {
        //FEHLER
        dwError = GetLastError();
        theApp.m_Log.LogErrorMessage(dwError, pCommand);
        bOK = FALSE;
        goto PROCESS_END_NOPIPE;
    }

    //Pipes eintragen
    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
    si.hStdOutput = hWritePipe;                        //Schreib-Ende der Pipe an Prozess übergeben
    si.hStdError = hWritePipe;                        //Schreib-Ende der Pipe an Prozess übergeben
    si.wShowWindow = SW_SHOWMINNOACTIVE;

    //Prozess starten
    bOK = CreateProcess(NULL,
                        pcCommandLine,
                        NULL,
                        NULL,
                        TRUE,
                        NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
                        lpEnvironment,
                        pCommand->m_cstrExecuteDir,
                        &si,
                        &pi);

    if(!bOK)
    {
        //FEHLER
        dwError = GetLastError();
        goto PROCESS_END_NOPROC;
    }

    //Auf Ende warten und Messages lesen
    while(dwWaitResult != WAIT_OBJECT_0)
    {
        dwWaitResult = WaitForSingleObject(pi.hProcess, 10);
        while(dwSizeLow = GetFileSize(hReadPipe, &dwSizeHigh))
        {
            ZeroMemory(cReadLine, MAX_LINE_LENGTH);
            //Aus dem Leseende der Pipe die Progzessausgaben lesen
            if(bDoRead = ReadFile(hReadPipe, cReadLine, MAX_LINE_LENGTH - 1, &dwBytesRead, NULL))
            {
                if(dwBytesRead)
                {
                    //hier Programmausgabe verarbeiten (z.B. send)
                }
            }
            else
            {
                bOK = FALSE;
                dwError = GetLastError();
            }
        }
        //Applikations-Messagequeue verarbeiten
        if(PeekMessage(&AppMsg, 0, 0, 0, PM_NOREMOVE))
        {
            GetMessage(&AppMsg, 0, 0, 0);
            TranslateMessage(&AppMsg);
            DispatchMessage(&AppMsg);
        }
    }

    if(bOK)
    {
        bOK = GetExitCodeProcess(pi.hProcess, &dwExitCode);
        if(bOK)
        {
            if(dwExitCode != 0)
            {
                //Prozess kehrt mit Ergebnis != 0 zurück
                bOK = FALSE;
            }
        }
        else
        {
            //FEHLER im GetExitCodeProcess
            dwError = GetLastError();
            bOK = FALSE;
        }
    }

    //Close handles
    m_hRunningProcess = NULL;
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

PROCESS_END_NOPROC:
    CloseHandle(hWritePipe);
    CloseHandle(hReadPipe);

PROCESS_END_NOPIPE:
    return bOK;
}
 
Vielen Dank Jokey2,

ist das ein MFC Code, denn bei mir werden 9 Fehler gezeigt mit nicht "deklarierten Bezeichner". Haste du ne Klasse geschrieben
 
Ja, das ist Code aus einer MFC-Applikation. Offensichtlich habe ich ein paar Sachen vergessen zu löschen ;-).
Das Error-Logging (Zeile 25 im Listing) mußt Du rausschmeißen.
Das Message-Handling kannst Du evtl, auch weglassen, obwohl das kein MFC ist.
Poste doch mal, was sonst nicht gefunden wird.
 
Habe jetzt 5 Fehler:

error C2065: 'MAX_LINE_LENGTH': nichtdeklarierter Bezeichner
error C2065: 'lpEnvironment': nichtdeklarierter Bezeichner
error C2065: 'pCommand': nichtdeklarierter Bezeichner
error C2227: Links von "->m_cstrExecuteDir" muss sich ein Zeiger auf Klassen-/Struktur-/Union-/generischen Typ befinden.
error C2065: 'm_hRunningProcess': nichtdeklarierter Bezeichner
 
'MAX_LINE_LENGTH' mußt du definieren, das bezeichnet nur die Größe des Lesepuffers (bei mir 1024 Bytes)
Für 'lpEnvironment' und 'pCommand->m_cstrExecuteDir' kannst Du im CreateProcess-Aufruf NULL einsetzen.
die Zeile mit 'm_hRunningProcess' kannst Du löschen

Sieht dann so aus (Ich hoffe, ich habe nicht noch was übersehen):
Code:
#define MAX_LINE_LENGTH 1024

BOOL CProcessingClass::ProcessCommandLine(char * pcCommandLine)
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    SECURITY_ATTRIBUTES sa;
    HANDLE hReadPipe, hWritePipe;
    DWORD dwWaitResult = WAIT_TIMEOUT, dwBytesRead, dwExitCode, dwSizeLow, dwSizeHigh, dwError;
    char cReadLine[MAX_LINE_LENGTH];
    BOOL bDoRead = TRUE, bOK = TRUE;
    MSG AppMsg;

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


    //Pipes erzeugen
    sa.nLength=sizeof(sa);
    sa.bInheritHandle=TRUE;
    sa.lpSecurityDescriptor=NULL;
    bOK = CreatePipe(&hReadPipe, &hWritePipe, &sa, 1048576);
    if(!bOK)
    {
        //FEHLER
        dwError = GetLastError();
        bOK = FALSE;
        goto PROCESS_END_NOPIPE;
    }

    //Pipes eintragen
    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
    si.hStdOutput = hWritePipe;                        //Schreib-Ende der Pipe an Prozess übergeben
    si.hStdError = hWritePipe;                        //Schreib-Ende der Pipe an Prozess übergeben
    si.wShowWindow = SW_SHOWMINNOACTIVE;

    //Prozess starten
    bOK = CreateProcess(NULL,
                        pcCommandLine,
                        NULL,
                        NULL,
                        TRUE,
                        NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
                        NULL,
                        NULL,
                        &si,
                        &pi);

    if(!bOK)
    {
        //FEHLER
        dwError = GetLastError();
        goto PROCESS_END_NOPROC;
    }

    //Auf Ende warten und Messages lesen
    while(dwWaitResult != WAIT_OBJECT_0)
    {
        dwWaitResult = WaitForSingleObject(pi.hProcess, 10);
        while(dwSizeLow = GetFileSize(hReadPipe, &dwSizeHigh))
        {
            ZeroMemory(cReadLine, MAX_LINE_LENGTH);
            //Aus dem Leseende der Pipe die Progzessausgaben lesen
            if(bDoRead = ReadFile(hReadPipe, cReadLine, MAX_LINE_LENGTH - 1, &dwBytesRead, NULL))
            {
                if(dwBytesRead)
                {
                    //hier Programmausgabe verarbeiten (z.B. send)
                }
            }
            else
            {
                bOK = FALSE;
                dwError = GetLastError();
            }
        }
        //Applikations-Messagequeue verarbeiten
        if(PeekMessage(&AppMsg, 0, 0, 0, PM_NOREMOVE))
        {
            GetMessage(&AppMsg, 0, 0, 0);
            TranslateMessage(&AppMsg);
            DispatchMessage(&AppMsg);
        }
    }

    if(bOK)
    {
        bOK = GetExitCodeProcess(pi.hProcess, &dwExitCode);
        if(bOK)
        {
            if(dwExitCode != 0)
            {
                //Prozess kehrt mit Ergebnis != 0 zurück
                bOK = FALSE;
            }
        }
        else
        {
            //FEHLER im GetExitCodeProcess
            dwError = GetLastError();
            bOK = FALSE;
        }
    }

    //Close handles
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

PROCESS_END_NOPROC:
    CloseHandle(hWritePipe);
    CloseHandle(hReadPipe);

PROCESS_END_NOPIPE:
    return bOK;
}
 
Vielen Dank.

So funktionierts:
Code:
#include <windows.h>
#include <iostream>

using namespace std;

#define MAX_LINE_LENGTH 1024

#pragma comment(lib,"user32.lib")

BOOL ProcessCommandLine(char * pcCommandLine)
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    SECURITY_ATTRIBUTES sa;
    HANDLE hReadPipe, hWritePipe;
    DWORD dwWaitResult = WAIT_TIMEOUT, dwBytesRead, dwExitCode, dwSizeLow, dwSizeHigh, dwError;
    char cReadLine[MAX_LINE_LENGTH];
    BOOL bDoRead = TRUE, bOK = TRUE;
    MSG AppMsg;

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


    //Pipes erzeugen
    sa.nLength=sizeof(sa);
    sa.bInheritHandle=TRUE;
    sa.lpSecurityDescriptor=NULL;
    bOK = CreatePipe(&hReadPipe, &hWritePipe, &sa, 1048576);
    if(!bOK)
    {
        //FEHLER
        dwError = GetLastError();
        bOK = FALSE;
        goto PROCESS_END_NOPIPE;
    }

    //Pipes eintragen
    si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
    si.hStdOutput = hWritePipe;                        //Schreib-Ende der Pipe an Prozess übergeben
    si.hStdError = hWritePipe;                        //Schreib-Ende der Pipe an Prozess übergeben
    si.wShowWindow = SW_SHOWMINNOACTIVE;

    //Prozess starten
    bOK = CreateProcess(NULL,
                        pcCommandLine,
                        NULL,
                        NULL,
                        TRUE,
                        NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,
                        NULL,
                        NULL,
                        &si,
                        &pi);

    if(!bOK)
    {
        //FEHLER
        dwError = GetLastError();
        goto PROCESS_END_NOPROC;
    }

    //Auf Ende warten und Messages lesen
    while(dwWaitResult != WAIT_OBJECT_0)
    {
        dwWaitResult = WaitForSingleObject(pi.hProcess, 10);
        while(dwSizeLow = GetFileSize(hReadPipe, &dwSizeHigh))
        {
            ZeroMemory(cReadLine, MAX_LINE_LENGTH);
            //Aus dem Leseende der Pipe die Progzessausgaben lesen
            if(bDoRead = ReadFile(hReadPipe, cReadLine, MAX_LINE_LENGTH - 1, &dwBytesRead, NULL))
            {
                if(dwBytesRead)
                {
                    //hier Programmausgabe verarbeiten (z.B. send)
                }
            }
            else
            {
                bOK = FALSE;
                dwError = GetLastError();
            }
        }
        //Applikations-Messagequeue verarbeiten
        if(PeekMessage(&AppMsg, 0, 0, 0, PM_NOREMOVE))
        {
            GetMessage(&AppMsg, 0, 0, 0);
            TranslateMessage(&AppMsg);
            DispatchMessage(&AppMsg);
        }
    }

    if(bOK)
    {
        bOK = GetExitCodeProcess(pi.hProcess, &dwExitCode);
        if(bOK)
        {
            if(dwExitCode != 0)
            {
                //Prozess kehrt mit Ergebnis != 0 zurück
                bOK = FALSE;
            }
        }
        else
        {
            //FEHLER im GetExitCodeProcess
            dwError = GetLastError();
            bOK = FALSE;
        }
    }

    //Close handles
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

PROCESS_END_NOPROC:
    CloseHandle(hWritePipe);
    CloseHandle(hReadPipe);

PROCESS_END_NOPIPE:
    return bOK;
}

int main(int argc, char* argv[])
{
    if(argc > 1)
    cout << ProcessCommandLine(argv[1]) << endl;

    return 0;
}

Kannst du mir kurz erklären was hier richtig passiert.
Wie schon gesagt möchte ich mit dem Client zum Server eine verbindung aufbauen und dann befehle an den server senden der diese dann ausführt. Der Server sollte dann die Ausgabe des gestarteten Prozesses zum Client übers Netzwerk umleiten. Also der Code oben wär dann wahrscheinlich im Server und die Ausgabe wird von CreateProcess abgefangen und umgeleitet wenn ich das richtig verstanden habe. Doch wieso sehe ich denn gestarteten externen Prozess nicht im gleich Konsolenfenster'?
 
Zurück