-1

My project actually requires no less than 7 .DLL (from the Microsoft System Center 2012 R2 Configuration Manager SDK) and i'd really like to deliver one .EXE instead of a handfull of files. The code used to run smooth so far... Then i embedded my assemblies in the project and the mess started !

I'm wondering what i've done wrong... Let's review the step i followed to achieve this :

1- program.cs is rather straightforward with an AssemblyResolve event handler to load embedded assemblies:

using System;
using System.Reflection;
using System.Collections.Generic;
using System.Windows.Forms;


namespace WindowsFormsApplication1
{
    static class Program
    {
        public static Dictionary<string, Assembly> _libs = new Dictionary<string, Assembly>();
        /// <summary>
        /// Point d'entrée principal de l'application.
        /// </summary>        
        [STAThread]
        static void Main()
        {
            AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
            {
                lock (_libs)
                {
                    string name = args.Name.Split(',')[0];
                    string culture = args.Name.Split(',')[2];
                    if (name.EndsWith(".resources") && !culture.EndsWith("neutral")) return null;
                    String resourceName = "WindowsFormsApplication1." + new AssemblyName(args.Name).Name + ".dll";
                    if (_libs.ContainsKey(resourceName)) return _libs[resourceName];

                    using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
                    {
                        Byte[] assemblyData = new Byte[stream.Length];
                        stream.Read(assemblyData, 0, assemblyData.Length);
                        Assembly assembly = Assembly.Load(assemblyData);
                        _libs[resourceName] = assembly;
                        return Assembly.Load(assemblyData);
                    }
                }
            };
            System.Windows.Forms.Application.EnableVisualStyles();
            System.Windows.Forms.Application.SetCompatibleTextRenderingDefault(false);
            System.Windows.Forms.Application.Run(new Form1());
        }
    }   
}

2- Form1.cs
notice that i'm only using 2 of the 7 DLLs for the demo :

using System;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using Microsoft.ConfigurationManagement.ManagementProvider;
using Microsoft.ConfigurationManagement.ManagementProvider.WqlQueryEngine;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private string SCCM_SERVER = "sccm.server.fqdn.com";
        private static WqlConnectionManager sccmConnection = new WqlConnectionManager();                


        public Form1()
        {
            try
            {
                sccmConnection.Connect(SCCM_SERVER);
            }
            catch (SmsException ex)
            {
                MessageBox.Show("Unable to connect to server. " + ex.Message);
            }
            catch (System.UnauthorizedAccessException ex2)
            {
                MessageBox.Show("Unable to authenticate. " + ex2.Message);
            }

            InitializeComponent();
        }
    }
}

Code compile, running... Bam ! unhandled System.ArgumentException fired by mscorlib : "the path is not of a legal form" at

sccmConnection.Connect(SCCM_SERVER);

Once again, with no .dll embedding, the code is working fine...

3- Embedding .DLL (screenshots here and there) -> Both references "Copy Local" Properties are set to "False" -> Both Embedded .DLL "Build Action" and "Copy to Output Dir" are set to "Embedded resource" and "Do not copy"

Thank you for your help !

Usul
  • 129
  • 8

1 Answers1

0

Have a look at the exception's stack :
à System.IO.Path.NormalizePath(String path, Boolean fullCheck, Int32 maxPathLength)
à System.IO.Path.GetDirectoryName(String path)
à Microsoft.ConfigurationManagement.AdminConsole.SmsSqmManager.LoadAndInitializeSqmSdk()
à Microsoft.ConfigurationManagement.AdminConsole.SmsSqmManager..ctor()
à Microsoft.ConfigurationManagement.ManagementProvider.ConnectionManagerBase.get_SqmManager()
à Microsoft.ConfigurationManagement.ManagementProvider.WqlQueryEngine.WqlConnectionManager.Connect(String configMgrServerPath)
...

Now let's review LoadAndInitializeSqmSdk() :

// Microsoft.ConfigurationManagement.AdminConsole.SmsSqmManager
private void LoadAndInitializeSqmSdk()
{
    string text = Path.GetDirectoryName(typeof(SmsSqmManager).Assembly.Location);
    text += "\\I386\\SqmApi.dll";

SmsSqmManager is inside Microsoft.ConfigurationManagement.ManagementProvider.dll which is embedded in my code, so the Assembly.Location returns null and triggers the Exception...

TL;DR : do not embed Microsoft.ConfigurationManagement.ManagementProvider.dll...

Usul
  • 129
  • 8