【问题标题】:OPOS_E_NOSERVICE after return from DllGetClassObject() in simple ATL COM OPOS Service Object从简单 ATL COM OPOS 服务对象中的 DllGetClassObject() 返回后的 OPOS_E_NOSERVICE
【发布时间】:2015-10-03 06:16:10
【问题描述】:

我正在编写的示例 MSR OPOS 服务对象未正确初始化。我添加这个问题是为了帮助遇到同样问题的其他人,因为各种搜索都没有任何帮助。

我的问题是:如何确定 OPOS 服务对象中缺少什么方法?是否有某种实用程序可以运行 OPOS 服务对象并告诉我缺少什么?有什么方法可以确定接口应该提供哪些方法以及缺少哪些方法?

我正在遵循Writing an OPOS Service Object using ATL 中的过程,以了解如何创建 OPOS 服务对象。我在 Windows XP 下使用 Visual Studio 2005。为了测试基本功能,我使用 NCR 零售服务管理器 (RSM) 实用程序为 MSR 创建配置文件,以便测试磁条阅读器模拟器服务对象的基本功能。

Visual Studio 项目创建 COM 对象并正确注册它。当我尝试在服务对象配置文件上使用 RSM 的诊断功能时,我收到错误 OPOS_E_NOSERVICE。我在 COM 对象中创建了一个日志文件记录函数,显示服务对象已加载,COM 对象的DLLMain() 函数被调用,DLLGetClassObject() 被调用。但是,没有创建记录各种服务对象接口方法的第二个日志文件,表明没有调用任何服务对象接口方法。

因此,服务对象接口似乎存在问题,导致在加载 COM 对象时进行的检查失败。

DllGetClassObject() 函数由 Visual Studio ATL 项目向导生成,不需要更改。

使用 POS .NET 1.12 附带的 Microsoft POS .NET 示例实用程序,我尝试使用示例实用程序。我可以在 MSR 节点下的树控件中看到使用 NCR RSM 创建的配置文件。但是,当我尝试 Open 时,会出现错误消息。 Windows 事件日志显示以下错误。

Microsoft.PointOfService.PosControlException:方法打开抛出了一个 例外。服务对象不支持以下一项或多项 其发布所需的方法。

【问题讨论】:

  • 如果您没有以正确的方式执行此操作,您的帖子最终将被删除。提出问题,发布答案。
  • @HansPassant,这样更好吗?我在OPOS_E_NOSERVICE 上进行了谷歌搜索,这个问题出现在结果的第一页。如果我两天前有这个问题,它会对我有所帮助,所以我希望它对其他人有所帮助。这似乎是一个相当深奥的领域,没有大量文档。

标签: visual-c++ atl point-of-sale opos service-object


【解决方案1】:

我终于通过检查和审查代码找到了缺失的方法。事实证明,Visual Studio 2005 ATL 接口向导没有正确创建一个方法 OpenService(),这可能是因为它是第一个添加到服务对象接口的方法。

当我尝试使用 Visual Studio 类向导将此方法添加到界面时,在我将方法签名输入到向导对话框并按下“下一步”按钮后,向导会发出错误消息。

使用新的 ATL 项目从头开始重试时,错误对话框包含以下文本:

添加/删除操作是不可能的,因为代码元素 'OpenServiceW' 是只读的。

虽然单击方法时该方法确实显示在类视图的 Visual Studio UI 中,但 .idl 文件中的接口定义将其显示为空。

interface IVirtSo : IDispatch{
};

我关闭了 Visual Studio 然后重新打开项目并尝试再次添加它,这次收到错误消息:

未能返回新的代码元素。可能是语法错误。新元素 名称:OpenService

进一步调查表明 Windows API 中有一个 OpenService() 方法,可能是 Visual Studio 2005 在我尝试将此方法添加到我的服务对象和它存在于 Windows API 之间发生冲突(实际名称似乎是 OpenServiceW())。

我最终做的是添加一个具有相同签名的接口方法,使用类向导命名为CheckService(),然后将我生成的代码中存在的接口方法名称更改为OpenService(),包括几个CheckService 是名称或标签的一部分的地方。出于某种原因,Visual Studio 类向导认为OpenService() 的接口方法存在,而实际上并不存在。

但是,在我能够成功执行此操作之前,我必须先退出 Visual Studio,然后删除 Intellisense 文件(.ncb 文件和 .suo 文件),以便使用类视图向导添加新方法才能正常工作。在删除文件之前,即使方法添加失败,向导中的 Add -> Method 的 id 号也会不断增加。删除 Intellisense 文件后,ID 号再次从 1 开始,我能够使用向导添加 CheckService() 方法,然后使用“匹配大小写”打开的查找工具手动将方法名称修改为 OpenService() 并“匹配整个单词”已关闭。

到目前为止,我能看到的唯一方法是根据服务对象的源代码实现来查看 OPOS 服务对象规范。

我正在寻找其他可能的解决方案来查找 OPOS 服务对象中缺少的方法。

根据文章和我目前的经验,似乎以下是 OPOS 服务对象中需要可用的常见方法子集,以便服务对象正确加载。其中一些仅作为启动和初始化服务对象的一部分被调用一次。其他的,例如GetPropertyNumber()GetPropertyString() 以及这些的 SET 版本可能会作为设置服务对象环境的一部分被多次调用。对于需要在服务对象中具有相应方法的特定设备类型,特定 OPOS 通用控件对象可能会提供其他入口点。

HRESULT OpenService(BSTR DeviceClass, BSTR DeviceName, IDispatch* pDispatch, [out, retval] long* pRC);
HRESULT CheckHealth(long Level, [out, retval] long* pRC);
HRESULT ClaimDevice(long ClaimTimeout, [out, retval] long* pRC);
HRESULT ClearInput([out, retval] long* pRC);
HRESULT CloseService([out, retval] long* pRC);
HRESULT COFreezeEvents(VARIANT_BOOL Freeze, [out, retval] long* pRC);
HRESULT DirectIO(long Command, [in, out] long* pData, [in, out] BSTR* pString, [out, retval] long* pRC);
HRESULT ReleaseDevice([out, retval] long* pRC);

HRESULT GetPropertyNumber(long PropIndex, [out, retval] long* pNumber);
HRESULT GetPropertyString(long PropIndex, [out, retval] BSTR* pString);
HRESULT SetPropertyNumber(long PropIndex, long Number);
HRESULT SetPropertyString(long PropIndex, BSTR PropString);

【讨论】:

  • 在初始 OPOS 版本 (1.0) 中为设备类定义的所有方法都必须在您的 SO 中才能成功打开。您可以在 OPOS 规范中找到方法和它们最初出现的版本。打开失败时,使用 GetOpenResult 方法获取描述性错误代码。
猜你喜欢
  • 2010-12-17
  • 2011-05-09
  • 2015-01-10
  • 2012-05-31
  • 2013-06-07
  • 2013-09-19
  • 2011-06-23
  • 2011-11-10
  • 2020-03-09
相关资源
最近更新 更多