2013-10-14 3 views
0

Я использую AppplicationDeployment класс, чтобы проверить, если обновление доступно, а затем обновить приложение, как показано нижеClickonce приложение не запускается после завершения обновления

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

Что вы имеете в виду, что перезапуск не работает? Что происходит? – Daniel

ответ

0

Вы можете попробовать перезапустить приложение так:

Dim applicationEntryPoint = ApplicationDeployment.CurrentDeployment.UpdatedApplicationFullName 

Process.Start(applicationEntryPoint) 

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

Нет, это также не работает. Есть ли способ получить обновленный исполняемый путь? – user2817774

+0

Вместо сохранения исполняемого файла приложения я сохранил ниже путь к реестру .., который решил мою проблему. Environment.GetFolderPath (Environment.SpecialFolder.Programs) + "\ Your publisher \ app_name.appref-ms" – user2817774

0

Я рекомендую поместить в какой-то в MessageBox или трассировку в точке, где она называет Application.Restart, чтобы убедиться, что это действительно называют это. Если вы подтвердите это и все еще не сработаете, возможно, у вас есть что-то заблокированное, и оно не будет перезапущено, пока оно не будет закрыто?

0

Это, скорее всего, из-за того, что вы используете приложение VB для одиночного экземпляра приложения в вашем приложении, использующем ClickOnce. Функция использует Mutex под капотом, который не освобождается вовремя, чтобы приложение перезапустилось. Таким образом, поведение, которое вы видите, оно не перезапускается.

У меня была такая же проблема только сейчас. Чтобы исправить это, мне пришлось использовать перевод VB и небольшую переделку трюка, который я нашел here. По сути, нам нужен общий экземпляр Mutex и 3-секундная пауза на Application.Restart(), чтобы дать выходному времени версии для выпуска своего Mutex. Не забудьте UNCHECK «Сделать одно приложение экземпляра» на вкладке «Приложение» на странице свойств вашего проекта.

enter image description here

Вот код, который я закончил с, ниже. Таким образом, у нас может быть лучший из всех миров - отличная прикладная структура VB, которой так много нравится, функция Single-Instance и ClickOnce API перезагружаются. Все вместе. Я головокружен.

Hat tip # 1: To devzoo, для его CodeProject posting, демонстрируя основную концепцию.

Hat Совет № 2: Для NullFX за его WinApi PostMessage() idea, как указано devzoo.

Hat Совет № 3: Чтобы @ cmptrs4now за IsRestarting 3-секундной идеи паузы here.

Кончик шляпы # 4: до @pstrjds для уточнения here. По его совету я изменил Mutex.ReleaseMutex() на Mutex.Close() ниже. Это выглядит безопаснее.

НТН

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 
Смежные вопросы