现在问题是能连上数据库,但是删除记录和修改记录存在问题,删除记录时,返回值hr为0表示成功,但是数据库里记录没有删除,不知道问题出在哪里,麻烦大侠帮帮看看,谢谢#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x0501
#define WINVER 0x0501#include <Windows.h>
#include <ole2.h>
#include <TCHAR.h>
#define COM_NO_WINDOWS_H //如果已经包含了Windows.h或不使用其他Windows
//库函数时
#define DBINITCONSTANTS
#define INITGUID
#define OLEDBVER 0x0270
#include <oledb.h>
#include <oledberr.h>
#include <msdasc.h>#define GRS_ROUNDUP_AMOUNT 8
#define GRS_ROUNDUP_(size,amount) (((ULONG)(size)+((amount)-1))&~((amount)-1))
#define GRS_ROUNDUP(size) GRS_ROUNDUP_(size, GRS_ROUNDUP_AMOUNT) #define GRS_ALLOC(size) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size)
#define GRS_FREE(p) if( NULL != (p) ){HeapFree(GetProcessHeap(),0,p);(p) = NULL;}#define GRS_COM_RELEASE(p) if(p){(p)->Release();(p)=NULL;}
#define GRS_COM_CHECK(a) if(FAILED(a)){::DebugBreak();goto GRS_CLEARUP;}#define GRS_USE_IDBCREATECOMMAND //使用IDBCreateCommand接口创建Session对象 注释后使用习惯的IOpenRowset接口
//#define GRS_USE_IMULTIPLERESULTS //使用IMultipleResults接口得到结果集 注释后直接使用int WINAPI _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)
{
::CoInitialize(NULL); IDBPromptInitialize* pIDBPromptInitialize = NULL;
IDBInitialize* pIDBInitialize = NULL;
IDBCreateSession* pIDBCreateSession = NULL;
IOpenRowset* pIOpenRowSet = NULL;
IDBCreateCommand* pIDBCreateCommand = NULL;
ICommandText* pICommandText = NULL;
ICommandProperties* pICommandProperties = NULL;
IMultipleResults* pIMultipleResults = NULL;
IRowset* pIRowset = NULL;
IColumnsInfo* pIColumnsInfo = NULL;
IAccessor* pIAccessor = NULL;
IRowsetChange* pIRowsetChange = NULL;
IRowsetUpdate* pIRowsetUpdate = NULL; DBPROPSET ps[1];
DBPROP prop[3];
//==============================================================================================
//注意改写这个SQL语句,首先保证SQL语句是正确的
TCHAR* pSQL = _T("SELECT name,id FROM bb");
//==============================================================================================
ULONG cColumns = 0;
DBCOLUMNINFO* rgColumnInfo = NULL;
LPWSTR pStringBuffer = NULL; DBROWCOUNT cRowsAffected = 0;//注意不要被这个参数迷惑大多数情况下它是没用的
//并不能通过它知道结果集中实际包含多少行 ULONG iCol = 0;
ULONG dwOffset = 0;
DBBINDING* rgBindings = NULL;
HACCESSOR phAccessor = NULL; void* pData = NULL;
ULONG cRowsObtained = 0;
HROW* rghRows = NULL;
ULONG iRow = 0;
LONG cRows = 10;//一次读取10行
DBROWSTATUS pdwStatus = 0; //行状态 实际就是DWORD类型
void* pCurData = NULL;
void* pNewData = NULL;
HROW hNewRows = NULL; HRESULT hr; DWORD dwUpdateRows;
HROW *pUpRow;//============================================================================================================
//1、初始化部分,数据库连接
GRS_COM_CHECK(CoCreateInstance(CLSID_DataLinks, NULL, CLSCTX_INPROC_SERVER,
IID_IDBPromptInitialize, (void **)&pIDBPromptInitialize));
//下面这句将弹出前面所说的对话框
GRS_COM_CHECK(pIDBPromptInitialize->PromptDataSource(NULL, ::GetDesktopWindow(),
DBPROMPTOPTIONS_PROPERTYSHEET, 0, NULL, NULL, IID_IDBInitialize,
(IUnknown **)&pIDBInitialize));
GRS_COM_CHECK(pIDBInitialize->Initialize());//根据对话框采集的参数连接到指定的数据库
//============================================================================================================//============================================================================================================
//2、创建事务部分
GRS_COM_CHECK( pIDBInitialize->QueryInterface(IID_IDBCreateSession, (void**)&pIDBCreateSession) );
//创建一个IOpenRowset接口 或者直接创建一个IDBCreateCommand 接口
#ifdef GRS_USE_IDBCREATECOMMAND
//使用IDBCreateCommand的方式
GRS_COM_CHECK(pIDBCreateSession->CreateSession(NULL,IID_IDBCreateCommand,(IUnknown**)&pIDBCreateCommand));
#else
//使用IOpenRowset的方式
GRS_COM_CHECK(pIDBCreateSession->CreateSession(NULL,IID_IOpenRowset,(IUnknown**)&pIOpenRowSet) );
GRS_COM_CHECK(pIOpenRowSet->QueryInterface(IID_IDBCreateCommand,(void**)&pIDBCreateCommand) );
#endif
//与IDBInitialize等价的IDBCreateSession可以释放了,需要时再Query出来就行了
GRS_COM_RELEASE(pIDBCreateSession);
//============================================================================================================//============================================================================================================
//3、创建Command对象
GRS_COM_CHECK(pIDBCreateCommand->CreateCommand(NULL,IID_ICommandText,(IUnknown**)&pICommandText));
#ifndef GRS_USE_IDBCREATECOMMAND
//当使用IOpenRowset接口创建Session对象时 IDBCreateCommand接口使用完毕就可以释放了 因为我们有IOpenRowset接口
GRS_COM_RELEASE(pIDBCreateCommand);
#endif
//============================================================================================================//============================================================================================================
//4、设置属性 主要是打开可更新的属性
ZeroMemory(ps,1 * sizeof(DBPROPSET));
ZeroMemory(prop, 3 * sizeof(DBPROP)); //prop[0].dwPropertyID = DBPROP_UPDATABILITY; prop[0].dwPropertyID = DBPROP_UPDATABILITY;
prop[0].vValue.vt = VT_I4;
V_I4(&prop[0].vValue) = DBPROPVAL_UP_CHANGE //打开Update属性
|DBPROPVAL_UP_DELETE //打开Delete属性
|DBPROPVAL_UP_INSERT; //打开Insert属性
// prop[0].vValue.lVal=DBPROPVAL_UP_CHANGE //打开Update属性
// |DBPROPVAL_UP_DELETE //打开Delete属性
// |DBPROPVAL_UP_INSERT; //打开Insert属性
prop[0].dwOptions = DBPROPOPTIONS_REQUIRED;
prop[0].dwStatus = DBPROPSTATUS_OK;
prop[0].colid = DB_NULLID;//
prop[1].dwPropertyID = DBPROP_IRowsetUpdate;
prop[1].vValue.vt = VT_BOOL;
prop[1].vValue.boolVal = VARIANT_TRUE;
prop[1].dwOptions = DBPROPOPTIONS_REQUIRED;
prop[1].colid = DB_NULLID; ps[0].guidPropertySet = DBPROPSET_ROWSET; //注意属性集合的名称
ps[0].cProperties = 2;
ps[0].rgProperties = prop; GRS_COM_CHECK(pICommandText->QueryInterface(IID_ICommandProperties,(void**)& pICommandProperties));
GRS_COM_CHECK(pICommandProperties->SetProperties(1,ps));//注意必须在Execute前设定属性
GRS_COM_RELEASE(pICommandProperties); //没有用了 就释放掉
//============================================================================================================//============================================================================================================
//5、设置SQL 并执行得到Rowset对象
GRS_COM_CHECK(pICommandText->SetCommandText(DBGUID_DBSQL, /*DBGUID_DEFAULT,*/pSQL));
#ifdef GRS_USE_IMULTIPLERESULTS
GRS_COM_CHECK(pICommandText->Execute(NULL,IID_IMultipleResults,NULL,NULL,(IUnknown**)& pIMultipleResults));
//-----------------------------------------------------------------------------------------------------------------------
//例子代码循环的得到每个结果集并处理之
//循环处理每一个结果集,当然这需要你起码知道你执行的多条SQL语句的顺序
//特别要注意使用S_OK直接判断返回值,而不是使用SUCCEEDED或FAILED宏来判断,否则会变成死循环
//while( S_OK == pIMultipleResults->GetResult(NULL,DBRESULTFLAG_DEFAULT,IID_IRowset,cRowsAffected,(IUnknown**)&pIRowset) )
//{
// ......//处理每一个IRowset
// pIRowset->Release();
// pIRowset = NULL;
//}
//-----------------------------------------------------------------------------------------------------------------------
#define _WIN32_WINNT 0x0501
#define WINVER 0x0501#include <Windows.h>
#include <ole2.h>
#include <TCHAR.h>
#define COM_NO_WINDOWS_H //如果已经包含了Windows.h或不使用其他Windows
//库函数时
#define DBINITCONSTANTS
#define INITGUID
#define OLEDBVER 0x0270
#include <oledb.h>
#include <oledberr.h>
#include <msdasc.h>#define GRS_ROUNDUP_AMOUNT 8
#define GRS_ROUNDUP_(size,amount) (((ULONG)(size)+((amount)-1))&~((amount)-1))
#define GRS_ROUNDUP(size) GRS_ROUNDUP_(size, GRS_ROUNDUP_AMOUNT) #define GRS_ALLOC(size) HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size)
#define GRS_FREE(p) if( NULL != (p) ){HeapFree(GetProcessHeap(),0,p);(p) = NULL;}#define GRS_COM_RELEASE(p) if(p){(p)->Release();(p)=NULL;}
#define GRS_COM_CHECK(a) if(FAILED(a)){::DebugBreak();goto GRS_CLEARUP;}#define GRS_USE_IDBCREATECOMMAND //使用IDBCreateCommand接口创建Session对象 注释后使用习惯的IOpenRowset接口
//#define GRS_USE_IMULTIPLERESULTS //使用IMultipleResults接口得到结果集 注释后直接使用int WINAPI _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)
{
::CoInitialize(NULL); IDBPromptInitialize* pIDBPromptInitialize = NULL;
IDBInitialize* pIDBInitialize = NULL;
IDBCreateSession* pIDBCreateSession = NULL;
IOpenRowset* pIOpenRowSet = NULL;
IDBCreateCommand* pIDBCreateCommand = NULL;
ICommandText* pICommandText = NULL;
ICommandProperties* pICommandProperties = NULL;
IMultipleResults* pIMultipleResults = NULL;
IRowset* pIRowset = NULL;
IColumnsInfo* pIColumnsInfo = NULL;
IAccessor* pIAccessor = NULL;
IRowsetChange* pIRowsetChange = NULL;
IRowsetUpdate* pIRowsetUpdate = NULL; DBPROPSET ps[1];
DBPROP prop[3];
//==============================================================================================
//注意改写这个SQL语句,首先保证SQL语句是正确的
TCHAR* pSQL = _T("SELECT name,id FROM bb");
//==============================================================================================
ULONG cColumns = 0;
DBCOLUMNINFO* rgColumnInfo = NULL;
LPWSTR pStringBuffer = NULL; DBROWCOUNT cRowsAffected = 0;//注意不要被这个参数迷惑大多数情况下它是没用的
//并不能通过它知道结果集中实际包含多少行 ULONG iCol = 0;
ULONG dwOffset = 0;
DBBINDING* rgBindings = NULL;
HACCESSOR phAccessor = NULL; void* pData = NULL;
ULONG cRowsObtained = 0;
HROW* rghRows = NULL;
ULONG iRow = 0;
LONG cRows = 10;//一次读取10行
DBROWSTATUS pdwStatus = 0; //行状态 实际就是DWORD类型
void* pCurData = NULL;
void* pNewData = NULL;
HROW hNewRows = NULL; HRESULT hr; DWORD dwUpdateRows;
HROW *pUpRow;//============================================================================================================
//1、初始化部分,数据库连接
GRS_COM_CHECK(CoCreateInstance(CLSID_DataLinks, NULL, CLSCTX_INPROC_SERVER,
IID_IDBPromptInitialize, (void **)&pIDBPromptInitialize));
//下面这句将弹出前面所说的对话框
GRS_COM_CHECK(pIDBPromptInitialize->PromptDataSource(NULL, ::GetDesktopWindow(),
DBPROMPTOPTIONS_PROPERTYSHEET, 0, NULL, NULL, IID_IDBInitialize,
(IUnknown **)&pIDBInitialize));
GRS_COM_CHECK(pIDBInitialize->Initialize());//根据对话框采集的参数连接到指定的数据库
//============================================================================================================//============================================================================================================
//2、创建事务部分
GRS_COM_CHECK( pIDBInitialize->QueryInterface(IID_IDBCreateSession, (void**)&pIDBCreateSession) );
//创建一个IOpenRowset接口 或者直接创建一个IDBCreateCommand 接口
#ifdef GRS_USE_IDBCREATECOMMAND
//使用IDBCreateCommand的方式
GRS_COM_CHECK(pIDBCreateSession->CreateSession(NULL,IID_IDBCreateCommand,(IUnknown**)&pIDBCreateCommand));
#else
//使用IOpenRowset的方式
GRS_COM_CHECK(pIDBCreateSession->CreateSession(NULL,IID_IOpenRowset,(IUnknown**)&pIOpenRowSet) );
GRS_COM_CHECK(pIOpenRowSet->QueryInterface(IID_IDBCreateCommand,(void**)&pIDBCreateCommand) );
#endif
//与IDBInitialize等价的IDBCreateSession可以释放了,需要时再Query出来就行了
GRS_COM_RELEASE(pIDBCreateSession);
//============================================================================================================//============================================================================================================
//3、创建Command对象
GRS_COM_CHECK(pIDBCreateCommand->CreateCommand(NULL,IID_ICommandText,(IUnknown**)&pICommandText));
#ifndef GRS_USE_IDBCREATECOMMAND
//当使用IOpenRowset接口创建Session对象时 IDBCreateCommand接口使用完毕就可以释放了 因为我们有IOpenRowset接口
GRS_COM_RELEASE(pIDBCreateCommand);
#endif
//============================================================================================================//============================================================================================================
//4、设置属性 主要是打开可更新的属性
ZeroMemory(ps,1 * sizeof(DBPROPSET));
ZeroMemory(prop, 3 * sizeof(DBPROP)); //prop[0].dwPropertyID = DBPROP_UPDATABILITY; prop[0].dwPropertyID = DBPROP_UPDATABILITY;
prop[0].vValue.vt = VT_I4;
V_I4(&prop[0].vValue) = DBPROPVAL_UP_CHANGE //打开Update属性
|DBPROPVAL_UP_DELETE //打开Delete属性
|DBPROPVAL_UP_INSERT; //打开Insert属性
// prop[0].vValue.lVal=DBPROPVAL_UP_CHANGE //打开Update属性
// |DBPROPVAL_UP_DELETE //打开Delete属性
// |DBPROPVAL_UP_INSERT; //打开Insert属性
prop[0].dwOptions = DBPROPOPTIONS_REQUIRED;
prop[0].dwStatus = DBPROPSTATUS_OK;
prop[0].colid = DB_NULLID;//
prop[1].dwPropertyID = DBPROP_IRowsetUpdate;
prop[1].vValue.vt = VT_BOOL;
prop[1].vValue.boolVal = VARIANT_TRUE;
prop[1].dwOptions = DBPROPOPTIONS_REQUIRED;
prop[1].colid = DB_NULLID; ps[0].guidPropertySet = DBPROPSET_ROWSET; //注意属性集合的名称
ps[0].cProperties = 2;
ps[0].rgProperties = prop; GRS_COM_CHECK(pICommandText->QueryInterface(IID_ICommandProperties,(void**)& pICommandProperties));
GRS_COM_CHECK(pICommandProperties->SetProperties(1,ps));//注意必须在Execute前设定属性
GRS_COM_RELEASE(pICommandProperties); //没有用了 就释放掉
//============================================================================================================//============================================================================================================
//5、设置SQL 并执行得到Rowset对象
GRS_COM_CHECK(pICommandText->SetCommandText(DBGUID_DBSQL, /*DBGUID_DEFAULT,*/pSQL));
#ifdef GRS_USE_IMULTIPLERESULTS
GRS_COM_CHECK(pICommandText->Execute(NULL,IID_IMultipleResults,NULL,NULL,(IUnknown**)& pIMultipleResults));
//-----------------------------------------------------------------------------------------------------------------------
//例子代码循环的得到每个结果集并处理之
//循环处理每一个结果集,当然这需要你起码知道你执行的多条SQL语句的顺序
//特别要注意使用S_OK直接判断返回值,而不是使用SUCCEEDED或FAILED宏来判断,否则会变成死循环
//while( S_OK == pIMultipleResults->GetResult(NULL,DBRESULTFLAG_DEFAULT,IID_IRowset,cRowsAffected,(IUnknown**)&pIRowset) )
//{
// ......//处理每一个IRowset
// pIRowset->Release();
// pIRowset = NULL;
//}
//-----------------------------------------------------------------------------------------------------------------------
{
goto GRS_CLEARUP;
}
#else//原文中此处为:
//GRS_COM_CHECK(pICommandText->Execute(NULL,IID_IRowsetChange,NULL,NULL,(IUnknown**)&pIRowsetChange));//2009年11月23日纠正为,请同时注意所有相关修改的地方,这样就可以使用IRowsetChange接口了// GRS_COM_CHECK(pICommandText->Execute(NULL,IID_IRowset,NULL,NULL,(IUnknown**)&pIRowset));
// GRS_COM_CHECK(pIRowset->QueryInterface(IID_IRowsetChange,(void**)&pIRowsetChange));
GRS_COM_CHECK(pICommandText->Execute(NULL,IID_IRowsetChange,NULL,NULL,(IUnknown**)&pIRowsetChange));
GRS_COM_CHECK(pIRowsetChange->QueryInterface(IID_IRowset,(void**)&pIRowset));
GRS_COM_CHECK(pIRowsetChange->QueryInterface(IID_IRowsetUpdate, (void**)&pIRowsetUpdate));
#endif
//============================================================================================================//============================================================================================================
//取得IRowset接口(注意修改的地方)
//============================================================================================================//============================================================================================================
//6、得到列信息生成绑定,这里使用了一个非常简单的动态绑定的方法,实际使用中这个地方还要仔细的修改
//通常需要根据Column Info 的 wType字段使用switch语句详细设定一些特殊类型的绑定方法
//有时为了方便,可以将绑定结构中的wType字段直接设置为我们想要的类型,让数据提供者在输出数据时直接进行数据类型转换
//通常我比较喜欢设置为字符串类型,让所有的类型都直接转换成字符串类型,以方便数据的显示
GRS_COM_CHECK(pIRowsetChange->QueryInterface(IID_IColumnsInfo,(void**)&pIColumnsInfo));
GRS_COM_CHECK(pIColumnsInfo->GetColumnInfo(&cColumns,&rgColumnInfo,&pStringBuffer));
//IColumnsInfo接口可以直接释放了,使用时重新检索出来即可
GRS_COM_RELEASE(pIColumnsInfo);
//如果成功了,那么rgColumnInfo中已经包含了一个关于列信息数据结构的数组,
//数组元素的个数即cColumns 也就是最终的列数
//动态分配绑定结构
rgBindings = (DBBINDING*)GRS_ALLOC(cColumns * sizeof(DBBINDING));
for( iCol = 0; iCol < cColumns; iCol++ )
{
rgBindings[iCol].iOrdinal = rgColumnInfo[iCol].iOrdinal;
rgBindings[iCol].dwPart = DBPART_VALUE|DBPART_LENGTH|DBPART_STATUS;
rgBindings[iCol].obStatus = dwOffset;
rgBindings[iCol].obLength = dwOffset + sizeof(DBSTATUS);
rgBindings[iCol].obValue = dwOffset+sizeof(DBSTATUS)+sizeof(ULONG);
rgBindings[iCol].dwMemOwner = DBMEMOWNER_CLIENTOWNED;
rgBindings[iCol].eParamIO = DBPARAMIO_NOTPARAM;
rgBindings[iCol].bPrecision = rgColumnInfo[iCol].bPrecision;
rgBindings[iCol].bScale = rgColumnInfo[iCol].bScale;
rgBindings[iCol].wType = rgColumnInfo[iCol].wType;
rgBindings[iCol].cbMaxLen = rgColumnInfo[iCol].ulColumnSize; dwOffset = rgBindings[iCol].cbMaxLen + rgBindings[iCol].obValue;
dwOffset = GRS_ROUNDUP(dwOffset);
}
//============================================================================================================//============================================================================================================
//7、创建访问器
GRS_COM_CHECK(pIRowsetChange->QueryInterface(IID_IAccessor,(void**)&pIAccessor));
GRS_COM_CHECK(pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,cColumns,rgBindings,0,&phAccessor,NULL));
//============================================================================================================
//8、得到并访问数据
//分配cRows行数据的缓冲,然后反复读取cRows行到这里,然后逐行处理之
pData = GRS_ALLOC(dwOffset * cRows);
hr = pIRowset->GetNextRows(DB_NULL_HCHAPTER,0,cRows,&cRowsObtained, &rghRows);
//注意下面的循环 一定使用S_OK判定GetNextRow的值,否则会形成一个死循环,因为到达行集末尾不是一个错误
do
{//循环读取数据,每次循环默认读取cRows行,实际读取到cRowsObtained行
for( iRow = 0; iRow < cRowsObtained; iRow++ )
{
hr = pIRowsetChange->DeleteRows(NULL,1,&rghRows[iRow],NULL);
pCurData = (BYTE*)pData + (dwOffset * iRow);
// GRS_COM_CHECK(pIRowset->GetData(rghRows[iRow],phAccessor,pCurData));
//pCurData中已经包含了结果数据,显示或者进行处理
//对行集数据进行修改,然后用SetData提交修改
// GRS_COM_CHECK(pIRowsetChange->SetData(rghRows[iRow],phAccessor,pCurData)); //删除一些行 需要测试时还原下面的行
// hr = pIRowsetChange->DeleteRows(NULL,1,&rghRows[iRow],&pdwStatus);
//GRS_COM_CHECK(pIRowsetChange->DeleteRows(NULL,1,&rghRows[iRow],&pdwStatus[0])); //复制插入一些行的例子
// pNewData = (BYTE*)GRS_ALLOC(dwOffset);
// CopyMemory(pNewData,pCurData,dwOffset);
// GRS_COM_CHECK(pIRowsetChange->InsertRow(NULL,phAccessor,pNewData,&hNewRows));
// // //插入成功释放新行的行句柄 以及新行的数据缓冲也一同释放
// GRS_COM_CHECK(pIRowset->ReleaseRows(1,&hNewRows,NULL,NULL,NULL));
// GRS_FREE(pNewData);
}
//注意下面两次释放代表不同的含义
if( cRowsObtained )
{//释放行句柄指向的行
GRS_COM_CHECK(pIRowset->ReleaseRows(cRowsObtained,rghRows,NULL,NULL,NULL));
}
//释放行句柄数组的内存
CoTaskMemFree(rghRows);
rghRows = NULL;
}
while( !FAILED( pIRowset->GetNextRows(DB_NULL_HCHAPTER,0,cRows,&cRowsObtained, &rghRows) ));//============================================================================================================
//清理释放部分
GRS_CLEARUP:
//GRS_FREE(pCurData); //这行多余 注释或删除之 2009-11-23修改
GRS_FREE(pData);
GRS_FREE(rgBindings);
if(pIAccessor)
{
pIAccessor->ReleaseAccessor(phAccessor,NULL);
}
GRS_COM_RELEASE(pIAccessor);
CoTaskMemFree(rgColumnInfo);
CoTaskMemFree(pStringBuffer);
GRS_COM_RELEASE(pIColumnsInfo);
GRS_COM_RELEASE(pIRowsetChange);
GRS_COM_RELEASE(pIRowset);
GRS_COM_RELEASE(pIMultipleResults);
GRS_COM_RELEASE(pICommandText);
GRS_COM_RELEASE(pICommandProperties);
GRS_COM_RELEASE(pIDBCreateCommand)
GRS_COM_RELEASE(pIOpenRowSet);
GRS_COM_RELEASE(pIDBCreateSession);
GRS_COM_RELEASE(pIDBInitialize);
GRS_COM_RELEASE(pIDBPromptInitialize);
//============================================================================================================ ::CoUninitialize();
return 0;
}