お世話になっております。

作業マシン:WINDOWS Server2008 (仮想)
開発ツール:VWD2010(VB)
使用DB:SQLServer2008R2
にて、Webアプリを開発しております。
ASP.NET開発の経験はおおよそ1ヶ月半程です。

現在、Process.Startで外部exeを実行しております。
この外部実行ファイルは3分くらい掛かる処理で、
WaitForExit() で結果を待たずに
次の画面(待機用画面)に遷移しています。

処理が終了したら、待機画面から結果画面へと遷移させたいのですが、
プロセスの完了と、その結果(戻り値)を、
Process.Startをコールした画面以外で受け取る事が出来るのでしょうか。

WaitForExitを使用するならば、
素直に終了を待ち、終了後にExitCodeを取得、
Ret = Process.Start() で戻り値も取得できましたが…
WaitForExit( ) をしない場合、どのようにして取得できるのでしょうか。

http://dobon.net/vb/dotnet/process/openfile.html
こちら等、Process.Start 非同期 などのキーワードで出てくるのは
Processを実行した同画面内での待機のケースが多く、
今自分が遭遇しているケースに応用するには
どうにも自分の理解が追いつけず質問いたします。

実行する画面でプロセスIDを取得し、セッションに持たせ、
終了を判断したい画面でプロセスIDを元にチェックをする…
と言うことも考えてみましたが、プロセスIDを頼りに、
終了したプロセスの戻り値を突き止める方法も見つからず
(発想自体が間違っているかもしれません)
皆様のお力を貸して頂けないでしょうか。何卒よろしくお願いします。

このQ&Aに関連する最新のQ&A

A 回答 (2件)

案1)


Process.Startの戻り値をSessionに保持する。

→ SessionがInProcモード以外だと問題

(案2)
(sessionID, Process)の組み合わせを独自の辞書で管理する。

// (sessionID, Process)の組み合わせを保持する辞書
private static Dictionary<string, Process> dic = new Dictionary<string, Process>();

→ Processクラスを別のPageスレッドで参照していいのか? MSDNではスレッドセーフが保障されない。

(案3)
別スレッドでEXEを起動する。
(sessionID, ExitCode)の組み合わせを独自の辞書で管理する。

public static class MyProcess
{
// (sessionID, ExitCode)の組み合わせを保持する辞書
private static Dictionary<string, int> dic = new Dictionary<string, int>();

public static void Start(string sessionID, ProcessStartInfo info)
{
dic[sessionID] = int.MinValue; //待機中

//Pageスレッドと別スレッドでEXEを起動
BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += delegate {
Process p = Process.Start(info);
p.WaitForExit();
dic[sessionID] = p.ExitCode;
};
bw.RunWorkerAsync();
}

public static int? GetExitCode(string sessionID)
{
if (dic.ContainsKey(sessionID))
return dic[sessionID]; //int.MinValue:待機中, 以外:終了コード
else
return null; //未起動
}

public static void Clear(string sessionID)
{
if (dic.ContainsKey(sessionID))
dic.Remove(sessionID);
}
}

(案4)
(sessionID, ExitCode)の組み合わせをデータベースで管理する。
    • good
    • 0
この回答へのお礼

todo36様、ありがとうございます。
簡単なのは1,4
許される条件によっては2,3、でしょうか。

そもそもの考え方から外れていまして、
どつぼに嵌っていたので本当に助かりました。
おかげさまで目的の結果を受け取る事が出来ています。
ありがとうございました。

お礼日時:2012/06/29 00:26

> WaitForExit( ) をしない場合、どのようにして取得できるのでしょうか。



Profess.Startを利用する限り、これ以外の方法はないと思います。

ASP.NETの中で非同期に処理を実行するための仕組み、というものが存在しています。
この仕組を利用して、外部の処理にあたる部分をどう組み込んでいったらいいか、というように考えていったほうがいいと思います。
    • good
    • 0
この回答へのお礼

ONOS様、いつもありがとうございます。

Process.Startで実行した処理の結果をどうとるかではなく、
そもそもの呼び方から考えるべきだったのですね。
具体的な方法の例を他の回答者様からも頂き、
何とか実現できそうです。ありがとうございました。

お礼日時:2012/06/29 00:13

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qc#でコマンドプロンプトを実行する方法

コマンドプロンプト上から音楽ファイルの変換が出来るffmpegを利用して
C#プログラムを作ろうと思い、下記のサイトを参考にしてc#プログラムを作りコマンドを入力してみたのですがうまくいきません。
しかし、同じコマンドをコマンドプロンプトを手動で開いて打ち込むと成功します。

参考にしたサイト:http://dobon.net/vb/dotnet/process/standardoutput.html
入力したコマンド:"E:/ffmpeg.exe" -i "E:/a.m4a" -b:a 320k "E:/a.mp3"
 ※コマンドの-b:a 320kの表記は320kbpsのビットレートで変換するコードです。
 ※a.m4aをa.mp3に320kbpsのビットレートで変換するコマンドになります。

現状をまとめると以下のようになります。
(1)コマンドプロンプトを手動で起動して、以下のコマンドを打ち込むとうまく変換してくれる。
"E:/ffmpeg.exe" -i "E:/a.m4a" -b:a 320k "E:/a.mp3"
(2)しかしこのコマンドを下記のコードで実行すると処理が行われない。
(3)そうなると下記のコード自体に問題があるように思われるが、
下記のコードで"dir c:\"など簡単なコマンドを実行すると成功する。

ダブルクオテーション(")やスペースなどに問題があるのかと思いいろいろと試してみましたがダメでした。
どうすれば下記のコードで"E:/ffmpeg.exe" -i "E:/a.m4a" -b:a 320k "E:/a.mp3"のようなコマンドを実行出来るのでしょうか?
実行する方法、もしくは違うコードで実行する方法などを知っておられる方、ぜひご教授ください!非常に困っております。


---------------------------------------------------------------------------------------------------
■コマンドプロンプトをC#上から実行するコード
http://dobon.net/vb/dotnet/process/standardoutput.htmlのコードの丸写し
---------------------------------------------------------------------------------------------------
//Processオブジェクトを作成
System.Diagnostics.Process p = new System.Diagnostics.Process();

//ComSpec(cmd.exe)のパスを取得して、FileNameプロパティに指定
p.StartInfo.FileName = System.Environment.GetEnvironmentVariable("ComSpec");
//出力を読み取れるようにする
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardInput = false;
//ウィンドウを表示しないようにする
p.StartInfo.CreateNoWindow = true;
//コマンドラインを指定("/c"は実行後閉じるために必要)


//○成功する
p.StartInfo.Arguments = "dir c:\";
//×失敗する
p.StartInfo.Arguments = "\"E:/ffmpeg.exe\" -i \"E:/a.m4a\" -b:a 320k \"E:/a.mp3\";


//起動
p.Start();
//出力を読み取る
string results = p.StandardOutput.ReadToEnd();
//プロセス終了まで待機する
//WaitForExitはReadToEndの後である必要がある
//(親プロセス、子プロセスでブロック防止のため)
p.WaitForExit();
p.Close();

//出力された結果を表示
Console.WriteLine(results);
---------------------------------------------------------------------------------------------------

コマンドプロンプト上から音楽ファイルの変換が出来るffmpegを利用して
C#プログラムを作ろうと思い、下記のサイトを参考にしてc#プログラムを作りコマンドを入力してみたのですがうまくいきません。
しかし、同じコマンドをコマンドプロンプトを手動で開いて打ち込むと成功します。

参考にしたサイト:http://dobon.net/vb/dotnet/process/standardoutput.html
入力したコマンド:"E:/ffmpeg.exe" -i "E:/a.m4a" -b:a 320k "E:/a.mp3"
 ※コマンドの-b:a 320kの表記は320kbpsのビットレートで変換するコー...続きを読む

Aベストアンサー

>うまくいきません。

「なにが」「どう」「いまくいかない」んでしょうか?

プロセス起動した後に無反応になる?
プロセス終了した後に表示されるべきメッセージが表示されない?
プロセス起動できない?
起動したffmpeg.exeが終了しても戻ってこない?

参考ページではcmd.exeに/cオプションを指定しているようですが、
変更されたソースでは指定していないようで…。
その場合、
p.WaitForExit();
でちゃんと戻ってこれるんですかね?
# 起動したcmd.exe自体は終了していないはずですが…
# /Cも/Kも無かった場合ってどういう動作するんですかね?(Windows7 Pro 64Bitでcmd dirとしたら無視されてしまいましたが)

cmd.exe経由でなくても、必要条件満たせばffmpeg.exeの起動は可能と思いますよ。
ffmpeg.exeを利用するフロントエンドアプリなんかもそうしているでしょうし。
「ffmpeg.exe フロントエンド」で検索してみるとアプリは見つかるかと。

QC# Process.Startメソッドで複数引数を渡したい

タイトルの通り、Process.Startメソッドで起動するアプリに複数2つ以上の引数を渡し、実行させたいのですが、方法がわかりません。
以下、サンプル1のように引数が1つならいいのですが、
サンプル2のように2つ以上の引数の場合、どうしたらよいでしょうか?ご存知の方、ご教授お願いいたします。

[サンプル1]
Process.start(abc.exe, "c:\abc.txt")

[サンプル2]
Process.start(abc.exe, "c:\abc.txt", "c:\def.txt")

Aベストアンサー

static methodとしてのProcess.Start()を動かすんですよね。

サンプル1は
Process.Start("abc.exe", @"c:\abc.txt");
だと思います。(第1引数もstringであることに注意)

要するにアプリケーション名とプロセス引数を「文字列として」渡すわけで、
Process.Start("apps", "args");
と書けば、コマンドラインで
>apps args↓
と打つのと同じ動作をするわけです。

なので、
>abc.exe arg1 arg2
と同等のことをやりたければ
Process.Start("abc.exe", "arg1 arg2");
でいけると思います。

QVB.NETで他のEXEを実行させる

VB.NETで他のEXEを実行させる以下の2つの方法が知りたいです。

1)perlのsystemのように実行完了後に制御が戻る

2)perlのexecのように実行完了後に制御が戻らない

あと、この2つの使い分けのコツ(用途)が知りたいです。

Aベストアンサー

http://jeanne.wankuma.com/tips/vb.net/process/
こちらの8番と9番をどうぞ。

使い分けですが、
実行完了を待って次の処理をする必要がある場合は、制御が戻るまで待つ、そうでないものはキックして終わり、です。

QProcess.Startで起動したアプリを最大化したいです。VB.NET

こんにちは、お世話になっております。
下記のようなコードでアプリケーションを起動して
ウィンドウを最大化したいのですが、
どのようにしたら良いでしょうか。
3行目のように大きさを画面いっぱいに設定する方法は
出来たのですが、最大化の方法がわかりません。
申し訳ありませんが、教えて頂きたくお願いいたします。

Dim p As System.Diagnostics.Process
p = System.Diagnostics.Process.Start("***")
MoveWindow(p.MainWindowHandle, 0, 0, 1024, 768, 1)

Aベストアンサー

>起動後のアプリが最大化されませんでした。
起動して、そのウインドウを最大化するサンプル
----------------------------------------------------------------
Imports System
Imports System.Text
Imports System.Diagnostics
Imports System.Threading
Imports System.Runtime.InteropServices
Imports Microsoft.VisualBasic
'vbc Example.vb /r:System.dll
Namespace Example
Class ExampleClass
'Win32API
<DllImport("USER32.DLL")> _
Public Shared Function ShowWindow( _
ByVal handle As IntPtr, _
ByVal style As Integer ) As Integer
End Function

Shared Sub Main()
const SW_MAXMIZE as Integer = 3
Dim instance As Process
instance=Process.Start("notepad.exe") 'アプリケーションを起動する
Dim hWnd As IntPtr
hWnd = instance.MainWindowHandle 'ウィンドウハンドルを得る
Thread.Sleep(5000) '起動の完了を5秒待つ
ShowWindow(hWnd, SW_MAXMIZE) '最大化する
End Sub
End Class
End Namespace

>起動後のアプリが最大化されませんでした。
起動して、そのウインドウを最大化するサンプル
----------------------------------------------------------------
Imports System
Imports System.Text
Imports System.Diagnostics
Imports System.Threading
Imports System.Runtime.InteropServices
Imports Microsoft.VisualBasic
'vbc Example.vb /r:System.dll
Namespace Example
Class ExampleClass
'Win32API
<DllImport("USER32.DLL")> _
Public Shared Function ShowWindow( _
ByVal...続きを読む

QPowerShellにおけるコマンドの戻り値につい

はじめまして質問させていただきます。

最近PowrShellを書き始めました

そこでですが、PowrShellにおいてBatならERRORLEVEL、Shellなら$?といったコマンドの実行結果コードをとる方法がありますしょうか?

PowerShelでも$?は使用できますが、True/Falseだけなので生後判定が2種類しかないので・・

Aベストアンサー

$LastExitCodeとか。
例外と使い分ける必要があります。

参考URL:http://technet.microsoft.com/ja-jp/library/bb978525.aspx

QVBプログラムから「管理者として実行」したい

コマンドプロンプトで実行したいコマンドが
「route add ***.***.***.*** mask 255.255.255.255 ***.***.***.***」 (*は、任意のIP)
だとします。

XPでは問題ないですが、Vista以降だと、管理者権限が必要なコマンドのため、
そもそもコマンドプロンプト自体を「管理者として実行」モードで起動する必要があります。

上記を、手作業で行う場合は、それで解決しますが、
同じ事を、VBのコードから実行したい場合、
System.Diagnostics.Process.Start
を使い、(以下サンプルコード)
---------------------------
Dim psi As New System.Diagnostics.ProcessStartInfo()

psi.FileName = System.Environment.GetEnvironmentVariable("ComSpec")
psi.UseShellExecute = False
psi.CreateNoWindow = True
psi.Arguments = "/c route add ***.***.***.*** mask 255.255.255.255 ***.***.***.***"

Dim p As System.Diagnostics.Process = System.Diagnostics.Process.Start(psi)
p.WaitForExit()

-----------------------------------------------------------

とすると、XPでは、管理者権限を問われないので実行できますが、
Vista以降だと、コマンドが管理者権限で実行されていないためか実行が完了せず、コマンドの内容も行われていません。(route addコマンドの記述にミスは無いとします。)

Vista以降の場合、手作業で、コマンドプロンプトを右クリックして「管理者として実行」を選んで起動し、コマンドを実行するのと同じ事を、
VBのコードから行うには、どうしたらいいのでしょうか?
分かる方、教えてください。お願いします。

コマンドプロンプトで実行したいコマンドが
「route add ***.***.***.*** mask 255.255.255.255 ***.***.***.***」 (*は、任意のIP)
だとします。

XPでは問題ないですが、Vista以降だと、管理者権限が必要なコマンドのため、
そもそもコマンドプロンプト自体を「管理者として実行」モードで起動する必要があります。

上記を、手作業で行う場合は、それで解決しますが、
同じ事を、VBのコードから実行したい場合、
System.Diagnostics.Process.Start
を使い、(以下サンプルコード)
---------------------------...続きを読む

Aベストアンサー

http://www.atmarkit.co.jp/fdotnet/dotnettips/954uacrunas/uacrunas.html

QVBからBATファイルを起動して戻り値の取得方法

VBからBATファイルを起動して戻り値(エラーコード)を
もらうにはどうすれば良いのでしょうか?
WshShellという関数を使用することは、何となく分かるのですが
宜しければサンプルを教えていただけないでしょうか?

Aベストアンサー

>WScript.CreateObjectの
>ところで"オブジェクトが必要です"となってしまいます。

VBのときは、CreateObjectですね。

Qbatファイルからsql文実行

クライアントOS:WIN2000
Oracle:9i(サーバ(UNIX)上にあります)

現在、クライアントからbatを起動し、SQL文を投げ、結果を取得したいと思っております。
(SQL文は単純にTBLをカウントしているだけです)

・batの中身
sqlplus %UID%/%PASS%@%SID% @test.sql > output

結果は取得出来るのですが、余分な情報も結果に出力されてしまいます。結果のみを出力させるにはどうすればよろしいでしょうか?

・余分な情報
Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.4.0 - Production
に接続されました。

Aベストアンサー

sqlplus に -S オプションを追加してみればどうでしょうか。

参考URL:http://biz.rivus.jp/sqlplus_overview.html

Q文字列の後ろから必要分だけ削除したい。

例1 Dim str As String = "あいうえお1234"

文字列の中の1234だけ削除したい場合は、
str = str.Remove(5,4)
という風に、5文字目の後から4文字削除にすればよいのですが、

例の"あいうえお"の部分の長さが毎回処理する度に異なる場合は、
文字列の頭から何文字目という指定ができないので、”後ろから4文字を削除したい”となります。その場合は、どのようなプロパティを使えばいいのでしょうか。

.NET環境です。

Aベストアンサー

Length(str)で文字数を取得できますので、後ろから4文字目は先頭から何文字目かは計算できると思いますが、どうでしょうか?

QCloseとDisposeの違い

みなさまこんばんわです。よろしくお願い申し上げます。

VB.NET 2008でコーディングしています。
CloseとDisposeの違いについて教えていただきたいのです。

これらのメソッドは、開いたファイルを閉じるときなどにも使いますが、今回お尋ねするのは、フォームを閉じるとき、しかも、自ら呼び出すとき(Me.Close() と、Me.Dispose() )のみに限ったこととしてお話しさせていただきます。

たとえば、ShowDialog() で呼び出したフォームは、そのフォーム内でMe.Close() しても、プロセスは残り、たとえば、タイマーコントロールのイベントに記述していますと、それは実行され続けます。

これを防ぐために、Me.Dispose() を使います。すると、きれいにプロセスは終了し、イベントは発生しない模様です。

そこで、「フォームを閉じる」意味のMe.Close() をすべてMe.Dispose() に変えてしまいました。確実にプロセスを破棄出来ると思ったからです。Webで調べると、違いは「再利用できる、できないの違い」という答えがありましたが、それはきっと、ファイルやオブジェクトのことで、フォームの場合は、再びShowまたはShowDialogで表示させることは可能でしたので、特に問題は感じていませんでした。

ところが、アプリケーション設定で、「最後のフォームを閉じるとき」にアプリケーションがシャットダウンする設定になってるのに、シャットダウンしてくれないことが起こりました。調べてみると、Me.Dispose() が原因。Me.Close() に変えるとうまくいきました。

わけわからなくなってきました。。。

ちなみに、その残ったフォームは、スタートアップフォームであり、別のフォームからShowまたはShowDialogメソッドで呼び出したものではありません。

ここで4つの仮説を立ててみました。

1. ShowDialogで呼び出したフォームは、Me.Dispose()、Showで呼び出した、あるいは、スタートアップフォームは、Me.Close() すれば破棄できる

2. ShowDialogで呼び出したフォームは、Me.Dispose()、スタートアップフォームは、Me.Close()、Showで呼び出したフォームは、どちらでも、破棄できる

3. 呼び出し方ではなく、別の要因が存在する

4. 併記する必要がある場合がある

Me.Close()
Me.Dispose()

または、

Me.Dispose()
Me.Close()



どれが正しいのでしょうか?どなたがご存じの方がいらっしゃいましたら、ご教授いただけませんでしょうか? どうぞよろしくお願い申し上げます。ありがとうございました。

みなさまこんばんわです。よろしくお願い申し上げます。

VB.NET 2008でコーディングしています。
CloseとDisposeの違いについて教えていただきたいのです。

これらのメソッドは、開いたファイルを閉じるときなどにも使いますが、今回お尋ねするのは、フォームを閉じるとき、しかも、自ら呼び出すとき(Me.Close() と、Me.Dispose() )のみに限ったこととしてお話しさせていただきます。

たとえば、ShowDialog() で呼び出したフォームは、そのフォーム内でMe.Close() しても、プロセスは残り、たとえば、...続きを読む

Aベストアンサー

Me.Close()
Me.Dispose()
は根本的に違うものです。

formについて、Close()メソッドはフォームの表示を終了させるメソッドです。

ほかのクラスも同様。すべてのDispose()メソッドについて、これはインスタンスの破棄を明示的に行うものです。

>再利用できる、できないの違い

Dispose()はインスタンスが破棄されるため、再びコンストラクタを用いて、インスタンスを生成しないいけません。

一方Close()はインスタンスが残っているので、それを利用することができます。

>1. ところが、アプリケーション設定で、「最後のフォームを閉じるとき」にアプリケーションがシャットダウンする設定になってるのに、シャットダウンしてくれないことが起こりました。調べてみると、Me.Dispose() が原因。
Me.Close() に変えるとうまくいきました。

通常はどちらでもうまくいきます。

>2. ShowDialogで呼び出したフォームは、Me.Dispose()、スタートアップフォームは、Me.Close()、Showで呼び出したフォームは、どちらでも、破棄できる

ShowDialogの場合は、メソッド内部で、ハンドルが破棄されているため、Close()メソッドの際にDispose()メソッドが呼び出されます。

>3. 呼び出し方ではなく、別の要因が存在する

そう思います。

>4. 併記する必要がある場合がある

インスタンスを明示的に破棄したほうがよい場合は多く存在します。
Disposeが使えるメンバはIDisposableをインターフェースとして持っているメンバです。
これらのメンバは、外部とのやり取りを行うものが多くあります。
たとえばSQLClientに含まれるようなメンバです。

外部とのコネクションを確実に破棄を保障してほしいなどという場合がありますよね、このようなときに使用します。

Using構文を使用するのとまったく同じ理由になります。
正確にはUsing構文を使用できるメンバには条件があります、IDisposableをインターフェースとして持っているメンバに限るというものです。

ほかにもガーベージコレクタによるファイナライズを伴うかどうかという違いがあります。
Disposeの場合はファイナライズが同時に行われるため、使用していたメモリ空間を開放することができます。

上記のような理由により、
Me.Close()
Me.Dispose()
は両方書いたほうがよいと思います。

蛇足ですが、
Me.Dispose()
Me.Close()
はエラーになります。
Me.Dispose()により、Me本体(インスタンス)は削除されてしまいます。
存在しないMeに対してCloseメソッドを要求することはできないためです。

Me.Close()
Me.Dispose()
は根本的に違うものです。

formについて、Close()メソッドはフォームの表示を終了させるメソッドです。

ほかのクラスも同様。すべてのDispose()メソッドについて、これはインスタンスの破棄を明示的に行うものです。

>再利用できる、できないの違い

Dispose()はインスタンスが破棄されるため、再びコンストラクタを用いて、インスタンスを生成しないいけません。

一方Close()はインスタンスが残っているので、それを利用することができます。

>1. ところが、アプリ...続きを読む


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング