现在手头有一个ocx控件,要调用其中的方法,写了如下代码:
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <strsafe.h>
#include <dbt.h>
/*#import "c:/windows/system32/cryptocx.ocx" \
no_namespace no_smart_pointers raw_interfaces_only \
raw_native_types no_implementation named_guids*/
#import "c:/windows/system32/cryptocx.ocx" \
named_guids
//这个地方只加了一个named_guids的参数,因为如果写no_namespace会报“使用未声明标识符”的错误,加其他参数也会有其他不同问题using namespace CRYPTOCXLib;void main()
{
try{
CoInitialize(NULL) ;
{
if(1)
{
_DCryptOcx* pCrypt = 0 ;
HRESULT hr = CoCreateInstance(
CLSID_CryptOcx,//Com对象标识符
0,//指向接口IUnknown指针
CLSCTX_ALL,//运行可执行代码上下文
DIID__DCryptOcx,//Com对象接口标识符
reinterpret_cast<void**>(&pCrypt)//用来接收指向Com对象接口地址指针变量
);
assert( SUCCEEDED(hr) ) ;
if(pCrypt){
pCrypt->OpenDevice(L"111111");
pCrypt->Release();
}
}
}
CoUninitialize() ;
}
catch(_com_error *e)
{
MessageBoxA(NULL,e->ErrorMessage(),NULL,NULL);
}
}
这样子写直接debug,编译通过,程序执行之后,会弹出一个visual studio的messagebox,报错USBTest.exe 中的 0x7c812afb 处未处理的异常: Microsoft C++ 异常: 内存位置 0x0012fcd8 处的 _com_error。加断点逐步调试,是执行到pCrypt->OpenDevice(L"111111");这一句,这个方法再去调用其它的方法时,会报“CXX0030: 错误: 无法计算表达式的值”,因为ocx不是我写的,只是拿过来用,对方给的javascript的例子,就在网页载入了这个ocx,然后就直接可以调用opendevice方法,所以我也不知道现在是什么原因报错,请问我上面代码写的有问题么?本人c++菜鸟一个,请达人指教,谢谢
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <strsafe.h>
#include <dbt.h>
/*#import "c:/windows/system32/cryptocx.ocx" \
no_namespace no_smart_pointers raw_interfaces_only \
raw_native_types no_implementation named_guids*/
#import "c:/windows/system32/cryptocx.ocx" \
named_guids
//这个地方只加了一个named_guids的参数,因为如果写no_namespace会报“使用未声明标识符”的错误,加其他参数也会有其他不同问题using namespace CRYPTOCXLib;void main()
{
try{
CoInitialize(NULL) ;
{
if(1)
{
_DCryptOcx* pCrypt = 0 ;
HRESULT hr = CoCreateInstance(
CLSID_CryptOcx,//Com对象标识符
0,//指向接口IUnknown指针
CLSCTX_ALL,//运行可执行代码上下文
DIID__DCryptOcx,//Com对象接口标识符
reinterpret_cast<void**>(&pCrypt)//用来接收指向Com对象接口地址指针变量
);
assert( SUCCEEDED(hr) ) ;
if(pCrypt){
pCrypt->OpenDevice(L"111111");
pCrypt->Release();
}
}
}
CoUninitialize() ;
}
catch(_com_error *e)
{
MessageBoxA(NULL,e->ErrorMessage(),NULL,NULL);
}
}
这样子写直接debug,编译通过,程序执行之后,会弹出一个visual studio的messagebox,报错USBTest.exe 中的 0x7c812afb 处未处理的异常: Microsoft C++ 异常: 内存位置 0x0012fcd8 处的 _com_error。加断点逐步调试,是执行到pCrypt->OpenDevice(L"111111");这一句,这个方法再去调用其它的方法时,会报“CXX0030: 错误: 无法计算表达式的值”,因为ocx不是我写的,只是拿过来用,对方给的javascript的例子,就在网页载入了这个ocx,然后就直接可以调用opendevice方法,所以我也不知道现在是什么原因报错,请问我上面代码写的有问题么?本人c++菜鸟一个,请达人指教,谢谢
// Created by Microsoft (R) C/C++ Compiler Version 15.00.21022.08 (90773aaa).
//
// e:\project\usbtest\usbtest\debug\cryptocx.tlh
//
// C++ source equivalent of Win32 type library c:/windows/system32/cryptocx.ocx
// compiler-generated file created 06/02/12 at 20:11:36 - DO NOT EDIT!#pragma once
#pragma pack(push, 8)#include <comdef.h>namespace CRYPTOCXLib {//
// Forward references and typedefs
//struct __declspec(uuid("d8af0d68-bea9-457f-ae9f-ae2f2f127d6c"))
/* LIBID */ __CRYPTOCXLib;
struct __declspec(uuid("c79bac42-db91-4937-9d2d-887d792b9c95"))
/* dispinterface */ _DCryptOcx;
struct __declspec(uuid("eaf2ecb8-e7fa-46af-adf2-147605ab0de0"))
/* dispinterface */ _DCryptOcxEvents;
struct /* coclass */ CryptOcx;//
// Smart pointer typedef declarations
//_COM_SMARTPTR_TYPEDEF(_DCryptOcx, __uuidof(_DCryptOcx));
_COM_SMARTPTR_TYPEDEF(_DCryptOcxEvents, __uuidof(_DCryptOcxEvents));//
// Type library items
//struct __declspec(uuid("c79bac42-db91-4937-9d2d-887d792b9c95"))
_DCryptOcx : IDispatch
{
//
// Wrapper methods for error-handling
// // Methods:
_bstr_t OpenDevice (
_bstr_t strPasswd );
_bstr_t CloseDevice ( );
_bstr_t VerifyPin (
_bstr_t strPasswd );
_bstr_t ChangePin (
_bstr_t oldPass,
_bstr_t newPass );
_bstr_t ReadCert (
_bstr_t certNo );
_bstr_t ClientHello (
_bstr_t dwFlags );
_bstr_t ClientAuth (
_bstr_t strServerHello,
_bstr_t dwFlags );
_bstr_t VerifyCert (
_bstr_t CertFlags,
_bstr_t Cert,
_bstr_t VerifyFlags,
_bstr_t OCSPIP );
_bstr_t ReloadKeyPin (
_bstr_t MasterPin,
_bstr_t newpin );
_bstr_t GetCKeyVerifyStatus ( );
_bstr_t ParseCert (
_bstr_t Cert,
_bstr_t parseStr,
_bstr_t base64Flag );
_bstr_t VerifySignbyCert (
_bstr_t Cert,
_bstr_t sign,
_bstr_t src );
_bstr_t GetVersion ( );
_bstr_t DigestData (
_bstr_t strData,
_bstr_t strAlgid );
_bstr_t SignData (
_bstr_t strData,
_bstr_t strSignAlgid,
_bstr_t strTime,
_bstr_t dwFlags );
_bstr_t VerifySign (
_bstr_t strData,
_bstr_t SignData,
_bstr_t CertData,
_bstr_t strSignAlgid,
_bstr_t dwFlags );
HRESULT AboutBox ( );
};struct __declspec(uuid("eaf2ecb8-e7fa-46af-adf2-147605ab0de0"))
_DCryptOcxEvents : IDispatch
{};struct __declspec(uuid("18ed5d4d-446e-436a-a839-f21382dd1f77"))
CryptOcx;
// [ default ] dispinterface _DCryptOcx
// [ default, source ] dispinterface _DCryptOcxEvents//
// Named GUID constants initializations
//extern "C" const GUID __declspec(selectany) LIBID_CRYPTOCXLib =
{0xd8af0d68,0xbea9,0x457f,{0xae,0x9f,0xae,0x2f,0x2f,0x12,0x7d,0x6c}};
extern "C" const GUID __declspec(selectany) DIID__DCryptOcx =
{0xc79bac42,0xdb91,0x4937,{0x9d,0x2d,0x88,0x7d,0x79,0x2b,0x9c,0x95}};
extern "C" const GUID __declspec(selectany) DIID__DCryptOcxEvents =
{0xeaf2ecb8,0xe7fa,0x46af,{0xad,0xf2,0x14,0x76,0x05,0xab,0x0d,0xe0}};
extern "C" const GUID __declspec(selectany) CLSID_CryptOcx =
{0x18ed5d4d,0x446e,0x436a,{0xa8,0x39,0xf2,0x13,0x82,0xdd,0x1f,0x77}};//
// Wrapper method implementations
//#include "e:\project\usbtest\usbtest\debug\cryptocx.tli"} // namespace CRYPTOCXLib#pragma pack(pop)
try{
CoInitialize(NULL) ;
{
if(1)
{
_DCryptOcxPtr pCrypt;
HRESULT hr = pCrypt.CreateInstance(__uuidof(_DCryptOcx));
if(pCrypt)
{
pCrypt->OpenDevice(L"");
pCrypt.Release();
}
}
}
CoUninitialize() ;
}
这样写HRESULT hr那一步hr的返回结果就不是成功的了,然后到if(pCrypt)这里就直接跳过了,应该是因为pCrypt为空,请问这样写是什么原因创建实例失败了呢?谢谢
inline _bstr_t _DCryptOcx::OpenDevice ( _bstr_t strPasswd ) {
BSTR _result = 0;
_com_dispatch_method(this, 0x1, DISPATCH_METHOD, VT_BSTR, (void*)&_result,
L"\x0008", (BSTR)strPasswd);
return _bstr_t(_result, false);
}
报错信息如下:
- _result 0x00000000 <错误的指针> wchar_t *
CXX0030: 错误: 无法计算表达式的值
_com_dispatch_method(this, 0x1, DISPATCH_METHOD, VT_BSTR, (void*)&_result,
L"\x0008", (BSTR)strPasswd);
你看看与0x1对应的函数是哪个, 然后在函数里面设置断点
不过我的项目中好像没有生成idl文件,请问这个我可以去哪里看0x1具体代表的函数含义呢?谢谢
请问可以给我具体说一下哪个参数应该改为什么么?应该就是从tlh文件中找吧?谢谢
CoCreateInstance(
CLSID_CryptOcx,//Com对象标识符
NULL,//指向接口IUnknown指针
CLSCTX_ALL,//运行可执行代码上下文
DIID__DCryptOcx,//Com对象接口标识符
reinterpret_cast<void**>(&pCrypt)//用来接收指向Com对象接口地址指针变量
);
其实用你之前的代码就可以了:
_DCryptOcxPtr pCrypt;
HRESULT hr = pCrypt.CreateInstance(CLSID_CryptOcx);
if(pCrypt)
_DCryptOcxPtr pCrypt;
HRESULT hr = pCrypt.CreateInstance(CLSID_CryptOcx);
if(pCrypt)
{
std::cout << "checkUSB result is "
//<< checkUSB
<< '\n' ;
pCrypt->AddRef();
BSTR bstrText=::SysAllocString(L"111111");
pCrypt->OpenDevice(bstrText);
::SysFreeString(bstrText);
pCrypt->GetVersion();
pCrypt.Release();
}
这样子写确实pCrypt可以继续执行,执行AddRef()都没有问题,可是到了OpenDevice就会去执行下面这个方法,位于comutil.h
inline _bstr_t::_bstr_t(const wchar_t* s)
: m_Data(new Data_t(s))
{
if (m_Data == NULL) {
_com_issue_error(E_OUTOFMEMORY);
}
}
接着就去执行下面的方法
inline void* _bstr_t::Data_t::operator new(size_t sz)
{
return ::operator new(sz);
}
再执行几步之后就有参数报指针错误和CXX0030错误,最后就会报内存异常。
我这个项目是用ocx的接口去读usbkey的信息,有朋友说读usbkey不能使用debug调试,但如果我直接生成后去执行exe,到了opendevice这一步就直接报c++ runtime error,application terminate in an unusual way之类的,不知道到底问题出在哪里。感觉前面CreateInstance已经成功了,就是不知道为什么不能调用方法
HRESULT hr = NULL;
IDispatch* pIDispatch = NULL;
hr = ::CoInitialize(NULL);
hr = ::CoCreateInstance(CLSID_CryptOcx, NULL, CLSCTX_INPROC_SERVER, IID_IDispatch, (void**)&pIDispatch);
if (SUCCEEDED(hr))
{
DISPID dispid;
LPOLESTR name=L"OpenDevice";
hr=pIDispatch->GetIDsOfNames(IID_NULL,&name,1,::GetUserDefaultLCID(),&dispid);
if (SUCCEEDED(hr))
{
UINT iError = -1;
VARIANT rarg;
::VariantInit(&rarg);
VARIANT var[1];
::VariantInit(&var[0]);
var[0].vt=VT_BSTR;
BSTR bstrText=::SysAllocString(L"111111");
var[0].bstrVal=bstrText; //参数值
::SysFreeString(bstrText);
DISPPARAMS param;
param.cArgs = 1;
param.rgvarg = var;
param.cNamedArgs = 0;
param.rgdispidNamedArgs = NULL;
hr = pIDispatch->Invoke(dispid, IID_NULL, GetUserDefaultLCID(), DISPATCH_METHOD, ¶m, &rarg, NULL, &iError);
if (SUCCEEDED(hr))
{
//调用成功
std::cout << "Device Open Successfully "
<< '\n' ;
}
::VariantClear(&rarg);
::VariantClear(&var[0]);
}
else
{
::MessageBox(NULL,"getIDsOfNames failed","Error",0x10010);
}
pIDispatch->Release();
}
这样写一直执行到hr = pIDispatch->Invoke都是没问题的,但是Invoke这个方法的返回结果始终不成功,一直是E_UNEXPECTED,之前GetidsOfNames返回的dispid的值也是正确的,和tli里面定义的值一样,只不过tli中用的是16进制,程序中返回的是一个Long型,不知道是不是其他参数写的有问题?还望达人赐教,谢谢