zoukankan      html  css  js  c++  java
  • 登陆功能的实现

    我不喜欢废话,上代码

             /// <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:
    {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 
  • 相关阅读:
    Grafana+Prometheus监控mysql性能
    性能测试监控平台Grafana的使用
    搭建grafana+telegraf+influxdb服务器性能监控平台
    cocos2d-x jsb 防止触摸事件传递
    web app 相关记录
    如何在Teamcenter中使用PMI?
    浅谈人机工程应用在数字化工艺中的作用
    关于奇葩说
    一些感想
    关于起名
  • 原文地址:https://www.cnblogs.com/xumaojun/p/8529175.html
Copyright © 2011-2022 走看看