博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
登陆功能的实现
阅读量:5057 次
发布时间:2019-06-12

本文共 5603 字,大约阅读时间需要 18 分钟。

我不喜欢废话,上代码

/// 
/// 运行程序返回进程pid
/// 
/// 
/// 
static public int RunProgram(string qqPath)
{
int pid = 0;
Process pro = Process.Start(qqPath);
if (pro != null)
{
pid = pro.Id;
}
try
{
ChannelName = null;
Console.WriteLine("Register");
RemoteHooking.IpcCreateServer
(ref ChannelName, WellKnownObjectMode.SingleCall);
Console.WriteLine("IpcCreateServer");
RemoteHooking.Inject(pid, "QqMonInject.dll", "QqMonInject.dll", ChannelName);
HookedSender.Init();
WndManager.Init();
 
}
catch (Exception ExtInfo)
{
Console.WriteLine("There was an error while connecting to target:\r\n{0}", ExtInfo.ToString());
}
 
return pid;
}
上面的代码实现了运行QQ,并使用EasyHook加载钩子,由于。net无法实现全局钩子,故使用EasyHook来实现,EasyHook是一个开源项目,大家可以google
 
/// 
/// 登陆,成功后返回窗体句柄
/// 
/// 
/// 
/// 
static public IntPtr Logon(string mainQQ, string mainQQPwd, ref string errorText)
{
IntPtr hWnd = IntPtr.Zero;
string qqPath = SqliteHelper.GetValue("select SC_QQPROPATH from sys_config").ToString();
int pid = RunProgram(qqPath);
if (pid < 100)
{
errorText = "无法运行QQ进程";
WriteLog(errorText);
return hWnd;
}
Thread.Sleep(SysConfig.QQProcessStartSleppTime);
//bool ad = !false;
//while (ad) { Thread.Sleep(2000); }
IntPtr hLogonWnd = GetLogonWnd(pid);
if (hLogonWnd == IntPtr.Zero) hLogonWnd = GetLogonWnd2(pid);
if (hLogonWnd == IntPtr.Zero)
{
errorText = "没有登陆窗口";
WriteLog(errorText);
return hWnd;
}
var cons = WndHelper.GetVisableControl(hLogonWnd, "ATL:30A561F0");
if (cons.Count < 1)
{
errorText = "没有找到登陆QQ输入框";
WriteLog(errorText);
return hWnd;
}  //没有找到QQ输入框
int retvar = WinAPIHelper.SendMessage(cons[0], WinAPIHelper.WM_SETTEXT, IntPtr.Zero, new StringBuilder(mainQQ));
if (retvar == 0)
{
errorText = "无法设置登陆QQ号码";
WriteLog(errorText);
return hWnd;
}//无法设置登陆QQ号码
cons = WndHelper.GetVisableControl(hLogonWnd, "Edit");
if (cons.Count < 1)
{
errorText = "没有找到密码输入框";
WriteLog(errorText);
return hWnd;
}//没有找到密码输入框
 
SETPASSWARD:
while (true)
{
if (WndHelper.IsWindowTopMost(hLogonWnd))
{
if (!WinAPIHelper.BringWindowToTop(hLogonWnd))
{
Console.WriteLine("登陆窗体置顶失败");
continue;
}
}
Console.WriteLine("登陆窗体设置焦点");
IntPtr hFocus = WinAPI.GetForegroundWindow();
if (hFocus == IntPtr.Zero)
{
Thread.Sleep(200);
Console.WriteLine("获取焦点窗体失败");
continue;
}
if (hFocus != hLogonWnd)
{
if (!WinAPIHelper.SetForegroundWindow(hLogonWnd))
{
Thread.Sleep(200);
Console.WriteLine("登陆窗体设置焦点失败");
//continue;
}
}
 
bool result = WinAPIHelper.SetForegroundWindow(hLogonWnd);
//if (!result) goto SETPASSWARD;
retvar = WinAPIHelper.SendMessage(cons[0], WinAPIHelper.WM_SETFOCUS, 0x001a0494, 0);
break;
//if (retvar == 0) goto SETPASSWARD;
}
 
Console.WriteLine("密码:" + mainQQPwd);
Console.WriteLine("输入密码");
#if DEBUG
for (int i = 0; i < 20; i++) SendKeys.SendWait("{DELETE}");
#endif
SendKeys.SendWait(mainQQPwd.Replace("+", "{+}").Replace("^", "{^}").Replace("%", "{%}"));
WndHelper.ClickWnd(hLogonWnd, 0x00c9012d);
if (WaitLogon(pid, ref errorText))
{
Console.WriteLine("登陆完成");
}
else
{
return IntPtr.Zero;
}
WindowEventArgs mainWea = WndManager.GetDesktopWnds(pid).Find(p => p.Pid == pid && p.ClassName == "TXGuiFoundation" && p.Title == "QQ2010");
if (mainWea != null)
{
const int width = 270;
const int height = 600;
WinAPIHelper.MoveWindow(mainWea.Hwnd, Screen.PrimaryScreen.WorkingArea.Width - width - 20, 20, width, height, true);
return mainWea.Hwnd;
}
return IntPtr.Zero;
}

登陆部分代码,关键点是WM_SETTEXT消息设置QQ号码,SendKeys.SendWait设置密码,然后模拟点击,实现登陆

static public bool WaitLogon(int pid, ref string errorText)
{
DateTime beginTime = DateTime.Now;
while (true)
{
TimeSpan ts = TimeSpan.FromTicks(DateTime.Now.Ticks - beginTime.Ticks);
if (ts.TotalMilliseconds > SysConfig.QQLogonTimeOut)
{
KillProcess(pid);
errorText = "登陆超时";
WriteLog(errorText);
return false;
}
var wnds = WndManager.GetDesktopWnds(pid);
WindowEventArgs pwdErrorWea = wnds.Find(p => p != null && p.Pid == pid && p.ClassName == "TXGuiFoundation" && p.Title == "密码验证错误");
if (pwdErrorWea != null)
{
bool result = WinAPIHelper.IsWindowVisible(pwdErrorWea.Hwnd);
if (result)
{
KillProcess(pid);
errorText = "密码错误";
WriteLog(errorText);
return false;
}
}
 
WindowEventArgs pwdErrorNet = wnds.Find(p => p != null && p.Pid == pid && p.ClassName == "TXGuiFoundation" && p.Title == "提示" && p.Size.Width == 350 && p.Size.Height == 160);
if (pwdErrorNet != null)
{
bool result = WinAPIHelper.IsWindowVisible(pwdErrorNet.Hwnd);
if (result)
{
KillProcess(pid);
errorText = "网络连接错误";
WriteLog(errorText);
return false;
}
}
WindowEventArgs mainWea = wnds.Find(p => p != null && p.Pid == pid && p.ClassName == "TXGuiFoundation" && p.Title == "QQ2010" && WinAPIHelper.IsWindowVisible(p.Hwnd));
if (mainWea != null)
{
bool result = WinAPIHelper.IsWindowVisible(mainWea.Hwnd);
if (result && mainWea.Size.Height > 338)
break;
}
WindowEventArgs codeWea = wnds.Find(p => p != null && p.Pid == pid && p.ClassName == "TXGuiFoundation" && p.Title == "帐号存在异常");
if (codeWea != null)
{
if (SysConfig.IsSkipValidateCode)
{
bool result = WinAPIHelper.IsWindowVisible(codeWea.Hwnd);
if (result)
{
KillProcess(pid);
errorText = "需要输入验证码";
WriteLog(errorText);
return false;
}
}
else
Thread.Sleep(1000);
 
}
WindowEventArgs saleWea = wnds.Find(p => p != null && p.Pid == pid && p.ClassName == "TXGuiFoundation" && p.Title == "帐号需解除限制后才能登录");
if (saleWea != null)
{
bool result = WinAPIHelper.IsWindowVisible(saleWea.Hwnd);
if (result)
{
KillProcess(pid);
errorText = "账号被限制";
WriteLog(errorText);
return false;
}
}
 
Thread.Sleep(1000);
}
return true;
}
上面的代码是各种情况的判断

涉及到知识点

  1. 窗体查找(遍历桌面窗体)
  2. 控件查找(子窗体,句柄循环)
  3. 使用windows API实现发送消息,为窗体置顶,设置焦点

今天到此为止,明天继续更新

转载于:https://www.cnblogs.com/Rolends/archive/2012/04/17/2454290.html

你可能感兴趣的文章
《梦断代码》读书笔记(三)
查看>>
Java8 Lambda表达应用 -- 单线程游戏server+异步数据库操作
查看>>
[Unity3D]Unity3D游戏开发MatchTarget的作用攀登效果实现
查看>>
AngularJS学习篇(一)
查看>>
关于Xshell无法连接centos6.4的问题
查看>>
css3动画——基本准则
查看>>
机器学些技法(9)--Decision Tree
查看>>
drf权限组件
查看>>
输入月份和日期,得出是今年第几天
查看>>
【linux】重置fedora root密码
查看>>
pig自定义UDF
查看>>
Kubernetes 运维学习笔记
查看>>
spring security 11种过滤器介绍
查看>>
图解算法时间复杂度
查看>>
代码实现导航栏分割线
查看>>
Windows Phone开发(7):当好总舵主 转:http://blog.csdn.net/tcjiaan/article/details/7281421...
查看>>
Vue-详解设置路由导航的两种方法
查看>>
一个mysql主从复制的配置案例
查看>>
大数据学习系列(8)-- WordCount+Block+Split+Shuffle+Map+Reduce技术详解
查看>>
【AS3代码】播放FLV视频流的三步骤!
查看>>