Using AssemblyResolve to Load SCCM SDK Assemblies On Demand

Using AssemblyResolve to Load SCCM SDK Assemblies On Demand

Overview

As detailed in Configuring Visual Studio to use SCCM Assemblies is it not permitted to take the assemblies from the SCCM console and bundle them with your application if distributing outside your company. One possible solution is to configure your application so that it will automatically load the required assemblies from a local installation of the SCCM console. This also has some advantages over bundling the assemblies with your application:

  • Simplified installation for the end-user. No need to write scripts or instructions for the end-user to copy the required SCCM DLLs into your program folder. Just a simple pre-requisite of “SCCM Console must be installed”.
  • Always up to date. SCCM is now updated every 6 months, and each release has updated assemblies. The SCCM console also updates itself when a new server version has been installed. Your program will always be using the correct version of assemblies for your instance of SCCM.
  • No legal worries distributing your program outside of the company.

AssemblyResolve Event

MSDN description of AppDomain.AssemblyResolve.

When you run your SCCM SDK based application without copying the relevant assemblies into the same folder as your executable you will get an exception when the missing assemblies attempt to load. The AssemblyResolve event is triggered whenever an assembly load is attempted and cannot be found. The event also provides the opportunity to load the requested assemblies from another location instead of just failing. The example code below shows how to use AssemblyResolve to allow an application to load the SCCM SDK assemblies directly from wherever it is installed. The way it works is:

  • Registers the AssemblyResolve event.
  • Only concerns itself with requests for assemblies that are used in SCCM:
    • AdminUI.*
    • DcmObjectModel*
    • Microsoft.ConfigurationManagement.*
  • Uses the environment variable SMS_ADMIN_UI_PATH to find an installation of the SCCM console.
  • Attempts to load the assembly from the SCCM console folder.
  • If unsuccessful, will show a popup to the end-user and describes the DLL file that is missing (nicer than an exception).

Examples and Downloads

The examples on this page can be downloaded from the GitHub repo:

AssemblyResolve

Using the AssemblyResolve event to load SCCM SDK assemblies from the SCCM Console folder.

internal class Program  
{
    private static void Main(string[] args)  
    {  
        // Catch assembly references that can't be resolved - then load them from the CM Admin Console folder
        AppDomain currentDomain = AppDomain.CurrentDomain;
        currentDomain.AssemblyResolve += OnResolveAssembly;
    }
    
    private static Assembly OnResolveAssembly(object sender, ResolveEventArgs args)
    {
        // Only concern ourself with CM related DLLs
        if (!args.Name.StartsWith("AdminUI.") && !args.Name.StartsWith("DcmObjectModel") && !args.Name.StartsWith("Microsoft.ConfigurationManagement."))
        {
            return null;
        }

        var askedAssemblyName = new AssemblyName(args.Name);

        string assemblyDllName = askedAssemblyName.Name + ".dll";
        string assemblyDllPath = string.Empty;

        // Get the console location
        string consolePath = Environment.GetEnvironmentVariable("SMS_ADMIN_UI_PATH");

        if (!string.IsNullOrEmpty(consolePath))
        {
            DirectoryInfo directoryInfo = Directory.GetParent(consolePath);
            assemblyDllPath = directoryInfo.FullName;
        }

        assemblyDllPath += "\\" + assemblyDllName;

        // Check if the file exists, if so load it and return
        if (File.Exists(assemblyDllPath))
        {
            Assembly assembly = Assembly.LoadFrom(assemblyDllPath);
            return assembly;
        }

        string message = "The following DLL is missing:\r\n" + assemblyDllName;
        message += "\r\n\r\n";
        message += "Please install the Configuration Manager Admin Console or copy the named DLL into the application directory.";

        MessageBox.Show(message);

        Environment.Exit(1);
        return null;
    }
}