我在 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 查看器中看到了该组件...
谢谢