这个程序主要还是靠钩子实现,然后利用manuResetEvent同步控制关机线程 。关机线程用重定向实现
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace magic
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.ShowInTaskbar = false;
this.WindowState = FormWindowState.Minimized;
}
private const int WM_KEYDOWN = 0x100;
private const int WM_KEYUP = 0x101;
private const int WM_SYSKEYDOWN = 0x104;
private const int WM_SYSKEYUP = 0x105;
private const int VK_SNAPSHOT = 0x2C;
//全局的事件
static int hKeyboardHook = 0; //键盘钩子句柄
//鼠标常量
public const int WH_KEYBOARD_LL = 13; //keyboard hook constant
HookProc KeyboardHookProcedure; //声明键盘钩子回调事件.
Process process = new Process();
//声明键盘钩子的封送结构类型
[StructLayout(LayoutKind.Sequential)]
public class KeyboardHookStruct
{
public int vkCode; //表示一个在 1 到 254 间的虚似键盘码
public int scanCode; //表示硬件扫描码
public int fags;
public int time;
public int dwExtraInfo;
}
//装置钩子的函数
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance,
int threadId);
//卸下钩子的函数
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern bool UnhookWindowsHookEx(int idHook);
//下一个钩挂的函数
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);
[DllImport("user32")]
public static extern int ToAscii(int uVirtKey, int uScanCode, byte[] lpbKeyState, byte[]
lpwTransKey, int fuState);
[DllImport("user32")]
public static extern int GetKeyboardState(byte[] pbKeyState);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("kernel32.dll")]
static extern int GetTickCount();
public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
public static ManualResetEvent capture_terminate_e;
private void Start_h()
{
//安装键盘钩子
if (hKeyboardHook == 0)
{
KeyboardHookProcedure = new HookProc(KeyboardHookProc);
Process curProcess = Process.GetCurrentProcess();
ProcessModule curModule = curProcess.MainModule;
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, GetModuleHandle(curModule.ModuleName), 0);
if (hKeyboardHook == 0)
{
Stop_h();
throw new Exception("SetWindowsHookEx is failed.");
}
}
}
private void Stop_h()
{
bool retKeyboard = true;
if (hKeyboardHook != 0)
{
retKeyboard = UnhookWindowsHookEx(hKeyboardHook);
hKeyboardHook = 0;
}
//如果卸下钩子失败
if (!(retKeyboard)) throw new Exception("UnhookWindowsHookEx failed.");
}
private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam)//钩子的回调函数。注意回调的特点:1:有循环机制。2:由系统调用
{
//lParam 参数只是数据的内存地址
KeyboardHookStruct MyKeyboardHookStruct =
(KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
Keys keyData = (Keys)MyKeyboardHookStruct.vkCode;
if (wParam == WM_KEYDOWN || wParam == WM_KEYDOWN)//对截获的消息不做处理,只是同步控制关机线程
{
capture_terminate_e.Set();
}
return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}
public void shoutdown()//关机线程
{
while (!capture_terminate_e.WaitOne())
{
return;
}
if(capture_terminate_e.WaitOne(100))
{
string strCmd = "shutdown /f /s /t 6000";
process.StandardInput.WriteLine(strCmd);
}
}
private void Form1_Load(object sender, EventArgs e)//在程序开始就让重定向,钩子,和控制关机的线程跑起来
{
process.StartInfo.FileName = "cmd.exe";//要打开进程的名字;
process.StartInfo.UseShellExecute = false;//此处注意一旦重定向一定要设置为fals;
process.StartInfo.CreateNoWindow = true; // 是否在新窗口中启动该进程的值
process.StartInfo.RedirectStandardInput = true;// 重定向输入流
process.Start();//重定向进程开始
Start_h();//设置钩子
capture_terminate_e = new ManualResetEvent(false);
//关机线程开启
ThreadStart workStart = new ThreadStart(shoutdown);
Thread workThread = new Thread(workStart);
workThread.IsBackground = true;
workThread.Start();
}
}
}
希望大家指点下,指出不足之处