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

类别:VC语言 点击:0 评论:0 推荐:

本文欢迎转载,唯请注明出处及作者 [email protected]
---------------------------------------------------

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

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

一、打开COM工程Step04
1)给接口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()
};

/////////////////////////////////////////////////////////////////////////////
// CSimple04
class 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];  // 可以根据需要修改大小--新

// ISimple04
public:
 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); // 新

// IObjectConstruct
public:
 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 ;
}

三、配置组件Step04
1)打开“组件服务”,展开刚才建立的组件“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_


 

本文地址:http://com.8s8s.com/it/it3226.htm