11

_popenを使用して、コマンドを実行し、出力を収集するプロセスを開始しています

これは私のc++コードです:

bool exec(string &cmd, string &result)
{
   result = "";

   FILE* pipe = _popen(cmd.c_str(), "rt");
   if (!pipe)
      return(false);

   char buffer[128];
   while(!feof(pipe))
   {
        if(fgets(buffer, 128, pipe) != NULL)
               result += buffer;
   }
   _pclose(pipe);
   return(true);
}

コンソールウィンドウを開かずにこれを行う方法はありますか(現在_popenステートメントで行っているように)?

4

3 に答える 3

4

Windowsでは、STARTF_USESSHOWWINDOWを含むdwFlagsを持つSTARTUPINFO構造体を使用してCreateProcessを実行します。次に、STARTUPINFO.dwFlagsをSW_HIDEに設定すると、トリガーされたときにコンソールウィンドウが非表示になります。サンプルコード(フォーマットが不十分で、C ++とWinAPIが混在している可能性があります):

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

using std::cout;
using std::endl;

void printError(DWORD);

int main()
{
  STARTUPINFOA si = {0};
  PROCESS_INFORMATION pi = { 0 };

  si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
  si.wShowWindow = SW_HIDE;
  BOOL result = ::CreateProcessA("c:/windows/system32/notepad.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
  if(result == 0) {
      DWORD error = ::GetLastError();
      printError(error);
      std::string dummy;
      std::getline(std::cin, dummy);
      return error;
  }

  LPDWORD retval = new DWORD[1];
  ::GetExitCodeProcess(pi.hProcess, retval);
  cout << "Retval: " << retval[0] << endl;
  delete[] retval;

  cout << "Press enter to continue..." << endl;
  std::string dummy;
  std::getline(std::cin, dummy);

  return 0;
}

void printError(DWORD error) {
    LPTSTR lpMsgBuf = nullptr;
     FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        error,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR) &lpMsgBuf,
        0, NULL );
     cout << reinterpret_cast<char*>(lpMsgBuf) << endl;
     LocalFree(lpMsgBuf);
}
于 2012-04-04T23:43:54.060 に答える
3

私の知る限り、1はできませんコンソールアプリケーション(cmd.exe、指定されたコマンドを実行します)を起動しており、Windowsはコンソールアプリケーションを起動すると常にコンソールウィンドウを作成します。


  1. ただし、プロセスの開始後にウィンドウを非表示にすることCreateProcessも、適切なフラグを;に渡せば非表示にすることもできます。問題は、これらのフラグを渡さないことです。そのため、パイプを作成する_popen代わりにWin32APIを使用する必要があります。_popen
于 2012-04-04T23:32:53.790 に答える
0

【最終編集】

同様のSOの質問は、上記のすべてをマージし、コンソールなしで出力C++popenコマンドを取得します

[再編集]

えーと。申し訳ありませんが、スポーンプロセスに興奮しました。私はあなたのqを読み直しました。余分なウィンドウは別として、実際にはプロセスのstdout/stderrを取得しようとしています。その目的のためにそれを追加したいのですが、私の提案はすべて悲しいことに無関係です。ただし、参考のためにここに残しておきます。

[編集]

特別な理由はありませんが(「open」がWindowsとMacの両方で機能することを除いて)、CreateProcessではなくShellExecuteをスポーンプロセスに使用します。これについては後で調べますが、これが私のStartProcess関数です。

非表示または最小化でも同じ結果が得られるようです。cmdウィンドウは作成されますが、最小化されており、デスクトップにポップアップ表示されることはありません。これが主な目標である可能性があります。

#if defined(PLATFORM_WIN32)
#include <Windows.h>
#include <shellapi.h>
#elif defined(PLATFORM_OSX)
#include <sys/param.h>
#endif
namespace LGSysUtils
{
// -----------------------------------------------------------------------
// pWindow      : {Optional} - can be NULL
// pOperation   : "edit", "explore", "find", "open", "print"
// pFile        : url, local file to execute
// pParameters  : {Optional} - can be NULL otherwise a string of args to pass to pFile
// pDirectory   : {Optional} - set cwd for process
// type         : kProcessWinNormal, kProcessWinMinimized, kProcessWinMaximized, kProcessHidden
//
bool StartProcess(void* pWindow, const char* pOperation, const char* pFile, const char* pParameters, const char* pDirectory, LGSysUtils::eProcessWin type)
{
    bool rc = false;
#if defined(PLATFORM_WIN32)

    int showCmd;
    switch(type)
    {
    case kProcessWinMaximized:
        showCmd = SW_SHOWMAXIMIZED;
        break;

    case kProcessWinMinimized:
        showCmd = SW_SHOWMINIMIZED;
        break;

    case kProcessHidden:
        showCmd = SW_HIDE;
        break;

    case kProcessWinNormal:
    default:
        showCmd = SW_NORMAL;
    }

    int shellRC = (int)ShellExecute(reinterpret_cast<HWND>(pWindow), pOperation,pFile,pParameters,pDirectory,showCmd);
    //Returns a value greater than 32 if successful, or an error value that is less than or equal to 32 otherwise.
    if( shellRC > 32 )
    {
        rc = true;
    }

#elif defined(PLATFORM_OSX)
    char cmd[1024];
    sprintf(cmd, "%s %s", pOperation, pFile);
    int sysrc = system( cmd );
    dbPrintf("sysrc = %d", sysrc);
    rc = true;
#endif
    return rc;
}

}

[そして前述の]

起動するアプリケーションのソースコードを管理している場合は、これをmain.cpp(または名前を付けたもの)の先頭に追加してみてください。

// make this process windowless/aka no console window
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )

これらのオプションをリンカーに直接フィードすることもできます。上記は、さまざまなビルド構成で簡単に操作できます。

于 2012-04-05T00:39:52.650 に答える