|
|
|
@@ -1,6 +1,7 @@
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Collections.ObjectModel;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Net.Http;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using System.Windows.Media;
|
|
|
|
@@ -178,18 +179,61 @@ namespace MarcusLaw.OutlookAddin.UI.ViewModels
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var deployment = System.Deployment.Application.ApplicationDeployment.CurrentDeployment;
|
|
|
|
|
var info = await Task.Run(() => deployment.CheckForDetailedUpdate(false)).ConfigureAwait(true);
|
|
|
|
|
if (!info.UpdateAvailable)
|
|
|
|
|
var currentVersion = deployment.CurrentVersion;
|
|
|
|
|
var manifestUri = deployment.UpdateLocation;
|
|
|
|
|
|
|
|
|
|
// ApplicationDeployment.CheckForDetailedUpdate triggers a
|
|
|
|
|
// TrustManager re-evaluation which throws TrustNotGranted
|
|
|
|
|
// inside a hosted VSTO process even when the publisher and
|
|
|
|
|
// permissions are unchanged. Bypass it by fetching the
|
|
|
|
|
// deployment manifest directly and reading the version.
|
|
|
|
|
Version? availableVersion = null;
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
UpdateStatusBrush = SuccessBrush;
|
|
|
|
|
UpdateStatus = "אתה על הגרסה האחרונה (" + deployment.CurrentVersion + ").";
|
|
|
|
|
availableVersion = await Task.Run(() => FetchManifestVersion(manifestUri)).ConfigureAwait(true);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception fetchEx)
|
|
|
|
|
{
|
|
|
|
|
_logger.Warning(fetchEx, "CheckForUpdate: manifest fetch failed");
|
|
|
|
|
UpdateStatusBrush = ErrorBrush;
|
|
|
|
|
UpdateStatus = "שגיאה בבדיקת השרת: " + fetchEx.Message;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UpdateStatus = $"זמינה גרסה {info.AvailableVersion} — מוריד…";
|
|
|
|
|
var result = await Task.Run(() => deployment.Update()).ConfigureAwait(true);
|
|
|
|
|
UpdateStatusBrush = SuccessBrush;
|
|
|
|
|
UpdateStatus = $"הותקנה גרסה {info.AvailableVersion}. סגור ופתח את Outlook כדי לטעון אותה.";
|
|
|
|
|
if (availableVersion == null)
|
|
|
|
|
{
|
|
|
|
|
UpdateStatusBrush = ErrorBrush;
|
|
|
|
|
UpdateStatus = "לא ניתן לקרוא את גרסת השרת מ-" + manifestUri;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (availableVersion <= currentVersion)
|
|
|
|
|
{
|
|
|
|
|
UpdateStatusBrush = SuccessBrush;
|
|
|
|
|
UpdateStatus = "אתה על הגרסה האחרונה (" + currentVersion + ").";
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// VSTO add-ins cannot be updated programmatically from inside
|
|
|
|
|
// a running Outlook — ApplicationDeployment.Update() throws.
|
|
|
|
|
// Open the .vsto URL via the shell; Windows hands it to
|
|
|
|
|
// VSTOInstaller.exe which installs the update correctly.
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(manifestUri.ToString())
|
|
|
|
|
{
|
|
|
|
|
UseShellExecute = true
|
|
|
|
|
});
|
|
|
|
|
UpdateStatusBrush = SuccessBrush;
|
|
|
|
|
UpdateStatus = $"זמינה גרסה {availableVersion} — אשר את ההתקנה בחלון שנפתח, ואז סגור ופתח את Outlook.";
|
|
|
|
|
}
|
|
|
|
|
catch (Exception launchEx)
|
|
|
|
|
{
|
|
|
|
|
_logger.Warning(launchEx, "CheckForUpdate: shell launch of installer URL failed");
|
|
|
|
|
UpdateStatusBrush = ErrorBrush;
|
|
|
|
|
UpdateStatus = $"זמינה גרסה {availableVersion} אבל לא הצלחנו לפתוח את חלון ההתקנה. גש ידנית ל-{manifestUri}";
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
catch (System.Deployment.Application.DeploymentDownloadException ex)
|
|
|
|
|
{
|
|
|
|
@@ -215,6 +259,33 @@ namespace MarcusLaw.OutlookAddin.UI.ViewModels
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Reads the top-level <assemblyIdentity> version from the
|
|
|
|
|
/// .vsto deployment manifest at <paramref name="manifestUri"/>.
|
|
|
|
|
/// Returns null if the document doesn't look like a deployment
|
|
|
|
|
/// manifest. Runs on a worker thread (synchronous HTTP).
|
|
|
|
|
/// </summary>
|
|
|
|
|
private static Version? FetchManifestVersion(Uri manifestUri)
|
|
|
|
|
{
|
|
|
|
|
// The .vsto manifest is small (≈6KB). Keep this synchronous —
|
|
|
|
|
// no point pulling in HttpClient and its lifecycle just for one
|
|
|
|
|
// GET. WebRequest works fine on .NET FW 4.8 and through proxies.
|
|
|
|
|
var req = System.Net.WebRequest.Create(manifestUri);
|
|
|
|
|
req.Timeout = 10_000;
|
|
|
|
|
using (var response = req.GetResponse())
|
|
|
|
|
using (var stream = response.GetResponseStream())
|
|
|
|
|
{
|
|
|
|
|
var doc = System.Xml.Linq.XDocument.Load(stream);
|
|
|
|
|
System.Xml.Linq.XNamespace asmv1 = "urn:schemas-microsoft-com:asm.v1";
|
|
|
|
|
var identity = doc.Root?
|
|
|
|
|
.Elements()
|
|
|
|
|
.FirstOrDefault(e => e.Name.LocalName == "assemblyIdentity" && e.Name.Namespace == asmv1);
|
|
|
|
|
var versionAttr = identity?.Attribute("version")?.Value;
|
|
|
|
|
if (string.IsNullOrWhiteSpace(versionAttr)) return null;
|
|
|
|
|
return Version.TryParse(versionAttr, out var v) ? v : null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool CanCheckForUpdate() => !IsCheckingForUpdate;
|
|
|
|
|
|
|
|
|
|
partial void OnIsCheckingForUpdateChanged(bool value)
|
|
|
|
|