一:描述
本文描述了使用C#來製作一個ActiveX控件,暴露相應的屬性、方法、事件等。
此例中主要是對RdpClient控件的二次封裝,可以通過在IE中打開TestRDP.html進行測試:
實現效果圖如下:
二:具體實現
基本的實現可以參考文章:
http://blog.csdn.net/veryhappy/article/details/1604406
其他具體的就不多描述了,看代碼吧。
完整代碼請於如下鏈接下載:
http://download.csdn.net/detail/tragicguy/5447715
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using MSTSCLib;
namespace PemRDPControl
{
[Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IObjectSafety
{
// methods
void GetInterfacceSafyOptions(
System.Int32 riid,
out System.Int32 pdwSupportedOptions,
out System.Int32 pdwEnabledOptions);
void SetInterfaceSafetyOptions(
System.Int32 riid,
System.Int32 dwOptionsSetMask,
System.Int32 dwEnabledOptions);
}
//the function for ie to call
[ComVisible(true)]
[Guid("89970EFC-0014-4A1C-BA19-A18332E7A0BB")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IPemRDPControl
{
[DispId(1)]
void SetControlSize(int width, int height);
[DispId(2)]
void Connect();
string Server
{
get;
set;
}
string UserName
{
get;
set;
}
string PassWord
{
get;
set;
}
string Domain
{
get;
set;
}
int RDPPort
{
get;
set;
}
bool ConnectToServerConsole
{
get;
set;
}
bool ConnectToAdministerServer
{
get;
set;
}
int DesktopWidth
{
get;
set;
}
int DesktopHeight
{
get;
set;
}
int Width
{
get;
set;
}
int Height
{
get;
set;
}
bool FullScreen
{
get;
set;
}
ExtendedDisconnectReasonCode ExtendedDisconnectReason
{
get;
}
}
//the events
[ComVisible(true)]
[Guid("60FB4E65-C928-4D2F-B52E-2993165D314D")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IPemRDPControlEvents
{
[DispId(21)]
void OnConnected();
[DispId(22)]
void OnConnecting();
[DispId(23)]
void OnDisconnected(int reasoncode);
}
[ClassInterface(ClassInterfaceType.None)]
[ComDefaultInterface(typeof(IPemRDPControl))]
[ComSourceInterfaces(typeof(IPemRDPControlEvents))]
[ComVisible(true)]
[Guid("845FC80C-753A-4095-96D4-9BA2F6DE8E23")]
public partial class UserControl1 : UserControl, IObjectSafety, IPemRDPControl
{
public delegate void OnConnectedHandler();
public delegate void OnConnectingHandler();
public delegate void OnDisconnectedHandler(int reasoncode);
public event OnConnectedHandler OnConnected;
public event OnDisconnectedHandler OnDisconnected;
public event OnConnectingHandler OnConnecting;
#region Property
public string Server
{
get;
set;
}
public string UserName
{
get;
set;
}
public string PassWord
{
get;
set;
}
public string Domain
{
get;
set;
}
public int RDPPort
{
get;
set;
}
public bool ConnectToServerConsole
{
get;
set;
}
public bool ConnectToAdministerServer
{
get;
set;
}
public int DesktopWidth
{
get;
set;
}
public int DesktopHeight
{
get;
set;
}
public int Width
{
get;
set;
}
public int Height
{
get;
set;
}
public bool FullScreen
{
get;
set;
}
#endregion
public UserControl1()
{
InitializeComponent();
Server = "";
UserName = "";
PassWord = "";
ConnectToServerConsole = true;
ConnectToAdministerServer = true;
RDPPort = 3389;
Domain = "";
Width = Height = 0;
DesktopWidth = DesktopHeight = 0;
FullScreen = false;
}
public ExtendedDisconnectReasonCode ExtendedDisconnectReason
{
get { return (ExtendedDisconnectReasonCode)0; }
}
public void Connect()
{
((Control)this).Width = Width;
((Control)this).Height = Height;
axMstscObj.Width = Width;
axMstscObj.Height = Height;
axMstscObj.DesktopWidth = DesktopWidth;
axMstscObj.DesktopHeight = DesktopHeight;
// axMstscObj.ful.FullScreen = FullScreen;
axMstscObj.Domain = Domain;
axMstscObj.Server = Server;
axMstscObj.UserName = UserName;
IMsRdpClientAdvancedSettings7 iClientSetting = (IMsRdpClientAdvancedSettings7)axMstscObj.AdvancedSettings;
iClientSetting.RedirectDrives = false;
iClientSetting.RedirectPrinters = true;
iClientSetting.RedirectPorts = false;
iClientSetting.RedirectSmartCards = true;
iClientSetting.RDPPort = RDPPort;
iClientSetting.ClearTextPassword = PassWord;
iClientSetting.ConnectToServerConsole = ConnectToServerConsole;
iClientSetting.ConnectToAdministerServer = ConnectToAdministerServer;
axMstscObj.Connect();
}
private void axMstscObj_OnConnected(object sender, EventArgs e)
{
//fire event to ie
OnConnected();
}
private void axMstscObj_OnDisconnected(object sender, AxMSTSCLib.IMsTscAxEvents_OnDisconnectedEvent e)
{
//fire event to ie
OnDisconnected(e.discReason);
}
private void axMstscObj_OnConnecting(object sender, EventArgs e)
{
//fire event to ie
OnConnecting();
}
private void axMstscObj_OnLogonError(object sender, AxMSTSCLib.IMsTscAxEvents_OnLogonErrorEvent e)
{
}
#region IPemRDPControl 成員
public void SetControlSize(int width, int height)
{
axMstscObj.Width = width;
axMstscObj.Height = height;
}
#endregion
#region IObjectSafety 成員
public void GetInterfacceSafyOptions(Int32 riid, out Int32 pdwSupportedOptions, out Int32 pdwEnabledOptions)
{
pdwSupportedOptions = 1;
pdwEnabledOptions = 2;
}
public void SetInterfaceSafetyOptions(Int32 riid, Int32 dwOptionsSetMask, Int32 dwEnabledOptions)
{
}
#endregion
private void axMstscObj_OnAuthenticationWarningDismissed(object sender, EventArgs e)
{
}
private void axMstscObj_OnAuthenticationWarningDisplayed(object sender, EventArgs e)
{
}
}
}
網頁調用代碼如下【運行前請先註冊控件】:
<html>
<head>
<title>Demo test</title>
<script language="javascript">
function TestConnect() {
try {
var obj = document.getElementById("MyActive");
obj.Server = "testserver";
obj.RDPPort = 3389;
obj.UserName = "root";
obj.PassWord = "testpwd";
obj.ConnectToServerConsole = true;
obj.ConnectToAdministerServer = true;
var screenHeight = 1920;
var screenWidth = 1080;
obj.Width = screenHeight;
obj.Height = screenWidth;
obj.DesktopWidth = screenHeight;
obj.DesktopHeight = screenWidth;
obj.Connect();
}
catch (e) {
alert(e.Message);
}
}
</script>
</head>
<body style=" margin-left:0; margin-right: 0; margin-top:0;margin-bottom:0" >
<script for="MyActive" event="OnConnected" language="javascript">
//alert("OnConnected");
</script>
<script for="MyActive" event="OnConnecting" language="javascript">
//alert("OnConnecting");
</script>
<script for="MyActive" event="OnDisConnected(reasoncode)" language="javascript">
alert("OnDisConnected:" + reasoncode);
//alert(document.getElementById("MyActive").ExtendedDisconnectReason);
</script>
<!--
<a href='javascript::' οnclick='TestConnect();'>connect</a> <br />
<a href='javascript::' οnclick='document.getElementById("MyActive").SetControlSize(300, 200);'>Set size</a><br />
<a href='javascript::' οnclick='alert(document.getElementById("MyActive").ExtendedDisconnectReason);'>show externalerrorcode</a><br />
-->
<object id="MyActive" name="MyActive" classid="clsid:845FC80C-753A-4095-96D4-9BA2F6DE8E23" VIEWASTEXT ></object>
<script language="javascript">
function OpenActiveX()
{
try {
var obj = document.getElementById("MyActive");
if (obj != null) {
// obj.mWidth = 1030;
// obj.mHeight = 780;
TestConnect();
}
else
alert("Load failed.");
}
catch(Err)
{
alert(Err.description);
}
}
OpenActiveX();
</script>
</body>
</html>
三:後續建議
請關注上圖中的 “RDPClient安全警告框.jpg”,在我封裝的過程中,使用WINFORM封裝控件,在部分機器上正常,而在WIN8等機器上則會出現:
同樣,我封裝的控件,在IE中也是加載不上來的,可以通過在JS中監控一個事件來驗證:
OnAuthenticationWarningDisplayed, 此事件在警告框彈出前會觸發。
後來對比了兩種代碼,發現正常的使用的是類AxMSTSCLib.AxMsTscAxNotSafeForScripting,而我不正常的使用的是AxMSTSCLib.AxMsRdpClient5,這導致了不同的行爲。
【這一塊沒有深究,希望哪位熟悉的給解釋一下兩者的不同】
通過“RDPClient安全警告框.jpg”中的提示,搜索到國外較多的資料,裏面有不少方法來設置解決,我這邊試過一些,暫未發現有效的。
另外有一鏈接中提到使用不同的方式來加載控件,即可避開此錯誤。
其他參考鏈接:
以下是我查看過的幾個鏈接:
http://blogs.msdn.com/b/rds/archive/2012/10/23/rdp-8-0-update-for-windows-7-sp1-released-to-web.aspx?PageIndex=2
http://social.technet.microsoft.com/Forums/en-US/w8itprosecurity/thread/1fd2f8d2-ef44-45a8-8561-7c805dfe9bb6
此文件中提到:
Problem solved for me - I used a different id for the control(MsTscAx.MsTscAx instead of MSRDP.MSRDP)
這個與我在處理控件封裝中解決提示問題的方法一致,如果能應用到加載RDPClient控件的JS腳本中,相信問題也就解決了