为什么Application.Restart()不可靠?

时间:2008-09-18 18:08:05

标签: c# .net

在C#中使用Application.Restart()方法应该重新启动当前应用程序:但似乎这并不总是有效。

这个问题是否有原因,有人可以告诉我,为什么它不能一直有效?

12 个答案:

答案 0 :(得分:27)

这可能有很多原因。这不是方法不起作用;相反,很多时候程序员忘记了他们在代码中放了一些东西会阻止应用程序自动关闭或启动。两个例子:

  • 表单上的Closing事件可以停止应用程序的关闭
  • 如果您正在检查已经在运行的进程,那么旧进程可能无法快速关闭以允许新进程启动。

检查你的代码是否有类似的问题。如果您在空白应用程序中看到此行为,那么实际功能的问题可能比您的代码更容易出现问题。

查看Microsoft的application restart源代码。

答案 1 :(得分:18)

在我的情况下(没有单一实例),其中

Application.Restart();

没用,

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

完成了这份工作!

答案 2 :(得分:7)

我遇到这种问题的唯一一次是在我的主要表单中,我有一个自定义FormClosing事件处理程序,它执行逻辑并取消了事件。

编辑:

我现在遇到了另一个实例,根据您的意见,它可能反映了您的体验。

当使用Mutex运行单个实例应用程序时,我从一个相当嵌入的位置调用Application.Restart(),这需要做很多清理工作。所以似乎重启是在前一个实例完成之前启动一个新实例,因此Mutex阻止了新实例的启动。

答案 3 :(得分:5)

在我的程序中,我有一个互斥锁,以确保只在计算机上运行一个应用程序实例。这导致新启动的应用程序无法启动,因为互斥锁未及时释放。结果,我将一个值放入Properties.Settings,表示应用程序正在重新启动。在致电Application.Restart()之前,Properties.Settings值设置为 true 。在Program.Main()中,我还添加了对该特定property.settings值的检查,以便在 true 时将其重置为 false 并且有{{1} }}

在你的程序中,你可能有逻辑:

Thread.Sleep(3000);

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

Program.Main()

就是这样。

答案 4 :(得分:2)

在转储前尝试锁定。这是我如何启动完整的app转储。可能不适合你。

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

答案 5 :(得分:1)

如果应用程序首次从网络位置启动并且未签名(您首先获得警告对话框),它将不会重新启动并且只会退出。

答案 6 :(得分:1)

试试这段代码:

bool appNotRestarted = true;

此代码也必须在函数中:

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

答案 7 :(得分:1)

Application.Restart();
Application.ExitThread();                                                     

这对我有用。谢谢。

答案 8 :(得分:1)

我试过下面的代码,它工作正常

static class Program
{
    static Mutex _mutex = new Mutex(false, "MYAPP");

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        if (!_mutex.WaitOne(1000, false))
        {
            MessageBox.Show("Another instance is already running!!!", "Already Running", MessageBoxButtons.OK,
                MessageBoxIcon.Error);
            return;
        }

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new PrimaryForm());

        _mutex.ReleaseMutex();
    }
}

//我调用应用程序重启的地方使用了这段代码

Application.Restart();
Application.ExitThread();

参考链接
https://www.codeproject.com/articles/25674/preventing-multiple-application-instances-when-usi

答案 9 :(得分:0)

我知道这是一个老线程,但我找到了一个解决方法。希望这将有助于其他有需要的人。

我需要一个解决方案,可以在代码中启动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 more than a link to .application file?此链接更详细地解释了这一点。

此代码适用于ClickOnce SingleInstance应用程序。

答案 10 :(得分:0)

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;
            }
        }
    }

答案 11 :(得分: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()工作了!