我正在使用AppplicationDeployment类来检查升级是否可用,然后升级应用程序,如下所示
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中创建新文件夹....我知道。但是,需要获取此路径并更新注册表。
任何人都有任何指示?
答案 0 :(得分:0)
您可以尝试重新启动应用程序,如下所示:
Dim applicationEntryPoint = ApplicationDeployment.CurrentDeployment.UpdatedApplicationFullName
Process.Start(applicationEntryPoint)
// Call any code to shut down the current instance of the application here...
答案 1 :(得分:0)
我建议在它调用Application.Restart的位置加入某种消息框或跟踪,以确保它真正调用它。如果您验证了它,但它仍然无效,那么您是否可能锁定某些内容并且在关闭之前不会重新启动?
答案 2 :(得分:0)
这很可能是因为您在ClickOnce部署的应用中使用了VB的原生单实例应用功能。该功能使用了引擎盖下的Mutex
,它不会及时释放,以便应用重启。因此,您所看到的行为 - 它不会重新启动。
我刚才遇到了同样的问题。为了解决这个问题,我不得不使用VB翻译并轻微改写我发现的here技巧。实质上我们需要的是Mutex
的共享实例和Application.Restart()
上的3秒暂停,以便让退出版本时间释放其Mutex
。不要忘记在项目的属性页的“应用程序”选项卡上取消选中'单个实例应用程序' 。
以下是我最终提供的代码。通过这种方式,我们可以拥有最好的世界 - 我们非常喜欢VB的漂亮应用程序框架,单实例功能和ClickOnce API重新启动。一次全部。我是个傻瓜。
帽子提示#1: devzoo ,对于他的CodeProject posting,展示了主要概念。
帽子提示#2: NullFX ,对于他的WinApi PostMessage() idea,由 devzoo 引用。
帽子提示#3: @ cmptrs4now 为IsRestarting
3秒暂停提示here。
帽子提示#4: @pstrjds 澄清here。根据他的建议,我将Mutex.ReleaseMutex()
更改为Mutex.Close()
以下。这看起来更安全。
HTH
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