Skip to content

Instantly share code, notes, and snippets.

@Sharuru
Created February 12, 2015 16:41
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save Sharuru/f54609b28730bc598336 to your computer and use it in GitHub Desktop.
Save Sharuru/f54609b28730bc598336 to your computer and use it in GitHub Desktop.
Merging a WPF application into a single EXE
第一步,找到项目文件下的 .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