作者:faaronzheng 转载请注明出处!
最近使用到c#调用远程控制软件实现远程控制,发现网上并没有现成可用的解决方案。
这里给出我的解决办法~
序:
先简单介绍一下常见的几种远程控制软件的优缺点:
AnyDesk(AD) 优点:体积较小,使用方便 。缺点:不稳定。
TeamView(TM) 优点:体积较大,但是功能更强大也更稳定。 缺点:软件本身收费,虽然可以免费使用但是有很多弹窗,并且由于服务器在国外的原因听说某些地方省份好像不能很好使用。
ultravnc(VNC)优点:三款远程控制软件中连接速度最快的,使用也很方便,体积很小。 缺点:自身不可以内网穿透。
解决方案
假设A想远程控制B的电脑,那么简单说来需要两个步骤:一:A需要获取B的远程控制软件ID和密码(密码既可以是远程控制软件随机生成的(仅TM),也可以获取B提前手动设置的一个固定密码(全部适用))。二:A使用ID和密码通过相应的远程控制软件连接B的电脑。
ID和密码的获取:对于ID,TM和AD可以采用Windows API来获取软件上的ID,VNC需要使用IP+端口的方式连接。除此之外,TM也可以通过注册表来获取ID。
对于TM的随机密码,也采用Windows API来获取。但是对于手动设置的固定密码则要去分析一下各个软件的配置文件之类的了(总是以某种方式保存在了某个地方)。
**方案一**
使用TeamView自带的API来实现远程控制。(仅限TM)
优点:简单。
缺点:需要借助浏览器。
本示例仅给出了获取ID和远程控制的代码,使用这种的方法仍需要输入对方的密码才能连接。随机密码的获取可以使用Windows API。
B获取本地TeamViewer的ID传给A或服务器
-------------------------------------首先引入命名空间
using System.Net;
using System.Net.Sockets;
-----------------------下面是客户端获取TeamViewerID并发送给服务器的函数
public void send()
{
TcpClient client;
try
{
client = new TcpClient();
client.Connect("localhost", 8500); // 与服务器连接
}
catch (Exception ex)
{
MessageBox.Show("连接服务器失败");
return;
}
RegistryKey key = Registry.LocalMachine;
RegistryKey keyID = key.OpenSubKey("SOFTWARE\\Wow6432Node\\TeamViewer", true);
String ID = keyID.GetValue("ClientID").ToString();
NetworkStream streamToServer = client.GetStream();
byte[] buffer = Encoding.Unicode.GetBytes(ID); // 获得缓存
streamToServer.Write(buffer, 0, buffer.Length); // 发往服务器
}
下面这一段代码是寻找注册表中TeamViewer的ID。有了ID就可以远程控制了。
RegistryKey key = Registry.LocalMachine;
RegistryKey keyID = key.OpenSubKey("SOFTWARE\\Wow6432Node\\TeamViewer", true);
string ID = keyID.GetValue("ClientID").ToString();
A获取B发送的TeamViewer ID从而实现远程控制。
--------------------------------------同样引入命名空间
using System.Net;
using System.Net.Sockets;
using Microsoft.Win32;
----------------------------------下面是服务器接收客户端内容并远程控制的代码
public void receive()
{
const int BufferSize = 8192; // 缓存大小,8192字节
IPAddress ip = new IPAddress(new byte[] { 127, 0, 0, 1 });
TcpListener listener = new TcpListener(ip, 8500);
listener.Start(); // 开始侦听
while(true)
{
TcpClient remoteClient = listener.AcceptTcpClient(); // 获取一个连接,同步方法,在此处中断
NetworkStream streamToClient = remoteClient.GetStream(); //获取Stream
byte[] buffer = new byte[BufferSize];
int bytesRead = streamToClient.Read(buffer, 0, BufferSize); // 获得请求的字符串
String ID = Encoding.Unicode.GetString(buffer, 0, bytesRead);
String teamViewer = "start.teamviewer.com/" + ID ;
System.Diagnostics.Process.Start("iexplore.exe", teamViewer); //启动IE浏览器远程控制
}
}
下面这一段就是远程控制的代码了~~
String teamViewer = "start.teamviewer.com/device/" + ID + "/au-thorization/password/mode/control";
System.Diagnostics.Process.Start("iexplore.exe", teamViewer); //启动IE浏览器远程制
是不是很简单~~~想具体了解的可以参考TeamViewer文档
**方案二**
使用Windows API实现远程控制
优点:不需借助浏览器,更加方便。
缺点:较为复杂。
首先B要自动获取自己的ID和密码。然后上传到服务器或者传给A。
B首先通过
IntPtr maindHwnd = FindWindow(null, "TeamViewer"); //获得句柄
获取TeamView或AnyDesk的句柄
接下来用一个循环遍历子窗口
IntPtr winPtr = GetWindow(maindHwnd, GetWindowCmd.GW_CHILD);
通过
GetClassName(winPtr, stringBuilder1, stringBuilder1.Capacity);
判断每一个子窗口的类型。如果是自己需要的就读取它的值。(通过Spy来查看TeamView和AnyDesk各个控件的句柄,以此判断自己需要子窗口的类型)
GetWindowText(winPtr, stringBuilder, stringBuilder.Capacity);
这样B就可以自动得到TeamView和AnyDesk的ID和密码了。A得到ID和密码后同样使用Windows API(SendMessage)可以自动输入ID和密码实现远程控制。
因为有人私信,下面给出部分代码参考.
首先引入相应命名空间
[DllImport("User32.dll", EntryPoint = "FindWindow")]
public extern static IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("User32.dll", EntryPoint = "FindWindowEx")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpClassName, string lpWindowName);
[DllImport("User32.dll", EntryPoint = "SendMessage")]
private static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, StringBuilder lParam);
[DllImport("user32.dll", EntryPoint = "GetWindowText")]
public static extern int GetWindowText(IntPtr hwnd, StringBuilder lpString, int cch);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr GetWindow(IntPtr hWnd, GetWindowCmd uCmd);
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32.dll", EntryPoint = "ShowWindow")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); //恢复窗口 1是 SW_SHOWNORMAL
获取TeamViewer的ID和随机密码:
public int getTeamViewInfo()
{
int index = 0;
int number = 0;
const int BM_CLICK = 0xF5;
const int WM_SETTEXT = 0xC;
const int WM_GETTEXT = 0xD;
while (true)
{
Thread.Sleep(1000);
number++;
IntPtr maindHwnd = FindWindow(null, "TeamViewer"); //获得句柄
if (maindHwnd != IntPtr.Zero)
{
IntPtr winPtr = GetWindow(maindHwnd, GetWindowCmd.GW_CHILD);
// 3、循环取得桌面下的所有子窗口
while (winPtr != IntPtr.Zero)
{
// 4、继续获取下一个子窗口
IntPtr winPtr1 = GetWindow(winPtr, GetWindowCmd.GW_CHILD);
while (winPtr1 != IntPtr.Zero)
{
StringBuilder stringBuilder1 = new StringBuilder(512);
StringBuilder stringBuilder2 = new StringBuilder(512);
StringBuilder stringBuilder3 = new StringBuilder(512);
GetWindowText(winPtr1, stringBuilder1, stringBuilder1.Capacity); //获取控件文本
GetClassName(winPtr1, stringBuilder2, stringBuilder2.Capacity); //获取控件类型
SendMessage(winPtr1, WM_GETTEXT, (IntPtr)stringBuilder3.Capacity, stringBuilder3); //向控件发送消息
str = stringBuilder1.ToString();
if (str.Equals("连接到伙伴"))
{
//
// SendMessage(winPtr1, BM_CLICK, (IntPtr)stringBuilder3.Capacity, stringBuilder3);
connect = winPtr1;
}
str = stringBuilder2.ToString();
if (str.Equals("ComboBox"))
{
connect_id = winPtr1;
}
if (str.Equals("Edit"))
{
teamviewer_id = stringBuilder3.ToString();
return 1;
//if (index == 0)
//{
// teamviewer_id = stringBuilder3.ToString();
//}
//if (index == 1)
//{
// teamviewer_password = stringBuilder3.ToString();
// return 1;
//}
//index++;
}
//获取当前子窗口中的下一个控件
winPtr1 = GetWindow(winPtr1, GetWindowCmd.GW_HWNDNEXT);
}
//获取当前子窗口中的下一个控件
winPtr = GetWindow(winPtr, GetWindowCmd.GW_HWNDNEXT);
}
}
if (number >10)
{
return 0;
}
}
}
获取AnyDesk的ID:
public int getAnyDeskInfo()
{
int index = 0;
int number = 0;
const int BM_CLICK = 0xF5;
const int WM_SETTEXT = 0xC;
const int WM_GETTEXT = 0xD;
while (true)
{
Thread.Sleep(1000);
number++;
IntPtr maindHwnd = FindWindow(null, "AnyDesk"); //获得句柄
if (maindHwnd != IntPtr.Zero)
{
IntPtr winPtr = GetWindow(maindHwnd, GetWindowCmd.GW_CHILD);
// 3、循环取得桌面下的所有子窗口
while (winPtr != IntPtr.Zero)
{
// 4、继续获取下一个子窗口
IntPtr winPtr1 = GetWindow(winPtr, GetWindowCmd.GW_CHILD);
while (winPtr1 != IntPtr.Zero)
{
IntPtr winPtr2 = GetWindow(winPtr1, GetWindowCmd.GW_CHILD);
while (winPtr2 != IntPtr.Zero)
{
StringBuilder stringBuilder1 = new StringBuilder(512);
// GetWindowText(winPtr1, stringBuilder1, stringBuilder1.Capacity);
SendMessage(winPtr2, WM_GETTEXT, (IntPtr)stringBuilder1.Capacity, stringBuilder1);
str = stringBuilder1.ToString();
if (str.Equals("This Desk") || str.Equals("此工作台"))
{
while (true)
{
winPtr2 = GetWindow(winPtr2, GetWindowCmd.GW_HWNDNEXT);
StringBuilder stringBuilder2 = new StringBuilder(512);
GetClassName(winPtr2, stringBuilder2, stringBuilder2.Capacity);
str = stringBuilder2.ToString();
if (str.Equals("id_label_cls#12\n"))
{
StringBuilder stringBuilder3 = new StringBuilder(512);
GetWindowText(winPtr2, stringBuilder3, stringBuilder3.Capacity);
anydesk_id = stringBuilder3.ToString();
return 1;
}
}
}
winPtr2 = GetWindow(winPtr2, GetWindowCmd.GW_HWNDNEXT);
}
winPtr1 = GetWindow(winPtr1, GetWindowCmd.GW_HWNDNEXT);
}
winPtr = GetWindow(winPtr, GetWindowCmd.GW_HWNDNEXT);
}
}
if (number > 10)
{
return 0;
}
}
}
最后
整个过程其实比较简单,主要是借助Windows API。获取TM和AD的函数都是项目中的实际代码
可以参考我的百度经验