MFC的Microsoft RDP Client Control避坑指南

参考网址
https://blog.csdn.net/wochendaixin/article/details/78412196
https://www.itdaan.com/blog/2018/07/26/43ee6775cc523e383b8301d4fcf8aa8f.html
https://www.itdaan.com/blog/2017/12/14/e79325703755e691efd113f71c5c36e2.html
https://blog.csdn.net/wochendaixin/article/details/78540828
https://blog.csdn.net/chaozi2008/article/details/8591109
https://blog.csdn.net/fuhanghang/article/details/119945096

创建基于对话框MFC项目
工具 -> 选择工具箱项 -> COM组件 -> Microsoft Terminal Services Client Control -> 勾选确定
工具箱 -> 常规 -> Microsoft RDP Client Control - version9 -> 拖放到对话框上
在IDC_MSTSCAX1上右键 -> 添加变量
项目管理器右键 -> 类向导 -> 添加类 -> 类型库中的MFC类 -> 文件 -> 位置里输入mstscax.dll -> 接口选择CMsRdpClientAdvancedSettings8
打开CMsRdpClientAdvancedSettings8.h文件 -> 注释#import "mstscax.dll" no_namespace
打开CMsRdpClientAdvancedSettings8.h文件 -> 加入#import "mstscax.dll" no_namespace rename("UINT_PTR", "MSTSCAX_UINT_PTR")
在OnInitDialog函数中加入
	CMsRdpClientAdvancedSettings8 advancedSettings = m_mstscax1.get_AdvancedSettings8();
	m_mstscax1.put_Server(L"192.168.10.169"); 
	m_mstscax1.put_UserName(L"Administrator"); 
	advancedSettings.put_ClearTextPassword(L"123");
	advancedSettings.put_RDPPort(8848);
	advancedSettings.put_SmartSizing(TRUE);
	m_mstscax1.put_DesktopHeight(768); 
	m_mstscax1.put_DesktopWidth(1024); 
	m_mstscax1.put_ColorDepth(32);
	m_mstscax1.put_ConnectingText(_T("请稍后..."));
	m_mstscax1.Connect();

消息映射 
BEGIN_EVENTSINK_MAP(xxxxxxDlg, CWnd)
	ON_EVENT(xxxxxxDlg, IDC_MSTSCAX1, 1, xxxxxxDlg::OnConnecting, VTS_NONE)
	ON_EVENT(xxxxxxDlg, IDC_MSTSCAX1, 2, xxxxxxDlg::OnConnected, VTS_NONE)
	ON_EVENT(xxxxxxDlg, IDC_MSTSCAX1, 3, xxxxxxDlg::OnLoginComplete, VTS_NONE)
	ON_EVENT(xxxxxxDlg, IDC_MSTSCAX1, 4, xxxxxxDlg::OnDisconnected, VTS_I4)
	ON_EVENT(xxxxxxDlg, IDC_MSTSCAX1, 5, xxxxxxDlg::OnEnterFullScreenMode, VTS_NONE)
	ON_EVENT(xxxxxxDlg, IDC_MSTSCAX1, 6, xxxxxxDlg::OnLeaveFullScreenMode, VTS_NONE)
	ON_EVENT(xxxxxxDlg, IDC_MSTSCAX1, 7, xxxxxxDlg::OnChannelReceivedData, VTS_BSTR VTS_BSTR)
	ON_EVENT(xxxxxxDlg, IDC_MSTSCAX1, 8, xxxxxxDlg::OnRequestGoFullScreen, VTS_NONE)
	ON_EVENT(xxxxxxDlg, IDC_MSTSCAX1, 9, xxxxxxDlg::OnRequestLeaveFullScreen, VTS_NONE)
	ON_EVENT(xxxxxxDlg, IDC_MSTSCAX1, 10, xxxxxxDlg::OnFatalError, VTS_I4)
	ON_EVENT(xxxxxxDlg, IDC_MSTSCAX1, 11, xxxxxxDlg::OnWarning, VTS_I4)
	ON_EVENT(xxxxxxDlg, IDC_MSTSCAX1, 12, xxxxxxDlg::OnRemoteDesktopSizeChange, VTS_I4 VTS_I4)
	ON_EVENT(xxxxxxDlg, IDC_MSTSCAX1, 13, xxxxxxDlg::OnIdleTimeoutNotification, VTS_NONE)
	ON_EVENT(xxxxxxDlg, IDC_MSTSCAX1, 14, xxxxxxDlg::OnRequestContainerMinimize, VTS_NONE)
	ON_EVENT(xxxxxxDlg, IDC_MSTSCAX1, 20, xxxxxxDlg::OnRemoteProgramResult, VTS_BSTR VTS_I4 VTS_BOOL)
	ON_EVENT(xxxxxxDlg, IDC_MSTSCAX1, 21, xxxxxxDlg::OnRemoteProgramDisplayed, VTS_BOOL VTS_I4)
	ON_EVENT(xxxxxxDlg, IDC_MSTSCAX1, 23, xxxxxxDlg::OnLogonError, VTS_I4)
	ON_EVENT(xxxxxxDlg, IDC_MSTSCAX1, 29, xxxxxxDlg::OnNetworkStatusChanged, VTS_I4 VTS_I4 VTS_I4)
	ON_EVENT(xxxxxxDlg, IDC_MSTSCAX1, 32, xxxxxxDlg::OnAutoReconnecting2, VTS_I4 VTS_BOOL VTS_I4 VTS_I4)
END_EVENTSINK_MAP()

接口定义
	// https://learn.microsoft.com/zh-cn/windows/win32/termserv/imstscaxevents-interface
	DECLARE_EVENTSINK_MAP()
	void OnConnecting();
	void OnConnected();
	void OnLoginComplete();
	void OnDisconnected(LONG reason);
	void OnEnterFullScreenMode();
	void OnLeaveFullScreenMode();
	void OnChannelReceivedData(BSTR chanName, BSTR data);
	void OnRequestGoFullScreen();
	void OnRequestLeaveFullScreen();
	void OnFatalError(LONG errorCode);
	void OnWarning(LONG warningCode);
	void OnRemoteDesktopSizeChange(LONG width, LONG height);
	void OnIdleTimeoutNotification();
	void OnRequestContainerMinimize();
	void OnRemoteProgramResult(BSTR bstrRemoteProgram, LONG lError, VARIANT_BOOL vbIsExecutable);
	void OnRemoteProgramDisplayed(VARIANT_BOOL vbDisplayed, ULONG uDisplayInformation);
	void OnLogonError(LONG lError);
	void OnNetworkStatusChanged(ULONG qualityLevel, LONG bandwidth, LONG rtt);
	void OnAutoReconnecting2(LONG disconnectReason, VARIANT_BOOL networkAvailable, LONG attemptCount, LONG maxAttemptCount);

1.基本操作教程https://blog.csdn.net/linlin003/article/details/52922741
2.VS2019的类向导里面没有类型库中的MFC类,需要低版本些的VS才有
3.注意CLSID,填错的话创建会失败,在GetClsid()和rc资源文件里面有

在这里插入图片描述
在这里插入图片描述
4.CLSID的各个版本https://docs.microsoft.com/en-us/windows/win32/termserv/using-remote-desktop-web-connection
在这里插入图片描述

5.可以用动态创建控件的方法

	CRect rect;
	GetClientRect(rect);
	int nScreenWidth = rect.Width();
	int nScreenHeight = rect.Height();
	CMstscax1 m_RemoteDesktopControl;
m_RemoteDesktopControl.Create(NULL,WS_VISIBLE|WS_TABSTOP|WS_EX_TOPMOST,CRect(0,0,nScreenWidth,nScreenHeight),this,IDC_MSTSCAX1);

CLSID IID_IMsRdpClientNonScriptable3 = { 0xb3378d90, 0x0728, 0x45c7,{ 0x8e, 0xd7, 0xb6, 0x15, 0x9f, 0xb9, 0x22, 0x19 } };
	IMsRdpClientNonScriptable3* rdp_client_non_script = 0;
	IDispatch* dispatch = (IDispatch*)m_mstscax.GetControlUnknown();
	if (SUCCEEDED(dispatch->QueryInterface(IID_IMsRdpClientNonScriptable3, (void**)&rdp_client_non_script)))
	{
		rdp_client_non_script->put_RedirectDynamicDevices(VARIANT_TRUE); // 重定向会话中枚举的动态连接的PnP驱动器
		rdp_client_non_script->put_RedirectDynamicDrives(VARIANT_TRUE); // 重定向会话中枚举的动态连接的PnP驱动器
		rdp_client_non_script->put_UIParentWindowHandle((wireHWND)GetSafeHwnd()); // 控件父窗口的窗口句柄
		rdp_client_non_script->Release();
	}

	IMsRdpClientSecuredSettings2* rdp_client_secured_settings = (IMsRdpClientSecuredSettings2*)m_mstscax.get_SecuredSettings2();
	if (rdp_client_secured_settings)
	{
		rdp_client_secured_settings->put_AudioRedirectionMode(0); // 将声音重定向到客户端
		rdp_client_secured_settings->put_KeyboardHookMode(1); // 在远程服务器上应用键组合
		rdp_client_secured_settings->Release();
	}

	ITSRemoteProgram2* remote_program = (ITSRemoteProgram2*)m_mstscax.get_RemoteProgram2();
	if (remote_program)
	{
		remote_program->put_RemoteProgramMode(VARIANT_TRUE);
		remote_program->Release();
	}

	CMsRdpClientAdvancedSettings8 rdp_client_advanced_settings(m_mstscax.get_AdvancedSettings8());
	rdp_client_advanced_settings.put_BitmapPeristence(1); // 启用位图缓存
	rdp_client_advanced_settings.put_Compress(1); // 启用压缩
	rdp_client_advanced_settings.put_DisableRdpdr(FALSE); // 启用打印机和剪贴板重定向
	rdp_client_advanced_settings.put_AcceleratorPassthrough(1); // 将键盘加速器传递
	rdp_client_advanced_settings.put_CachePersistenceActive(1); // 使用持久位图缓存
	rdp_client_advanced_settings.put_ClearTextPassword(m_pass_word.c_str()); // 登陆密码
	rdp_client_advanced_settings.put_DisableCtrlAltDel(0); // 不显示 Winlogon 中的初始说明屏幕
	rdp_client_advanced_settings.put_DisplayConnectionBar(VARIANT_TRUE); // 使用连接栏
	rdp_client_advanced_settings.put_DoubleClickDetect(1); // 识别服务器的双击
	rdp_client_advanced_settings.put_EnableWindowsKey(1); // 在远程会话中使用 Windows 键
	rdp_client_advanced_settings.put_GrabFocusOnConnect(VARIANT_TRUE); // 客户端控件在连接时应具有焦点
	rdp_client_advanced_settings.put_PerformanceFlags(0x00000001); // 服务器上设置以提高性能
	rdp_client_advanced_settings.put_RDPPort(_wtoi(m_server_port.c_str())); // 连接端口
	rdp_client_advanced_settings.put_RedirectDrives(VARIANT_TRUE); // 允许磁盘驱动器重定向
	rdp_client_advanced_settings.put_RedirectPorts(VARIANT_TRUE); // 允许重定向本地端口
	rdp_client_advanced_settings.put_RedirectPrinters(VARIANT_TRUE); // 允许打印机重定向
	rdp_client_advanced_settings.put_RedirectSmartCards(VARIANT_TRUE); // 允许智能卡重定向
	rdp_client_advanced_settings.put_SmartSizing(VARIANT_FALSE); // 缩放显示以适合控件的工作区
	rdp_client_advanced_settings.put_EnableAutoReconnect(VARIANT_TRUE); // 允许客户端控件在网络断开时自动重新连接到会话
	rdp_client_advanced_settings.put_ConnectionBarShowMinimizeButton(VARIANT_TRUE); // 在连接栏上显示最小化按钮
	rdp_client_advanced_settings.put_ConnectionBarShowRestoreButton(VARIANT_TRUE); // 在连接栏上显示恢复按钮
	rdp_client_advanced_settings.put_RedirectClipboard(TRUE); // 剪贴板重定向
	rdp_client_advanced_settings.put_RedirectDevices(TRUE); // 设备重定向
	rdp_client_advanced_settings.put_EnableCredSspSupport(VARIANT_TRUE); // 为此连接启用了凭据安全服务提供程序
	rdp_client_advanced_settings.put_RelativeMouseMode(VARIANT_TRUE); // 鼠标使用相对模式

	m_mstscax.put_DesktopHeight(GetSystemMetrics(SM_CYSCREEN)); // 远程桌面上的高度
	m_mstscax.put_DesktopWidth(GetSystemMetrics(SM_CXSCREEN)); // 远程桌面上的宽度
	m_mstscax.put_Server(m_ip_address.c_str()); // 服务器的名称
	m_mstscax.put_UserName(m_user_name.c_str()); // 用户名登录凭据
	m_mstscax.put_ColorDepth(32); // 颜色深度
	m_mstscax.put_FullScreen(FALSE); // 非全屏模式

	m_mstscax.Connect();
	return m_mstscax.get_Connected();

无法打开管理员权限进程?
1.将用户添加到管理员组
2.程序安全页设置会话权限
3.HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System EnableLUA设置为0
4.重启电脑

专门PsExec配置?
1.HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\system /v LocalAccountTokenFilterPolicy /t REG_DWORD /d 1 /f
2.netsh advfirewall set allprofiles state off
3.net use \\computername\ipc$ /user:adminname password
4.net share admin$
5.PsExec.exe \192.168.10.216 -d -i 会话id -u 用户名 -p 密码 cmd.exe

Windos Server 2012无法开启服务器?
https://jingyan.baidu.com/article/925f8cb8bf55f1c0dde056fb.html

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值