我的任务是升级内部企业Web应用程序。用户输入一些数据,然后Web应用程序编译自定义winforms EXE(自我提取器/安装程序类型的应用程序),然后网站将其作为下载服务。
我们最近了解到这个自定义编译的安装程序在Windows 7中显示兼容性错误/警告。经过一些研究,我了解到我需要提供一个指定与Windows 7兼容的应用程序清单:
相关链接:
这是我第一次使用自定义/动态编译的代码和应用程序清单。
由于这个应用程序是动态编译的(来自单个代码文件和一些嵌入式资源),我不能只为项目添加清单。所以我在编译时使用了编译器的“/ win32manifest”编译器选项来引用清单文件。
以下是自定义“归档编译器”类的一些代码,它实际上进行了编译:(我只添加了Application Manifest部分)
public void CompileArchive(string archiveFilename, bool run1stItem, string iconFilename)
{
CodeDomProvider csc = new CSharpCodeProvider();
CompilerParameters cp = new CompilerParameters();
cp.GenerateExecutable = true;
cp.OutputAssembly = archiveFilename;
cp.CompilerOptions = "/target:winexe";
// Custom option to run a file after extraction
if (run1stItem) {
cp.CompilerOptions += " /define:RUN_1ST_ITEM";
}
if (!string.IsNullOrEmpty(iconFilename)) {
cp.CompilerOptions += " /win32icon:" + iconFilename;
}
cp.ReferencedAssemblies.Add("System.dll");
cp.ReferencedAssemblies.Add("System.Windows.Forms.dll");
// Add application manifest to specify operating system compatibility (to fix compatibility warning in Windows 7)
string AppManifestPath = Path.Combine( System.Web.HttpContext.Current.Server.MapPath( "~/Content/" ), "CustomInstaller.exe.manifest" );
if ( File.Exists( AppManifestPath ) ) {
cp.CompilerOptions += string.Format( " /win32manifest: \"{0}\"", AppManifestPath );
}
// Add compressed files as resource
cp.EmbeddedResources.AddRange(filenames.ToArray());
// Compile standalone executable with input files embedded as resource
CompilerResults cr = csc.CompileAssemblyFromFile(cp, sourceCodeFilePath);
// yell if compilation error
if (cr.Errors.Count > 0) {
string msg = "Errors building " + cr.PathToAssembly;
foreach (CompilerError ce in cr.Errors) { msg += Environment.NewLine + ce.ToString(); }
throw new ApplicationException(msg);
}
}
然而,当我编译时,我一直遇到这个错误:
构建D:\ Projects \ MySolution \ WebAppName \ App_Data \ MyUsername \ CustomInstaller.exe的错误 错误CS2007:无法识别的选项:'/ win32manifest:'
我找不到相关信息,除了声明此参数存在且有效的文章。 Web应用程序位于visual studio 2010中,并在框架2.0上运行。动态编译的应用程序也引用.net 2.0(使用反编译器验证)。我不确定调用什么EXE来执行编译,或者我还可以检查以解决这个问题。任何帮助将不胜感激。
答案 0 :(得分:2)
可能需要删除此行中/win32manifest:
和\"{0}\"
之间的空格cp.CompilerOptions += string.Format( " /win32manifest: \"{0}\"", AppManifestPath );
没有空格它工作正常,当我添加空格时,就像你的代码一样,我有错误:
Errors building C:\Projects\Services\Services.WebUI\Binaries\install\temp\codedom.exe
error CS2005: Missing file specification for '/win32manifest:' option
warning CS2008: No source files specified
答案 1 :(得分:1)
/ win32manifest开关的MSDN文档页面最早存在于Visual Studio 2008中。所以也许它是在.NET v3.5中添加的。
您可以在CSharpCodeProvider构造函数中指定“CompilerVersion”。
我必须坚持使用.NET 2.0,所以我将使用mt.exe方法。
答案 2 :(得分:0)
经过更多研究,我了解了mt.exe,这是一个用于添加应用程序清单的简单命令行实用程序。我将exe的副本放入我的web项目中,然后添加代码以在编译应用程序后调用此过程:
//Add an application manifest using mt.exe
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = Path.Combine( System.Web.HttpContext.Current.Server.MapPath( "~/Content/" ), "mt.exe" );
string AppManifestPath = Path.Combine( System.Web.HttpContext.Current.Server.MapPath( "~/Content/" ), "CustomInstaller.exe.manifest" );
startInfo.Arguments = string.Format( "-nologo -manifest \"{0}\" -outputresource:\"{1};#1\"", AppManifestPath, cp.OutputAssembly );
process.StartInfo = startInfo;
process.Start();
process.WaitForExit( 10000 ); //wait until finished (up to 10 sec)
这样可以快速轻松地将我的清单添加到已编译的EXE中。我还发现了这个Manifest Viewer,可以很容易地验证我的清单的内容。