实战COM(07)----COM+的特性之建立者字符串

    技术2022-05-11  132

    本文欢迎转载,唯请注明出处及作者 blackcolor@263.net---------------------------------------------------

                       实战COM(07)----COM+的特性之建立者字符串

        本文以上一节的例子为基础介绍在COM+中如何使用“建立者字符串”。所谓建立者字符串,有些书将其命名为“构造字符串”,实际上是在实例化COM+组件时,由COM+环境传递给COM+组件的一个字符串,一般可用于设置连接数据库的DSN。

    一、打开COM工程Step041)给接口ISimple04增加一个函数      HRESULT GetConstructString(BSTR *bString)

    2)修改Simple04.h文件:// Simple04.h : Declaration of the CSimple04#include <comsvcs.h> // 头文件来自于SDK--新

    #include <atldbcli.h> // 数据库操作

    #ifndef __SIMPLE04_H_#define __SIMPLE04_H_

    #include "resource.h"       // main symbols

    // 定义一个新类class CAuthors{public: // 数据--宽度来源于表Authors CHAR m_szAu_Id[11];   CHAR m_szAu_lName[40]; CHAR m_szAu_fName[20];  // 输出绑定 BEGIN_COLUMN_MAP(CAuthors)  COLUMN_ENTRY(1, m_szAu_Id)  COLUMN_ENTRY(2, m_szAu_lName)  COLUMN_ENTRY(3, m_szAu_fName) END_COLUMN_MAP()

     // 参数绑定 BEGIN_PARAM_MAP(CAuthors)  COLUMN_ENTRY(1, m_szAu_lName) END_PARAM_MAP()};

    /// CSimple04class ATL_NO_VTABLE CSimple04 :  public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<CSimple04, &CLSID_Simple04>, public IObjectConstruct,   // 新 public IDispatchImpl<ISimple04, &IID_ISimple04, &LIBID_STEP04Lib>{public: CSimple04() {  strcpy(m_szConstruct, "In CSimple04"); // 新  m_hr = E_FAIL;  // 初始化 }

    DECLARE_REGISTRY_RESOURCEID(IDR_SIMPLE04)

    DECLARE_PROTECT_FINAL_CONSTRUCT()

    BEGIN_COM_MAP(CSimple04) COM_INTERFACE_ENTRY(ISimple04) COM_INTERFACE_ENTRY(IDispatch) COM_INTERFACE_ENTRY(IObjectConstruct)  // 新END_COM_MAP()

    // 加入变量public: CDataSource m_Connection; CSession m_session; CCommand<CAccessor<CAuthors> > m_Authors; HRESULT  m_hr; char  m_szConstruct[30];  // 可以根据需要修改大小--新

    // ISimple04public: STDMETHOD(DisConnect)(void); STDMETHOD(MoveNext)(void); STDMETHOD(GetAu_fname)(/*[out, retval]*/BSTR * bAu_fname); STDMETHOD(GetAu_lname)(/*[out, retval]*/BSTR * bAu_lname); STDMETHOD(GetAu_id)(/*[out, retval]*/BSTR * bAu_id); STDMETHOD(ConnectToSQL)(void); STDMETHOD(GetConstructString)(/*[out, retval]*/BSTR * bString); // 新

    // IObjectConstructpublic: STDMETHODIMP Construct(IDispatch * pUnk); // 新

    };

    #endif //__SIMPLE04_H_

    3)修改Simple04.cpp文件// Simple04.cpp : Implementation of CSimple04#include "stdafx.h"#include "Step04.h"#include "Simple04.h"// 加入comutil支持#include <comutil.h>#pragma comment( lib, "comsupp.lib" )

    #pragma comment( lib, "svcguid.lib" ) // 来自于SDK -- 新

    // CSimple04

    // 连接到服务SQL器,并取回Authors数据STDMETHODIMP CSimple04::ConnectToSQL(){ // 如果已经建立了连接,先关闭 if(SUCCEEDED(m_hr)) {  m_session.Close();  m_Connection.Close();  // 关闭连接  m_hr = E_FAIL; }

     // 打开数据库 CDBPropSet dbinit(DBPROPSET_DBINIT); dbinit.AddProperty(DBPROP_INIT_DATASOURCE, OLESTR("GP2000"));   // 服务器名 dbinit.AddProperty(DBPROP_AUTH_USERID, OLESTR("sa"));    // 用户名 dbinit.AddProperty(DBPROP_AUTH_PASSWORD, OLESTR("123"));   // 密码 dbinit.AddProperty(DBPROP_AUTH_PERSIST_SENSITIVE_AUTHINFO, false); dbinit.AddProperty(DBPROP_INIT_CATALOG, OLESTR("pubs"));   // 数据库名 dbinit.AddProperty(DBPROP_INIT_LCID, (long)2052); dbinit.AddProperty(DBPROP_INIT_PROMPT, (short)4); m_hr = m_Connection.Open(_T("SQLOLEDB.1"), &dbinit); if (FAILED(m_hr)) return m_hr;  m_hr = m_session.Open(m_Connection); if (FAILED(m_hr))  {  m_Connection.Close();  return m_hr; } // 设置查询条件   strcpy(m_Authors.m_szAu_lName, "%h%");  // au_lname中包含"h"的作者 m_Authors.Open(m_session,                "select au_id, au_lname, au_fname from authors where au_lname like ?");

     return S_OK;}// 取结果集STDMETHODIMP CSimple04::MoveNext(){ if(SUCCEEDED(m_hr)) {  m_hr=m_Authors.MoveNext(); } else { // 关闭连接  DisConnect(); }

     return m_hr;}// 取数据STDMETHODIMP CSimple04::GetAu_id(BSTR *bAu_id){ if(SUCCEEDED(m_hr)) {  *bAu_id = _com_util::ConvertStringToBSTR(m_Authors.m_szAu_Id); }

     return S_OK;}

    STDMETHODIMP CSimple04::GetAu_lname(BSTR *bAu_lname){ if(SUCCEEDED(m_hr)) {  *bAu_lname = _com_util::ConvertStringToBSTR(m_Authors.m_szAu_lName); }

     return S_OK;}

    STDMETHODIMP CSimple04::GetAu_fname(BSTR *bAu_fname){ if(SUCCEEDED(m_hr)) {  *bAu_fname = _com_util::ConvertStringToBSTR(m_Authors.m_szAu_fName); }

     return S_OK;}

    STDMETHODIMP CSimple04::DisConnect(){ if(SUCCEEDED(m_hr)) {  m_session.Close();  m_Connection.Close();  // 关闭连接  m_hr = E_FAIL; }

     return S_OK;}// 取构造字符串--新STDMETHODIMP CSimple04::Construct(IDispatch * pUnk){ if (!pUnk) return E_UNEXPECTED;

     IObjectConstructString * pString=NULL; HRESULT  hr = E_FAIL; hr=pUnk->QueryInterface(IID_IObjectConstructString, (void **)&pString); if (FAILED(hr)) return hr;

     if(pString) {  BSTR bStr;  pString->get_ConstructString(&bStr);

      char *pszString;  pszString = _com_util::ConvertBSTRToString(bStr);  strcpy(m_szConstruct, pszString);

      // 释放内存  delete pszString;  SysFreeString(bStr);  pString->Release(); } else  strcpy(m_szConstruct, "Error!");

     return S_OK;}

    // 取构造字符串--新STDMETHODIMP CSimple04::GetConstructString(BSTR *bString){ *bString = _com_util::ConvertStringToBSTR(m_szConstruct);

     return S_OK;}

    4)编译连接Step04工程,并将其配置成COM+组件Step04,请参考“实战COM(05)----创建一个COM+应用”

    二、建立客户端1)客户端文件如下:// Client.cpp 文件 -- 取构造字符串

    #include <windows.h>#include <stdio.h>#include <winerror.h>

    // 加入comutil支持#include <comutil.h>#pragma comment( lib, "comsupp.lib" )

    // 包含com的定义文件,以下两个文件从step04中拷贝出来#include "../step04/step04.h"#include "../step04/step04_i.c"

    void main(){ ISimple04 * pISimple04=NULL;  // 我们定义的接口 BSTR  bString;

     // 初始化 HRESULT hr = CoInitialize(NULL); if(FAILED(hr)) {  printf("Coinitialize failed! hr=0x%x", hr);  return ; }

     // 创建COM对象 hr = CoCreateInstance(CLSID_Simple04, NULL, CLSCTX_ALL,                    IID_ISimple04, (void **)&pISimple04); if(FAILED(hr)) {  printf("create com failed! hr=0x%x", hr);  CoUninitialize();  return ; } // 取字符串 bString hr = pISimple04->GetConstructString(&bString); if(FAILED(hr)) {  printf("pISimple04->GetConstructString() failed! hr=0x%x", hr);  pISimple04->Release();  CoUninitialize();  return ; } char *pszConstruct; pszConstruct = _com_util::ConvertBSTRToString(bString);  printf("The Construct is %s/n", pszConstruct);

     // 释放分配的内存 SysFreeString(bString); delete pszConstruct;

     pISimple04->Release(); CoUninitialize();

     return ;}

    三、配置组件Step041)打开“组件服务”,展开刚才建立的组件“Step04”,如下图:

    2)右击图中的COM对象“Step04.Simple04.1”,从菜单中选择“属性”3)单击窗口“Step04.Simple04.1 属性”中的“激活”标签,选中“启用对象结构”,在下面的编辑框中输入“My String”,然后确定,如下图

    四、运行1)从服务器导出该组件的客户端,并安装到WINDOWS 98上2)在该98上运行上面的客户端client.exe,应该出现下面的提示:          The Construct is My String

    五、说明1)上面文件中,凡注明“新”,说明是本次修改的部分2)如果你是在同一台98上编译Step04的COM对象,可能需要先注销Step04.dll,再安装导出的客户端,否则运行结果可能会出现:“The Construct is In CSimple04”3)由于接口“IObjectConstruct”是COM+新增的内容,而VC6没有上面所提到的头文件与库文件,你可能需要安装一个Platform SDK,如果你没有SDK,请用下列文件替换,替换时删除原来文件中的#include <comsvcs.h>和#pragma comment( lib, "svcguid.lib" )两句

    // my_construct.h 用于替换SDK的文件,by blackcolor. 2001.08#ifndef __MY_CONSTRUCT_H_#define __MY_CONSTRUCT_H_

    const IID IID_IObjectConstructString =       {0x41C4F8B2,0x7439,0x11D2,{0x98,0xCB, 0x00,0xC0,0x4F,0x8E,0xE1,0xC4}};

    MIDL_INTERFACE("41C4F8B3-7439-11D2-98CB-00C04F8EE1C4")IObjectConstruct : public IUnknown{    public:        virtual HRESULT STDMETHODCALLTYPE Construct(             /* [in] */ IDispatch __RPC_FAR *pCtorObj) = 0;   };

    MIDL_INTERFACE("41C4F8B2-7439-11D2-98CB-00C04F8EE1C4")IObjectConstructString : public IDispatch{    public:        virtual /* [helpstring][id][propget] */ HRESULT STDMETHODCALLTYPE get_ConstructString(             /* [retval][out] */ BSTR __RPC_FAR *pVal) = 0;   };

    #endif //__MY_CONSTRUCT_H_

     


    最新回复(0)