登陆功能的实现

简介: 我不喜欢废话,上代码 /// /// 运行程序返回进程pid /// /// /// static public int RunProgram(string qqPath) ...

我不喜欢废话,上代码

         /// <summary>
        /// 运行程序返回进程pid
        /// </summary>
        /// <param name="qqPath"></param>
        /// <returns></returns>
        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<HookedInterface>(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
 
        /// <summary>
        /// 登陆,成功后返回窗体句柄
         /// </summary>
        /// <param name="mainQQ"></param>
        /// <param name="mainQQPwd"></param>
        /// <returns></returns>
        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实现发送消息,为窗体置顶,设置焦点

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

 

转载请注明:http://www.cnblogs.com/Rolends 
目录
相关文章
|
存储 前端开发 PHP
构建一个简单的网站,包括用户注册、登录功能
构建一个简单的网站,包括用户注册、登录功能
341 1
|
Java 数据安全/隐私保护
登陆页面实现保存帐号密码功能
本文主要讲如何登陆页面实现保存帐号密码功能
484 0
登陆页面实现保存帐号密码功能
|
6月前
|
SQL 关系型数据库 MySQL
MySQL数据库基础练习系列13、用户注册与登录系统
MySQL数据库基础练习系列13、用户注册与登录系统
48 1
|
API 数据安全/隐私保护
漏刻有时忘记超级管理员密码的解决方案:通过API接口设置超级管理员
漏刻有时忘记超级管理员密码的解决方案:通过API接口设置超级管理员
87 0
|
Java 数据安全/隐私保护 容器
【JavaWeb】案例:用户登录、用户自动登录
本期主要介绍案例:用户登录、用户自动登录
327 0
【JavaWeb】案例:用户登录、用户自动登录
|
Java 数据库连接 数据库
实现用户登陆功能的实现
在javaEE中,实现用户登陆功能的实现(图文结合)
实现用户登陆功能的实现
后台登录模块理解
后台登录模块理解
|
JavaScript Java 数据安全/隐私保护
Java实现登录功能(含修改密码 退出登录等)
Java实现登录功能(含修改密码 退出登录等)
1934 0
Java实现登录功能(含修改密码 退出登录等)
|
前端开发 PHP
如何实现网站用户登陆之后跳转到登陆之前的页面
主体思路就是在网站的公共头部文件里session中记录当前网页地址以及上一个页面的网页地址,然后就是登陆成功之后如果session中有上一个页面的网址就跳转到上一个页面去,如果session中没有上一个页面就跳转到会员中心去。
293 1