⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hotopcserver.cpp

📁 VC 编写的OPC客户端
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		// 指针,并将它们保存到成员变量 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 + -