From 655fefa822ae10b37ee43c7a1f2107a3ab889918 Mon Sep 17 00:00:00 2001 From: PointStar Date: Sun, 24 May 2026 20:17:32 +0300 Subject: [PATCH] fix(updater): stop trying to install in-process; tell user to restart Outlook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v1.2.6 fired VSTOInstaller.exe /I directly. It returned 0x8007007E (ERROR_MOD_NOT_FOUND) — the loaded add-in DLLs are file-locked by the running Outlook, so even the canonical installer can't overwrite them while the host is up. This caps a series of failed attempts: - 1.2.0/1/2: ApplicationDeployment.Update() → TrustNotGrantedException - 1.2.3/4: Process.Start(.vsto URL, shell) → Chrome downloads to local-machine zone → InvalidDeploymentException - 1.2.5/6: VSTOInstaller.exe /I → 0x8007007E file lock There is no API that updates a running VSTO add-in. The VSTO runtime's own auto-update path (check manifest on Outlook startup, install before loading) is the only mechanism that works — and it already does, every time the user restarts Outlook. So the button now just detects the new version via manifest HTTP GET and displays "זמינה גרסה X. סגור ופתח את Outlook — הגרסה החדשה תותקן אוטומטית בעלייה." No install attempt, no spawned process, no zone or trust dance. The status line is honest about what the user has to do. Removed the now-unused FindVstoInstaller registry-walk helper. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../ViewModels/SettingsViewModel.cs | 99 ++++--------------- src/OutlookAddin/OutlookAddin.csproj | 2 +- src/OutlookAddin/Properties/AssemblyInfo.cs | 4 +- 3 files changed, 22 insertions(+), 83 deletions(-) diff --git a/src/OutlookAddin.UI/ViewModels/SettingsViewModel.cs b/src/OutlookAddin.UI/ViewModels/SettingsViewModel.cs index 504b5b4..a0b8258 100644 --- a/src/OutlookAddin.UI/ViewModels/SettingsViewModel.cs +++ b/src/OutlookAddin.UI/ViewModels/SettingsViewModel.cs @@ -214,42 +214,25 @@ namespace MarcusLaw.OutlookAddin.UI.ViewModels return; } - // VSTO add-ins cannot be updated programmatically from inside - // a running Outlook — ApplicationDeployment.Update() throws. - // Don't shell-launch the .vsto URL either: Chrome / Edge will - // download it to disk, and the resulting file has a different - // security zone than the deployment manifest, which fails with - // InvalidDeploymentException ("no matching security zones"). - // Call VSTOInstaller.exe directly so the URL is processed in - // the Internet zone, matching the manifest. - var installerPath = FindVstoInstaller(); - if (installerPath != null) - { - try - { - System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo( - installerPath, "/I \"" + manifestUri + "\"") - { - UseShellExecute = false - }); - UpdateStatusBrush = SuccessBrush; - UpdateStatus = $"זמינה גרסה {availableVersion} — אשר את ההתקנה בחלון שנפתח, ואז סגור ופתח את Outlook."; - } - catch (Exception launchEx) - { - _logger.Warning(launchEx, "CheckForUpdate: VSTOInstaller launch failed"); - UpdateStatusBrush = ErrorBrush; - UpdateStatus = $"זמינה גרסה {availableVersion} — סגור ופתח את Outlook כדי להתקין אוטומטית."; - } - } - else - { - // VSTOInstaller not at the canonical path — VSTO runtime - // still picks up new manifests on Outlook startup, so - // ask the user to restart instead of attempting a hack. - UpdateStatusBrush = SuccessBrush; - UpdateStatus = $"זמינה גרסה {availableVersion} — סגור ופתח את Outlook כדי להתקין אוטומטית."; - } + // A running Outlook holds file locks on the loaded add-in + // DLLs. Neither ApplicationDeployment.Update (TrustNotGranted) + // nor a direct VSTOInstaller.exe /I call (0x8007007E + // ERROR_MOD_NOT_FOUND) nor Process.Start(.vsto URL) (Chrome + // downloads to local-machine zone — InvalidDeploymentException) + // can install over those locks. The only path that actually + // works is the one VSTO runtime takes automatically on Outlook + // startup: it checks the manifest URL before loading the + // add-in, downloads + installs if there's a newer version, + // then loads it. + // + // So the button's job is just to tell the user: "close and + // reopen Outlook." That's the same flow the user has been + // doing manually all along; we're just confirming the new + // version is there waiting. + UpdateStatusBrush = SuccessBrush; + UpdateStatus = + $"זמינה גרסה {availableVersion}. סגור ופתח את Outlook — " + + "הגרסה החדשה תותקן אוטומטית בעלייה."; return; } catch (System.Deployment.Application.DeploymentDownloadException ex) @@ -303,50 +286,6 @@ namespace MarcusLaw.OutlookAddin.UI.ViewModels } } - /// - /// Locates VSTOInstaller.exe on the machine. The path is stable - /// for VSTO 4.0 (Office 2010+) — falls back to a registry lookup - /// if the default install location was customised. - /// - private static string? FindVstoInstaller() - { - string[] candidates = - { - @"C:\Program Files (x86)\Common Files\Microsoft Shared\VSTO\10.0\VSTOInstaller.exe", - @"C:\Program Files\Common Files\Microsoft Shared\VSTO\10.0\VSTOInstaller.exe" - }; - foreach (var p in candidates) - { - if (System.IO.File.Exists(p)) return p; - } - - // Registry fallback: HKCR\VstoFile\shell\Open\command stores - // the verb VSTOInstaller registers for the .vsto extension. - try - { - using (var key = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(@"VstoFile\shell\Open\command")) - { - var cmd = key?.GetValue(null) as string; - if (!string.IsNullOrEmpty(cmd)) - { - // Value looks like: "C:\...\VSTOInstaller.exe" "%1" - var firstQuote = cmd!.IndexOf('"'); - if (firstQuote == 0) - { - var endQuote = cmd.IndexOf('"', 1); - if (endQuote > 1) - { - var exe = cmd.Substring(1, endQuote - 1); - if (System.IO.File.Exists(exe)) return exe; - } - } - } - } - } - catch { /* registry access denied or schema differs — fall through */ } - return null; - } - private bool CanCheckForUpdate() => !IsCheckingForUpdate; partial void OnIsCheckingForUpdateChanged(bool value) diff --git a/src/OutlookAddin/OutlookAddin.csproj b/src/OutlookAddin/OutlookAddin.csproj index 1c379fa..215b58c 100644 --- a/src/OutlookAddin/OutlookAddin.csproj +++ b/src/OutlookAddin/OutlookAddin.csproj @@ -36,7 +36,7 @@ C:\Users\Chaim\source\repos\OutlookAddin\Publish\ https://gitea.dev.marcus-law.co.il/espocrm-extensions/OutlookAddin/raw/branch/main/Publish/ en - 1.2.6.0 + 1.2.7.0 false true 7 diff --git a/src/OutlookAddin/Properties/AssemblyInfo.cs b/src/OutlookAddin/Properties/AssemblyInfo.cs index 106a786..23625a2 100644 --- a/src/OutlookAddin/Properties/AssemblyInfo.cs +++ b/src/OutlookAddin/Properties/AssemblyInfo.cs @@ -33,6 +33,6 @@ using System.Security; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.2.6.0")] -[assembly: AssemblyFileVersion("1.2.6.0")] +[assembly: AssemblyVersion("1.2.7.0")] +[assembly: AssemblyFileVersion("1.2.7.0")]