You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
619 lines
21 KiB
619 lines
21 KiB
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
|
|
|
|
}
|
|
|
|
}
|
|
|