我通过取消选中发布属性The application should check for updates
来禁用Visual Studio中的更新检查。
我的应用检查更新,用户必须选择拒绝更新。
问题是,当用户跳过更新时,下次启动应用程序时,将再次显示默认的ClickOnce更新屏幕。
如何确保它永远不会显示默认的ClickOnce更新对话框?
我的更新代码:
private void CheckForUpdates()
{
if (!ApplicationDeployment.IsNetworkDeployed)
{
return;
}
var currentDeployment = ApplicationDeployment.CurrentDeployment;
UpdateCheckInfo info;
try
{
info = currentDeployment.CheckForDetailedUpdate();
}
catch (Exception e)
{
return;
}
if (!info.UpdateAvailable)
{
return;
}
var changelogDialog = new Changelog();
if (changelogDialog.ShowDialog() != true)
{
return;
}
currentDeployment.Update();
Exit();
}
这是我的清单:
<?xml version="1.0" encoding="utf-8"?>
<asmv1:assembly xsi:schemaLocation="urn:schemas-microsoft-com:asm.v1 assembly.adaptive.xsd" manifestVersion="1.0" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns="urn:schemas-microsoft-com:asm.v2" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xrml="urn:mpeg:mpeg21:2003:01-REL-R-NS" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:co.v1="urn:schemas-microsoft-com:clickonce.v1" xmlns:co.v2="urn:schemas-microsoft-com:clickonce.v2">
<assemblyIdentity name="test.ccpl.Desktop.application" version="1.0.0.89" publicKeyToken="7613da056444d824" language="en-CA" processorArchitecture="x86" xmlns="urn:schemas-microsoft-com:asm.v1" />
<description asmv2:publisher="test ccpl" co.v1:suiteName="test" asmv2:product="test ccpl" xmlns="urn:schemas-microsoft-com:asm.v1" />
<deployment install="true" mapFileExtensions="true" co.v1:createDesktopShortcut="true">
<deploymentProvider codebase="https://test-test.test.ca/Installers/test.ccpl.Desktop.application" />
</deployment>
<dependency>
<dependentAssembly dependencyType="install" codebase="Application Files\test.ccpl.Desktop_1_0_0_89\test.ccpl.Desktop.exe.manifest" size="58997">
<assemblyIdentity name="test.ccpl.Desktop.exe" version="1.0.0.89" publicKeyToken="7613da056444d824" language="en-CA" processorArchitecture="x86" type="win32" />
<hash>
<dsig:Transforms>
<dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
</dsig:Transforms>
<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<dsig:DigestValue>u36JKY4n1mmu2LZC3Ea5uRLheiM=</dsig:DigestValue>
</hash>
</dependentAssembly>
</dependency>
<compatibleFrameworks xmlns="urn:schemas-microsoft-com:clickonce.v2">
<framework targetVersion="4.7.2" profile="Full" supportedRuntime="4.0.30319" />
</compatibleFrameworks>
<publisherIdentity ...>
答案 0 :(得分:4)
我认为您所看到的一切都是设计使然。
调用currentDeployment.CheckForDetailedUpdate()
后,clickonce会将该更新元数据存储在注册表中。在下次启动时,clickonce将始终查看此信息,以查看是否有挂起的部署,如果有,则还将确定用户是否已跳过此较新版本。不管您是否愿意,这都是设计使然。
但是,如果您真的想摆脱启动时的clickonce更新对话框,那么可以使用一个丑陋的解决方案:-) 更新:请参见下面的第二种解决方法。
首先,让我们看一下注册表以及一切工作原理:
导航到该位置:
HKEY_CURRENT_USER\Software\Classes\Software\Microsoft\Windows\CurrentVersion\Deployment\SideBySide\2.0\PackageMetadata\{2ec93463-b0c3-45e1-8364-327e96aea856}_{3f471841-eef2-47d6-89c0-d028f03a4ad5}\
对于每个已安装的clickonce应用程序,您将看到3个子键。
在我的情况下,该应用程序称为WindowsApplication,公共密钥令牌为a619d47505395849。因此,要查找的重要密钥始于wind..tion_a619d47505395849_
您应该会看到类似于 test..tion_7613da056444d824_xxxxxxxxxx 的内容。只需遍历密钥,查找公共密钥令牌并选择最短的密钥即可。
现在是重要的部分。查看名称以!PendingDeployment
结尾的值。调用CheckForDetailedUpdate
方法后,它应如下所示:
这就是显示“更新对话框”的原因。
然后将其替换为该值即可完成
然后将不再显示“更新”对话框。用户可以在应用程序中手动检查更新,一次又一次接受或忽略它。
您可以手动测试这些步骤,以查看是否一切正常。将其放入代码应类似于以下内容:
var changelogDialog = new Changelog();
if (changelogDialog.ShowDialog() != true)
{
RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Classes\Software\Microsoft\Windows\CurrentVersion\Deployment\SideBySide\2.0\PackageMetadata\{2ec93463-b0c3-45e1-8364-327e96aea856}_{3f471841-eef2-47d6-89c0-d028f03a4ad5}");
var subkeyName = key.GetSubKeyNames().Where(x => x.Contains("7613da056444d824")).OrderBy(x => x.Length).First();
var subkey = key.OpenSubKey(subkeyName, true);
subkey.SetValue("{2ad613da-6fdb-4671-af9e-18ab2e4df4d8}!PendingDeployment", new byte[] { 00, 00 }, RegistryValueKind.Binary);
return;
}
另一种解决方法:
您可以创建自己的“ CheckForUpdate”方法,而不是调用内置函数CheckForDetailedUpdate()
。没什么大不了的:
private CustomUpdateCheckInfo CheckForUpdate()
{
var info = new CustomUpdateCheckInfo();
var currentVersion = ApplicationDeployment.CurrentDeployment.CurrentVersion;
var manifestUri = ApplicationDeployment.CurrentDeployment.UpdateLocation;
using (XmlTextReader reader = new XmlTextReader(manifestUri.AbsoluteUri))
{
var doc = XDocument.Load(reader);
var version = doc.Descendants().FirstOrDefault(n => n.Name.LocalName == "assemblyIdentity").Attribute("version").Value;
info.NewestVersion = version;
info.IsUpdateAvailable = currentVersion.ToString() != version;
}
return info;
}
它将比较清单文件中当前部署的版本和最新版本,并返回CustomUpdateCheckInfo
的实例:
public class CustomUpdateCheckInfo
{
public bool IsUpdateAvailable { get; set; }
public string NewestVersion { get; set; }
}