_popen in WinMain ?



  • Hallo!
    Ich habe eine Frage zu der Funktion

    FILE *_popen(
       const char *command,
       const char *mode 
    );
    

    Und zwar warum das Folgende Programm nicht funktioniert:

    //---------------------------------------------------------------------------
    
    #include <windows.h>
    #include <stdio.h>
    WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
            FILE* handle = _popen("dir", "rt");
            return 0;
    }
    //---------------------------------------------------------------------------
    

    in einem normalem Konsolen-Programm (main()) läuft das aber. Warum?



  • das ist aber dokumentiert:

    If used in a Windows program, the _popen function returns an invalid file pointer that causes the program to stop responding indefinitely. _popen works properly in a console application. To create a Windows application that redirects input and output, see Creating a Child Process with Redirected Input and Output in the Platform SDK.



  • Dieser Thread wurde von Moderator/in Phoemuex aus dem Forum C++ in das Forum WinAPI verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • och mensch, das ist aber Schade. Das Beispiel ist aber so kompliziert...

    #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");
    
    // Set the bInheritHandle flag so pipe handles are inherited. 
    
       saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
       saAttr.bInheritHandle = TRUE; 
       saAttr.lpSecurityDescriptor = NULL; 
    
    // Create a pipe for the child process's STDOUT. 
    
       if ( ! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0) ) 
          ErrorExit(TEXT("StdoutRd CreatePipe")); 
    
    // Ensure the read handle to the pipe for STDOUT is not inherited.
    
       if ( ! SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) )
          ErrorExit(TEXT("Stdout SetHandleInformation")); 
    
    // Create a pipe for the child process's STDIN. 
    
       if (! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)) 
          ErrorExit(TEXT("Stdin CreatePipe")); 
    
    // Ensure the write handle to the pipe for STDIN is not inherited. 
    
       if ( ! SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) )
          ErrorExit(TEXT("Stdin SetHandleInformation")); 
    
    // Create the child process. 
    
       CreateChildProcess();
    
    // Get a handle to an input file for the parent. 
    // This example assumes a plain text file and uses string output to verify data flow. 
    
       if (argc == 1) 
          ErrorExit(TEXT("Please specify an input file.\n")); 
    
       g_hInputFile = CreateFile(
           argv[1], 
           GENERIC_READ, 
           0, 
           NULL, 
           OPEN_EXISTING, 
           FILE_ATTRIBUTE_READONLY, 
           NULL); 
    
       if ( g_hInputFile == INVALID_HANDLE_VALUE ) 
          ErrorExit(TEXT("CreateFile")); 
    
    // Write to the pipe that is the standard input for a child process. 
    // Data is written to the pipe's buffers, so it is not necessary to wait
    // until the child process is running before writing data.
    
       WriteToPipe(); 
       printf( "\n->Contents of %s written to child STDIN pipe.\n", argv[1]);
    
    // Read from pipe that is the standard output for child process. 
    
       printf( "\n->Contents of child process STDOUT:\n\n", argv[1]);
       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 CreateChildProcess()
    // Create a child process that uses the previously created pipes for STDIN and STDOUT.
    { 
       TCHAR szCmdline[]=TEXT("child");
       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 = g_hChildStd_OUT_Wr;
       siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
       siStartInfo.hStdInput = g_hChildStd_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 ) 
          ErrorExit(TEXT("CreateProcess"));
       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(piProcInfo.hProcess);
          CloseHandle(piProcInfo.hThread);
       }
    }
    
    void WriteToPipe(void) 
    // Read from a file and write its contents to the pipe for the child's STDIN.
    // Stop when there is no more data. 
    { 
       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; 
       } 
    
    // Close the pipe handle so the child process stops reading. 
    
       if ( ! CloseHandle(g_hChildStd_IN_Wr) ) 
          ErrorExit(TEXT("StdInWr CloseHandle")); 
    } 
    
    void ReadFromPipe(void) 
    // Read output from the child process's pipe for STDOUT
    // and write to the parent process's pipe for STDOUT. 
    // Stop when there is no more data. 
    { 
       DWORD dwRead, dwWritten; 
       CHAR chBuf[BUFSIZE]; 
       BOOL bSuccess = FALSE;
       HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    
    // Close the write end of the pipe before reading from the 
    // read end of the pipe, to control child process execution.
    // The pipe is assumed to have enough buffer space to hold the
    // data the child process has already written to it.
    
       if (!CloseHandle(g_hChildStd_OUT_Wr)) 
          ErrorExit(TEXT("StdOutWr CloseHandle")); 
    
       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) 
    // Format a readable error message, display a message box, 
    // and exit from the application.
    { 
        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);
    }
    

    kann man denn da auch einen systembefehl ausführen? wie z.B. "dir" ?



  • cmd /c dir



  • Ha, ha, ich hab einen Schreibfehler gefunden! Statt "popen in WinMain" müsste es "poppen in WinMain" heißen.



  • Das Beispiel oben. Da muss man ja als Parameter eine Text-Datei geben. Wofür das denn?
    Ich finde das voll umständlich.



  • so hier habe ich was gefuden:

    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;
    }
    

    aus http://www.codeproject.com/KB/cpp/9505Yamaha_1.aspx


Anmelden zum Antworten