添加项目文件。
This commit is contained in:
32
Common/Attributes/ADPCommandAttribute.cs
Normal file
32
Common/Attributes/ADPCommandAttribute.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Common.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// 标记可加载到指令集中的类或方法
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
|
||||
public sealed class ADPCommandAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// 指令描述(用于工具提示)
|
||||
/// </summary>
|
||||
public string Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 指令分类(用于树形视图分组)
|
||||
/// </summary>
|
||||
public string Category { get; set; } = "默认分类";
|
||||
|
||||
public ADPCommandAttribute() { }
|
||||
|
||||
public ADPCommandAttribute(string description)
|
||||
{
|
||||
Description = description;
|
||||
}
|
||||
}
|
||||
}
|
||||
15
Common/Common.csproj
Normal file
15
Common/Common.csproj
Normal file
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ncalc" Version="1.3.8" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.5-beta1" />
|
||||
<PackageReference Include="System.IO.Ports" Version="11.0.0-preview.4.26230.115" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
112
Common/MiniDump.cs
Normal file
112
Common/MiniDump.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Common
|
||||
{
|
||||
public static class MiniDump
|
||||
{
|
||||
[Flags]
|
||||
public enum Option : uint
|
||||
{
|
||||
Normal = 0x00000000,
|
||||
WithDataSegs = 0x00000001,
|
||||
WithFullMemory = 0x00000002,
|
||||
WithHandleData = 0x00000004,
|
||||
FilterMemory = 0x00000008,
|
||||
ScanMemory = 0x00000010,
|
||||
WithUnloadedModules = 0x00000020,
|
||||
WithIndirectlyReferencedMemory = 0x00000040,
|
||||
FilterModulePaths = 0x00000080,
|
||||
WithProcessThreadData = 0x00000100,
|
||||
WithPrivateReadWriteMemory = 0x00000200,
|
||||
WithoutOptionalData = 0x00000400,
|
||||
WithFullMemoryInfo = 0x00000800,
|
||||
WithThreadInfo = 0x00001000,
|
||||
WithCodeSegs = 0x00002000,
|
||||
WithoutAuxiliaryState = 0x00004000,
|
||||
WithFullAuxiliaryState = 0x00008000,
|
||||
WithPrivateWriteCopyMemory = 0x00010000,
|
||||
IgnoreInaccessibleMemory = 0x00020000,
|
||||
ValidTypeFlags = 0x0003ffff,
|
||||
}
|
||||
|
||||
enum ExceptionInfo
|
||||
{
|
||||
None,
|
||||
Present
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4)] // Pack=4 is important! So it works also for x64!
|
||||
struct MiniDumpExceptionInformation
|
||||
{
|
||||
public uint ThreadId;
|
||||
public IntPtr ExceptionPointers;
|
||||
[MarshalAs(UnmanagedType.Bool)]
|
||||
public bool ClientPointers;
|
||||
}
|
||||
|
||||
// MiniDumpWriteDump function declarations
|
||||
[DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
|
||||
static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, ref MiniDumpExceptionInformation expParam, IntPtr userStreamParam, IntPtr callbackParam);
|
||||
|
||||
[DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
|
||||
static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, IntPtr expParam, IntPtr userStreamParam, IntPtr callbackParam);
|
||||
|
||||
[DllImport("kernel32.dll", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)]
|
||||
static extern uint GetCurrentThreadId();
|
||||
|
||||
static bool Write(SafeHandle fileHandle, Option options, ExceptionInfo exceptionInfo, Exception exception = null)
|
||||
{
|
||||
Process currentProcess = Process.GetCurrentProcess();
|
||||
IntPtr currentProcessHandle = currentProcess.Handle;
|
||||
uint currentProcessId = (uint)currentProcess.Id;
|
||||
|
||||
MiniDumpExceptionInformation exp;
|
||||
exp.ThreadId = GetCurrentThreadId();
|
||||
exp.ClientPointers = false;
|
||||
exp.ExceptionPointers = IntPtr.Zero;
|
||||
|
||||
if (exceptionInfo == ExceptionInfo.Present && exception != null)
|
||||
{
|
||||
// Get exception pointers
|
||||
exp.ExceptionPointers = Marshal.GetExceptionPointers();
|
||||
}
|
||||
|
||||
// Write dump
|
||||
bool result = exp.ExceptionPointers == IntPtr.Zero
|
||||
? MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint)options, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero)
|
||||
: MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint)options, ref exp, IntPtr.Zero, IntPtr.Zero);
|
||||
|
||||
if (exception != null)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static Boolean TryDump(String dmpPath, Option dmpType = Option.Normal, Exception exception = null)
|
||||
{
|
||||
var path = Path.Combine(Environment.CurrentDirectory, dmpPath);
|
||||
var dir = Path.GetDirectoryName(path);
|
||||
if (dir != null && !Directory.Exists(dir))
|
||||
{
|
||||
Directory.CreateDirectory(dir);
|
||||
}
|
||||
|
||||
using (var fs = new FileStream(path, FileMode.Create))
|
||||
{
|
||||
return Write(fs.SafeFileHandle, dmpType, exception == null ? ExceptionInfo.None : ExceptionInfo.Present, exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
104
Common/Tool/ExpressionEvaluator.cs
Normal file
104
Common/Tool/ExpressionEvaluator.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using NCalc;
|
||||
|
||||
namespace Common.Tools
|
||||
{
|
||||
public class ExpressionEvaluator
|
||||
{
|
||||
public static bool EvaluateExpression(string expression, Dictionary<string, object>? variables = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 预处理:替换中文变量名为英文别名
|
||||
var (processedExpression, processedVariables) = PreprocessExpression(expression, variables);
|
||||
|
||||
var expr = new Expression(processedExpression, EvaluateOptions.IgnoreCase);
|
||||
|
||||
if (processedVariables != null)
|
||||
{
|
||||
foreach (var kvp in processedVariables)
|
||||
{
|
||||
expr.Parameters[kvp.Key] = kvp.Value;
|
||||
}
|
||||
}
|
||||
|
||||
if (expr.HasErrors())
|
||||
{
|
||||
throw new ArgumentException($"条件表达式格式错误: {expr.Error}");
|
||||
}
|
||||
|
||||
var result = expr.Evaluate();
|
||||
return Convert.ToBoolean(result);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new ArgumentException($"条件表达式异常: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private static (string, Dictionary<string, object>) PreprocessExpression(
|
||||
string expression,
|
||||
Dictionary<string, object>? variables)
|
||||
{
|
||||
if (variables == null || variables.Count == 0)
|
||||
return (expression, variables ?? new Dictionary<string, object>());
|
||||
|
||||
// 生成变量名映射 (中文 -> 英文别名)
|
||||
var chineseToAlias = new Dictionary<string, string>();
|
||||
var aliasToValue = new Dictionary<string, object>();
|
||||
int counter = 1;
|
||||
|
||||
foreach (var key in variables.Keys)
|
||||
{
|
||||
if (ContainsChinese(key))
|
||||
{
|
||||
string alias = $"var_{counter}";
|
||||
counter++;
|
||||
chineseToAlias[key] = alias;
|
||||
aliasToValue[alias] = variables[key];
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有中文变量名,直接返回原始数据
|
||||
if (chineseToAlias.Count == 0)
|
||||
return (expression, variables);
|
||||
|
||||
// 替换表达式中的中文变量名
|
||||
string processedExpression = expression;
|
||||
foreach (var pair in chineseToAlias)
|
||||
{
|
||||
// 使用正则确保完整匹配变量名
|
||||
string pattern = $@"\b{Regex.Escape(pair.Key)}\b";
|
||||
processedExpression = Regex.Replace(
|
||||
processedExpression,
|
||||
pattern,
|
||||
pair.Value,
|
||||
RegexOptions.Compiled
|
||||
);
|
||||
}
|
||||
|
||||
// 创建新变量字典(英文别名 + 原始英文变量)
|
||||
var newVariables = new Dictionary<string, object>(aliasToValue);
|
||||
foreach (var key in variables.Keys)
|
||||
{
|
||||
if (!ContainsChinese(key))
|
||||
{
|
||||
newVariables[key] = variables[key];
|
||||
}
|
||||
}
|
||||
|
||||
return (processedExpression, newVariables);
|
||||
}
|
||||
|
||||
// 检查字符串是否包含中文字符
|
||||
private static bool ContainsChinese(string text)
|
||||
{
|
||||
return text.Any(c => c >= 0x4E00 && c <= 0x9FFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user