调用DLL实现DCOM连接后,程序结束正常结束但不能从内存退出,该怎么处理
调用DLL实现DCOM连接后,程序结束正常结束但不能从内存退出
1)编写DLL通过DCOM实现数据存储,查询。主程序采用静态调用方式,函数工作正常,但主程序正常关闭后,主程序不能从内存里退出。
2)DLL里面有多个输出函数需要用到数据模块Tdm_StoredData,频繁调用这个dll是否需要考虑数据模块冲突的问题?
3)DLL调用数据模块中的CDS组件获得查询结果,如何将结果传递到调用主程序,现在使用的是动态数组,有没有更好解决方法?
4)如何实现大块数据在DCOM间传递,那样就可以把这些代码放到DCOM中实现?
------解决方案--------------------
看看下面这代码对楼主有没啥助益(几年前为VB当中做远程调用写的,可能代码看起来会有些许别扭,将就着看吧)
1)编写DLL通过DCOM实现数据存储,查询。主程序采用静态调用方式,函数工作正常,但主程序正常关闭后,主程序不能从内存里退出。
2)DLL里面有多个输出函数需要用到数据模块Tdm_StoredData,频繁调用这个dll是否需要考虑数据模块冲突的问题?
3)DLL调用数据模块中的CDS组件获得查询结果,如何将结果传递到调用主程序,现在使用的是动态数组,有没有更好解决方法?
4)如何实现大块数据在DCOM间传递,那样就可以把这些代码放到DCOM中实现?
- C/C++ code
//dll入口 int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved) { switch(reason) { case DLL_PROCESS_ATTACH: HRESULT coret = CoInitialize(NULL); if(coret ! = S_OK && coret != S_FALSE) { //异常 } else { dm_StoredData =new Tdm_StoredData(NULL); } break; case DLL_PROCESS_DETACH: if(dm_StoredData !=NULL) { delete dm_StoredData; } CoUninitialize(); break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; default: break; } //变量定义 typedef struct { AnsiString SID; //.... }SAT, pSAT; typedef DynamicArray<SAT> ASAT; //函数 extern "C" __declspec(dllexport)__stdcall int Sat_Add(ASAT &asat) { AnsiString CMDSQL; int nReturnVal = -1; AnsiString satData; int x=0; CMDSQL = "USE cs select * from work "; try { try{ dm_StoredData->cds->Active = false; dm_StoredData->cds->CommandText = CMDSQL; dm_StoredData->cds->Active = true; if(dm_StoredData->cds->RecordCount) { asat.Length = dm_StoredData->cds->RecordCount; while(!dm_StoredData->cds->Eof) { asat[x].SatID = dm_StoredData->cds->FieldByName("id")->AsString; //... x++ dm_StoredData->cds->Next(); } } dm_StoredData->cds->Active = false; } catch(Exception &E) { //ShowMessage(E.Message); } } __finally { dm_StoredData->cds->Active = false; } return nReturnVal; }
------解决方案--------------------
看看下面这代码对楼主有没啥助益(几年前为VB当中做远程调用写的,可能代码看起来会有些许别扭,将就着看吧)
- C/C++ code
// EASYDCOMOBJECTIMPL.H : Declaration of the TEasyDCOMObjectImpl #ifndef EasyDCOMObjectImplH #define EasyDCOMObjectImplH #define ATL_APARTMENT_THREADED #include "EasyDCOMObject_TLB.h" #include "SConnect.hpp" #include "MConnect.hpp" ///////////////////////////////////////////////////////////////////////////// // TEasyDCOMObjectImpl Implements IEasyDCOMObject, default interface of EasyDCOMObject // ThreadingModel : Apartment // Dual Interface : TRUE // Event Support : FALSE // Default ProgID : Project1.EasyDCOMObject // Description : ///////////////////////////////////////////////////////////////////////////// class ATL_NO_VTABLE TEasyDCOMObjectImpl : public CComObjectRootEx<CComSingleThreadModel>, public CComCoClass<TEasyDCOMObjectImpl, &CLSID_EasyDCOMObject>, public IDispatchImpl<IEasyDCOMObject, &IID_IEasyDCOMObject, &LIBID_EasyDCOMObject> { private: int Port; TInvokeType InvokeType; char MethodName; char ComputerName[MAX_COMPUTERNAME_LENGTH + 1]; public: TSocketConnection *SocketServer; TWebConnection *WebServer; TDCOMConnection *DCOMServer; TEasyDCOMObjectImpl() { SocketServer=new TSocketConnection(NULL); WebServer=new TWebConnection(NULL); DCOMServer=new TDCOMConnection(NULL); ZeroMemory(ComputerName,MAX_COMPUTERNAME_LENGTH + 1); DWORD dNameLen=MAX_COMPUTERNAME_LENGTH + 1; GetComputerName(ComputerName,&dNameLen); InvokeType=eoiSocketInvoke; Port=SocketServer->Port; } ~TEasyDCOMObjectImpl() { SocketServer->Free(); WebServer->Free(); DCOMServer->Free(); } // Data used when registering Object // DECLARE_THREADING_MODEL(otApartment); DECLARE_PROGID("EasyDCOMObject.EasyDCOMObject"); DECLARE_DESCRIPTION(""); // Function invoked to (un)register object // static HRESULT WINAPI UpdateRegistry(BOOL bRegister) { TTypedComServerRegistrarT<TEasyDCOMObjectImpl> regObj(GetObjectCLSID(), GetProgID(), GetDescription()); return regObj.UpdateRegistry(bRegister); } BEGIN_COM_MAP(TEasyDCOMObjectImpl) COM_INTERFACE_ENTRY(IEasyDCOMObject) COM_INTERFACE_ENTRY2(IDispatch, IEasyDCOMObject) END_COM_MAP() // IEasyDCOMObject public: STDMETHOD(GetName(BSTR* S)); STDMETHOD(set_Port(const int Value)); STDMETHOD(get_Port(int* Value)); STDMETHOD(set_InvokeType(const TInvokeType Value)); STDMETHOD(get_InvokeType(TInvokeType* Value)); STDMETHOD(GetObj(const BSTR PROGID,const BSTR SERVER,IDispatch ** iObj)); }; #endif //EasyDCOMObjectImplH