(一)C# QQ讨论组广告群发工具——QQ登陆功能的实现上篇(附源码)

作者: 时间: 2012-04-22 分类: 技术文章 | 4 评论数 |

您的支持,是我前进的动力

C# QQ登陆功能的实现源码,我不喜欢废话,上代码……C#/Java技术交流群:96020642,传送门:http://www.cnblogs.com/Rolends
涉及到知识点:
1、窗体查找(遍历桌面窗体);
2、控件查找(子窗体,句柄循环);
3、使用windows API实现发送消息,为窗体置顶,设置焦点;

 C# Code By wuleba.com
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/// <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

 C# Code By wuleba.com
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/// <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 (
“输入密码”);
G
for (int i = 0; i < 20; i++) SendKeys.SendWait (“{DELETE}”);

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 – 
2020, width, height, true);
return mainWea.Hwnd;
}
return IntPtr.Zero;
}

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

 C# Code By wuleba.com
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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;
}

上面的代码是各种情况的判断。
今天到此为止,明天继续更新…下一篇的传送门:http://www.wuleba.com/2009.html

搜妹子,搜出妹子做壁纸!

本文采用 CC协议 发布,转载请注明:转载自 吾乐吧软件站

本文链接地址:http://www.wuleba.com/?p=2005

4 条评论 给“(一)C# QQ讨论组广告群发工具——QQ登陆功能的实现上篇(附源码)”

  1. 找了很久了,可惜段位太低看不懂啊。求大神的完整工程文件! [泪]

  2. 模拟得很到位,哈哈

  3. 开源的,必须支持

发表评论


微软MSDN资源免费订阅,MSDN 我告诉你