1、需求
开发设计到的类库比较多,全部生成到根目录下显得比较乱,需要将部分dll及配置文件放到dlls文件夹下,让根目录较为简洁清晰。(上为正式需求文档,实际上就是领导看着不舒服,要改( ╯□╰ ))
2、解决方案
前置知识:
WPF程序在启动时,dll文件大致分为两部分加载,一部分为启动时必须用到的dll,这些文件无法更换路径;一部分可以在程序启动后再加载,这部分可以更换路径。
程序启动后加载的文件
可以通过以下方法,在App.xaml.cs中添加
protected override void OnStartup(StartupEventArgs e)
{
AssemblyLoadContext.Default.Resolving += Default_Resolving;
base.OnStartup(e);
}
private Assembly? Default_Resolving(AssemblyLoadContext assemblyLoadContext, AssemblyName assemblyName)
{
var probeSetting = "dlls";
var pathMaybe = Path.Combine(AppContext.BaseDirectory, probeSetting , $"{assemblyName.Name}.dll");
if (File.Exists(pathMaybe))
return assemblyLoadContext.LoadFromAssemblyPath(pathMaybe);
return null;
}
主要逻辑就是在程序启动时加载dlls文件夹下面的文件
程序启动前需要的文件
现在的问题就是如何确定程序启动前需要的文件。
这里提供一个办法
- 将根目录下除了主程序exe以外,将其他的文件统一放到dlls文件夹中
- 双击主程序exe,程序会无法启动
- 打开系统日志(右键我的电脑-管理-事件查看器-WIndows日志-应用程序),查看2的日志,会出现类似以下的日志
- 将缺少的文件从dlls文件夹中剪切到根目录下,然后重复2、3、4,知道程序能正常运行。
通过上述方法就能找到对应文件
3、未验证解决方案
使用.net Framework可以使用运行时配置来实现,在App.config中添加以下节点,具体解释见官方文档<probing> 元素 - .NET Framework | Microsoft Learn
使用.net 5+开发的WPF程序不支持此方法
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="dlls"/>
</assemblyBinding>
</runtime>
</configuration>