390 lines
16 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|