Files
2026-07-02 10:11:39 +00:00

390 lines
16 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace Lskj.Util
{
public enum ShowWindowCommands : int
{
SW_HIDE = 0,
SW_SHOWNORMAL = 1, //用最近的大小和位置显示,激活
SW_NORMAL = 1,
SW_SHOWMINIMIZED = 2,
SW_SHOWMAXIMIZED = 3,
SW_MAXIMIZE = 3,
SW_SHOWNOACTIVATE = 4,
SW_SHOW = 5,
SW_MINIMIZE = 6,
SW_SHOWMINNOACTIVE = 7,
SW_SHOWNA = 8,
SW_RESTORE = 9,
SW_SHOWDEFAULT = 10,
SW_MAX = 10
}
public class NativeMethods
{
[DllImport("user32.dll")]
public static extern IntPtr EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i);
public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);
}
/// <summary>
/// 句柄操作静态类
/// </summary>
public static class HandleHelper
{
const int GWL_STYLE = -16;
const int WS_BORDER = 0x00800000;
const int WS_DLGFRAME = 0x00400000;
const int WS_CAPTION = WS_BORDER | WS_DLGFRAME;
const int WS_THICKFRAME = 0x00040000;
const int WS_MINIMIZE = 0x20000000;
const int WS_MAXIMIZEBOX = 0x00010000;
const int WS_SYSMENU = 0x00080000;
const uint SWP_NOMOVE = 0x0002;
const uint SWP_NOSIZE = 0x0001;
const uint SWP_NOZORDER = 0x0004;
const uint SWP_FRAMECHANGED = 0x0020;
const int SW_HIDE = 0;
const int SW_SHOW = 5;
[DllImport("user32.dll")]
public static extern int GetDpiForWindow(IntPtr hwnd);
[DllImport("shell32.dll")]
public static extern IntPtr ShellExecute(IntPtr hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, ShowWindowCommands nShowCmd);
[DllImport("user32.dll", EntryPoint = "SendMessageA")]
public static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
[DllImport("user32.dll")]
public static extern IntPtr EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr i);
public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);
[DllImport("user32.dll")]
public static extern int EnumThreadWindows(int dwThreadId, WndEnumProc lpfn, int lParam);
[DllImport("user32.dll")]
public static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("shell32.dll")]
public static extern int FindExecutable(string lpFile, string lpDirectory, [Out] StringBuilder lpResult);
[DllImport("User32.dll", EntryPoint = "SetParent")]
public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll", EntryPoint = "ShowWindow")]
public static extern int ShowWindow(IntPtr hwnd, int nCmdShow);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool MoveWindow(IntPtr hwnd, int x, int y, int cx, int cy, bool repaint);
[DllImport("user32.dll")]
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
[DllImport("user32.dll")]
public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
[DllImport("user32.dll")]
public static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", EntryPoint = "SetWindowLong", CharSet = CharSet.Auto)]
public static extern IntPtr SetWindowLongPtr32(HandleRef hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", CharSet = CharSet.Auto)]
public static extern IntPtr SetWindowLongPtr64(HandleRef hWnd, int nIndex, int dwNewLong);
public static IntPtr SetWindowLong(HandleRef hWnd, int nIndex, int dwNewLong)
{
if (IntPtr.Size == 4)
{
return SetWindowLongPtr32(hWnd, nIndex, dwNewLong);
}
return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
}
/// <summary>
/// 枚举窗口时的委托参数
/// </summary>
/// <param name="hWnd"></param>
/// <param name="lParam"></param>
/// <returns></returns>
public delegate bool WndEnumProc(IntPtr hWnd, int lParam);
/// <summary>
/// 枚举所有窗口
/// </summary>
/// <param name="lpEnumFunc"></param>
/// <param name="lParam"></param>
/// <returns></returns>
[DllImport("user32")]
public static extern bool EnumWindows(WndEnumProc lpEnumFunc, int lParam);
/// <summary>
/// 获取窗口的父窗口句柄
/// </summary>
/// <param name="hWnd"></param>
/// <returns></returns>
[DllImport("user32.dll", EntryPoint = "GetParent", SetLastError = true)]
public static extern IntPtr GetParent(IntPtr hWnd);
[DllImport("user32")]
public static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32")]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lptrString, int nMaxCount);
[DllImport("user32")]
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32")]
public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);
[DllImport("user32")]
public static extern bool GetWindowRect(IntPtr hWnd, ref LPRECT rect);
[StructLayout(LayoutKind.Sequential)]
public readonly struct LPRECT
{
public readonly int Left;
public readonly int Top;
public readonly int Right;
public readonly int Bottom;
}
public static bool EnumWindow(IntPtr hWnd, IntPtr parameter)
{
GCHandle gch = GCHandle.FromIntPtr(parameter);
var list = gch.Target as List<IntPtr>;
if (list == null)
{
throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
}
list.Add(hWnd);
return true;
}
/// <summary>
/// 窗体列表
/// </summary>
public static List<WindowInfo> windowList;
/// <summary>
/// 获取 Win32 窗口的一些基本信息。
/// </summary>
public struct WindowInfo
{
public IntPtr Hwnd { get; }
public string ClassName { get; }
public string Title { get; }
public bool IsVisible { get; }
public Rectangle Bounds { get; }
public bool IsMinimized => Bounds.Left == -32000 && Bounds.Top == -32000;
public WindowInfo(IntPtr hWnd, string className, string title, bool isVisible, Rectangle bounds) : this()
{
Hwnd = hWnd;
ClassName = className;
Title = title;
IsVisible = isVisible;
Bounds = bounds;
}
}
/// <summary>
/// 重置位置
/// </summary>
/// <param name="exeMainHandle"></param>
/// <param name="control"></param>
public static void ResizeEmbeddedWindow(IntPtr exeMainHandle, System.Windows.Forms.Control control)
{
if (exeMainHandle == IntPtr.Zero)
return;
//SetWindowPos(exeMainHandle, IntPtr.Zero, 0, 0, control.Width, control.Height, SWP_NOZORDER);
MoveWindow(exeMainHandle, 0, 0, control.Width, control.Height, false);
}
/// <summary>
/// 把 string[] 类型的参数数组转换为单个命令行字符串,自动添加引号并转义
/// </summary>
public static string CombineArgs(string[] args)
{
if (args == null || args.Length == 0)
return string.Empty;
// 简单处理:遇到有空格或特殊符号,加双引号包裹
// 并转义内部双引号
var combined = new System.Text.StringBuilder();
foreach (var arg in args)
{
if (string.IsNullOrWhiteSpace(arg))
{
combined.Append("\"\"");
}
else if (arg.Contains(" ") || arg.Contains("\""))
{
string escaped = arg.Replace("\"", "\\\"");
combined.Append("\"").Append(escaped).Append("\"");
}
else
{
combined.Append(arg);
}
combined.Append(" ");
}
return combined.ToString().TrimEnd();
}
/// <summary>
/// 遍历窗口并查找窗口相关WindowInfo信息
/// </summary>
/// <param name="match"></param>
/// <returns></returns>
public static List<WindowInfo> FindAllWindows(Predicate<WindowInfo> match = null)
{
windowList = new List<WindowInfo>();
EnumWindows(OnWindowEnum, 0);
return windowList.FindAll(match ?? DefaultPredicate);
}
public static bool OnWindowEnum(IntPtr hWnd, int lparam)
{
// 仅查找顶层窗口。
if (GetParent(hWnd) == IntPtr.Zero)
{
// 获取窗口类名。
var lpString = new StringBuilder(512);
GetClassName(hWnd, lpString, lpString.Capacity);
var className = lpString.ToString();
// 获取窗口标题。
var lptrString = new StringBuilder(512);
GetWindowText(hWnd, lptrString, lptrString.Capacity);
var title = lptrString.ToString().Trim();
// 获取窗口可见性。
var isVisible = IsWindowVisible(hWnd);
// 获取窗口位置和尺寸。
LPRECT rect = default;
GetWindowRect(hWnd, ref rect);
var bounds = new Rectangle(rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top);
// 添加到已找到的窗口列表。
windowList.Add(new WindowInfo(hWnd, className, title, isVisible, bounds));
}
return true;
}
/// <summary>
/// 设置一个进程为无边框并且嵌入到指定的控件中
/// </summary>
/// <param name="exeMainHandle"></param>
public static void SetFormNoneStyle(IntPtr exeMainHandle, System.Windows.Forms.Control control)
{
// 将exe窗口设置为panel的子窗口
SetParent(exeMainHandle, control.Handle);
// 调整大小填充panel
ResizeEmbeddedWindow(exeMainHandle, control);
// 自动响应panel大小变化调整嵌入窗口大小
control.Resize += (s, e) =>
{
ResizeEmbeddedWindow(exeMainHandle, control);
};
}
public static readonly Predicate<WindowInfo> DefaultPredicate = x => x.IsVisible && !x.IsMinimized && x.Title.Length > 0;
}
public class JobControl
{
public enum JobObjectInfoType
{
AssociateCompletionPortInformation = 7,
BasicLimitInformation = 2,
BasicUIRestrictions = 4,
EndOfJobTimeInformation = 6,
ExtendedLimitInformation = 9,
SecurityLimitInformation = 5,
GroupInformation = 11
}
[StructLayout(LayoutKind.Sequential)]
public struct SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr lpSecurityDescriptor;
public int bInheritHandle;
}
[StructLayout(LayoutKind.Sequential)]
struct JOBOBJECT_BASIC_LIMIT_INFORMATION
{
public Int64 PerProcessUserTimeLimit;
public Int64 PerJobUserTimeLimit;
public Int16 LimitFlags;
public UInt32 MinimumWorkingSetSize;
public UInt32 MaximumWorkingSetSize;
public Int16 ActiveProcessLimit;
public Int64 Affinity;
public Int16 PriorityClass;
public Int16 SchedulingClass;
}
[StructLayout(LayoutKind.Sequential)]
struct IO_COUNTERS
{
public UInt64 ReadOperationCount;
public UInt64 WriteOperationCount;
public UInt64 OtherOperationCount;
public UInt64 ReadTransferCount;
public UInt64 WriteTransferCount;
public UInt64 OtherTransferCount;
}
[StructLayout(LayoutKind.Sequential)]
struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
{
public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
public IO_COUNTERS IoInfo;
public UInt32 ProcessMemoryLimit;
public UInt32 JobMemoryLimit;
public UInt32 PeakProcessMemoryUsed;
public UInt32 PeakJobMemoryUsed;
}
/// <summary>
/// 创建作业对象
/// </summary>
/// <param name="lpJobAttributes">该作业的安全描述符</param>
/// <param name="name">作业名字</param>
/// <returns></returns>
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
static extern IntPtr CreateJobObject(IntPtr lpJobAttributes, string name);
/// <summary>
/// 将进程注册为作业对象进程
/// </summary>
/// <param name="job">作业对象句柄</param>
/// <param name="process">进程句柄</param>
/// <returns></returns>
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process);
/// <summary>
/// 设置作业对象限制
/// </summary>
/// <param name="hJob">标识要限制的作业 </param>
/// <param name="infoType">枚举类型,用于指明要使用的限制类型</param>
/// <param name="lpJobObjectInfo">包含限制设置值的数据结构的地址</param>
/// <param name="cbJobObjectInfoLength">指明第三个参数的大小</param>
/// <returns></returns>
[DllImport("kernel32.dll")]
static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, uint cbJobObjectInfoLength);
const System.String job_name = "Leventure_SeatJob";
private System.UInt32 job_ptr = 0;
private System.IntPtr job_handle = System.IntPtr.Zero;
/// <summary>
/// 构造函数,声明作业对象,限制作业对象。
/// </summary>
public JobControl()
{
job_handle = CreateJobObject(System.IntPtr.Zero, job_name);
JOBOBJECT_BASIC_LIMIT_INFORMATION info = new JOBOBJECT_BASIC_LIMIT_INFORMATION();
info.LimitFlags = 0x2000;
JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION();
extendedInfo.BasicLimitInformation = info;
//Design by LeventureQys
int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length);
Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);
if (!SetInformationJobObject(job_handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length))
throw new Exception(string.Format("Unable to set information. Error: {0}", Marshal.GetLastWin32Error()));
}
/// <summary>
/// 为该dll注册子进程,当主程序崩溃的时候,子进程一样退出
/// </summary>
/// <param name="added_process"></param>
/// <returns></returns>
public bool AddProcess(IntPtr intPtr)
{
System.IntPtr handle = System.IntPtr.Zero;
handle = intPtr;
return AssignProcessToJobObject(job_handle, handle);
}
}
}