這很可能是因爲您在ClickOnce部署的應用程序中使用了VB的本機單實例應用程序功能。該功能使用了引擎蓋下的Mutex
,該應用程序不能及時發佈以重新啓動應用程序。因此,你看到的行爲 - 它不會重新啓動。
我剛纔也有同樣的問題。爲了解決這個問題,我不得不使用VB翻譯,並且稍微修改了我發現的技巧here。實質上,我們需要的是Mutex
的共享實例和Application.Restart()
上的3秒暫停,以便讓現有版本發佈其Mutex
。不要忘記在項目的Property Pages的Application選項卡上UNCHECK '製作單實例應用程序'。
這是我最後的代碼,如下。通過這種方式,我們可以擁有最好的世界 - 我們非常喜歡的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
你是什麼意思重啓不起作用?怎麼了? – Daniel