利用API揪出抢占Win8窗口焦点的熊孩纸

起因:谁在抢镜头?!

为了开始Windows Phone 8的开发,这两天将系统升级到了Windows8.1,安装倒是又快又方便的,解压ISO镜像双击Setup一路下一步(嘛其实还输了密钥之类的)就安装好了~
不过不知道为什么去年买的正版密钥激活不了了,于是按照指示拨打了微软的客服电话,客服妹纸问了几个问题就给激活了~然后花了两三个小时进行各种配置美化和常用软件安装,看起来好极了~

01

可耻的晒桌面(其实和之前用Win7时没啥区别……已经一年多没换过主题了……)

刚开始用着感觉没啥问题啊,速度也挺快,可是打开VS写了几行代码就发现有些不对劲了,智能感应总是会莫名其妙的半路消失,然后发现聊QQ时经常打一半字输入法不见了,更糟糕的是逛B站全屏视频时会时不时跳出到窗口模式……根据十几年(啊天哪我怎么这么老了= -)的视窗操作系统(其实就是Windows~听起来逼格高那么一点?)使用经验,首先想到的是焦点被抢占了~之后用一般窗口程序观察了一下,发现的确是这样,时不时就会失去焦点半秒然后再恢复,网上查了一下,大多数说是支付宝安全控件之类的,可是我貌似不是因为这个引起的……那么究竟是谁干的呢?

04

经过:捕捉熊孩子,我有特殊的技巧

作为半个程序猿,当然就要用程序猿的方式解决咯(事实上是因为我找不到其它方法……),很久很久以前就知道了Windows有提供获得焦点窗口句柄(handle,话说为什么要翻译成“句柄”这种不明所以的东西? )的API,看来这次是可以用的上咯~
网上查了查发现不难而且有相关例子,直接打开VS,新建一个WinForm程序,拖了一个Label一个TextBox和一个Timer

00

就这么简单~

Timer设为10ms检测一次焦点窗口并输出相关信息,包括句柄号、进程PID号、进程名称、窗口名称和窗口类名,Label显示句柄号,TextBox记录相关变化
以下为代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;


namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        [DllImport("user32", EntryPoint = "GetWindowThreadProcessId")]
        private static extern int GetWindowThreadProcessId(
            IntPtr hwnd, //窗口句柄
            out int pid  //输出所在进程的PID
        );//通过句柄获取PID

        [DllImport("user32", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern IntPtr GetForegroundWindow();//获取当前激活窗口

        [DllImport("user32", SetLastError = true)]
        public static extern int GetWindowText(
            IntPtr hWnd, //窗口句柄
            StringBuilder lpString, //标题
            int nMaxCount  //最大值
        );

        [DllImport("user32")]
        private static extern int GetClassName(
            IntPtr hWnd, //句柄
            StringBuilder lpString, //类名
            int nMaxCount //最大值
        );

        public Form1()
        {
            InitializeComponent();
            timer1.Start();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            IntPtr myPtr = GetForegroundWindow();
            int pid = 0;

            // 窗口进程PID
            GetWindowThreadProcessId(myPtr, out pid);

            // 窗口标题
            StringBuilder title = new StringBuilder(512);
            GetWindowText(myPtr, title, title.Capacity);

            // 窗口进程
            Process localById = Process.GetProcessById(pid);

            // 窗口类名
            StringBuilder className = new StringBuilder(512);
            GetClassName(myPtr, className, className.Capacity);

            //如果焦点窗体发生变化则记录
            if (label1.Text != myPtr.ToString())
            {
                label1.Text = myPtr.ToString();
                textBox1.Text = DateTime.UtcNow
                    + "\r\n" + pid.ToString()
                    + "\r\n" + localById.ProcessName
                    + "\r\n" + title.ToString()
                    + "\r\n" + className.ToString()
                    + "\r\n\r\n===================================================\r\n\r\n"
                    + textBox1.Text;
            }
        }
    }
}

运行起来一切正常,就差熊孩纸出现了!

点我下载熊孩子探测器

结果:嘿嘿我捉到你了!

写完代码运行了一段时间才猛然发现,在这期间居然没有出现过被抢占焦点的问题,难道狡猾的熊孩纸发现了我的阴谋?
当然这不可能啦~该出现的迟早是要出现的,于是先让它运行着,然后继续聊QQ看视频……
又过了一个小时,熊孩纸终于按捺不止又开始捣乱啦~赶快切换到探测器,终于发现了……

QQ截图20140831000327

原来是这个名为DrUpdate.exe的进程,看名字就知道,这是我们万恶的校园网登入客户端Dr.Com的自动升级进程,

03

这哪里是熊孩子捣乱,分明是州官放火啊
没办法,又不能删掉,试着用资源监视器挂起了这个进程,没想到这货居然会自动重启,最后一怒之下直接把这个文件重命名了……然后一切都安宁了~~

后记

虽然通过重命名执行文件的方式暂时解决了问题,不过后来发现重启电脑或关闭客户端后会导致无法再次打开客户端,于是只能再重命名回来(还好留了个心眼没有直接删掉),等客户端启动后再次重命名,感觉真是麻烦,不过就暂时先这样咯,反正我一般不关电脑的~

C#模拟系统按键

摘自http://msdn.microsoft.com/zh-tw/library/ms171548(v=vs.110).aspx

首先,使用DllImport引入两个函数:

// Get a handle to an application window.
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName,
string lpWindowName);

// Activate an application window.
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);

然后首先使用FindWindow函数获取到需要按键的窗口句柄,以计算器为例。这里体现了这个方法的局限性,就是似乎不能触发全局快捷键。

// Get a handle to the Calculator application. The window class
// and window name were obtained using the Spy++ tool.
IntPtr calculatorHandle = FindWindow("CalcFrame","Calculator");

然后使用SetForegroundWindow函数将这个窗口调到最前。

SetForegroundWindow(calculatorHandle);

接下来就可以直接使用SendKeys.SendWait之类的发送按键了。

SendKeys.SendWait("111");
SendKeys.SendWait("*");
SendKeys.SendWait("11");
SendKeys.SendWait("=");

完整代码如下:

using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Windows.Forms;
// Get a handle to an application window.
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName,
string lpWindowName);

// Activate an application window.
[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);

// Send a series of key presses to the Calculator application.
private void button1_Click(object sender, EventArgs e)
{
// Get a handle to the Calculator application. The window class
// and window name were obtained using the Spy++ tool.
IntPtr calculatorHandle = FindWindow("CalcFrame","Calculator");

// Verify that Calculator is a running process.
if (calculatorHandle == IntPtr.Zero)
{
MessageBox.Show("Calculator is not running.");
return;
}

// Make Calculator the foreground application and send it
// a set of calculations.
SetForegroundWindow(calculatorHandle);
SendKeys.SendWait("111");
SendKeys.SendWait("*");
SendKeys.SendWait("11");
SendKeys.SendWait("=");
}

注意如果是命令行程序的话需要手动添加System.Windows.Forms引用,否则找不到SendKeys类。

Win7风格的文件夹选择对话框

.NET中默认的FolderBrowserDialog是一个很丑的XP风格的文件夹选择对话框,对用户极其不友好。微软估计也是想到了这个问题,所以提供了一套叫

Windows® API Code Pack for Microsoft® .NET Framework的东西,这里面实现了一个Win7风格的文件夹选择对话框,非常漂亮,而且比较友好。

下载地址及介绍:http://archive.msdn.microsoft.com/WindowsAPICodePack

百度网盘下载地址:http://pan.baidu.com/s/1i3606m5

本地组策略与安全策略的自动导入

本地组策略与安全策略的自动导入

   昨天接到一个需求,由于公司要求服务器要部署必需的一些安全策略,但是对于未加入域的服务器希望能有一个便捷的部署办法。

首先,提取出需要部署的策略中能通过组策略或安全策略实施的项如表所示(部分演示):

序号 要求
1 “密码必须符合复杂性要求”选择“已启动”
2 “密码最长存留期”设置为“90天”
3 “账户锁定阀值”设置为小于或等于 6次
4 “从远端系统强制关机”设置为“只指派给Administrtors组”
5 “关闭系统”设置为“只指派给Administrators组”
6 “取得文件或其它对象的所有权”设置为“只指派给Administrators组”
7 审核登录事件,设置为成功和失败都审核。
8 “审核策略更改”设置为“成功” 和“失败”都要审核
9 “审核对象访问”设置为“成功”和“失败”都要审核
10 “审核目录服务器访问”设置为“成功” 和“失败”都要审核
11 “审核目录服务器访问”设置为“成功” 和“失败”都要审核
12 “审核系统事件”设置为“成功” 和“失败”都要审核
13 “审核账户管理”设置为“成功” 和“失败”都要审核
14 “审核过程追踪”设置为 “失败”需要审核
15 “Microsoft网络服务器”设置为“在挂起会话之前所需的空闲时间”为15分钟。
16 启用屏幕保护程序,设置等待时间为“5分钟”,启用“在恢复时使用密码保护”。
17 所有驱动器均“关闭自动播放”

上表中前15项属于安全策略,第16项属于组策略中的计算机配置策略,第17项属于用户配置策略。下面仅对Windows 2003平台的操作进行了分析与测试。

    一、 对于安全策略,可以用以下步骤进行应用部署:

::在测试用机上,先使用gpedit.msc手工更改策略(如表中前15面),再用以下命令导出当前策略

secedit /export /cfg sec.inf

::用文本编辑器编辑sec.inf文件,去除不需要调整的内容,仅保留要定制策略

表中15条策略对应的inf文件内容如下:

[Unicode]
Unicode=yes
[Version]
signature=”$CHICAGO$”
Revision=1
[System Access]
MaximumPasswordAge = 90
PasswordComplexity = 1
LockoutBadCount = 6
[Event Audit]
AuditSystemEvents = 3
AuditLogonEvents = 3
AuditObjectAccess = 3
AuditPrivilegeUse = 3
AuditPolicyChange = 3
AuditAccountManage = 3
AuditProcessTracking = 2
AuditDSAccess = 3
[Registry Values]
machine/system/currentcontrolset/services/lanmanserver/parameters/autodisconnect=4,15
[Privilege Rights]
seremoteshutdownprivilege = *S-1-5-32-544
seshutdownprivilege = *S-1-5-32-544
setakeownershipprivilege = *S-1-5-32-544

::用命令生成一个sdb文件

secedit /configure /db  sec.sdb  /cfg sec.inf

::用命令把定制策略更新到目标服务器,不能用/overwrite参数,否则除定制策略外的其它策略丢失

secedit /configure /db sec.sdb

::刷新组策略

gpupdate /force

    二、其他组策略的应用

以前曾经研究过利用gpcvreg与gpscript命令行程序来应用组策略,并且写了autoit3脚本的UDF,这次正好可以利用。
使用gpedit.msc在测试机修改16/17两条策略,在不关闭gpedit.msc的同时用regedit查看HKEY_CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/Group Policy Objects下,分析得到相应设置并存成Reg文件

machine.reg, 禁用所有驱动器自动播放

[HKEY_LOCAL_MACHINE/Software/Microsoft/Windows/CurrentVersion/Policies/Explorer]
“NoDriveTypeAutoRun”=dword:000000FF

user.reg,定制屏幕保护设置

[HKEY_CURRENT_USER/Software/Policies/Microsoft/Windows/Control Panel/Desktop]
“ScreenSaverIsSecure”=”1”
“ScreenSaveActive”=”1”
“ScreenSaveTimeOut”=”300”
“SCRNSAVE.EXE”=”scrnsave.scr”

三、批量应用脚本

有了sec.sdb、machine.reg及user.reg文件,然后利用以前写的poledit.au3 UDF ,只需要以下脚本就可以进行前文所列出的策略的自动应用了。


#RequireAdmin
#NoTrayIcon
#include "PolEdit.au3"

If FileExists("sec.sdb") Then RunWait(@ComSpec & " /c " & "secedit /configure /db sec.sdb", @ScriptDir, @SW_HIDE)
_RegWriteToPol("machine.reg", "MACHINE", 1)
_RegWriteToPol("user.reg")
_gpupdate()

10 个免费的 C/C++ 集成开发环境

集成开发环境(IDE)可以给程序员提供很大的帮助。大多数的IDE包含编译器和解释器。例如微软的 Visual Studio 本身内置的编译器和解释就是很好的例子,Eclipse 是另一个很好的例子。鼓励程序员使用IDE的主要原因是开发软件应用程序的各个组成部分之间可方便的进行切换。

一般一个特定的IDE是负责处理一种编程语言,但也有一些支持多种编程语言的 IDE,例如 NetBeans,Microsoft Visual Studio,MyEclipse,WinDev和Xcode等等。IDE 的宗旨是提供了一个强大和易于使用的用于创作,修改,编译,部署,调试软件,并增加开发人员的生产力的环境。

今天,我们将为程序员分享一些最好的C和C++的免费IDE。
1) Codeblocks
Code::Blocks (codeblocks)是一个开源、免费、跨平台的c++ IDE。官方网站上称其能满足最苛刻的用户的需求。虽有点夸张,但既然敢这样说,也说明它的功能肯定不差。可扩展插件,有插件向导功能,让你很方便的创建 自己的插件。Code::Blocks是用c++编写的(用wxWidgets库),捆绑了MinGW编译器。

164852012681277851

2) kDevelop KDevelop-Project诞生于1998年,其目的是为KDE提供一个易用的集成开发环境(Integrated Development Environment)。此后,KDevelop IDE采用GPL进行发布, 它支持很多 程序设计语言.

164852111882263441

3) Pellesc Pelles C是一款windows下的C IDE,支持调试,且为免费。
它有一个高效率的链接器,目前已被广泛采用为各种语言的后台链接器使用LCC作为编译器
并且完整支持win32编程,支持任何API调用,包含所有winAPI的库且含有完整 C Runtime Library。

16485227494860761

4) Anjuta Anjuta是一个C/C++ IDE,它最大的特色是灵活,同时打开多个文件,内嵌代码级的调试器(调用gdb),应用程序向导(Application widzards)可以方便的帮助你创建GNOME程序而不需要你自己写一些与你兴趣无关的代码。

16485231101371601

5) Bloodshed Dev-C++是一个Windows下的C和C++程序的集成开发环境。它使用MingW32/GCC编 译器,遵循C/C++标准。开发环境包括多页面窗 口、工程编辑器以及调试器等,在工程编辑器中集合了编辑器、编译器、连接程序和执行程序,提供高亮度语法显示的,以减少编辑错误,还有完善的调试功能,能 够适合初学者与编程高手的不同需求,是学习C或C++的首选开发工具!多国语言版中包含简繁体中文语言界面及技巧提示,还有英语、俄语、法语、德语、意大 利语等二十多个国家和地区语言提供选择。

164856411209347271

6) Eclipse CDT Eclipse CDT 是 Eclipse 插件,它将把 Eclipse 转换为功能强大的 C/C++ IDE。它被设计为将 Java 开发人员喜爱的许多 Eclipse 优秀功能提供给 C/C++ 开发人员,例如项目管理、集成调试、类向导、自动构建、语法着色和代码完成。当 Eclipse 被用作 Java IDE 时,它将利用 JDK 并与之集成。同样地,CDT 将利用标准的 C/C++ 工具并与之集成,例如 g++、make 和 GDB。这使得 CDT 在 Linux 中变得非常流行,这些工具都可在 Linux 中使用并用于大多数 C++ 开发。可以在 Windows 上设置 CDT 以使用相同的工具。

eclipse1

7) Visual Mingw
Visual-MinGW 是一个专门为MinGW所设计的IDE。如果,你曾经用过VC++ 6.0这个IDE,你的第一感觉就是,Visual-MinGW和VC++ 6.0非常相似。所以,对于曾经用惯VC的朋友们来说,Visual-MinGW不失是一个好的选择。然而,Visual-MinGW的开发与更新似乎并 不积极。因此,还有不足的地方。Visual-MinGW的理念是提供一个高效的,快速的创建代码的IDE。

16485664904080671

8) Ecere
eCere,一门“新”的编程语言,以下简称为“eC”。

eC,是一位加拿大人jerome历时十二年开发的一门编译型编程语言,拥有C++项目的性能、Java的跨平台性以及Python语法的简洁性。 不似Object C、C++和C#,eC更像是一个C语言的Shell,他将程序员与C之间的复杂性隔离开来,还有就是他在跨平台支持方面要更优越一些。eC不仅给传统的 C语言引入了完整的OO编程实现,其真正强大之处在于作者目前所实现的C库,包括一个内建的3D引擎实现(支持Direct3D和 OpenGL)和一套接近于VB的GUI库实现以及对网络编程的支持。

16485674544593231

9) Relo
Relo是一个帮助开发人员研究大型代码库的好工具,它能够一步步的跟踪你所展开的代码包,并快速生成类似UML的类图。

16485682190673751

10) Ultimate++ U++是一个开源的跨平台C++ RAD平台,作者从98年就开始开发,到今年持续了十一年了。U++一直都是一个非常非常小众的开发平台,几乎没什么人用,与当今火红的几个开源C++ Framewrok比如wxwidgets, QT等相比,它实在是被人冷落的可以。换做旁人早就歇菜了,在SourceForge上搜一下,能搜出一堆半路夭折的C++Framework。而U++ 却仍在不断的开发中,可算是特立独行。

16485697113498131