You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在同一进程与AppDomain中通过反射加载并运行WPF EXE?解决TinyJitHook加载时无法定位XAML资源的问题

解决同一进程加载WPF EXE时的"Cannot locate resource 'mainwindow.xaml'"错误

这个问题的核心原因是:当你通过Assembly.LoadFrom加载外部WPF程序集时,WPF的资源查找机制默认会使用当前宿主进程的AppDomain基目录/工作目录,而不是WPF EXE文件所在的目录。这就导致WPF无法找到嵌入在目标程序集里的XAML资源文件。

下面是几个可行的解决方案,结合你的TinyJitHook场景来调整:

方案1:修改AppDomain的应用基目录

在加载WPF程序集之前,把AppDomain的基目录设置为WPF EXE所在的路径,让WPF资源系统能正确定位到资源:

public static void Main(string[] args) {
    string filePath = @"WpfApp1.exe";
    string wpfExeFullPath = Path.GetFullPath(filePath);
    string wpfExeDir = Path.GetDirectoryName(wpfExeFullPath);

    // 临时修改AppDomain的应用基目录为WPF EXE所在目录
    string originalAppBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
    AppDomain.CurrentDomain.SetData("APPBASE", wpfExeDir);

    Assembly asm = Assembly.LoadFrom(wpfExeFullPath);
    MainJitHook hook = new MainJitHook(asm, IntPtr.Size == 8);
    hook.OnCompileMethod += ChangeExample;
    hook.Hook();

    try {
        MethodInfo method = asm.EntryPoint;
        method.Invoke(null, new object[] { });
    } catch (Exception extInfo) {
        Console.WriteLine(extInfo.ToString());
    } finally {
        // 恢复原来的应用基目录
        AppDomain.CurrentDomain.SetData("APPBASE", originalAppBase);
        hook.Unhook();
    }

    Console.WriteLine("DONE");
    Console.ReadKey();
}

方案2:手动初始化WPF Application并指定资源程序集

如果修改AppDomain基目录会影响你的控制台程序逻辑,可以手动创建WPF Application实例,强制指定资源程序集为加载的WPF程序集:

public static void Main(string[] args) {
    string filePath = @"WpfApp1.exe";
    Assembly asm = Assembly.LoadFrom(filePath);
    MainJitHook hook = new MainJitHook(asm, IntPtr.Size == 8);
    hook.OnCompileMethod += ChangeExample;
    hook.Hook();

    try {
        // 获取WPF的App类型
        Type appType = asm.GetType("WpfApp1.App");
        if (appType != null) {
            // 创建Application实例
            Application app = (Application)Activator.CreateInstance(appType);
            // 强制设置资源程序集为加载的WPF程序集
            Application.ResourceAssembly = asm;
            // 手动启动应用(替代直接调用EntryPoint)
            app.Run();
        }
    } catch (Exception extInfo) {
        Console.WriteLine(extInfo.ToString());
    }

    hook.Unhook();
    Console.WriteLine("DONE");
    Console.ReadKey();
}

补充说明

  • 为什么Process.Start能正常运行?因为它是启动了一个独立的进程,WPF的资源系统会自动使用该进程的基目录(即WPF EXE所在目录)来查找资源,所以不会出错。
  • 如果你需要保留原有的EntryPoint调用方式,方案1会更直接;如果希望更精细地控制WPF应用的初始化,方案2更灵活。
  • 注意:在多程序集场景下,可能还需要处理AppDomain.CurrentDomain.AssemblyResolve事件,确保WPF依赖的其他程序集能被正确加载。

内容的提问来源于stack exchange,提问作者SkyStar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 15:32:35