Compare commits

...

3 Commits

Author SHA1 Message Date
PointStar 2228353c48 fix(updater): check for updates on every Outlook startup, not every 7 days
Why v1.2.7→v1.2.8 didn't auto-install on Outlook restart: the manifest
was published with <UpdateInterval>7</UpdateInterval> + units=days, which
tells the VSTO runtime "don't even check the manifest URL more often
than once a week." MinimumRequiredVersion (set by CI to the same tag
version) would have forced the install — but only AFTER the check runs,
and the check was throttled to weekly.

Replace UpdateInterval/UpdateIntervalUnits with UpdatePeriodically=false.
This omits the <expiration> element from the deployment manifest, which
ClickOnce/VSTO interprets as "check before every host start." The extra
HTTP GET on the .vsto manifest at Outlook launch is ~6KB, ~100ms — a
non-issue for startup time, vs. the previous behavior where new
releases sat unused on platform.dev for up to a week per user.

From v1.2.9 onward, tag → CI publishes → next Outlook launch on each
lawyer's PC installs it. This is what we wanted the auto-update chain
to look like all along.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 20:50:31 +03:00
PointStar eea0d92d85 publish: 1.2.8 — verify v1.2.7's restart-to-update flow end-to-end
No code change. Confirms that on a clean v1.2.7 install (correct
simplified updater), pressing "בדוק עדכונים" reports the new version
honestly, and the VSTO runtime auto-installs v1.2.8 on the next
Outlook startup with no errors.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 20:40:58 +03:00
PointStar 655fefa822 fix(updater): stop trying to install in-process; tell user to restart Outlook
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 <url>       → 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) <noreply@anthropic.com>
2026-05-24 20:17:32 +03:00
3 changed files with 23 additions and 85 deletions
@@ -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
}
}
/// <summary>
/// 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.
/// </summary>
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)
+2 -3
View File
@@ -36,11 +36,10 @@
<PublishUrl>C:\Users\Chaim\source\repos\OutlookAddin\Publish\</PublishUrl>
<InstallUrl>https://gitea.dev.marcus-law.co.il/espocrm-extensions/OutlookAddin/raw/branch/main/Publish/</InstallUrl>
<TargetCulture>en</TargetCulture>
<ApplicationVersion>1.2.6.0</ApplicationVersion>
<ApplicationVersion>1.2.9.0</ApplicationVersion>
<AutoIncrementApplicationRevision>false</AutoIncrementApplicationRevision>
<UpdateEnabled>true</UpdateEnabled>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<ProductName>MarcusLaw.OutlookAddin</ProductName>
<PublisherName />
<SupportUrl />
+2 -2
View File
@@ -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.9.0")]
[assembly: AssemblyFileVersion("1.2.9.0")]