コンソールアプリケーションからwinformを実行するにはどうすればよいですか?
-
07-07-2019 - |
質問
コンソール アプリケーション内から winform を作成、実行、制御するにはどうすればよいですか?
解決
最も簡単なオプションは、Windowsフォームプロジェクトを開始し、出力タイプをコンソールアプリケーションに変更することです。または、System.Windows.Forms.dllへの参照を追加して、コーディングを開始します。
using System.Windows.Forms;
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.Run(new Form()); // or whatever
}
重要なビットは、 Main()
メソッドの [STAThread]
です。これは完全なCOMサポートに必要です。
他のヒント
最近これをやりたいと思ったのですが、ここでの答えのどれにも満足できないことがわかりました。
Marc のアドバイスに従い、出力タイプをコンソール アプリケーションに設定すると、2 つの問題が発生します。
1) エクスプローラーからアプリケーションを起動すると、フォームの背後に煩わしいコンソール ウィンドウが表示され、プログラムが終了するまで消えません。GUI (Application.Run) を表示する前に FreeConsole を呼び出すことで、この問題を軽減できます。ここで厄介なのは、コンソール ウィンドウがまだ表示されていることです。それはすぐに消えますが、それでもしばらく存在します。
2) コンソールから起動して GUI を表示した場合、GUI が終了するまでコンソールはブロックされます。これは、コンソール (cmd.exe) が、コンソール アプリを同期的に起動し、Windows アプリを非同期的に起動する必要があると考えるためです (UNIX の「myprocess &」に相当)。
出力タイプを Windows アプリケーションのままにした場合、 正しく AttachConsole を呼び出すと、コンソールから呼び出したときに 2 番目のコンソール ウィンドウが表示されず、エクスプローラーから呼び出したときに不要なコンソールが表示されません。AttachConsole を呼び出す正しい方法は、それに -1 を渡すことです。これにより、プロセスが親プロセスのコンソール (起動したコンソール ウィンドウ) にアタッチされます。
ただし、これには 2 つの異なる問題があります。
1) コンソールは Windows アプリをバックグラウンドで起動するため、すぐにプロンプトが表示され、さらに入力できるようになります。これは良いニュースである一方で、GUI アプリではコンソールがブロックされていませんが、出力をコンソールにダンプし、GUI を決して表示しない場合、プログラムの出力はプロンプトの後に表示され、新しいプロンプトは表示されません。完了すると表示されます。これは、「コンソール アプリ」がバックグラウンドで実行されており、実行中にユーザーが他のコマンドを自由に実行できることは言うまでもなく、少し混乱しているように見えます。
2) ストリームのリダイレクトも混乱します。「myapp someparameters > somefile」はリダイレクトに失敗します。ストリーム リダイレクトの問題は、標準ハンドルを修正するために大量の p/Invoke を必要としますが、解決可能です。
何時間も調査と実験を行った結果、これを完璧に行う方法は存在しないという結論に達しました。コンソールとウィンドウの両方の利点を副作用なしにすべて得ることはできません。アプリケーションの目的に応じて、どの副作用が最も煩わしくないかを選択することが重要です。
私が見つけた最良の方法は次のとおりです。 最初に、プロジェクトの出力タイプを「Windowsアプリケーション」に設定し、次にAllocConsoleをP / Invokeしてコンソールウィンドウを作成します。
internal static class NativeMethods
{
[DllImport("kernel32.dll")]
internal static extern Boolean AllocConsole();
}
static class Program
{
static void Main(string[] args) {
if (args.Length == 0) {
// run as windows app
Application.EnableVisualStyles();
Application.Run(new Form1());
} else {
// run as console app
NativeMethods.AllocConsole();
Console.WriteLine("Hello World");
Console.ReadLine();
}
}
}
それは非常に簡単です:
Mainメソッドに次の属性とコードを追加するだけです:
[STAThread]
void Main(string[] args])
{
Application.EnableVisualStyles();
//Do some stuff...
while(!Exit)
{
Application.DoEvents(); //Now if you call "form.Show()" your form won´t be frozen
//Do your stuff
}
}
これでWinFormsを完全に表示できるようになりました:)
VS2005 / VS2008でwinformプロジェクトを作成し、そのプロパティをコマンドラインアプリケーションに変更できます。その後、コマンドラインから起動できますが、winformが開きます。
Winformアプリと同じ方法でApplicationクラスを使用できるはずです。おそらく、新しいプロジェクトを開始する最も簡単な方法は、Marcが提案したことを実行することです。新しいWinformプロジェクトを作成し、オプションでコンソールアプリケーションに変更します
これは私のニーズに合っていました...
Task mytask = Task.Run(() =>
{
MyForm form = new MyForm();
form.ShowDialog();
});
これは、新しいスレッドから開始し、フォームが閉じられるまでスレッドを解放しません。 Task
は.Net 4以降にあります。
実装方法は、選択によって完全に異なります。
a。添付プロセス、例:フォームへの入力とコンソールでの印刷
b。独立したプロセス、例:タイマーを開始し、コンソールが終了しても閉じないでください。
の場合、
Application.Run(new Form1());
//or -------------
Form1 f = new Form1();
f.ShowDialog();
bの場合、 スレッドを使用するか、何かをする、 winフォームを個別に開く方法
Form Freeze からエスケープし、編集(ボタンのテキストなど)を使用する場合は、このコードを使用します
Form form = new Form();
Form.Button.Text = "randomText";
System.Windows.Forms.Application.EnableVisualStyles();
System.Windows.Forms.Application.Run(form);
上記の答えはすべて大きな助けですが、絶対的な初心者のためにさらにヒントを追加することを考えました。
だから、コンソールアプリケーションで Windowsフォームで何かをしたい:
ソリューションエクスプローラーのコンソールアプリケーションプロジェクトで、 System.Windows.Forms.dll への参照を追加します。 (ソリューション名-> add->参照...を右クリック)
コードで名前空間を指定します: using System.Windows.Forms;
フォームに追加するコントロールのクラスで必要なプロパティを宣言します。
e.g。 int Left {get;セット; } //フォーム上のボタンの左位置を指定する必要がある
そして、次のコードスニペットを Main()
に追加します:
static void Main(string[] args)
{
Application.EnableVisualStyles();
Form frm = new Form(); // create aForm object
Button btn = new Button()
{
Left = 120,
Width = 130,
Height = 30,
Top = 150,
Text = "Biju Joseph, Redmond, WA"
};
//… more code
frm.Controls.Add(btn); // add button to the Form
// …. add more code here as needed
frm.ShowDialog(); // a modal dialog
}