C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

アプリケーションを正常に終了させる方法

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■100401 / inTopicNo.1)  アプリケーションを正常に終了させる方法
  
□投稿者/ 河童 (26回)-(2022/07/27(Wed) 16:52:23)

分類:[C#] 

VS2019 C# .net framework4 フォームアプリを作成しています。

CopyPGとMainPGの2種類のPGがあります。
MainPGとCopyPGは、別々にPGを作成しています。

処理の流れ:
1.最初にCopyPGを起動
2.システムファイルの読込
3.更新ファイルのコピー処理の実行
4.MainPGを起動
5.CopyPGを終了

困っている事:
CopyPGのフォームLoad時においてシステムファイルの読込時にエラーが発生した場合、
MianPGを起動させて、CopyPGを終了させています。
このときCopyPGのフォーム画面は表示されていないのですが、プロセスが残った状態になります。

試した事:
フォームShown時に同じ処理を実行したのですが、結果は同じでした。
Shown時は、フォームにあるラベルやロゴの表示がくずれてしまいます。

教えていただきたい事:
プロセスを残さずCopyPGを終了させるにはどのようにすればよいでしょうか。
システム設定ファイルは、1度しか読み込ませないので、Load時に処理させています。
読み込ませるタイミングも関係しているのでしょうか。

ちなみに、正常にシステム設定ファイルを読み込み、コピーが正常終了したときは、
問題なくCopyPGは終了しています。

    private void F01_Copy_Load(object sender, EventArgs e)
    {
            // システム設定ファイル読込
            setSys = File.ReadSerializeXml();
            if (setSys == null)
            {
                // MainPG起動        
                Main_Start();
                // CopyPG 終了
                Environment.Exit(0);
            }

            // バージョン表示
            lblNewVer.Text = setSys.update_version;
            lblOldVer.Text = setSys.current_version;
        }

        private void F01_Copy_Shown(object sender, EventArgs e)
        {
           
        }

        private void F01_Copy_Activated(object sender, EventArgs e)
        {
            try
            {
                Thread.Sleep(1000);
                this.Refresh();

                // コピー処理
                Set_CopyDirectory();

                // MainPG起動
                Main_Start();
                // CopyPG 終了
                Environment.Exit(0);   
            }
            catch (System.Exception ex)
            {
                // MainPG起動
                Main_Start();
                // CopyPG 終了
                Environment.Exit(0);
            }
        }

        private void Main_Start()
        {
            try
            {
                var proc = new System.Diagnostics.Process();
                proc.StartInfo.FileName = @"C:\Main\Main.exe";

                proc.Start();
                // 1秒待機
                proc.WaitForExit(1000);

            }
            catch (System.Exception ex)
            {
                MessageBox.Show("MainPGが起動ができません");
            }

        }

引用返信 編集キー/
■100402 / inTopicNo.2)  Re[1]: アプリケーションを正常に終了させる方法
□投稿者/ 魔界の仮面弁士 (3441回)-(2022/07/27(Wed) 19:03:44)
No100401 (河童 さん) に返信
> Environment.Exit(0);
その方法は使わない方が良いですよ。
https://dobon.net/vb/dotnet/programing/applicationexit.html


> CopyPGのフォームLoad時においてシステムファイルの読込時にエラーが発生した場合、
> MianPGを起動させて、CopyPGを終了させています。
そもそも何故、Form 上にチェック処理を記述しているのでしょうか。

Form 内ではなく、その前の Program.cs の Main メソッドの時点でファイルチェックを行い、
Process.Start を呼び出した場合は、そもそも Appplication.Run を呼ばずに
Main メソッドを return してしまえば済むように思います。
引用返信 編集キー/
■100403 / inTopicNo.3)  Re[1]: アプリケーションを正常に終了させる方法
□投稿者/ KOZ (304回)-(2022/07/27(Wed) 20:44:52)
2022/07/27(Wed) 20:45:17 編集(投稿者)
No100401 (河童 さん) に返信
> 2.システムファイルの読込

弁士さんがおっしゃるように Main で行いましょう。

> 3.更新ファイルのコピー処理の実行

別スレッドで行いましょう。
別スレッドを起動するタイミングは Load イベントか、Show イベントが良いと思います。
複数のフォームを表示すると何度でも起きる可能性があるので Activate イベントは適当ではないです。

処理が終わったら BeginInvoke してフォームを閉じます。

private void F01_Copy_Shown(object sender, EventArgs e) {
    Task.Run(Startup);
}

private void Startup() {
    try {
        Set_CopyDirectory();

    } finally {
        BeginInvoke((Action)(() => { this.Close(); }));
    }
}

>4.MainPGを起動

フォームを閉じるとき(FormClosing イベント)に行いましょう。

引用返信 編集キー/
■100407 / inTopicNo.4)  Re[2]: アプリケーションを正常に終了させる方法
□投稿者/ 河童 (28回)-(2022/07/28(Thu) 08:15:24)
No100402 (魔界の仮面弁士 さん) に返信
No100403 (KOZ さん) に返信

ありがとうございます。
なるほど、勉強になります。Main メソッドでファイルチェックできるんですね。

今まで設定ファイルの読込はフォームLoad時で行っていて、
Mainでは最初に表示するフォームを設定するしかしてこなかったです。

プログラムを改善します。
引用返信 編集キー/
■100449 / inTopicNo.5)  Re[3]: アプリケーションを正常に終了させる方法
□投稿者/ 河童 (29回)-(2022/08/12(Fri) 16:24:10)
No100402 (魔界の仮面弁士 さん) に返信
No100403 (KOZ さん) に返信

プログラムを修正しました。
Task.Run がビルドでエラーが発生していたので、
.netFramework4.0 から .netFramework4.8 に変更しました。

設定ファイルのチェックを Main で行うように修正しました。
エラー時にプロセスが残らないようになりました。

ここで1つ教えていただきたいことができました。
Main から フォームへ値を受け渡す方法です。
今はMain で取得した値(バージョンやフォルダーのパス)を変数ごとに代入してフォームへ渡しています。
これでも正常に動作できているのですが、
もし変数が増えた場合や後学のために他の方法があれば教えていただきたいです。
受け渡すためのクラスを作成したのですが、
Program.cs で静的クラスでインスタンスのメンバーを宣言することができませんでした。

よろしくお願いいたします。


// Program.cs
namespace FilceCopy
{
internal static class Program
{
/// <summary>
/// アプリケーションのメイン エントリ ポイントです。
/// </summary>
[STAThread]
static void Main()
{

//string srvIP = ""; // 接続先サーバIPアドレス
string pUpdate_version = ""; // 更新バージン
string pCurrent_version = ""; // 現行バージョン
string pCopyFldName = @"C:\Test\Update\Main"; //コピー元のフォルダー(※フルパスはサーバのIPを結合する)
string pPasteFldName = @"C:\Main"; //コピー先のフォルダー
string pFilePath = @"setting\\setting.xml"; // システム設定ファイル確認

// システム設定ファイルの存在確認
if (!File.Exists(pFilePath))
{
Main_Start(); // メインPG起動
return;
}
// コピー元の存在を確認します
if (!Directory.Exists(pCopyFldName))
{
Main_Start(); // メインPG起動
return;
}
// コピー先の存在を確認します
if (!Directory.Exists(pPasteFldName))
{
Main_Start(); // メインPG起動
return;
}

// 更新バージョン取得
pUpdate_version = "Ver2.0.0";
// 現行バージョン取得
pCurrent_version = "Ver1.0.0";

Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1(pUpdate_version, pCurrent_version, pCopyFldName, pPasteFldName));
//Application.Run(new Form1());
}

static private void Main_Start()
{
try
{
var proc = new System.Diagnostics.Process();
proc.StartInfo.FileName = @"C:\Main\Main.exe";

proc.Start();
// 1秒待機
proc.WaitForExit(1000);

}
catch (System.Exception ex)
{
MessageBox.Show("メインPGが起動ができません");
//MessageBox.Show(ex.ToString());
}

}
}
}

// From1.cs
namespace FilceCopy
{
public partial class Form1 : Form
{

public string update_version = "";
public string current_version = "";
public string copyFldName = "";
public string pasteFldName = "";

public Form1(string pUpdate_version, string pCurrent_version, string pCopyFldName, string pPasteFldName)
{

update_version = pUpdate_version;
current_version = pCurrent_version;
copyFldName = pCopyFldName;
pasteFldName = pPasteFldName;

InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
// 別スレッドで更新ファイルのコピー処理の実行
Task.Run(Startup);
}

private void Startup()
{
try
{
Set_CopyDirectory(copyFldName, pasteFldName);

}
finally
{
BeginInvoke((Action)(() => { this.Close(); }));
}
}

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Main_Start(); // メインPG起動
}

private void Main_Start()
{
try
{
var proc = new System.Diagnostics.Process();
proc.StartInfo.FileName = @"C:\Main\Main.exe";

proc.Start();
// 1秒待機
proc.WaitForExit(1000);

}
catch (System.Exception ex)
{
MessageBox.Show("メインPGが起動ができません");
}
}

static bool Set_CopyDirectory(string CopyFld, string PasteFld)
{

// 処理省略
}

}
}

引用返信 編集キー/
■100450 / inTopicNo.6)  Re[4]: アプリケーションを正常に終了させる方法
□投稿者/ KOZ (309回)-(2022/08/12(Fri) 17:12:56)
No100449 (河童 さん) に返信
> プログラムを修正しました。
> Task.Run がビルドでエラーが発生していたので、
> .netFramework4.0 から .netFramework4.8 に変更しました。

var th = new System.Threading.Thread(Startup);
th.Start();

でもいいです。

> ここで1つ教えていただきたいことができました。
> Main から フォームへ値を受け渡す方法です。

クラスでも構造体でも作って渡せば良いです。

static class Program
{
    [STAThread]
    static void Main() {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        var form1 = new Form1();
        form1.StartupInfo = new StartupInfo() {
                    update_version = "....",
                    current_version = "....",
                    copyFldName = "....",
                    pasteFldName = "...."
                };
        Application.Run(form1);
    }

    public class StartupInfo
    {
        public string update_version { get; set; }
        public string current_version { get; set; }
        public string copyFldName { get; set; }
        public string pasteFldName { get; set; }
    }
}

public partial class Form1 : Form
{
    internal Program.StartupInfo StartupInfo;
(略)
}

> Program.cs で静的クラスでインスタンスのメンバーを宣言することができませんでした。
どういう意味でしょうか?

引用返信 編集キー/
■100452 / inTopicNo.7)  Re[5]: アプリケーションを正常に終了させる方法
□投稿者/ 河童 (30回)-(2022/08/12(Fri) 18:07:50)
No100450 (KOZ さん) に返信
> var th = new System.Threading.Thread(Startup);
> th.Start();
.netFramework4.0 でも実行できるんですね。

まさにやりたい事です。

> public class StartupInfo
> {
> public string update_version { get; set; }
> public string current_version { get; set; }
> public string copyFldName { get; set; }
> public string pasteFldName { get; set; }
> }
> }
>
> public partial class Form1 : Form
> {
> internal Program.StartupInfo StartupInfo;
> (略)
> }

ありがとうございました。
プロセスの問題とデータの渡し方、とても勉強になりました。
解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ