2009-11-26 71 views
2

我們正在嘗試實現一個.NET服務對象,該對象支持COM接口來模擬POSPrinter,但仍舊與舊技術兼容。使用.NET POS SDK連接C++ POS控件的問題

我們有我們的接口,並在下面的類類對象..

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我們yRPosPrinterDotNet.POSPrinter

的進程id

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限定的104 (const LONG OPOS_E_NOSERVICE = 4 + OPOSERR;)和以下堆棧跟蹤

----------------------------------- 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++ 

回答

2

這似乎是一個DispInterface。這是一個可怕的COM黑客來支持Visual Basic。基本上,所有功能都被編號。在第一次調用時,查找並緩存所有函數編號。例如,你似乎錯過了Close()函數。按照您所看到的方式,這會導致查找失敗。

從報價「OLE零售POS控制指南 - 相對1.1。」:

  • 通過調用 的查找所有的服務對象的方法的調度ID服務對象實例的 m_lpDispatchGetIDsOfNames函數。 更新生成的服務對象 方法將這些調度ID傳遞給InvokeHelper成員函數的 。如果 任何所需調度ID均爲 未在服務對象中找到,則 關閉調度接口, 返回OPOS_E_NOSERVICE。