从另一个C#应用程序无法加载在C#中创建的DLL

4

概述

目标

我有两个C#项目。第一个项目的输出是一个DLL(在Visual Studio中的输出类型设置为类库),可以让我从其他语言控制我的应用程序。它基本上启动了一个不显示任何UI窗口的应用程序实例。我可以在其他编程语言(如Python、Matlab)中使用这个DLL,没有任何问题。

但现在我想在另一个C#项目中使用那个DLL。为了做到这一点,在我的项目中添加了该DLL作为引用。要启动我的应用程序的一个实例,我创建了一个在DLL中定义的类型的对象:

namespace MyDLL
{
    class Program
    {
        static void Main(string[] args)
        {
            MyApp app = new MyApp();
        }
    }
}

这会导致异常抛出:
System.InvalidOperationException: 'The 'ResourceAssembly' property of the 'Application' type cannot be changed after it has been set.'

这个异常的原因是因为MyApp设置了ResourceAssembly来加载应用程序的资源(例如UI图片):
System.Windows.Application.ResourceAssembly = typeof(AppBase.MainWindow).Assembly; 

我尝试过的事情

由于Application.ResourceAssembly只能设置一次,所以我尝试了一种方法来绕过它,如这篇StackOverflow帖子的第二个解决方案所述。这可以防止ResourceAssembly异常被抛出。

然后DLL对象尝试启动,但随后抛出以下异常:

System.InvalidOperationException: 'The Application object is being shut down.'

此异常的InnerException值为null,但其源值为PresentationFramework。以下是该异常的堆栈跟踪:
at System.Windows.Application.GetResourcePackage(Uri packageUri)
at System.Windows.Application.GetResourceOrContentPart(Uri uri)
at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
at App.MainWindow..ctor(Boolean showWindow)
at MyDLL.MyApp.startApp()
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
2个回答

2

好的,异常信息显示:应用程序对象正在关闭。这可能意味着您的wpf应用程序提前结束了,因此建议您尝试调试应用程序内部发生的情况。

我注意到一件事情,就是您的应用程序启动代码似乎不太对。

static void Main(string[] args)
{
    MyApp app = new MyApp();
}

假设MyApp是一个Wpf Application类,你需要调用Run方法并传入一个Window参数。
因此,我期望你的代码看起来像这样:
static int Main(string[] args)
{
    MyWindow window = new MyWindow();
    MyApp app = new MyApp();
    return app.Run(window);
}

同时注意我如何改变了Main的返回类型,这样我们就可以返回适当的返回代码。

编辑:(我显然错过了关于ResourceAssembly的部分)

您完全可以为应用程序设置资源程序集,但正如您所正确指出的那样,您不允许进行两次设置。

第一次在哪里设置?如果您知道需要稍后将其设置为其他内容,为什么要进行设置?

很遗憾,如果没有进一步的信息,我们可能无法提供帮助。


资源程序集仅在DLL中明确设置,以便将应用程序指向所需的资源(例如在UI中使用的图像)。我不会在尝试使用DLL的C#应用程序中显式设置资源程序集。因此,我实际上只设置了一次。是否可以应用某种默认设置,从而导致它被设置两次? - jasper-bosch
@jasper-bosch,在特殊情况下,您只能手动设置资源程序集。WPF应用程序必须从未托管的程序集中托管,或者必须使用除执行程序集之外的方法加载到新的应用程序域中。您是如何引用您的应用程序的?如果仅仅是DLL引用,或者您已经加载了程序集,那么它将在与父应用程序相同的应用程序域中,这将无法正常工作。 - Doctor Jones

1
作为一种选择,您可以将您的类库发布为 NuGet 包到本地包源中,并在其他解决方案中使用它作为常规的 NuGet 包。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接