以编程方式更新 ClickOnce 应用程序的部署清单会导致缺少 4.0 中所需的 <兼容框架> 元素

2024-05-09

我正在致力于自动化 .NET 4.0 ClickOnce WPF 应用程序的安装程序,该应用程序需要在应用程序配置文件。我经历了寻找必须遵循的具体步骤的棘手过程Mage.exe http://msdn.microsoft.com/en-us/library/acz3y3te.aspx(即更新并重新签署应用程序和部署清单),现在正在尝试自动化安装。

我选择使用.deploy扩展以尽量减少问题IIS http://en.wikipedia.org/wiki/Internet_Information_Services/Internet Explorer安全机制,所以本质上算法如下(基于在 ClickOnce 中签署和重新签署清单 (Saurabh Bhatia) http://blogs.msdn.com/b/vsto/archive/2009/04/29/signing-and-re-signing-manifests-in-clickonce.aspx and 使用 Mage 或 MageUI 更新 ClickOnce WPF 应用程序的配置 http://www.eggheadcafe.com/tutorials/xaml/a8788ed5-c1b5-41d5-b49c-ea4760c3b820/update-configuration-of-a-clickonce-wpf-application-using-mage-or-mageui.aspx,作为主要来源):

  1. 前往\Application Files\App_%HighestVersion%\ folder
  2. Remove .deploy具有该扩展名的文件
  3. Run  mage -u %app%.exe.manifest -cf cert.pfx
  4. Restore .deploy扩大
  5. Run  mage -u %app%.application -appm %app%.exe.manifest -cf cert.pfx
  6. Copy %app%.application向上 2 级(至..\..- 部署根)

如果手动完成,效果非常好。我可以运行一个.cmd文件,根据环境细节(路径等)定制,但是我需要包括mage.exe在部署中,微软是否允许我们这样做对我来说是一个悬而未决的问题。因此,我试图在Installer class:

X509Certificate2 ct = new X509Certificate2(sPathCert);

//  .. Remove .deploy extension (for files in the sPathApp folder).

sPathMft = Directory.GetFiles(sPathApp, "*.exe.manifest")[0];
ApplicationManifest am = ManifestReader.ReadManifest( "ApplicationManifest", sPathMft, false ) as ApplicationManifest;
if (am == null)
    throw new ArgumentNullException("AppManifest");
am.ResolveFiles();
am.UpdateFileInfo( );
ManifestWriter.WriteManifest(am, sPathMft);
SecurityUtilities.SignFile(ct, null, sPathMft);

//    .. Restore .deploy extensions to files touched above.

sPathMft = Directory.GetFiles(sPathApp, "*.application")[0];
DeployManifest dm = ManifestReader.ReadManifest("DeployManifest", sPathMft, false) as DeployManifest;
if (dm == null)
    throw new ArgumentNullException( "DplManifest" );
dm.ResolveFiles();
dm.UpdateFileInfo();
ManifestWriter.WriteManifest(dm, sPathMft);
SecurityUtilities.SignFile(ct, null, sPathMft);

File.Copy(sPathMft, sPathBin + "\\" + dm.AssemblyIdentity.Name, true);

现在,这是关键点。除了第 5 步之外,一切都运行良好。当应用程序下载到用户的计算机时,部署清单出现问题:

  • 部署清单在语义上无效。
  • 部署清单缺少 。

事实上,该部分已不再存在(但是,它位于原始的 %app%.application 中!)。类似的结果描述于ClickOnce - .NET 4.0 错误:“部署清单在语义上无效”和“部署清单缺少 ” http://blogs.msdn.com/b/msiclickonce/archive/2010/08/03/clickonce-net-4-0-errors-quot-deployment-manifest-is-not-semantically-valid-quot-and-quot-deployment-manifest-is-missing-lt-compatibleframeworks-gt-quot.aspx,但是是不同进程(msbuild)的结果。本节是 4.0 清单的新部分(也是必需的),所以我唯一的猜测是,当 ManifestWriter 将更改持久保存到磁盘时,它会以 3.5 的方式进行吗?我三次检查是否使用了正确的库(C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.0\Microsoft.Build.Tasks.v4.0.dll)。是什么赋予了?

到目前为止,我尝试手动添加缺少的部分来代替答案:

dm.CompatibleFrameworks.Clear(); // Unnecessary as dm.CompatibleFrameworks.Count == 0 indeed!
CompatibleFramework cf = new CompatibleFramework();
cf.Version= "4.0";
cf.SupportedRuntime = "4.0.30319";
cf.Profile= "Client";
dm.CompatibleFrameworks.Add(cf);
cf = new CompatibleFramework();
cf.Version = "4.0";
cf.SupportedRuntime = "4.0.30319";
cf.Profile = "Full";
dm.CompatibleFrameworks.Add(cf);

但这没有任何效果,无论我将这段代码放在哪里,之前dm.ResolveFiles( ), dm.UpdateFileInfo( ) or ManifestWriter.WriteManifest(..)!

我的结果类似于 Stack Overflow 问题MageUI.exe 删除 CompatibleFrameworks 元素 https://stackoverflow.com/questions/6186282/ or 为什么 Mage.exe 不生成兼容框架属性? https://stackoverflow.com/questions/2654320/ or MageUI.exe 不包含兼容的Frameworks 元素 https://stackoverflow.com/questions/3471194/,但我没有使用mageui, mage甚至msbuild at all!

这是怎么回事?


我自己想出来了。罪魁祸首是ManifestReader.ReadManifest(“DeployManifest”, sPathMft,true ).

MSDN http://msdn.microsoft.com/en-us/library/ms125928说,[preserveStream 参数]“指定是否在生成的清单对象的 InputStream 属性中保留输入流。由 ManifestWriter 用于重构未在对象表示中表示的输入。”

抛开措辞,设置true本身还不够:dm.CompatibleFrameworks.Count仍然是 0,但现在添加了CompatibleFramework物品才会有效果!

对于同样情况的其他人,我以前这样做过dm.ResolveFiles( ):

if(  dm.CompatibleFrameworks.Count <= 0  )
{
    CompatibleFramework cf= new CompatibleFramework( );
    cf.Profile= "Client";       cf.Version= "4.0";      cf.SupportedRuntime=    "4.0.30319";
    dm.CompatibleFrameworks.Add( cf );              //  cf= new CompatibleFramework( );
    cf.Profile= "Full";     //  cf.Version= "4.0";      cf.SupportedRuntime=    "4.0.30319";
    dm.CompatibleFrameworks.Add( cf );              /// no need for separate object
}

@davidair,感谢您的建议!同意,尽管我更喜欢使用 API 对象(相对于 XML)。
另一种选择是致电mage(直接或从 .cmd 文件),因为我们似乎被允许 http://msdn.microsoft.com/en-us/library/ff699301.aspx重新分配它。


我还添加了以下部分,这对问题本身没有影响,但对于遵循相同路径的任何人来说可能非常重要(/client是部署根目录,可以自定义):

dm.DeploymentUrl=   string.Format( "http://{0}/{1}/client/{1}.application",
                        Dns.GetHostName( ), Context.Parameters[ scTokVirtDir ] );
dm.UpdateMode=      UpdateMode.Background;
dm.UpdateUnit=      UpdateUnit.Weeks;
dm.UpdateInterval=  1;
dm.UpdateEnabled=   true;

2019年10月8日
刚刚偶然发现一个问题app.manifest:
compatibility部分与supportedOS元素在部署期间被剥离。

根本原因相同;应该设置的行读数preserveStream to true:

ApplicationManifest am = ManifestReader.ReadManifest( "ApplicationManifest", sPathMft, true ) as ApplicationManifest;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

以编程方式更新 ClickOnce 应用程序的部署清单会导致缺少 4.0 中所需的 <兼容框架> 元素 的相关文章

  • 多个源的 makefile

    在学习 make 文件时 我试图为多个源目录编写一个 make 文件 似乎我在某个地方错了 这是我的代码结构 directory common fun2 c inc fun h src fun1 c main c 这是我的生成文件 CC c
  • 添加 Nullable int 时保持 null?

    我想添加可为空的int 并保留null当所有值都是null 我想要这个结果 1 2 3 1 null 1 null null null O null 0 问题是 如果我将一个值与 null 相加 结果为 null int i1 1 int
  • 在 Java 中创建 T 的新实例

    在C 中 我们可以定义一个泛型class A
  • linq 中使用字符串数组 c# 的 'orderby'

    假设我有一个这样的方法定义 public CustomerOrderData GetCustomerOrderData string CustomerIDs var query from a in db Customer join b in
  • 在 C# 中调用 C++ 库 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我有很多用 C 编写的库 我想从 C 调用这些库 但是 我遇到了很多问题 我想知道是否有书籍或指南告诉我如何做到这一点 Dll导入 htt
  • 如何使用 SOAP 且不使用 WSE 在 .NET 中签署 Amazon Web 服务请求

    亚马逊产品广告 API 以前称为 Amazon Associates Web Service 或 Amazon AWS 实施了一项新规则 即自 2009 年 8 月 15 日起 向其发送的所有 Web 服务请求都必须经过签名 他们在其网站上
  • 如何制作可启动程序?

    所以 这个问题可能看起来很奇怪 但假设我编译了 int main void int x 3 int y 4 int z x y 是否可以让CPU这样运行 如何 例如 这允许我写入监视器吗 如果我没记错的话 内存中有些地方可以写入要显示的内容
  • 一元 +/- 运算符如何可能导致“-a”或“+a”中的整数提升,“a”是算术数据类型常量/变量?

    这句看似微不足道的台词摘自我的迈克 巴纳汉和布雷迪的 C 书 第 2 8 8 2 节 http publications gbdirect co uk c book chapter2 expressions and arithmetic h
  • 使用 LINQ 更新 IEnumerable 对象的简单方法

    假设我有一个这样的业务对象 class Employee public string name public int id public string desgination public int grade List
  • MFC:如何设置CEdit框的焦点?

    我正在开发我的第一个简单的 MFC 项目 但我正在努力解决一个问题 想要设置所有的焦点CEdit其中一个对话框中的框 我的想法是 当打开对话框时 焦点位于第一个编辑框上 然后使用 选项卡 在它们之间交换 我看到了方法SetFocus 但我无
  • C#6 中的长字符串插值行

    我发现 虽然字符串插值在应用于现有代码库的字符串 Format 调用时非常好 但考虑到通常首选的列限制 字符串对于单行来说很快就会变得太长 特别是当被插值的表达式很复杂时 使用格式字符串 您将获得一个可以拆分为多行的变量列表 var str
  • 从BackgroundWorker线程更新图像UI属性

    在我正在编写的 WPF 应用程序中 我有一个 TransformedBitmap 属性 该属性绑定到 UI 上的 Image 对象 每当我更改此属性时 图像就会更新 因此显示在屏幕上的图像也会更新 为了防止在检索下一张图像时 UI 冻结或变
  • 英文日期差异

    接近重复 如何计算相对时间 https stackoverflow com questions 11 how do i calculate relative time 如何在 C 中计算某人的年龄 https stackoverflow c
  • ASP.NET MVC 路由:如何从 URL 中省略“索引”

    我有一个名为 StuffController 的控制器 具有无参数索引操作 我希望从表单中的 URL 调用此操作mysite com stuff 我的控制器定义为 public class StuffController BaseContr
  • 逆向工程 ASP.NET Web 应用程序

    我有一个 ASP NET Web 应用程序 我没有源代码 该 bin 包含 10 个程序集和一个 compiled 文件 我在 App Code dll 上使用 Reflector 它向我显示了类和命名空间之类的东西 但它太混乱了 有没有什
  • 如何调试 .NET 运行时中的内部错误?

    我正在尝试调试一些处理大文件的工作 代码本身works 但 NET 运行时本身会报告零星错误 对于上下文 这里的处理是一个 1 5GB 文件 仅加载到内存中一次 在循环中处理和释放 故意尝试重现此否则不可预测的错误 我的测试片段基本上是 t
  • 通过 Tab 键浏览 XML 文档字段

    In VB NET you can move through the fields in the XML member documentation with the Tab key 这在 C 中不起作用 还有其他方法吗 除了用鼠标将光标放在
  • INotifyPropertyChanged 和 propertyName

    我一直不确定它的含义propertyName实施时INotifyPropertyChanged 所以一般来说你实现INotifyPropertyChanged as public class Data INotifyPropertyChan
  • DataContractSerializer 事件/委托字段问题

    在我的 WPF 应用程序中 我正在使用DataContractSerializer序列化对象 我发现它无法序列化具有事件或委托声明的类型 考虑以下失败的代码 Serializable public abstract class BaseCl
  • 如何将 SQL“LIKE”与 LINQ to Entities 结合使用?

    我有一个文本框 允许用户指定搜索字符串 包括通配符 例如 Joh Johnson mit ack on 在使用 LINQ to Entities 之前 我有一个存储过程 该存储过程将该字符串作为参数并执行以下操作 SELECT FROM T

随机推荐