web-dev-qa-db-ja.com

Application.Restart()が信頼できないのはなぜですか?

C#でApplication.Restart()メソッドを使用すると、現在のアプリケーションが再起動します。ただし、これは常に機能するとは限りません。

この問題の理由はありますか、誰かが私に言うことができますか、なぜそれが常に機能しないのですか?

44
MADMap

これには多くの理由があります。メソッドが機能しないわけではありません。むしろ、多くの場合、プログラマーは、アプリケーションが自動的にシャットダウンしたり起動したりするのを止めるようなコードをコードに入れたことを忘れます。 2つの例:

  • フォームのClosingイベントは、アプリのシャットダウンを停止できます
  • すでに実行中のプロセスをチェックしている場合、古いプロセスは、新しいプロセスを起動できるほど速く閉じられない可能性があります。

そのような落とし穴がないか、コードを確認してください。空白のアプリケーション内でこの動作が発生している場合、コードよりも実際の機能に問題がある可能性が高くなります。

application restart のMicrosoftのソースコードを確認してください。

28
TheSmurf

私の場合(シングルインスタンスではない)、ここで

Application.Restart();

うまくいかなかった、

System.Diagnostics.Process.Start(Application.ExecutablePath);
Application.Exit();

仕事をしました!

18
cprcrack

この種の問題に遭遇したのは、メインフォームにカスタムFormClosingイベントハンドラーがあり、それがロジックを実行してイベントをキャンセルしたときだけです。

編集:

私は今、別のインスタンスに遭遇しました、そして、あなたのコメントに基づいて、それはあなたが経験していたことを多分反映します。

Mutexを使用してシングルインスタンスアプリケーションを実行しているとき、かなり埋め込まれた場所からApplication.Restart()を呼び出していました。これには多くのクリーンアップが必要でした。そのため、前のインスタンスが完了する前に再起動が新しいインスタンスを起動していたようであるため、Mutexは新しいインスタンスの起動を妨げていました。

7
Timothy Carter

私のプログラムでは、コンピューター上で実行されるアプリケーションのインスタンスが1つだけであることを保証するミューテックスを持っています。これにより、ミューテックスがタイムリーにリリースされなかったため、新しく起動したアプリケーションが起動しなくなりました。その結果、アプリケーションを再起動していることを示す値を_Properties.Settings_に入れました。 Application.Restart()を呼び出す前に、_Properties.Settings_値がtrueに設定されます。 Program.Main()で、その特定の_property.settings_値のチェックも追加したため、truefalseにリセットされ、Thread.Sleep(3000);

あなたのプログラムには、ロジックがあるかもしれません:

_if (ShouldRestartApp)
{
   Properties.Settings.Default.IsRestarting = true;
   Properties.Settings.Default.Save();
   Application.Restart();
}
_

Program.Main()

_[STAThread]
static void Main()
{
   Mutex runOnce = null;

   if (Properties.Settings.Default.IsRestarting)
   {
      Properties.Settings.Default.IsRestarting = false;
      Properties.Settings.Default.Save();
      Thread.Sleep(3000);
   }

   try
   {
      runOnce = new Mutex(true, "SOME_MUTEX_NAME");

      if (runOnce.WaitOne(TimeSpan.Zero))
      {
         Application.EnableVisualStyles();
         Application.SetCompatibleTextRenderingDefault(false);
         Application.Run(new Form1());
      }
   }
   finally
   {
      if (null != runOnce)
         runOnce.Close();
   }
}
_

それでおしまい。

6
cmptrs4now

ダンプする前にロックしてみてください。完全なアプリダンプを開始する方法は次のとおりです。あなたのために働くかもしれませんが、そうではないかもしれません。

Context.Application.Lock();
Context.Session.Abandon();
Context.Application.RemoveAll();
Context.Application.Restart();
Context.Application.UnLock();
2
Oli

アプリケーションが最初にネットワーク上の場所から起動され、署名されていない場合(警告ダイアログが最初に表示されます)、再起動せずに終了するだけです。

1
Matt Hanson
Application.Restart();
Application.ExitThread();                                                     

これは私に感謝しました。

1
shima lagzian

このコードを試してください:

bool appNotRestarted = true;

このコードは関数にも含まれている必要があります。

if (appNotRestarted == true)
{
    appNotRestarted = false;
    Application.Restart();
    Application.ExitThread();
}
1
ferhatayhan

私はこれが古いスレッドであることを知っていますが、回避策を見つけました。うまくいけば、これが困っている他の誰かを助けるでしょう。

ClickOnceアプリケーションをコードから起動するときに更新シーケンスをトリガーするソリューションが必要でした。 Applicatoin.Restartはこれをしませんでした。更新を確認し、組み込みの更新マネージャーを呼び出すことができるようにしたかったので、カスタムの更新マネージャーを作成する必要はありませんでした。

    'VB Code Sample
    Dim strStart As String = System.Environment.GetFolderPath(Environment.SpecialFolder.StartMenu) & "\Programs\Folder\YourApplication.appref-ms"
    Application.Exit()
    Try
        Process.Start(strStart)
    Catch ex As Exception
        'Do something with the exception
    End Try

この回避策で発生する唯一の問題は、ユーザーがスタートメニューからショートカットを削除できることです。それが懸念される場合は、スタートメニューリンクを選択したフォルダー(できればClickOnceアプリケーションフォルダー)にコピーするためのコードを書くことができます。アプリケーションのスタートメニューアイコンは.lnkや.exeではなく、実際には.appref-msリンクであるため、これは重要です。 ClickOnce .appref-msは.applicationファイルへのリンク以上ですか? を参照してください。このリンクではこれについて詳しく説明しています。

このコードは、ClickOnceシングルインスタンスアプリケーションで機能します。

0
Nathan
public static void ApplicationRestart(params string[] commandLine)
    {
        lock (SynchObj)
        {
            if (Assembly.GetEntryAssembly() == null)
            {
                throw new NotSupportedException("RestartNotSupported");
            }

            if (_exiting)
                return;

            _exiting = true;

            if (Environment.OSVersion.Version.Major < 6) return;

            bool cancelExit = true;

            try
            {
                foreach (Form f in Application.OpenForms.OfType<Form>().ToList())
                {
                    f.InvokeIfRequired(frm =>
                    {
                        frm.FormClosing += (sender, args) => cancelExit = args.Cancel;
                        frm.Close();
                    });

                    if (cancelExit) break;
                }

                if (cancelExit) return;

                Process.Start(new ProcessStartInfo
                {
                    UseShellExecute = true,
                    WorkingDirectory = Environment.CurrentDirectory,
                    FileName = Application.ExecutablePath,
                    Arguments = commandLine.Length > 0 ? string.Join(" ", commandLine) : string.Empty
                });

                Application.Exit();
            }
            finally
            {
                _exiting = false;
            }
        }
    }
0

.Net 4.7フレームワークでも同じ問題があります。受け入れられた答えは私の成功の鍵でした。 FormClosingイベントには、時間がかかり再起動プロセスを停止するコードがありました。私がやったことは、このようなセンチネルを置くことでした:

If JustCloseIT = False Then
   'all closing code, like logging the session log-out to a database and all those goodies we all do.
 End If

その後、Application.Restart()が機能しました!

0
Nandostyle