Ast*_*tor 6 c# installation clickonce .net-4.0
我正致力于自动化.NET 4.0 ClickOnce WPF应用程序的安装程序,该应用程序需要在app.config文件中设置一些项目.我已经经历了一个棘手的过程,即找到我必须遵循的特定步骤,使用Mage.exe(即更新并重新签名应用程序和部署清单),现在我正在尝试将其自动化以进行安装.
我选择使用.deploy扩展来最小化IIS/Internet Explorer安全机制的问题,因此基本上算法如下(基于ClickOnce(Saurabh Bhatia)中的签名和重新签名清单以及使用Mage的ClickOnce WPF应用程序的更新配置或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
在部署中,以及Microsoft是否允许我们这样做对我来说是一个悬而未决的问题.因此,我正在尝试在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);
Run Code Online (Sandbox Code Playgroud)
现在,这是踢球者.除步骤5外,一切都运行良好.当应用程序下载到用户的计算机时,部署清单存在问题:
实际上,此部分已不再存在(但是,它位于原始的%app%.应用程序中!).ClickOnce - .NET 4.0错误中描述了类似的结果:"部署清单在语义上无效"和"部署清单缺失<compatibleFrameworks>",但是是不同进程(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);
Run Code Online (Sandbox Code Playgroud)
但是在dm.ResolveFiles(),dm.UpdateFileInfo()或ManifestWriter.WriteManifest(..)之前,无论我放置此代码的位置,这都没有效果!
我的结果类似于Stack Overflow问题MageUI.exe删除compatibleFrameworks元素或为什么Mage.exe不生成compatibleFrameworks属性?或MageUI.exe不包含compatibleFrameworks元素,但我没有使用 mageui
,mage
甚至msbuild
根本没有!
这是怎么回事?
自己搞清楚了.罪魁祸首是ManifestReader.ReadManifest("DeployManifest",sPathMft,true).
MSDN说,[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
}
Run Code Online (Sandbox Code Playgroud)
@davidair,谢谢你的建议!同意,虽然我更喜欢使用API对象(与XML相比).
另一种方法是调用mage
(直接或从.cmd文件),因为我们似乎可以重新分发它.
我还添加了以下部分,它对问题本身没有影响,但对于遵循相同路径的任何人来说可能非常重要(/ 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;
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
8325 次 |
最近记录: |