📄 hotopcserver.cpp
字号:
// 指针,并将它们保存到成员变量 pointers and save them as member variables:
if (SUCCEEDED (hr))
{
TRACE (_T("OTC: Initializing server %s interfaces.\r\n"), GetServerName());
// 检查IOPCServer接口指针:
if (SUCCEEDED (m_arrMultiQI [MQI_IOPCSERVER].hr))
{
m_pIServer = (IOPCServer *)m_arrMultiQI [MQI_IOPCSERVER].pItf;
if (m_pIServer == NULL)
ASSERT (FALSE); //虽然成功但指针为空发出警告
}
else
{
if (m_arrMultiQI [MQI_IOPCSERVER].pItf != NULL)
ASSERT (FALSE);//虽然失败但指针不为空发出警告
TRACE (_T("OTC: Failed to query IOPCServer (%08X).\r\n"),
m_arrMultiQI [MQI_IOPCSERVER].hr);
}
// IOPCCommon
if (SUCCEEDED (m_arrMultiQI [MQI_IOPCCOMMON].hr))
{
m_pICommon = (IOPCCommon *)m_arrMultiQI [MQI_IOPCCOMMON].pItf;
if (m_pICommon == NULL)
{
ASSERT (FALSE);
}
}
else
{
if (m_arrMultiQI [MQI_IOPCCOMMON].pItf != NULL)
ASSERT (FALSE);
TRACE (_T("OTC: Failed to query IOPCCommon (%08X).\r\n"),
m_arrMultiQI [MQI_IOPCCOMMON].hr);
}
// IConnectionPointContainer
if (SUCCEEDED (m_arrMultiQI [MQI_IOPCCONNPT].hr))
{
m_pIConnPtContainer =
(IConnectionPointContainer *)m_arrMultiQI [MQI_IOPCCONNPT].pItf;
if (m_pIConnPtContainer == NULL)
ASSERT (FALSE);
}
else
{
if (m_arrMultiQI [MQI_IOPCCONNPT].pItf != NULL)
ASSERT (FALSE);
TRACE (_T("OTC: Failed to query IConnectionPoint (%08X).\r\n"),
m_arrMultiQI [MQI_IOPCCONNPT].hr);
}
// IOPCItemProperties
if (SUCCEEDED (m_arrMultiQI [MQI_IOPCITEMPROP].hr))
{
m_pIItemProps =
(IOPCItemProperties *)m_arrMultiQI [MQI_IOPCITEMPROP].pItf;
if (m_pIItemProps == NULL)
ASSERT (FALSE);
}
else
{
if (m_arrMultiQI [MQI_IOPCITEMPROP].pItf != NULL)
ASSERT (FALSE);
TRACE (_T("OTC: Failed to query IOPCItemProperties (%08X).\r\n"),
m_arrMultiQI [MQI_IOPCITEMPROP].hr);
}
// IOPCBrowseServerAddressSpace
if (SUCCEEDED (m_arrMultiQI [MQI_IOPCBROWSE].hr))
{
m_pIBrowse =
(IOPCBrowseServerAddressSpace *)m_arrMultiQI [MQI_IOPCBROWSE].pItf;
if (m_pIBrowse == NULL)
ASSERT (FALSE);
}
else
{
if (m_arrMultiQI [MQI_IOPCBROWSE].pItf != NULL)
ASSERT (FALSE);
TRACE (_T("OTC: Failed to query IOPCBrowseServerAddressSpace (%08X).\r\n"),
m_arrMultiQI [MQI_IOPCBROWSE].hr);
}
// IOPCServerPublicGroups
if (SUCCEEDED (m_arrMultiQI [MQI_IOPCPUBLIC].hr))
{
m_pIPublicGroups =
(IOPCServerPublicGroups *)m_arrMultiQI [MQI_IOPCPUBLIC].pItf;
if (m_pIPublicGroups == NULL)
ASSERT (FALSE);
}
else
{
if (m_arrMultiQI [MQI_IOPCPUBLIC].pItf != NULL)
ASSERT (FALSE);
TRACE (_T("OTC: Failed to query IOPCServerPublicGroups (%08X).\r\n"),
m_arrMultiQI [MQI_IOPCPUBLIC].hr);
}
//IPersistFile
if (SUCCEEDED (m_arrMultiQI [MQI_IOPCPERSIST].hr))
{
m_pIPersistFile =
(IPersistFile *)m_arrMultiQI [MQI_IOPCPERSIST].pItf;
if (m_pIPersistFile == NULL)
ASSERT (FALSE);
}
else
{
if (m_arrMultiQI [MQI_IOPCPERSIST].pItf != NULL)
ASSERT (FALSE);
TRACE (_T("OTC: Failed to query IPersistsFile (%08X).\r\n"),
m_arrMultiQI [MQI_IOPCPERSIST].hr);
}
// IConnectionPointContainer
if (m_pIConnPtContainer != NULL)
{
//如果这个服务支持shutdown接口, 就为服务器提供一个接收器
// 取得 IConnectionPoint 指针:
IConnectionPoint *pCP = NULL;
hr = m_pIConnPtContainer->FindConnectionPoint (IID_IOPCShutdown, &pCP);
// 如果得到连接点,实例化IHotShutdown
if (SUCCEEDED (hr))
{
try
{
// 实例化,并将管理器加1
m_pIShutdownSink = new IHotShutdown (this);
m_pIShutdownSink->AddRef ();
// 给连接点一个指向我们 IHotShutdown的指针
// (m_dwCookieShutdown反回后保存唯一识别这个连接的值
hr = pCP->Advise (m_pIShutdownSink, &m_dwCookieShutdown);
pCP->Release ();
}
catch (...)
{
ASSERT (FALSE);
hr = E_FAIL;
}
}
}
// 只有当m_pIServer不为空时才有效
m_bConnected = (m_pIServer != NULL);
}
}
return (m_bConnected);
}
void CHotOpcServer::Disconnect(void)
{
// 连接标记设为false断开连接
m_bConnected = false;
// Release 所有指针
SAFE_RELEASE(m_pIServer);
SAFE_RELEASE(m_pICommon);
if (m_pIConnPtContainer)
{
if (m_dwCookieShutdown != 0)
{
HRESULT hr = E_FAIL;
IConnectionPoint *pCP = NULL;
hr = m_pIConnPtContainer->FindConnectionPoint (IID_IOPCShutdown, &pCP);
if (SUCCEEDED (hr))
{
hr = pCP->Unadvise (m_dwCookieShutdown);
pCP->Release ();
}
if (FAILED (hr))
{
TRACE (_T("OTC: CHotServer::Disconnect () - failed to unadvise shutdown notifications\r\n"));
}
m_dwCookieShutdown = 0;
}
SAFE_RELEASE(m_pIShutdownSink);
SAFE_RELEASE(m_pIConnPtContainer)
}
SAFE_RELEASE (m_pIItemProps)
SAFE_RELEASE (m_pIBrowse)
SAFE_RELEASE (m_pIPublicGroups)
SAFE_RELEASE (m_pIPersistFile)
SAFE_DELETE (m_pServerList);
}
HRESULT CHotOpcServer::GetCLSID (CLSID &clsid)
{
#ifdef UNICODE
// 如果使用Unicode编码,保存在m_strServerName中的服务器名将是宽字符
// 格式,可以直接传递到CLSIDFromProgID.
return (CLSIDFromProgID (m_strServerName, &clsid));
#else
//如果不是Unicode就要转成宽字符
// 为要转换的串申请空间
WCHAR wszProgID [MAX_PATH];
// 转换
if (!MultiByteToWideChar (CP_ACP, 0, m_strServerName, -1, wszProgID, sizeof (wszProgID) / sizeof (WCHAR)))
{
ASSERT (FALSE);
}
// 使用转换玩的串调用 CLSIDFromProgID
//CLSIDFromProgID函数功能为通过给定的名称,在注册表中查找CLSID
return (CLSIDFromProgID (wszProgID, &clsid));
#endif
}
void CHotOpcServer::ShutdownRequest (LPCTSTR lpszReason)
{
// Notify the document that an object has been shutdown (i.e., invalidated):
// First get a pointer to the application's main window:
/*CMainWnd *pWnd = (CMainWnd *) AfxGetMainWnd ();
// Post the user defined "UM_SERVER_SHUTDOWN" message to the main window.
// It will pass the message along to the docoument object. It will expect
// a pointer to this server object passed a the lParam.
if (pWnd)
pWnd->PostMessage (UM_SERVER_SHUTDOWN, 0, (LPARAM) this);*/
}
bool CHotOpcServer::IsAlive ()
{
// Assume server connection is dead:
bool bAlive = false;
// If we don't think we are connected, i.e. m_bConnected or m_pIServer is
// NULL, then there is no need to test connection.
if (m_bConnected && m_pIServer)
{
// We think we are connected. Let's test that...
// Wrap our test in exception handler just in case we get a bad pointer:
try
{
OPCSERVERSTATUS *pStatus;
// Use the Get status member function of the IOPCServer interface
// to test connection. If this succeeds, then we know connection
// is alive.
if (SUCCEEDED (m_pIServer->GetStatus (&pStatus)))
{
// COM requires us to free memory allocated for [out] and [in/out]
// arguments (i.e. vender info string and pStatus)
if (pStatus->szVendorInfo)
CoTaskMemFree (pStatus->szVendorInfo);
CoTaskMemFree (pStatus);
// Don't forget to set the return status to "true":
bAlive = true;
}
}
catch (...)
{
ASSERT (FALSE);
bAlive = false;
}
}
return (bAlive);
}
// **************************************************************************
// Start ()
//
// Description:
// Connect to OPC Server, then add and start all its OPC Groups.
//
// Parameters:
// none
//
// Returns:
// void
// **************************************************************************
void CHotOpcServer::Start ()
{
// Attempt to connect to the OPC Server:
Connect ();
// Regardless of connection success, add the groups. (They will be added
// invalid (i.e, for edits) if the server is not connected.)
// Start with head of linked list:
CHotOpcGroup *pGroup = m_pGroupHead;
// Keep looping we hit the end of the link list (where pGroup will be NULL):
while (pGroup)
{
// Add the group to OPC Server. (Second argument is "true" which will
// prevent the group from being added to our group list again.):
AddGroup (pGroup, true);
// Start the group:
pGroup->Start ();
// Look at next group in list next time around:
pGroup = pGroup->GetNext ();
}
}
// **************************************************************************
// Stop ()
//
// Description:
// Remove all OPC Groups from OPC Server and disconnect. Our CHotOpcGroup
// objects will not be deleted at this point. We will delete them when
// they are actually removed from project.
//
// Parameters:
// none
//
// Returns:
// void
// **************************************************************************
void CHotOpcServer::Stop ()
{
// Remove all OPC Groups. Passing "false" will prevent our CHotOpcGroups
// from being deleted.
RemoveAllGroups (false);
// Disconnect from the OPC Server we are connected to:
Disconnect ();
}
void CHotOpcServer::Serialize(CArchive& ar)
{
// Save server properties:
if (ar.IsStoring ())
{
//////////////////////////////
// Save archive properties //
//////////////////////////////
// Output current archive version. If we add server properties that
// must be made persistent, then we will have to update the archive
// version so we know how to read the additional data.
ar << CURRENT_VERSION;
//////////////////////////////
// Save server properties //
//////////////////////////////
// Output info about associated OPC Server:
ar << m_strServerName << m_strRemoteMachine;
// Output flags in bit field:
ar.Write (&m_bfFlags, sizeof (m_bfFlags));
// Output number of groups so we will know how many block of group
// data follows when we read this archive later:
ar << m_cdwGroups;
//////////////////////////////////
// Serialize all of our groups //
//////////////////////////////////
//Start with head of linked list:
CHotOpcGroup *pGroup = m_pGroupHead;
// Keep looping we hit the end of the link list (where pGroup will be NULL):
while (pGroup)
{
// Call group's serialize function so that it can add its properties
// to the archive:
pGroup->Serialize (ar);
// Process next group next time around:
pGroup = pGroup->GetNext ();
}
}
// Load server properties:
else
{
DWORD dwSchema;
DWORD dwIndex;
//////////////////////////////
// Load archive properties //
//////////////////////////////
ar >> dwSchema;
// dwSchema is really the archive version.
switch (dwSchema)
{
case VERSION_1:
//////////////////////////////
// Load server properties //
//////////////////////////////
// Input info about associated OPC Server:
ar >> m_strServerName >> m_strRemoteMachine;
// Input flags in bit field:
ar.Read (&m_bfFlags, sizeof (m_bfFlags));
// Input number of groups so we will know how many block of group
// data follows:
ar >> m_cdwGroups;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -