0

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はオブジェクトを作成できないと表示されます。

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(); 
        }
    }
}
4

2 に答える 2

2

残念ながら、実行可能なソリューションからはかけ離れています警告は正確であり、[ComVisible]で作成したクラスはいずれもCOMクライアントで作成できません。MyCashDrawerに必要なデフォルトのコンストラクターがありません。COMクライアントアプリはコンストラクターに引数を渡すことができません。VirtualManagerは公開されておらず、[ComVisible]ではないインターフェイスから派生しています

このコードには、IOleObject、IOleInPlaceObject、IOleInplaceActiveObject、IOleWindow、IViewObjectなどのActiveXコンポーネントをActiveXホストウィンドウで機能させるインターフェイスに必要な実装も含まれていません。さらに、ActiveXオブジェクトでは処理できない実装の詳細を公開しています。COMのスレッドモデルは、.NETのスレッドモデルとは大きく異なります。

真剣に異なるアプローチが必要になります。System.Windows.Forms.Controlから表示可能なオブジェクトを取得することを検討してください。これにより、ActiveXインターフェイスの実装要件が最小限に抑えられます。そして、あなたの問題をスレッド化してください、それを解決するためにそれをクライアントに任せないでください。

于 2012-06-09T15:16:36.137 に答える
0

レガスム警告は問題ではありません。VirtualManagerクラスが公開されていないためかもしれません。クラスを公開するようにしてください。

于 2012-06-09T14:34:00.837 に答える