// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. namespace WixToolset.Mba.Host { using System; using System.Configuration; using System.Reflection; using System.Runtime.InteropServices; using WixToolset.Mba.Core; /// /// Entry point for the managed host to create and return the BA to the engine. /// [ClassInterface(ClassInterfaceType.None)] public sealed class BootstrapperApplicationFactory : MarshalByRefObject, IBootstrapperApplicationFactory { /// /// Creates a new instance of the class. /// Entry point for the MBA host. /// public BootstrapperApplicationFactory() { } /// /// Loads the bootstrapper application assembly and calls its IBootstrapperApplicationFactory.Create method. /// /// Pointer to BOOTSTRAPPER_CREATE_ARGS struct. /// Pointer to BOOTSTRAPPER_CREATE_RESULTS struct. /// The bootstrapper application assembly /// does not define the . public void Create(IntPtr pArgs, IntPtr pResults) { // Get the wix.boostrapper section group to get the name of the bootstrapper application assembly to host. var section = ConfigurationManager.GetSection("wix.bootstrapper/host") as HostSection; if (null == section) { throw new MissingAttributeException(); // TODO: throw a more specific exception than this. } // Load the BA's IBootstrapperApplicationFactory. var baFactoryType = BootstrapperApplicationFactory.GetBAFactoryTypeFromAssembly(section.AssemblyName); var baFactory = (IBootstrapperApplicationFactory)Activator.CreateInstance(baFactoryType); if (null == baFactory) { throw new InvalidBootstrapperApplicationFactoryException(); } baFactory.Create(pArgs, pResults); } /// /// Locates the and returns the specified type. /// /// The assembly that defines the IBootstrapperApplicationFactory implementation. /// The bootstrapper application factory . private static Type GetBAFactoryTypeFromAssembly(string assemblyName) { Type baFactoryType = null; // Load the requested assembly. Assembly asm = AppDomain.CurrentDomain.Load(assemblyName); // If an assembly was loaded and is not the current assembly, check for the required attribute. // This is done to avoid using the BootstrapperApplicationFactoryAttribute which we use at build time // to specify the BootstrapperApplicationFactory assembly in the manifest. if (!Assembly.GetExecutingAssembly().Equals(asm)) { // There must be one and only one BootstrapperApplicationFactoryAttribute. // The attribute prevents multiple declarations already. var attrs = (BootstrapperApplicationFactoryAttribute[])asm.GetCustomAttributes(typeof(BootstrapperApplicationFactoryAttribute), false); if (null != attrs) { baFactoryType = attrs[0].BootstrapperApplicationFactoryType; } } if (null == baFactoryType) { throw new MissingAttributeException(); } return baFactoryType; } } }