jasper-bosch
jasper-bosch

Reputation: 90

Unable to load DLL created in C# from another C# app

Summary

Goal

I have two C# projects. The output of the first project is a DLL (output type in Visual Studio is set to Class Library) that lets me control my application from other languages. It basically starts an instance of my application without showing any of its UI windows. I can use this DLL in other programming languages (like Python, Matlab) without any problems.

But now I want to use that DLL in another C# project. To do this, I have added the DLL as a reference in my project. To initiate an instance of my application, I create an object of the type that is defined in the DLL:

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

This results in an exception:

System.InvalidOperationException: 'The 'ResourceAssembly' property of the 'Application' type cannot be changed after it has been set.'

The cause of this exception is the fact that MyApp sets the ResourceAssembly in order to load the application's resources (things like UI images):

System.Windows.Application.ResourceAssembly = typeof(AppBase.MainWindow).Assembly; 

What I've tried

Since Application.ResourceAssembly can only be set once, I tried a way around it as described in the second solution of this StackOverflow post. This prevents the ResourceAssembly exception from being thrown.

The DLL object the attempts to start but then throws the following exception:

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

The InnerException value of this exception is null, but its source value is PresentationFramework. This is the StackTrace of the exception:

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()

Upvotes: 4

Views: 270

Answers (2)

Doctor Jones
Doctor Jones

Reputation: 21674

Well, the exception states The Application object is being shut down.. This might mean that your wpf application is prematurely ending, so I'd try debugging what's happening inside the app.

One thing that I did notice, is that your app startup code doesn't seem quite right.

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

Assuming that MyApp is a Wpf Application class, you're lacking the required call to the Run method, which requires a Window as an argument.

So I'd expect your code to look something like:

static int Main(string[] args)
{
    MyWindow window = new MyWindow();
    MyApp app = new MyApp();
    return app.Run(window);
}

Also, note how I've changed the return type of Main, so we can return the appropriate return code.

Edit: (I clearly missed the part about the ResourceAssembly)

You can absolutely set the Resource Assembly for the application, but as you've correctly stated, you're not allowed to do it twice.

Where do you set it the first time? And why are you setting it, if you know that you need to set it to something else later?

Unfortunately, I don't think we'll be able to help, without further information.

Upvotes: 2

Michael Mankiewicz
Michael Mankiewicz

Reputation: 42

As an option, you can publish your class library as NuGet Package in local package source and use it it in other solutions as regular NuGet Package.

Upvotes: 1

Related Questions