【问题标题】:Problem interfacing C++ POS controls with the .NET POS SDK将 C++ POS 控件与 .NET POS SDK 连接时出现问题
【发布时间】:2009-11-26 14:52:27
【问题描述】:

我们正在尝试实现一个 .NET 服务对象,它支持 COM 接口来模拟 POSPrinter,但仍与旧技术兼容。

我们在下面的类中有我们的接口和类对象..

using [...]

namespace yRPOSPrinterDotNet
{
    [Guid("2D570F11-4BD8-40e7-BF14-38772063AAF0")]
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    public interface yRPosPrinterCOM
    {

        long Open(String DeviceName);
        long PrintNormal(long Station, String Data);

    }

    [Guid("478176F4-5105-435c-8EBC-D4CB90B7B1C7")]
    [ClassInterface(ClassInterfaceType.None)]
    //[ProgId("yRPOSPrinterDotNet.POSPrinter")] //will be set automatically as the progid <namespace><clsid>
    public class POSPrinter : yRPosPrinterCOM
    {

        #region yRPosPrinterCOM Members
        public long Open()
        {
            return 0;
        }

        public long Open(String DeviceName)
        {
            Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));
            FileStream objStream = new FileStream("C:\\yRPOSLog.txt", FileMode.OpenOrCreate);
            TextWriterTraceListener objTraceListener = new TextWriterTraceListener(objStream);
            Trace.Listeners.Add(objTraceListener);
            Trace.AutoFlush = true;
            Trace.Indent();
            Trace.WriteLine("Entering Main");
            Debug.WriteLine("How does this one do??");
            Console.WriteLine("Hello World.");
            Trace.WriteLine("Exiting Main");
            Trace.Unindent();
            return 0;
        }


        public long PrintNormal(long Station, string Data)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

}

然后在HKEY_LOCAL_MACHINE\SOFTWARE\OLEforRetail\ServiceOPOS\POSPrinter\yReceipts我们的ProgID yRPosPrinterDotNet.POSPrinter 中输入

HKEY_CLASSES_ROOT\CLSID\{478176F4-5105-435C-8EBC-D4CB90B7B1C7} 在构建后正确地拥有我们的 ProgID (yRPosPrinterDotNet.POSPrinter)

我们可以使用这个类通过如下测试类调用DLL(找到ProgID)

using [...]

namespace TestYRPosPrinterDotNet
{
    /// <summary>
    /// Summary description for UnitTest1
    /// </summary>
    [TestClass]
    public class UnitTest1
    {
        public UnitTest1()
        {

        }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        [TestMethod]
        public void TestMethod1()
        {
            String sProgID = "yRPosPrinterDotNet.POSPrinter";
            // We get the type using just the ProgID
            Type oType = Type.GetTypeFromProgID(sProgID);
            if (oType != null)
            {
               POSPrinter pp = (POSPrinter)Activator.CreateInstance(oType);
               long retVal = pp.Open("Nothing");
            }

        }
    }
}

但是当我们尝试通过示例 TestApp 调用时(它确实显示为 serviceObject)

{"Method Open threw an exception.  The service object does not support one or more of the methods required by its release."} System.Exception {Microsoft.PointOfService.PosControlException}

通过一个示例 C++ 控制对象,我们收到一个在 opos.h 中定义为 (const LONG OPOS_E_NOSERVICE = 4 + OPOSERR;) 的 104,并带有以下堆栈跟踪

----------------------------------- Doesn't work --------------------------------------------------------

 POSPrinterExample.exe!COleDispatchDriver::InvokeHelperV(long dwDispID=37, unsigned short wFlags=1, unsigned short vtRet=3, void * pvRet=0x0012f1e0, const unsigned char * pbParamInfo=0x00702014, char * argList=0x0012f110)  Line 

397 C++
 POSPrinterExample.exe!COleControlSite::InvokeHelperV(long dwDispID=37, unsigned short wFlags=1, unsigned short vtRet=3, void * pvRet=0x0012f1e0, const unsigned char * pbParamInfo=0x00702014, char * argList=0x0012f10c)  Line 1093 

C++
  POSPrinterExample.exe!CWnd::InvokeHelper(long dwDispID=37, unsigned short wFlags=1, unsigned short vtRet=3, void * pvRet=0x0012f1e0, const unsigned char * pbParamInfo=0x00702014, ...)  Line 382 C++
  POSPrinterExample.exe!COPOSPOSPrinter::Open(const char * DeviceName=0x00271f00)  Line 192 + 0x1c bytes C++

【问题讨论】:

    标签: .net c++ com point-of-sale opos


    【解决方案1】:

    这似乎是一个 DispInterface。这是支持 Visual Basic 的可怕 COM hack。基本上,所有功能都有编号。在第一次调用时,会查找并缓存所有函数编号。例如,您似乎缺少 Close() 函数。如您所见,这将导致查找失败。

    引用“OLE for Retail POS Control Guide - Rel. 1.1”:

    1. 通过调用查找所有服务对象方法的调度 ID 服务对象实例的 m_lpDispatch  GetIDsOfNames 函数。 更新生成的服务对象 将这些调度 ID 传递给的方法 InvokeHelper 成员函数。如果 任何必需的调度 ID 都是 未在服务对象中找到,则 关闭调度界面并 返回 OPOS_E_NOSERVICE。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-06
      • 2014-12-03
      • 2018-02-09
      • 2012-01-27
      相关资源
      最近更新 更多