2011-12-17 50 views
2

た処理を実行し、文字列として出力を返すためには、内からのVisual Studioで2010のCreateProcessとCreatePipe VC++

をC++/CLRのフォームアプリケーション私のWindowsフォームアプリケーション私は子プロセス(コンソールアプリケーション)を実行し、Windowsフォームアプリケーション内でstd::stringstd::wstring、またはSystem::String^のように出力を返します。さらに、私は、新しく作成された子プロセスにウィンドウを生成させたくありません。

コンソールアプリケーションは自分で作成したものですから、そのソースも制御できます。

私は次の例を見てきましたが、私は私が何をしようとしています何を達成するためにコードを変更する方法を理解していない:

MSDNコードは2つのコンソールアプリケーションとして記述されており、一方は他方を呼び出すように見えます。コードが私に混乱しています。私はC++で約4ヶ月しか働いていないので、まだすべてを理解していません。それは、私がする必要のないテキストファイルを参照するように見えます。

MSDNの200行以上のコードまたはkguiの300行以上のコードより簡単な方法がありますか?

回答hereは役に立ちましたが、単純すぎます。私は、基本的なソースの例(複雑なコードの何百もの行を必要としないものが望ましい)を見たいと思っていました。私はMFCコードを使用していただろうが、私はそれを私の目的に適合させるのが難しかった(私はMFCを使用していない)。続き

は、コードプロジェクトからのコードの私の適応である:私は私のWindowsフォームアプリケーション内からこれを使って試してみました

string ExecuteExternalFile(string csExeName, string csArguments) 
{ 
    string 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; 

    //Create the process here. 

    CreateProcess(0,(LPWSTR)csExecute.c_str(),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; 
    string m_csOutput,csTemp; 
    BOOL res; 
    do 
    { 
        res=::ReadFile(rPipe,buf,100,&reDword,0); 
        csTemp=buf; 
        m_csOutput+=csTemp; 
    }while(res); 
    return m_csOutput; 
} 

、それはOKコンパイルし、エラーが発生することはありませんが、それはdoesnのどちらもうまくいくようです。なぜ私は考えていない。

これは私が上記のコードを実行する方法されています

std::string ping = ExecuteExternalFile("ping.exe", "127.0.0.1"); 

をその後の実行で、出力として非常に奇妙な3つの文字を与える最初の実行上の点を除いて、何かをするようには見えませんでした、何もない。

+1

あなたはそれを難し​​いやり方にしていますが、その理由はわかりません。代わりにProcessStartInfo :: RedirectStandardOutputプロパティを使用してください。 –

+0

"代わりにProcessStartInfo :: RedirectStandardOutputプロパティを使用してください。"あなたはもっと具体的に何を意味するのかを教えてください。たぶん、例へのリンクを提供しますか? – Jason

+1

Googleのクエリにコピー/パスタ。最初のヒットを取る、それは良いものです。 –

答えて

2

私が探していたまさに行うコードのこの明確でシンプルな作品に私を得たleadためのハンスアンパッサンに感謝ために。

/// this namespace call is necessary for the rest of the code to work 
using namespace System::Diagnostics; 
using namespace System::Text;/// added for encoding 

Process^ myprocess = gcnew Process; 
Encoding^ Encoding;/// added for encoding 
Encoding->GetEncoding(GetOEMCP());/// added for encoding 

myprocess->StartInfo->FileName = "ping.exe"; 
myprocess->StartInfo->Arguments = "127.0.0.1"; 
myprocess->StartInfo->UseShellExecute = false; 

/// added the next line to keep a new window from opening 
myprocess->StartInfo->CreateNoWindow = true; 

myprocess->StartInfo->RedirectStandardOutput = true; 
myprocess->StartInfo->StandardOutputEncoding = Encoding;/// added for encoding 
myprocess->Start(); 

String^ output = gcnew String(myprocess->StandardOutput->ReadToEnd()); 

myprocess->WaitForExit(); 

/// OutputBox is the name of a Windows Forms text box in my app. 
OutputBox->Text = output; 

EDIT:エンコード情報を追加しました。上記のコードを参照してください。

+0

あなたはそれを難し​​い方法でやっていますが、その理由はわかりません。 System :: Net :: NetworkInformation :: Pingクラスを使用してください:) –

+0

@HansPassant - 実際には、pingはこのコードをテストするための単なる例でした。それは何かがあったかもしれない。助けてくれてありがとう。上記は本当に正確に必要なものです。 – Jason

+0

@Jason私はそれが前のHans'esのコメントへの言及の形で冗談だと信じています。それでも、このコードにデコードを追加する必要があります(コンソールアプリケーションでは、非ユニコードGUIアプリケーション用に設定されたCP_ACPとは異なる、CP_OEMCPコードページが使用されます)。 .NETはreadyオプションを提供していないので、 'kernel32.dll'から' GetOEMCP() '関数をインポートして、これを行う必要があります:' myprocess-> StandardOutputEncoding = Encoding-> GetEncoding(GetOEMCP()) ; '。 – GSerg

3

::ReadFile()機能を正しく使用していません。ここではそれについて

読むには:http://msdn.microsoft.com/en-us/library/ms891445.aspx

基本的には、機能がこれまでにTRUEを返していない場合は、エラーで失敗したく、そしてあなたはそれがゼロreDwordを生み出すまでループ維持したいです。

buf[reDword] = '\0';bufは、それを行う前に101文字長であることを確認してください)、::ReadFile()はあなたのためにデータをゼロ終了しません。)

EDIT: 私はいくつかのサンプルコードを提供するように頼まれたので、ここではそれは私が実際にそれが動作することを確認するために、コンパイルの手間を経ていないのに、ですので、構文エラーに注意してください、と一般的にのみ、それが行われるべき方向へのラフポインタとしてそれを考慮してください。

#define BUFFER_SIZE 100 
string csoutput; 
for(;;) 
{ 
    char buf[BUFFER_SIZE+1]; 
    DWORD redword; 
    if(!::ReadFile(rPipe,buf,BUFFER_SIZE,&redword,0)) 
    { 
     DWORD error = ::GetLastError(); 
     //throw new Exception("Error " + error); //or something similar 
    } 
    if(redword == 0) 
     break; 
    buf[redword] = '\0'; 
    string cstemp = buf; 
    csoutput += cstemp; 
} 
return csoutput; 
+0

こんにちはマイク。迅速な対応をありがとう。上記のコードに記述したコード例を表示することは可能ですか? – Jason

+0

@Jason私はいくつかのコード例を提供するために答えを編集しました。私は、 'ReadFile()'の誤った使用が必ずあなたの問題だと言っているわけではありません。もしそうでなければ、それを言いなさい、そして、私たちはそれがうまくいかないかもしれない他の理由を理解しようとすることができます。 –

+0

このコードを提供いただき、ありがとうございます。残念ながら、私はまだその関数から出力文字列を取得しません。ハンスの提案は私を解決に導いてくれました。これは期限が切れると投稿します。 – Jason