首页 / 知识

关于c#:为什么Application.Restart()不可靠?

2023-04-17 07:15:00

关于c#:为什么Application.Restart()不可靠?

Why is Application.Restart() not reliable?

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

有人可以告诉我,为什么这个问题一直不起作用吗?


可能有很多原因。这并不是说该方法无效;而是,很多时候程序员忘记了自己在代码中放了一些东西,这些东西会阻止应用程序自动关闭或启动。两个例子:

  • 表单上的关闭事件可以停止应用程序的关闭
  • 如果要检查已经运行的进程,则旧进程可能关闭得不够快,无法启动新进程。

检查您的代码是否有这样的陷阱。如果您在空白应用程序中看到此行为,则实际功能比代码更有可能是问题。

检查Microsoft的应用程序重新启动源代码。


就我而言(没有单实例),

1
Application.Restart();

没用

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

做好了!


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

编辑:

我现在遇到另一个实例,根据您的评论,它可能反映了您所遇到的情况。

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


在我的程序中,我有一个互斥体以确保仅在计算机上运行该应用程序的一个实例。这导致新启动的应用程序无法启动,因为互斥锁没有及时发布。结果,我在Properties.Settings中输入了一个值,指示应用程序正在重新启动。在调用Application.Restart()之前,将Properties.Settings值设置为true。在Program.Main()中,我还添加了对该特定property.settings值的检查,以便将其设置为true时将其重置为false并存在一个Thread.Sleep(3000);

在您的程序中,您可能具有以下逻辑:

1
2
3
4
5
6
if (ShouldRestartApp)
{
   Properties.Settings.Default.IsRestarting = true;
   Properties.Settings.Default.Save();
   Application.Restart();
}

Program.Main()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[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();
   }
}

而已。


在转储之前尝试锁定。这是我启动完整应用转储的方式。可能会为您工作,可能不会。

1
2
3
4
5
Context.Application.Lock();
Context.Session.Abandon();
Context.Application.RemoveAll();
Context.Application.Restart();
Context.Application.UnLock();

1
2
Application.Restart();
Application.ExitThread();

这对我有用,谢谢。


试试这个代码:

1
bool appNotRestarted = true;

此代码也必须在函数中:

1
2
3
4
5
6
if (appNotRestarted == true)
{
    appNotRestarted = false;
    Application.Restart();
    Application.ExitThread();
}

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


我对.Net 4.7框架有同样的问题。接受的答案是我成功的关键。
我确实在FormClosing事件中包含代码,该事件花费一些时间并停止了重新启动过程。
我要做的是放一个这样的哨兵:

1
2
3
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()才起作用!


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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;
            }
        }
    }

我知道这是一个旧线程,但是我找到了一种解决方法。希望这会帮助需要帮助的其他人。

我需要一种解决方案,该解决方案在从代码启动ClickOnce Application的过程中触发更新序列。 Applicatoin.Restart没有这样做。我想要一种能够检查更新,然后调用内置的更新管理器的方法,这样我就不必编写自定义的更新。

1
2
3
4
5
6
7
8
    '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 SingleInstance应用程序一起使用。


应用程序重新启动方法不可靠

最新内容

相关内容

猜你喜欢