我们正在尝试实现支持COM接口的.NET服务对象来模拟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
放在yRPosPrinterDotNet.POSPrinter的ProgID中
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++
答案 0 :(得分:2)
这似乎是一个DispInterface。这是一个可怕的COM黑客来支持Visual Basic。基本上,所有功能都有编号。在第一次调用时,查找并缓存所有功能号。例如,您似乎缺少Close()函数。这会导致它以您看到的方式在查找中失败。
引用“OLE for Retail POS Control Guide - Rel.1.1”:
- 通过调用查找所有服务对象方法的调度ID 服务对象实例 m_lpDispatchGetIDsOfNames函数。 更新生成的服务对象 将这些调度ID传递给的方法 InvokeHelper成员函数。如果 任何所需的发送ID都是 然后,在服务对象中找不到 关闭调度接口和 返回OPOS_E_NOSERVICE。
醇>