Vb.net Clickonce应用程序不';t升级完成后重新启动

Vb.net Clickonce应用程序不';t升级完成后重新启动,vb.net,clickonce,restart,Vb.net,Clickonce,Restart,我正在使用类来检查升级是否可用,然后升级应用程序,如下所示 Dim AD As System.Deployment.Application.ApplicationDeployment = System.Deployment.Application.ApplicationDeployment.CurrentDeployment Dim info As System.Deployment.Application.UpdateCheckInfo = Nothing Me.DialogResult =

我正在使用类来检查升级是否可用,然后升级应用程序,如下所示

Dim AD As System.Deployment.Application.ApplicationDeployment = System.Deployment.Application.ApplicationDeployment.CurrentDeployment
Dim info As System.Deployment.Application.UpdateCheckInfo = Nothing

Me.DialogResult = Windows.Forms.DialogResult.Cancel
Me.Close()

AD.Update()

Application.Restart() // this doesn't work which is still ok.
重新启动不起作用,因此我正在尝试获取升级的应用程序可执行路径并更新注册表,以便当用户重新启动系统时,将启动最新的应用程序

我无法获取升级后安装应用程序的路径。它在c\document…\user…(文档…\user…)中创建新文件夹。。。。我知道。但是,需要获取此路径并更新注册表


有人有任何指针吗?

您可以尝试如下方式重新启动应用程序:

Dim applicationEntryPoint = ApplicationDeployment.CurrentDeployment.UpdatedApplicationFullName

Process.Start(applicationEntryPoint)

// Call any code to shut down the current instance of the application here...

我建议在调用应用程序的地方放一个消息框或跟踪。重新启动以确保它真的在调用它。如果您验证了这一点,但它仍然不起作用,那么您是否可能锁定了某些东西,并且在关闭之前它不会重新启动?

这可能是因为您在ClickOnce部署的应用程序中使用了VB的本机单实例应用程序功能。该功能在引擎盖下使用了一个
互斥锁
,无法及时释放,应用程序无法重新启动。因此,您看到的行为不会重新启动

我刚才也有同样的问题。为了修复它,我不得不使用VB翻译和对我发现的技巧的轻微修改。本质上,我们需要的是
互斥体的共享实例和
应用程序上的3秒钟暂停。Restart()
给退出版本释放其
互斥体的时间。不要忘记在项目属性页的应用程序选项卡上取消选中“生成单实例应用程序”

下面是我最后得到的代码。这样我们就可以拥有世界上最好的——VB的漂亮应用程序框架,我们非常喜欢它,单实例功能和ClickOnce API重新启动。一下子。我头晕

帽贴#1:给devzoo,作为他的,展示主要概念

帽檐小贴士#2:devzoo引述NullFX的话,为了他的

帽子提示#3:To@cmptrs4now,因为他的
IsRestarting
3秒暂停想法

帽子提示#4:请@pstrjds澄清。根据他的建议,我将下面的
Mutex.ReleaseMutex()
更改为
Mutex.Close()
。这看起来更安全

Friend类Main
继承System.Windows.Forms.Form
受保护的覆盖子WndProc(ByRef消息作为消息)
如果Message.Msg=SingleInstance.WM\u SHOWFIRSTINSTANCE,则
ShowWindow()
如果结束
MyBase.WndProc(消息)
端接头
私有子窗口()
Me.WindowState=FormWindowState.Normal
我
端接头
Private Sub cmdUpdate\单击(发件人作为对象,e作为事件参数)处理cmdUpdate。单击
如果ApplicationDeployment.IsNetworkDeployed,则
如果ApplicationDeployment.CurrentDeployment.CheckForUpdate(False)
ApplicationDeployment.CurrentDeployment.Update()
MsgBox(“应用程序已更新,现在将重新启动。”,MsgBoxStyle.Information)
My.Settings.IsRestarting=True
My.Settings.Save()
Application.Restart()
如果结束
如果结束
端接头
末级
名称空间我的
'以下事件可用于MyApplication:
' 
'启动:在创建启动窗体之前,在应用程序启动时引发。
'关闭:在关闭所有申请表后引发。如果应用程序异常终止,则不会引发此事件。
'UnhandledException:如果应用程序遇到未处理的异常,则引发。
'StartupNextInstance:在启动单实例应用程序且该应用程序已处于活动状态时引发。
'NetworkAvailabilityChanged:在连接或断开网络连接时引发。
部分友元类MyApplication
私有子MyApplication\u Startup(发送方作为对象,e作为ApplicationServices.StartupEventArgs)处理我。Startup
如果My.Settings.IsRestarting,则
My.Settings.IsRestarting=False
My.Settings.Save()
线程。睡眠(3000)
如果结束
如果不是SingleInstance.Start(),则
SingleInstance.ShowFirstInstance()
e、 取消=真
如果结束
端接头
私有子MyApplication_Shutdown(发送方作为对象,e作为EventArgs)处理我。Shutdown
SingleInstance.Stop()
端接头
末级
结束命名空间
公共不可继承类SingleInstance
公共共享只读WM_SHOWFIRSTINSTANCE As Integer=WinApi.RegisterWindowMessage(“WM_SHOWFIRSTINSTANCE |{0}”,ProgramInfo.AssemblyGuid)
作为互斥体的私有共享互斥体
作为布尔值的公共共享函数Start()
Dim lIsOnlyInstance作为布尔值
将名称设置为字符串
lIsOnlyInstance=False
sMutexName=String.Format(“本地\{0}”,ProgramInfo.AssemblyGuid)
“如果你希望你的应用程序仅限于一个实例
'跨所有会话(多用户和终端服务),
'然后改为使用以下行:
'sMutexName=String.Format(“全局\\{0}”,ProgramInfo.AssemblyGuid);
互斥量=新互斥量(True、sMutexName、lIsOnlyInstance)
返回lIsOnlyInstance
端函数
公共共享子ShowFirstInstance()
PostMessage(新的IntPtr(WinApi.HWND_广播),WM_SHOWFIRSTINSTANCE,IntPtr.Zero,IntPtr.Zero)
端接头
公共共享子[停止]()
Mutex.Close()
端接头
末级
公共不可继承类WinApi
_
公共共享函数RegisterWindowMessage(消息为字符串)为整数
端函数
_
作为布尔值的公共共享函数PostMessage(hwnd作为IntPtr,msg作为Integer,wparam作为IntPtr,lparam作为IntPtr)
端函数
_
作为布尔值的公共共享函数ShowWindow(hWnd作为IntPtr,nCmdShow作为Integer)
端函数
_
公共共享函数SetForegroundWindow(hWnd作为IntPtr)作为布尔值
端函数
公共共享函数RegisterWindowMessage(模板为字符串,ParamArray值为Object())为整数
返回RegisterWindowMessage(String.Format(模板,值))
端函数
公共共享子showtoron
Friend Class Main
  Inherits System.Windows.Forms.Form

  Protected Overrides Sub WndProc(ByRef Message As Message)
    If Message.Msg = SingleInstance.WM_SHOWFIRSTINSTANCE Then
      ShowWindow()
    End If
    MyBase.WndProc(Message)
  End Sub

  Private Sub ShowWindow()
    Me.WindowState = FormWindowState.Normal
    Me.Focus()
  End Sub

  Private Sub cmdUpdate_Click(Sender As Object, e As EventArgs) Handles cmdUpdate.Click
    If ApplicationDeployment.IsNetworkDeployed Then
      If ApplicationDeployment.CurrentDeployment.CheckForUpdate(False)
        ApplicationDeployment.CurrentDeployment.Update()

        MsgBox("The application has been updated and will now restart.", MsgBoxStyle.Information)

        My.Settings.IsRestarting = True
        My.Settings.Save()

        Application.Restart()
      End If
    End If
  End Sub
End Class

Namespace My
  ' The following events are availble for MyApplication:
  ' 
  ' Startup: Raised when the application starts, before the startup form is created.
  ' Shutdown: Raised after all application forms are closed.  This event is not raised if the application terminates abnormally.
  ' UnhandledException: Raised if the application encounters an unhandled exception.
  ' StartupNextInstance: Raised when launching a single-instance application and the application is already active. 
  ' NetworkAvailabilityChanged: Raised when the network connection is connected or disconnected.
  Partial Friend Class MyApplication
    Private Sub MyApplication_Startup(sender As Object, e As ApplicationServices.StartupEventArgs) Handles Me.Startup
      If My.Settings.IsRestarting Then
        My.Settings.IsRestarting = False
        My.Settings.Save()
        Thread.Sleep(3000)
      End If

      If Not SingleInstance.Start() Then
        SingleInstance.ShowFirstInstance()
        e.Cancel = True
      End If
    End Sub

    Private Sub MyApplication_Shutdown(sender As Object, e As EventArgs) Handles Me.Shutdown
      SingleInstance.Stop()
    End Sub
  End Class
End Namespace

Public NotInheritable Class SingleInstance
  Public Shared ReadOnly WM_SHOWFIRSTINSTANCE As Integer = WinApi.RegisterWindowMessage("WM_SHOWFIRSTINSTANCE|{0}", ProgramInfo.AssemblyGuid)
  Private Shared Mutex As Mutex

  Public Shared Function Start() As Boolean
    Dim lIsOnlyInstance As Boolean
    Dim sMutexName As String

    lIsOnlyInstance = False
    sMutexName = String.Format("Local\{0}", ProgramInfo.AssemblyGuid)

    ' If you want your app to be limited to a single instance
    ' across ALL SESSIONS (multiple users & terminal services),
    ' then use the following line instead:
    ' sMutexName = String.Format("Global\\{0}", ProgramInfo.AssemblyGuid);

    Mutex = New Mutex(True, sMutexName, lIsOnlyInstance)
    Return lIsOnlyInstance
  End Function

  Public Shared Sub ShowFirstInstance()
    WinApi.PostMessage(New IntPtr(WinApi.HWND_BROADCAST), WM_SHOWFIRSTINSTANCE, IntPtr.Zero, IntPtr.Zero)
  End Sub

  Public Shared Sub [Stop]()
    Mutex.Close()
  End Sub
End Class

Public NotInheritable Class WinApi
  <DllImport("user32")> _
  Public Shared Function RegisterWindowMessage(message As String) As Integer
  End Function

  <DllImport("user32")> _
  Public Shared Function PostMessage(hwnd As IntPtr, msg As Integer, wparam As IntPtr, lparam As IntPtr) As Boolean
  End Function

  <DllImport("user32")> _
  Public Shared Function ShowWindow(hWnd As IntPtr, nCmdShow As Integer) As Boolean
  End Function

  <DllImport("user32")> _
  Public Shared Function SetForegroundWindow(hWnd As IntPtr) As Boolean
  End Function

  Public Shared Function RegisterWindowMessage(Template As String, ParamArray Values As Object()) As Integer
    Return RegisterWindowMessage(String.Format(Template, Values))
  End Function

  Public Shared Sub ShowToFront(Window As IntPtr)
    ShowWindow(Window, SW_SHOWNORMAL)
    SetForegroundWindow(Window)
  End Sub

  Public Const HWND_BROADCAST As Integer = &HFFFF
  Public Const SW_SHOWNORMAL As Integer = 1
End Class

Public NotInheritable Class ProgramInfo
  Public Shared ReadOnly Property AssemblyGuid As String
    Get
      Dim aAttributes As Object()

      aAttributes = Assembly.GetEntryAssembly.GetCustomAttributes(GetType(GuidAttribute), False)

      If aAttributes.Length = 0 Then
        AssemblyGuid = String.Empty
      Else
        AssemblyGuid = DirectCast(aAttributes(0), GuidAttribute).Value
      End If
    End Get
  End Property
End Class