1

我在 C# 中编写的活动 x 组件有问题。尽管我已经用 regasm 注册了 dll,但我目前无法创建一个活动的 x 对象......

这是我在课堂上的代码:

using System;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Security.Policy;
using System.Security;
using Ch.XXX.System6.Modules.Logger;

namespace Gadget.Interop
{
    /// <summary>
    /// GadgetAdapter is the starting point for loading and unloading .NET assemblies
    /// from javascript or any COM-based environment.
    /// </summary>
    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.None)]
    [Guid("21A72577-3D2D-4664-93F7-1BE02AE68240")]
    [ProgId("GadgetInterop.GadgetAdapter")]
    [ComDefaultInterface(typeof(IGadgetInterop))]
    public class GadgetAdapter : IGadgetInterop, IDisposable, IObjectSafety
    {
        [DllImport("kernel32.dll")]
        static extern IntPtr GetModuleHandle(string module);
        [DllImport("kernel32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool FreeLibrary(IntPtr handle);
        [DllImport("kernel32.dll")]
        public extern static bool GetModuleHandleExA(int dwFlags, string ModuleName, ref IntPtr phModule);
        [DllImport("kernel32.dll")]
        static extern IntPtr LoadLibrary(string lpFileName);

        /// <summary>
        /// Gadget.Interop.dll Name for FreeLibrary Function
        /// </summary>
        private const string DLLNAME = "Gadget.Interop.dll";

        /// <summary>
        /// Parameters for the constructor
        /// </summary>
        private ArrayList paramList = new ArrayList(); // Array list to  hold constructor parameters

        /// <summary>
        /// Zusätzliche AppDomain
        /// </summary>
        private AppDomain appDomain;


        /// <summary>
        /// Standard Konstruktor
        /// </summary>
        public GadgetAdapter() { }

        #region IGadgetInterop Members
        /// <summary>
        /// Adds an object to be passed to a class' constructor.  Values must be passed to 
        /// this method in the same order of the constructor's arguments.
        /// </summary>
        /// <param name="parameter">Constructor agrument value</param>
        public void AddConstructorParam(object parameter)
        {                
            paramList.Add(parameter);
        }

        /// <summary>
        /// Creates an instance of the specified type.  Constructor parameters are used when
        /// calling this method if they exist, but are forcibly cleared after object creation.
        /// </summary> 
        /// <param name="assemblyFullPath">Full path to and name of the assembly to load</param>
        /// <param name="className">Full namespace and class name of the type to create</param>
        /// <returns>Instance of an object represented by the className arg ument</returns>
        public object LoadType(string assemblyFullPath, string className)
        {
            try
            {
                ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.Name);

                log.Info("Finally we arrived our C# code");
                return LoadTypeWithParams(assemblyFullPath, className, false);
            }
            catch (Exception ex)
            {
                // Javascript-friendly exception
                throw new Exception("Finally we arrived c# code" + ex.Message);
            }
        }
        /// <summary>
        /// Creates an instance of the specified type. 
        /// <param name="preserveParams">Clears the constructor parameters if false</param>
        /// <returns>Instance of an object represented by the className argument</returns>
        public object LoadTypeWithParams(string assemblyFullPath, string className, bool preserveParams)
        {
            //Load Gadget.Interop.dll over the Gadget.Interop.dll
            LoadLibrary(DLLNAME);

            //Setup extra AppDomain
            AppDomainSetup setup = new AppDomainSetup();
            setup.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;

            setup = AppDomain.CurrentDomain.SetupInformation;
            setup.PrivateBinPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
            setup.PrivateBinPathProbe = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
            setup.ApplicationName = "GadgetAdapter-Loader";
            setup.ShadowCopyFiles = "true";

            appDomain = AppDomain.CreateDomain(
               /*Generate a dynamic name*/
              "GadgetAdapter - Assembly" + Path.GetRandomFileName(), null, setup);

            try
            {
                //Set security
                object[] hostEvidence = { new Zone(SecurityZone.MyComputer) };

                //Create an Evidence based on the Security Zone
                //Evidence intEvidence = new Evidence(hostEvidence, null);

                //Load an assembly in an own application domain
                return (appDomain.CreateInstanceFromAndUnwrap(
                     assemblyFullPath,
                     className, true, BindingFlags.CreateInstance | BindingFlags.Instance | BindingFlags.Public,
                     null, paramList.ToArray(), CultureInfo.CurrentCulture, null));
            }
            catch (Exception ex)
            {
                //Eintrag ins EventLog schreiben
                string sSource;
                string sLog;
                string sEvent;

                sSource = "XXX Sidebar Gadget";
                sLog = "Sidebar Gadget";
                sEvent = "Unhandled Exception in Gadget.Interop.GadgetAdapter";

                //Eventlog Eintrag schreiben
                if (!EventLog.SourceExists(sSource))
                    EventLog.CreateEventSource(sSource, sLog);
                EventLog.WriteEntry(sSource, sEvent + Environment.NewLine + ex.Message + Environment.NewLine + ex.InnerException,
                    EventLogEntryType.Error);

                throw new Exception(ex.InnerException.ToString());
            }
        }

        /// <summary>
        /// Call the object's Dispose method and sets the object to null;
        /// </summary>
        /// <param name="typeToUnload">Type implementing IDisposable to be destroyed</param>
        public void UnloadType(object typeToUnload)
        {
            try
            {
                //Verfiy Unloadtype
                if (typeToUnload != null && typeToUnload is IDisposable)
                {
                    //Dispose
                    (typeToUnload as IDisposable).Dispose();

                    if (appDomain != null)
                    {
                        //Unload ApplicationDomain
                        AppDomain.Unload(appDomain);
                        appDomain = null;
                    }
                }

                //Set instance to null
                typeToUnload = null;                
            } 
            catch (Exception exception)
            {
                //Eintrag ins Eventlog schreiben
                string sSource;
                string sLog;
                string sEvent;

                sSource = "XXX Sidebar Gadget";
                sLog = "Sidebar Gadget";
                sEvent = "Unhandled Exception in Gadget.Interop.GadgetAdapter";

                //Eventlog Eintrag schreiben
                if (!EventLog.SourceExists(sSource))
                    EventLog.CreateEventSource(sSource, sLog);
                EventLog.WriteEntry(sSource, sEvent + Environment.NewLine + exception.Message + Environment.NewLine + exception.InnerException,
                    EventLogEntryType.Error);
            } 
        }

        #endregion

        #region IDisposable Members 

        /// <summary>
        /// Dispose Methode for the GadgetAdapter
        /// </summary>
        public void Dispose()
        {
            //Clear constructor parameters
            this.paramList.Clear();
            paramList = null;

            try
            {
                //Unload the GadgetAdapter over Kernel32 functions
                IntPtr hMod = IntPtr.Zero;
                if (GetModuleHandleExA(0, DLLNAME, ref hMod))
                {
                    bool s = false;
                    do
                    {
                        s = FreeLibrary(hMod);
                    } while (s);
                }
            }
            finally
            {
                GC.SuppressFinalize(this);
            }

        }

        #region IObjectSafety Members
        public enum ObjectSafetyOptions
        {
            INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001,
            INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002,
            INTERFACE_USES_DISPEX = 0x00000004,
            INTERFACE_USES_SECURITY_MANAGER = 0x00000008
        };

        public int GetInterfaceSafetyOptions(ref Guid riid, out int pdwSupportedOptions, out int pdwEnabledOptions)
        {
            ObjectSafetyOptions m_options = ObjectSafetyOptions.INTERFACESAFE_FOR_UNTRUSTED_CALLER | ObjectSafetyOptions.INTERFACESAFE_FOR_UNTRUSTED_DATA;
            pdwSupportedOptions = (int)m_options;
            pdwEnabledOptions = (int)m_options;
            return 0;
        }
        public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
        {
            return 0;
        }
        #endregion

        #endregion
    }
}

这是界面:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;

namespace Gadget.Interop
{
    /// <summary>
    /// Interface required COM registration.  This interface outlines methods
    /// used to create and destroy managed .NET types
    /// </summary>
    [ComVisible(true)]
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    [Guid("618ACBAF-B4BC-4165-8689-A0B7D7115B05")]
    public interface IGadgetInterop
    {
        object LoadType(string assemblyFullPath, string className);
        object LoadTypeWithParams(string assemblyFullPath, string className, bool preserveParams);
        void AddConstructorParam(object parameter);
        void UnloadType(object typeToUnload);
    }
}

当我在 vb 脚本中尝试一个简单的 CreateObject

Set wshShell2 = CreateObject("GadgetInterop.GadgetAdapter")

我也试过:

Set wshShell2 = CreateObject("Gadget.Interop.GadgetAdapter")

我收到错误:800A01AD ActiveX 组件无法创建对象

其他人有同样的问题吗?

编辑:我还在 ole 查看器中看到了该组件...

谢谢

4

1 回答 1

2

64 位 COM 对象不能直接从 32 位应用程序中使用,反之亦然。在这种情况下,您应该将基于 .net 的 COM 对象指定为 AnyCPU,并将其注册为此 SO 答案中指定的两种 CPU 架构。基本上,您需要在

C:\Windows\Microsoft.NET\Framework\v2.0.50727>

C:\Windows\Microsoft.NET\Framework64\v2.0.50727>

于 2012-02-29T18:02:37.960 回答