我编写了一个C#类库,想在vbscript中使用它。 这是我的代码:
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.PointOfService;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.Reflection;
using System.ComponentModel;
namespace IndigoDynamic
{
#region class implements IAsyncResult
[ProgId("IndigoDynamic.VirtualManager")]
[ClassInterface(ClassInterfaceType.AutoDispatch)]
[ComVisible(true)]
public class AsyncResult : IAsyncResult
{
object _state;
private bool m_completed;
private System.Threading.ManualResetEvent m_handle;
private Exception m_exception;
public bool IsCompleted
{
get { return m_completed; }
set { m_completed = value; }
}
public System.Threading.WaitHandle AsyncWaitHandle
{
get { return m_handle; }
set { m_handle = (System.Threading.ManualResetEvent)value; }
}
public object AsyncState
{
get
{
if (Exception != null)
{
throw Exception;
}
return _state;
}
internal set
{
_state = value;
}
}
public bool CompletedSynchronously { get { return IsCompleted; } }
internal Exception Exception
{
get { return m_exception; }
set { m_exception = value; }
}
}
#endregion
#region extends CashDrawer
[ProgId("IndigoDynamic.VirtualManager")]
[ClassInterface(ClassInterfaceType.AutoDispatch)]
[ComVisible(true)]
public class MyCashDrawer
{
private CashDrawer me;
public delegate void status_callback(int newstatus);
private status_callback myF;
public MyCashDrawer(CashDrawer param)
{
me = param;
me.StatusUpdateEvent += new StatusUpdateEventHandler(this.StatusUpdate);
}
[ComVisible(true)]
public void Claim(int timeout) { me.Claim(timeout); }
[ComVisible(true)]
public void Close() { me.Close(); }
[ComVisible(true)]
public void Open() { me.Open(); }
[ComVisible(true)]
public void OpenDrawer() { me.OpenDrawer(); }
[ComVisible(true)]
public void Release() { me.Release(); }
[ComVisible(true)]
public void Release(int timeout, int freq, int duration, int delay)
{
me.WaitForDrawerClose(timeout, freq, duration, delay);
}
[ComVisible(true)]
public int StatusClosed() { return CashDrawer.StatusClosed; }
[ComVisible(true)]
public int StatusOpen() { return CashDrawer.StatusOpen; }
[ComVisible(true)]
public bool Claimed() { return me.Claimed; }
[ComVisible(true)]
public bool DeviceEnabled() { return me.DeviceEnabled; }
[ComVisible(true)]
public bool DrawerOpened() { return me.DrawerOpened; }
[ComVisible(true)]
public ControlState State() { return me.State; }
[ComVisible(true)]
public void addStatusCallback(status_callback f)
{
myF = f;
}
[ComVisible(true)]
public void removeStatusCallback(status_callback f)
{
if (myF == f)
myF = null;
}
[ComVisible(true)]
private void StatusUpdate(object sender, StatusUpdateEventArgs arg)
{
if (myF != null)
myF(arg.Status);
}
}
#endregion
[ProgId("IndigoDynamic.VirtualManager")]
[ClassInterface(ClassInterfaceType.AutoDispatch)]
[ComVisible(true)]
class VirtualManager : ISynchronizeInvoke
{
private readonly object _sync;
// Constructor
public VirtualManager()
{
_sync = new object();
}
#region implements methods of ISynchronizeInvoke
public IAsyncResult BeginInvoke(Delegate method, object[] args) {
AsyncResult result = new AsyncResult();
System.Threading.ThreadPool.QueueUserWorkItem(delegate {
result.AsyncWaitHandle = new System.Threading.ManualResetEvent(false);
try {
result.AsyncState = Invoke(method, args);
} catch (Exception exception) {
result.Exception = exception;
}
result.IsCompleted = true;
});
return result;
}
public object EndInvoke(IAsyncResult result) {
if (!result.IsCompleted) {
result.AsyncWaitHandle.WaitOne();
}
return result.AsyncState;
}
public object Invoke(Delegate method, object[] args) {
lock (_sync) {
return method.DynamicInvoke(args);
}
}
public bool InvokeRequired {
get { return true; }
}
#endregion
[ComVisible(true)]
public MyCashDrawer getCashDrawer()
{
PosExplorer posExplorer = new PosExplorer(this);
DeviceInfo deviceInfo = posExplorer.GetDevice(DeviceType.CashDrawer);
if (deviceInfo == null)
{
//<report failure >
return null;
}
else
{
CashDrawer cd = posExplorer.CreateInstance(deviceInfo) as CashDrawer;
return new MyCashDrawer(cd);
}
}
[ComVisible(true)]
public MyCashDrawer getCashDrawer(String name)
{
PosExplorer posExplorer = new PosExplorer(this);
DeviceInfo deviceInfo = posExplorer.GetDevice(DeviceType.CashDrawer, name);
if (deviceInfo == null)
{
//<report failure >
return null;
}
else
{
CashDrawer cd = posExplorer.CreateInstance(deviceInfo) as CashDrawer;
return new MyCashDrawer(cd);
}
}
[ComRegisterFunction()]
public static void RegisterClass(string key)
{
StringBuilder sb = new StringBuilder(key);
sb.Replace(@"HKEY_CLASSES_ROOT\", "");
RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(), true);
RegistryKey ctrl = k.CreateSubKey("Control");
ctrl.Close();
RegistryKey inprocServer32 = k.OpenSubKey("InprocServer32", true);
inprocServer32.SetValue("CodeBase", Assembly.GetExecutingAssembly().CodeBase);
inprocServer32.Close();
k.Close();
}
[ComUnregisterFunction()]
public static void UnregisterClass(string key)
{
StringBuilder sb = new StringBuilder(key);
sb.Replace(@"HKEY_CLASSES_ROOT\", "");
RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(), true);
if (k == null)
{
return;
}
k.DeleteSubKey("Control", false);
RegistryKey inprocServer32 = k.OpenSubKey("InprocServer32", true);
inprocServer32.DeleteSubKey("CodeBase", false);
inprocServer32.Close();
k.Close();
}
}
}
构建之后,我使用RegAsm,但它抛出警告没有注册类型。 然后我在vbs中编写了一个示例代码,但它说ActiveX不能创建Object。
Sub main
set objTest = CreateObject("IndigoDynamic.VirtualManager")
end sub
call main
有人说我必须检查AssemblyInfo.cs并确保我有
[assembly: ComVisible(true)]
我当然有,但问题仍未解决。 谁能告诉我一个解决方案?
我改变了我的代码。更简单,没有线程,没有界面,都是公开的。 但它仍然无效。 拜托,我真的需要帮助。
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.PointOfService;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.Reflection;
using System.ComponentModel;
namespace IndigoDynamic
{
[ProgId("IndigoDynamic.VirtualManager")]
[ClassInterface(ClassInterfaceType.AutoDispatch)]
[ComVisible(true)]
public class VirtualManager
{
public VirtualManager()
{
}
[ComVisible(true)]
public CashDrawer getCashDrawer()
{
PosExplorer posExplorer = new PosExplorer();
DeviceInfo deviceInfo = posExplorer.GetDevice(DeviceType.CashDrawer);
if (deviceInfo == null)
{
//<report failure >
return null;
}
else
{
CashDrawer cd = posExplorer.CreateInstance(deviceInfo) as CashDrawer;
return cd;
}
}
[ComVisible(true)]
public CashDrawer getCashDrawer(String name)
{
PosExplorer posExplorer = new PosExplorer();
DeviceInfo deviceInfo = posExplorer.GetDevice(DeviceType.CashDrawer, name);
if (deviceInfo == null)
{
//<report failure >
return null;
}
else
{
CashDrawer cd = posExplorer.CreateInstance(deviceInfo) as CashDrawer;
return cd;
}
}
[ComRegisterFunction()]
public static void RegisterClass(string key)
{
StringBuilder sb = new StringBuilder(key);
sb.Replace(@"HKEY_CLASSES_ROOT\", "");
RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(), true);
RegistryKey ctrl = k.CreateSubKey("Control");
ctrl.Close();
RegistryKey inprocServer32 = k.OpenSubKey("InprocServer32", true);
inprocServer32.SetValue("CodeBase", Assembly.GetExecutingAssembly().CodeBase);
inprocServer32.Close();
k.Close();
}
[ComUnregisterFunction()]
public static void UnregisterClass(string key)
{
StringBuilder sb = new StringBuilder(key);
sb.Replace(@"HKEY_CLASSES_ROOT\", "");
RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(), true);
if (k == null)
{
return;
}
k.DeleteSubKey("Control", false);
RegistryKey inprocServer32 = k.OpenSubKey("InprocServer32", true);
inprocServer32.DeleteSubKey("CodeBase", false);
inprocServer32.Close();
k.Close();
}
}
}
答案 0 :(得分:2)
很遗憾,非常远离可行的解决方案。警告是准确的,没有一个类由COM客户端创建[ComVisible]。 MyCashDrawer缺少必需的默认构造函数,COM客户端应用程序无法将参数传递给构造函数。 VirtualManager不是公共的,并且源自不是[ComVisible]
的接口代码也缺少使ActiveX组件在ActiveX主机窗口上工作的接口所需的实现,如IOleObject,IOleInPlaceObject,IOleInplaceActiveObject,IOleWindow,IViewObject等。此外,您正在公开ActiveX对象无法处理的实现细节,COM中的线程模型与.NET中的线程模型非常不同。
您将需要一种严重不同的方法。考虑从System.Windows.Forms.Control派生可见对象,它负责最小的ActiveX接口实现要求。并使线程你的问题,不要让它留给客户端进行整理。
答案 1 :(得分:0)
诉讼警告不是问题。 也许这是因为VirtualManager类不公开。尝试将您的课程公开。