Created
February 12, 2015 16:41
-
-
Save Sharuru/f54609b28730bc598336 to your computer and use it in GitHub Desktop.
Merging a WPF application into a single EXE
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
第一步,找到项目文件下的 .csprojc 文件,用文本编辑器打开它,并找到下面这行: | |
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | |
把下面的 XML 粘贴到文件中,然后保存并在 Visual Studio 中重载: | |
<Target Name="AfterResolveReferences"> | |
<ItemGroup> | |
<EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'"> | |
<LogicalName>%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)</LogicalName> | |
</EmbeddedResource> | |
</ItemGroup> | |
</Target> | |
粘贴后的文件应该差不多长这样: | |
</ItemGroup> | |
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> | |
<Target Name="AfterResolveReferences"> | |
<ItemGroup> | |
<EmbeddedResource Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.Extension)' == '.dll'"> | |
<LogicalName>%(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)</LogicalName> | |
</EmbeddedResource> | |
</ItemGroup> | |
<!-- To modify your build process, add your task inside one of the targets | |
Other similar extension points exist, see Microsoft.Common.targets. | |
<Target Name="BeforeBuild"> | |
</Targe> | |
<Targer Name="AfterBuild"> | |
</Target> | |
--> | |
</Project> | |
第二步,你需要在你的项目中新建一个文件(e.g. Program.cs)然后把下列代码加入(根据你的程序命名/结构): | |
[STAThread] | |
public static void Main() | |
{ | |
AppDomain.CurrentDomain.AssemblyResolve += OnResolveAssembly; | |
App.Main(); // Run WPF startup code. | |
} | |
private static Assembly OnResolveAssembly(object sender, ResolveEventArgs e) | |
{ | |
var thisAssembly = Assembly.GetExecutingAssembly(); | |
// Get the Name of the AssemblyFile | |
var assemblyName = new AssemblyName(e.Name); | |
var dllName = assemblyName.Name + ".dll"; | |
// Load from Embedded Resources - This function is not called if the Assembly is already | |
// in the same folder as the app. | |
var resources = thisAssembly.GetManifestResourceNames().Where(s => s.EndsWith(dllName)); | |
if (resources.Any()) | |
{ | |
// 99% of cases will only have one matching item, but if you don't, | |
// you will have to change the logic to handle those cases. | |
var resourceName = resources.First(); | |
using (var stream = thisAssembly.GetManifestResourceStream(resourceName)) | |
{ | |
if (stream == null) return null; | |
var block = new byte[stream.Length]; | |
// Safely try to load the assembly. | |
try | |
{ | |
stream.Read(block, 0, block.Length); | |
return Assembly.Load(block); | |
} | |
catch (IOException) | |
{ | |
return null; | |
} | |
catch(BadImageFormatException) | |
{ | |
return null; | |
} | |
} | |
} | |
// in the case the resource doesn't exist, return null. | |
return null; | |
} | |
第三步,设定你的项目属性,确定程序的启动窗体(Startup object)是上面的这段代码。 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment