0

Application.Restart()メソッドを呼び出すと、アプリケーションが現在実行されているかどうかを検出するエラーが表示されます。とにかくこれの周りにありますか?

    static void Main(string[] args)
    {
        string proc = Process.GetCurrentProcess().ProcessName;
        Process[] processes = Process.GetProcessesByName(proc);
        if (processes.Length > 1)
        {
            MessageBox.Show("Program is already running.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        else
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
4

5 に答える 5

3

Mutexを使用します。例:閉じたときにシステムトレイを最小化するシングルインスタンスアプリケーション。この例はおそらく必要なものよりも複雑ですが、ミューテックスを使用するという基本的な単一インスタンスの概念はうまく機能します。

于 2009-10-30T03:23:30.187 に答える
1

これを行う最も効果的な方法はWindowsFormsApplicationBase、C#でも使用できるVB.Netのクラスから継承し、IsSingleInstanceプロパティをに設定することtrueです。これはミューテックスを使用し、EXEファイルの名前が変更されても機能し続けます。

于 2009-10-30T03:23:56.793 に答える
1

私も同様の問題を抱えていましたが、24時間年中無休で実行する必要のあるアプリでは見つけることができなかった管理不能なメモリリークに関連していました。お客様と一緒に、メモリ消費量が定義された値を超えた場合、アプリを再起動する安全な時間は午前3時であることに同意しました。

試してみApplication.Restartましたが、すでに実行中に新しいインスタンスを起動するメカニズムを使用しているようですので、別のスキームを選びました。私は、ファイルシステムが処理するトリックを使用して、ファイルシステムを作成したプロセスが停止するまで保持します。そのため、アプリケーションから、ファイルをディスクにドロップしましたがDispose()、ハンドルはありませんでした。このファイルを使用して、「myself」実行可能ファイルと開始ディレクトリも送信しました(柔軟性を高めるため)。

コード:

_restartInProgress = true;
string dropFilename = Path.Combine(Application.StartupPath, "restart.dat");
StreamWriter sw = new StreamWriter(new FileStream(dropFilename, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite));
sw.WriteLine(Application.ExecutablePath);
sw.WriteLine(Application.StartupPath);
sw.Flush();
Process.Start(new ProcessStartInfo
{
    FileName = Path.Combine(Application.StartupPath, "VideoPhill.Restarter.exe"),
    WorkingDirectory = Application.StartupPath,
    Arguments = string.Format("\"{0}\"", dropFilename)
});
Close();

Close()最後にアプリのシャットダウンが開始され、ここで使用したファイルハンドルは、StreamWriterプロセスが実際に停止するまで開いたままになります。それで...

Reseter.exeが動作します。排他モードでファイルを読み取ろうとし、メインアプリが停止しなくなるまでファイルにアクセスできないようにしてから、メインアプリを起動し、ファイルを削除して存在します。私はそれがもっと簡単になることはできないと思います:

static void Main(string[] args)
{
    string filename = args[0];
    DateTime start = DateTime.Now;
    bool done = false;
    while ((DateTime.Now - start).TotalSeconds < 30 && !done)
    {
        try
        {
            StreamReader sr = new StreamReader(new FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite));
            string[] runData = new string[2];
            runData[0] = sr.ReadLine();
            runData[1] = sr.ReadLine();
            Thread.Sleep(1000);
            Process.Start(new ProcessStartInfo { FileName = runData[0], WorkingDirectory = runData[1] });
            sr.Dispose();
            File.Delete(filename);
            done = true;
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        Thread.Sleep(1000);
    }
}
于 2011-04-09T09:14:54.630 に答える
0

これを行う最も簡単な方法は、終了する前に遅延を追加することです。

言い換えると、

string proc = Process.GetCurrentProcess().ProcessName;
if (Process.GetProcessesByName(proc).Length > 1) {
    Thread.Sleep(500);      //500 milliseconds; you might need to wait longer
    if (Process.GetProcessesByName(proc).Length > 1) {
        MessageBox.Show("Program is already running.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return;
    }
}    //no else
于 2009-10-30T03:19:11.123 に答える
0

リスタートコードをリスナーメソッドとしてApplication.ApplicationExitイベントにフックしてみてください。次に、Application.Exitを呼び出して、コードを間接的に実行します。

編集:コードサンプルを追加:

たとえば、ユーザーが再起動ボタンをクリックするか、アプリが再起動することを決定した場合、このRestartMeSmartly()メソッドを呼び出します。トリックについて心配する必要はありません-それは機能します。

void RestartMeSmartly() {
    Application.ApplicationExit += BeforeExiting;
    Application.Exit();
}

void BeforeExiting(object sender, EventArgs args) {
    Application.Restart();
}
于 2009-10-30T03:22:27.240 に答える