using Apewer.Internals.Interop; using Microsoft.Win32; using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using System.Text; #if NETFX using System.Management; #endif #if NETFX || NETCORE using System.Windows.Forms; #endif namespace Apewer { /// <summary>Windows 实用工具。</summary> public class WindowsUtility { #region 进程。 #if NETFX /// <summary>操作系统是否基于 64 位架构。</summary> public static bool WindowsIsX64 { get { try { string vbit = String.Empty; var options = new ConnectionOptions(); var scope = new ManagementScope("\\\\localhost", options); var query = new ObjectQuery("select addresswidth from win32_processor"); var searcher = new ManagementObjectSearcher(scope, query); var collection = searcher.Get(); foreach (var i in collection) { if (i["addresswidth"].ToString() == "64") return true; } } catch (Exception ex) { Console.WriteLine(ex.ToString()); } return false; } } #endif /// <summary>当前进程是否基于 64 位架构。</summary> /// <remarks>此属性读取 System.Environment.Is64BitProcess,由 mscorlib.dll 定义。</remarks> public static bool ProcessIsX64 { #if NET20 get { return IntPtr.Size == 8; } #else get { return Environment.Is64BitProcess && IntPtr.Size == 8; } #endif } /// <summary>调用 System.Diagnostics.Process.Start 启动进程。</summary> /// <param name="path">程序路径。</param> /// <param name="args">参数。</param> /// <param name="uac">以管理员身份启动。</param> public static Process StartProcess(string path, string[] args, bool uac = false) { var merged = (args == null || args.Length < 1) ? "" : TextUtility.MergeProcessArgument(args); return StartProcess(path, merged, uac); } /// <summary>调用 System.Diagnostics.Process.Start 启动进程。</summary> /// <param name="path">程序路径。</param> /// <param name="args">参数。</param> /// <param name="uac">以管理员身份启动。</param> public static Process StartProcess(string path, string args = null, bool uac = false) { var psi = new ProcessStartInfo(); psi.FileName = path ?? ""; psi.Arguments = args ?? ""; if (uac) psi.Verb = "runas"; try { var process = Process.Start(psi); return process; } catch { return null; } } /// <summary>从 Win32 程序启动进程。</summary> /// <param name="path">程序路径。</param> /// <param name="args">参数。</param> public static bool StartNativeProcess(string path, string args = null) { if (string.IsNullOrEmpty(path)) return false; if (!File.Exists(path)) return false; try { var si = new StartupInfo(); var pi = new ProcessInformation(); var created = Kernel32.CreateProcess(path, args ?? "", IntPtr.Zero, IntPtr.Zero, false, 0, IntPtr.Zero, null, ref si, ref pi); return created; } catch { return false; } } /// <summary>结束当前进程。</summary> public static bool KillCurrentProcess() { #if NETFX || NETCORE Application.Exit(); #endif return KillProcess(Process.GetCurrentProcess()); } /// <summary>结束所有具有指定名称的进程。</summary> public static void KillProcesses(string name) { try { var processes = Process.GetProcessesByName(name); foreach (var process in processes) KillProcess(process); } catch { } } /// <summary>结束具有指定 PID 的进程。</summary> /// <param name="pid">PID。</param> public static bool KillProcess(int pid) { try { return KillProcess(Process.GetProcessById(pid)); } catch { return false; } } /// <summary>结束进程。</summary> public static bool KillProcess(Process process) { try { process.Kill(); return true; } catch { return false; } } /// <summary>查询指定的进程 ID 是否存在。</summary> /// <param name="pid">进程 ID。</param> public static bool ProcessIsAlive(int pid) { if (pid > 0) { int vhp = 0, vec = 0; vhp = Kernel32.OpenProcess(Constant.PROCESS_QUERY_INFORMATION, 0, pid); Kernel32.GetExitCodeProcess(vhp, out vec); Kernel32.CloseHandle(vhp); if (vec == Constant.STILL_ALIVE) return true; else return false; } return false; } #if NETFX || NETCORE /// <summary>当前程序名是否已经运行。</summary> public static bool ProcessPreviousis { get { var path = Application.ExecutablePath; var filename = Path.GetFileName(path); return !FirstProcess(filename); } } /// <summary>指定的进程名称是否为首次运行。</summary> /// <param name="name">进程名。</param> public static bool FirstProcess(string name) { bool ret = false; if (Kernel32.OpenMutex(0x1F0001, 0, name) == IntPtr.Zero) { Kernel32.CreateMutex(IntPtr.Zero, 0, name); ret = true; } return ret; } /// <summary>获取启动了应用程序的可执行文件的路径,不包括可执行文件的名称。</summary> public static string StartupPath { get { return Application.StartupPath; } } /// <summary>获取启动了应用程序的可执行文件的路径,包括可执行文件的名称。</summary> public static string ExecutablePath { get { return Application.ExecutablePath; } } #endif #endregion #region 控制台。 /// <summary>启动控制台进程,获取输出。</summary> public static string RunConsole(string cmd, string arg = null) { // var list = new List<string>(); var output = null as string; try { var startInfo = new ProcessStartInfo(); startInfo.FileName = cmd ?? ""; startInfo.Arguments = arg ?? ""; startInfo.UseShellExecute = false; // 必须禁用操作系统外壳程序。 startInfo.CreateNoWindow = true; startInfo.RedirectStandardOutput = true; // startInfo.RedirectStandardInput = true; // startInfo.RedirectStandardError = true; using (var process = Process.Start(startInfo)) { output = process.StandardOutput.ReadToEnd(); process.WaitForExit(); process.Close(); } } catch { } return output; } #endregion #region 硬件。 private static void ExitWindows(int flag) { bool ok; TokenPrivilege tp; IntPtr hproc = Kernel32.GetCurrentProcess(); IntPtr htok = IntPtr.Zero; ok = AdvApi32.OpenProcessToken(hproc, Constant.TOKEN_ADJUST_PRIVILEGES | Constant.TOKEN_QUERY, ref htok); tp.Count = 1; tp.Luid = 0; tp.Attr = Constant.SE_PRIVILEGE_ENABLED; ok = AdvApi32.LookupPrivilegeValueA(null, Constant.SE_SHUTDOWN_NAME, ref tp.Luid); ok = AdvApi32.AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero); ok = User32.ExitWindowsEx(flag, 0); } /// <summary>强制关机。</summary> public static void Shutdown() { ExitWindows(Constant.EWX_FORCE | Constant.EWX_POWEROFF); } /// <summary>强制重启。</summary> public static void Reboot() { ExitWindows(Constant.EWX_FORCE | Constant.EWX_REBOOT); } /// <summary>强制注销。</summary> public static void LogOff() { ExitWindows(Constant.EWX_FORCE | Constant.EWX_LOGOFF); } #if NETFX private static string GetHardwareInfomation(string device, string property) { var vmc = new ManagementClass(); var vmoc = vmc.GetInstances(); var vinfo = ""; foreach (var vmbo in vmoc) { if (!string.IsNullOrEmpty(property)) { var vvalue = ""; try { vvalue = vmbo.Properties[property].Value.ToString(); } catch { } vinfo += vvalue + ";"; } else { foreach (var vpd in vmbo.Properties) { var vvalue = ""; try { return vpd.Value.ToString(); } catch { } vinfo += vpd.Name + "=" + vvalue + ";"; } } } return vinfo; } /// <summary>获取处理器的信息。</summary> public static string GetProcessorInfomation() { return GetHardwareInfomation("win32_processor", "processorid"); } /// <summary>获取媒体介质的信息。</summary> public static string GetMediaDiskInfomation() { var vpm = GetHardwareInfomation("win32_physicalmedia", "serialnumber"); var vdd = GetHardwareInfomation("win32_diskdrive", "serialnumber"); return vpm + vdd; } /// <summary>获取主板的信息。</summary> public static string GetBaseBoardInfomation() { var vbb = GetHardwareInfomation("win32_baseboard", "serialnumber"); var vb = GetHardwareInfomation("win32_bios", "serialnumber"); return vbb + vb; } #endif #endregion #region 屏幕/桌面。 /// <summary>关闭屏幕。</summary> public static void CloseScreen() { User32.SendMessage(IntPtr.Zero, 274, 61808, 2); } /// <summary>获取系统支持的屏幕分辨率。</summary> public static List<System.Drawing.Size> GetAvailableScreenResolution() { var list = new List<System.Drawing.Size>(); int rc = -1; int mn = 0; while (rc != 0) { var dm = new DevMode(); rc = User32.EnumDisplaySettings(null, mn, ref dm); if (rc != 0) { var size = new System.Drawing.Size(dm.dmPelsHeight, dm.dmPelsWidth); var exist = false; foreach (var cell in list) { if ((size.Width == cell.Width) && (size.Height == cell.Height)) { exist = true; break; } } if (!exist) list.Add(size); mn += 1; } } return list; } /// <summary>设置屏幕分辨率。</summary> public static bool SetScreenResolution(System.Drawing.Size resolution) { if (resolution == null) return false; return SetScreenResolution(resolution.Width, resolution.Height, 0); } /// <summary>设置屏幕分辨率。</summary> public static bool SetScreenResolution(System.Drawing.Size resolution, short depth) { if (resolution == null) return false; return SetScreenResolution(resolution.Width, resolution.Height, depth); } /// <summary>设置屏幕分辨率。</summary> public static bool SetScreenResolution(int width, int height) { return SetScreenResolution(width, height, 0); } /// <summary>设置屏幕分辨率。</summary> public static bool SetScreenResolution(int width, int height, short depth) { if (width < 0) return false; if (height < 0) return false; if (depth < 0) return false; // 初始化 DEVMODE 结构。 var dm = new DevMode(); dm.dmDeviceName = new String(new char[32]); dm.dmFormName = new String(new char[32]); dm.dmSize = (short)Marshal.SizeOf(dm); var verify = User32.EnumDisplaySettings(null, Constant.ENUM_CURRENT_SETTINGS, ref dm); if (verify != 0) { dm.dmPelsWidth = width; dm.dmPelsHeight = height; //if (argDepth > 0) vdm.dmBitsPerPel = argDepth; // 改变分辨率。 int cds = User32.ChangeDisplaySettings(ref dm, Constant.CDS_TEST); if (cds == Constant.DISP_CHANGE_FAILED) return false; cds = User32.ChangeDisplaySettings(ref dm, Constant.CDS_UPDATEREGISTRY); switch (cds) { case Constant.DISP_CHANGE_SUCCESSFUL: return true; case Constant.DISP_CHANGE_RESTART: return true; default: return false; } } // 指定的分辨率不受支持。 return false; } private static void UnitiGoFullScreen() { const int GWL_STYLE = -16; const int WS_BORDER = 1; IntPtr i = User32.FindWindow("UnityWndClass", null); User32.SetWindowLong(i, GWL_STYLE, WS_BORDER); User32.ShowWindow(i, 1); } #endregion #region 鼠标指针。 /// <summary>移动鼠标指针。</summary> public static void MousePointerMove(int x, int y) { User32.mouse_Callback(MouseCallbackFlag.LeftDown, x, y, 0, UIntPtr.Zero); } /// <summary>按下鼠标左键。</summary> public static void MouseLeftDown(int x, int y) { User32.mouse_Callback(MouseCallbackFlag.LeftDown, x, y, 0, UIntPtr.Zero); } /// <summary>释放鼠标左键。</summary> public static void MouseLeftUp(int x, int y) { User32.mouse_Callback(MouseCallbackFlag.LeftUp, x, y, 0, UIntPtr.Zero); } /// <summary>按下鼠标中键。</summary> public static void MouseMiddleDown(int x, int y) { User32.mouse_Callback(MouseCallbackFlag.MiddleDown, x, y, 0, UIntPtr.Zero); } /// <summary>释放鼠标中键。</summary> public static void MouseMiddleUp(int x, int y) { User32.mouse_Callback(MouseCallbackFlag.MiddleUp, x, y, 0, UIntPtr.Zero); } /// <summary>按下鼠标右键。</summary> public static void MouseRightDown(int x, int y) { User32.mouse_Callback(MouseCallbackFlag.RightDown, x, y, 0, UIntPtr.Zero); } /// <summary>释放鼠标右键。</summary> public static void MouseRightUp(int x, int y) { User32.mouse_Callback(MouseCallbackFlag.RightUp, x, y, 0, UIntPtr.Zero); } #endregion #region 窗体控制。 /// <summary>获取指定窗体的句柄。</summary> /// <param name="title">窗体标题。</param> public static IntPtr GetWindowHandle(string title) { var handle = User32.FindWindow(null, title ?? ""); return handle; } private static List<IntPtr> WindowHandleList = null; private static bool EnumWindowsCallBack(int hwnd, int lparam) { WindowHandleList.Add(new IntPtr(hwnd)); return true; } /// <summary>获取所有窗体的句柄。</summary> /// <returns></returns> public static List<IntPtr> GetWindowHandle() { if (WindowHandleList != null) { WindowHandleList.Clear(); WindowHandleList = null; } WindowHandleList = new List<IntPtr>(); var callback = new EnumWindowsCallBack(EnumWindowsCallBack); var enumResult = User32.EnumWindows(callback, 0); return WindowHandleList; } /// <summary>获取指定窗体的标题。</summary> /// <param name="handle">窗体句柄。</param> public static string GetWindowTitle(IntPtr handle) { var sb = new StringBuilder(1024); var rc = User32.GetWindowTextW(handle, sb, sb.Capacity); var title = sb.ToString(); return title; } /// <summary>向指定窗体发送消息。</summary> public static void PostMessage(IntPtr argHandle, int argMessage) { if (argHandle != IntPtr.Zero) { User32.PostMessage(argHandle, argMessage, IntPtr.Zero, IntPtr.Zero); } } /// <summary>还原显示指定窗体,并设置焦点至该窗体。</summary> /// <param name="argHandle"></param> public static void RestoreWindow(IntPtr argHandle) { if (argHandle != IntPtr.Zero) { User32.ShowWindow(argHandle, Constant.SW_RESTORE); User32.SetForegroundWindow(argHandle); } } #endregion #region 注册表。 #if NETFX /// <summary>获取用于记录卸载信息的注册表路径。</summary> public static string[] GetUnInstallPath() { const string win32uninstall = "software\\microsoft\\windows\\currentversion\\uninstall"; const string wow64uninstall = "software\\wow6432node\\microsoft\\windows\\currentversion\\uninstall"; var vuninstallpath = new List<string>(); var vwin32rk = Registry.LocalMachine.OpenSubKey(win32uninstall); var vwin32skns = vwin32rk.GetSubKeyNames(); foreach (var i in vwin32skns) vuninstallpath.Add(win32uninstall + "\\" + i); vwin32rk.Close(); if (WindowsIsX64) { var vwow64rk = Registry.LocalMachine.OpenSubKey(wow64uninstall); var vwow64skns = vwow64rk.GetSubKeyNames(); foreach (var i in vwow64skns) vuninstallpath.Add(wow64uninstall + "\\" + i); vwow64rk.Close(); } return vuninstallpath.ToArray(); } #endif #endregion #region COM #if NETFX /// <summary>创建快捷方式。</summary> /// <param name="linkPath">快捷方式路径。</param> /// <param name="linkIcon">快捷方式图标。可使用 c:\source.exe,0 格式。</param> /// <param name="linkDescription">快捷方式说明。</param> /// <param name="sourcePath">源路径。</param> /// <param name="sourceArgs">源参数。</param> /// <param name="directory">工作目录。</param> public static void CreateShortcut(string linkPath, string sourcePath, string sourceArgs = null, string linkIcon = null, string linkDescription = null, string directory = null) { // var desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); // var shortcut = (IWshShortcut)new WshShellClass().CreateShortcut(linkPath); var wshShellClass = new IWshRuntimeLibrary.WshShellClass(); var wshObject = wshShellClass.CreateShortcut(linkPath); var wshShortcut = (IWshRuntimeLibrary.IWshShortcut)wshObject; var shortcut = wshShortcut; shortcut.TargetPath = sourcePath ?? ""; shortcut.Arguments = sourceArgs ?? "arg1"; shortcut.Description = linkDescription ?? "Invalid Description"; shortcut.WorkingDirectory = directory ?? ""; shortcut.IconLocation = linkIcon; shortcut.WindowStyle = 1; // shortcut.WorkingDirectory = ""; // shortcut.RelativePath = ""; shortcut.Save(); } #endif #endregion } }