- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在为 .NET 4.0 ClickOnce WPF 应用程序自动化安装程序,它需要在 app.config 文件中设置一些项目。我经历了使用 Mage.exe 寻找必须遵循的特定步骤的棘手过程。 (即,更新和重新签署应用程序和部署 list )现在我正在尝试自动化安装。
我选择使用 .deploy 扩展来最小化 IIS 的问题/Internet Explorer 安全机制,因此基本上算法如下(基于 Signing and re-signing manifests in ClickOnce (Saurabh Bhatia) 和 Update Configuration of a ClickOnce WPF Application Using Mage or MageUI ,作为其他主要来源):
\Application Files\App_%HighestVersion%\
文件夹mage -u %app%.exe.manifest -cf cert.pfx
mage -u %app%.application -appm %app%.exe.manifest -cf cert.pfx
%app%.application
向上复制 2 级(到 ..\..
- 部署根目录)如果手动完成,效果会很好。我可以运行一个 .cmd 文件,为环境细节(路径等)定制,但我需要在部署中包含 mage.exe
,以及是否微软允许我们这样做对我来说是一个悬而未决的问题。因此,我试图在 Installer
类中执行类似的操作:
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 步外,一切正常。当应用程序下载到用户计算机时,部署 list 出现问题:
事实上,该部分已不存在(但是,它在原始的 %app%.application 中!)。 ClickOnce - .NET 4.0 errors: "Deployment manifest is not semantically valid" and "Deployment manifest is missing <compatibleFrameworks>" 中描述了类似的结果,但它是不同进程 (msbuild) 的结果。这部分是 4.0 list 的新部分(并且是必需的),所以我唯一的猜测是,当 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( ) 或 ManifestWriter.WriteManifest 之前(..)!
我的结果类似于 Stack Overflow 问题 MageUI.exe removes compatibleFrameworks element 或 Why does Mage.exe not generate a compatibleFrameworks attribute? 或 MageUI.exe is not including a compatibleFrameworks element ,但我根本没有使用 mageui
、mage
甚至 msbuild
!
这是怎么回事?
最佳答案
我自己想出来了。罪魁祸首是 ManifestReader.ReadManifest( "DeployManifest", sPathMft, true )。
MSDN说,[preserveStream argument] “指定是否在结果 list 对象的 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 文件),因为看起来我们 are allowed重新分发它。
我还添加了以下部分,这对问题本身没有影响,但对于遵循相同路径的任何人来说可能非常重要(/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-08
刚刚偶然发现了 app.manifest
的问题:
包含 supportedOS
元素的 compatibility
部分在部署期间被删除。
相同的根本原因;读取它的行应将 preserveStream
设置为 true:
ApplicationManifest am = ManifestReader.ReadManifest( "ApplicationManifest", sPathMft, true ) as ApplicationManifest;
关于c# - 以编程方式更新 ClickOnce 应用程序的部署 list 会导致缺少 <compatibleFrameworks> 元素,这在 4.0 中是必需的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11141655/
我想使用 R 预定义这样的列表 DATA<-list( list(list(),list(),list()), list(list(),list(),list()), list(list(),l
如何将一个列表添加到另一个列表,返回一个列表的列表? foo :: [a] -> [a] -> [[a]] 例如,我想要的结果是: foo [1,2] [3,4] 将是 [[1,2], [3,4]]。
我还没有在这里找到类似问题的解决方案,所以我会寻求你的帮助。 有 2 个列表,其中之一是列表列表: categories = ['APPLE', 'ORANGE', 'BANANA'] test_re
这个问题不同于Converting list of lists / nested lists to list of lists without nesting (这会产生一组非常具体的响应,但无法解决
原始列表转换为 List正好。为什么原始列表的列表不能转换为 List 的列表? { // works List raw = null; List wild = raw; } {
在下面的代码中,get()被调用并将其结果分配给类型为 List> 的变量. get()返回 List>并在类型参数为 T 的实例上调用设置为 ? ,所以它应该适合。 import java.util
原始列表转换为 List正好。为什么原始列表的列表不能转换为 List 的列表? { // works List raw = null; List wild = raw; } {
在insufficiently-polymorphic 作者说: def foo[A](fst: List[A], snd: List[A]): List[A] There are fewer way
我有下面的代码有效。 class ListManipulate(val list: List, val blockCount: Int) { val result: MutableList>
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 5 年前。 Improve this ques
在 scala (2.9) 中转换列表列表的最佳方法是什么? 我有一个 list : List[List[A]] 我想转换成 List[A] 如何递归地实现这一点?或者还有其他更好的办法吗? 最佳答案
我编写了这个函数来确定给定元素是否存储在元组列表的列表中,但目前它只搜索第一个列表。我将如何搜索其余列表? fun findItem (name : command, ((x,y)::firstlis
我创建了一个类名 objectA,它有 4 个变量:约会时间;字符串文本;变量 1,变量 2 我需要创建一个 ObjectA() 列表。然后首先按时间对它们进行分组,其次按 var1,然后按 var2
我有一套说法 char={'J','A'} 和列表的列表 content = [[1,'J', 2], [2, 'K', 3], [2, 'A', 3], [3,'A', 9], [5, 'J', 9
我有以下列表 List >>> titles = new ArrayList >>> ();我想访问它的元素,但我不知道该怎么做.. 该列表有 1 个元素,它又包含 3 个元素,这 3 个元素中的
转换 List[List[Long]] 的最佳方法是什么?到 List[List[Int]]在斯卡拉? 例如,给定以下类型列表 List[List[Long]] val l: List[List[Lo
我有一个来自 Filereader (String) 的 List-List,如何将其转换为 List-List (Double):我必须返回一个包含 line-Array 的第一个 Values 的
我收集了List> 。我需要将其转换为List> 。这是我尝试过的, List> dataOne = GetDataOne(); var dataTwo = dataOne.Select(x => x
这个问题在这里已经有了答案: Cannot convert from List to List> (3 个答案) 关闭 7 年前。 我没有得到这段代码以任何方式编译: List a = new Ar
这个问题在这里已经有了答案: Cannot convert from List to List> (3 个答案) 关闭 7 年前。 我没有得到这段代码以任何方式编译: List a = new Ar
我是一名优秀的程序员,十分优秀!