将Feature/XP.Common和Feature/XP.Hardware分支合并至Develop/XP.forHardwareAndCommon,完善XPapp注册和相关硬件类库通用类库功能。
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
namespace XP.Common.Dump.Configs
|
||||
{
|
||||
/// <summary>
|
||||
/// Dump 功能配置实体(从 App.config 读取)
|
||||
/// Dump feature configuration entity (loaded from App.config)
|
||||
/// </summary>
|
||||
public class DumpConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// Dump 文件存储路径 | Dump file storage path
|
||||
/// </summary>
|
||||
public string StoragePath { get; set; } = @"D:\XplorePlane\Dump";
|
||||
|
||||
/// <summary>
|
||||
/// 是否启用定时触发 | Enable scheduled trigger
|
||||
/// </summary>
|
||||
public bool EnableScheduledDump { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// 定时触发间隔(分钟)| Scheduled trigger interval (minutes)
|
||||
/// </summary>
|
||||
public int ScheduledIntervalMinutes { get; set; } = 60;
|
||||
|
||||
/// <summary>
|
||||
/// Mini Dump 文件大小上限(MB)| Mini Dump file size limit (MB)
|
||||
/// </summary>
|
||||
public long MiniDumpSizeLimitMB { get; set; } = 100;
|
||||
|
||||
/// <summary>
|
||||
/// 文件保留天数 | File retention days
|
||||
/// </summary>
|
||||
public int RetentionDays { get; set; } = 7;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
namespace XP.Common.Dump.Configs
|
||||
{
|
||||
/// <summary>
|
||||
/// Dump 触发类型 | Dump trigger type
|
||||
/// </summary>
|
||||
public enum DumpTriggerType
|
||||
{
|
||||
/// <summary>
|
||||
/// 崩溃触发 | Crash trigger
|
||||
/// </summary>
|
||||
Crash,
|
||||
|
||||
/// <summary>
|
||||
/// 定时触发 | Scheduled trigger
|
||||
/// </summary>
|
||||
Scheduled,
|
||||
|
||||
/// <summary>
|
||||
/// 手动触发 | Manual trigger
|
||||
/// </summary>
|
||||
Manual
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using XP.Common.Dump.Configs;
|
||||
using XP.Common.Logging.Interfaces;
|
||||
|
||||
namespace XP.Common.Dump.Implementations
|
||||
{
|
||||
/// <summary>
|
||||
/// Dump 文件自动清理组件,按保留天数策略删除过期文件
|
||||
/// Auto cleanup component for dump files, deletes expired files based on retention policy
|
||||
/// </summary>
|
||||
internal class DumpCleaner
|
||||
{
|
||||
private readonly DumpConfig _config;
|
||||
private readonly ILoggerService _logger;
|
||||
|
||||
public DumpCleaner(DumpConfig config, ILoggerService logger)
|
||||
{
|
||||
_config = config ?? throw new ArgumentNullException(nameof(config));
|
||||
_logger = logger?.ForModule<DumpCleaner>() ?? throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 执行清理操作:删除超过保留天数的 .dmp 文件
|
||||
/// Execute cleanup: delete .dmp files older than retention days
|
||||
/// </summary>
|
||||
public void CleanExpiredFiles()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(_config.StoragePath))
|
||||
{
|
||||
_logger.Debug("存储目录不存在,跳过清理:{Path} | Storage directory does not exist, skipping cleanup: {Path}", _config.StoragePath);
|
||||
return;
|
||||
}
|
||||
|
||||
var dmpFiles = Directory.GetFiles(_config.StoragePath, "*.dmp");
|
||||
var cutoffTime = DateTime.Now.AddDays(-_config.RetentionDays);
|
||||
var deletedCount = 0;
|
||||
|
||||
foreach (var filePath in dmpFiles)
|
||||
{
|
||||
try
|
||||
{
|
||||
var creationTime = File.GetCreationTime(filePath);
|
||||
if (creationTime < cutoffTime)
|
||||
{
|
||||
var fileName = Path.GetFileName(filePath);
|
||||
File.Delete(filePath);
|
||||
deletedCount++;
|
||||
_logger.Info("已删除过期 Dump 文件:{FileName} | Deleted expired dump file: {FileName}", fileName);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "删除 Dump 文件失败:{FilePath} | Failed to delete dump file: {FilePath}", filePath);
|
||||
}
|
||||
}
|
||||
|
||||
_logger.Info("Dump 清理完成,共删除 {Count} 个文件 | Dump cleanup completed, {Count} files deleted", deletedCount);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Dump 清理过程发生异常:{Message} | Dump cleanup error: {Message}", ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,321 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using XP.Common.Dump.Configs;
|
||||
using XP.Common.Dump.Interfaces;
|
||||
using XP.Common.Dump.Native;
|
||||
using XP.Common.Logging.Interfaces;
|
||||
|
||||
namespace XP.Common.Dump.Implementations
|
||||
{
|
||||
/// <summary>
|
||||
/// Dump 文件管理服务实现,负责 Dump 生成、崩溃事件订阅、定时调度和清理
|
||||
/// Dump file management service implementation, handles dump generation, crash event subscription, scheduled tasks and cleanup
|
||||
/// </summary>
|
||||
public class DumpService : IDumpService
|
||||
{
|
||||
private readonly DumpConfig _config;
|
||||
private readonly ILoggerService _logger;
|
||||
private readonly DumpCleaner _cleaner;
|
||||
private Timer? _scheduledTimer;
|
||||
private Timer? _cleanupTimer;
|
||||
private bool _isStarted;
|
||||
private bool _disposed;
|
||||
|
||||
/// <summary>
|
||||
/// 默认存储路径 | Default storage path
|
||||
/// </summary>
|
||||
private const string DefaultStoragePath = @"D:\XplorePlane\Dump";
|
||||
|
||||
public DumpService(DumpConfig config, ILoggerService logger)
|
||||
{
|
||||
_config = config ?? throw new ArgumentNullException(nameof(config));
|
||||
_logger = logger?.ForModule<DumpService>() ?? throw new ArgumentNullException(nameof(logger));
|
||||
_cleaner = new DumpCleaner(config, logger);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 生成 Dump 文件名(纯函数)| Generate dump file name (pure function)
|
||||
/// 格式:XplorePlane_{yyyyMMdd_HHmm}_{TriggerType}.dmp
|
||||
/// </summary>
|
||||
/// <param name="triggerType">触发类型 | Trigger type</param>
|
||||
/// <param name="timestamp">时间戳 | Timestamp</param>
|
||||
/// <returns>文件名 | File name</returns>
|
||||
internal static string GenerateFileName(DumpTriggerType triggerType, DateTime timestamp)
|
||||
{
|
||||
return $"XplorePlane_{timestamp:yyyyMMdd_HHmm}_{triggerType}.dmp";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证 Mini Dump 文件大小是否在限制范围内 | Validate Mini Dump file size is within limit
|
||||
/// </summary>
|
||||
/// <param name="fileSizeBytes">文件大小(字节)| File size in bytes</param>
|
||||
/// <param name="sizeLimitMB">大小限制(MB)| Size limit in MB</param>
|
||||
/// <returns>true 表示在限制内 | true if within limit</returns>
|
||||
internal static bool ValidateFileSize(long fileSizeBytes, long sizeLimitMB)
|
||||
{
|
||||
return fileSizeBytes <= sizeLimitMB * 1024 * 1024;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 写入 Dump 文件的核心方法 | Core method to write dump file
|
||||
/// </summary>
|
||||
/// <param name="triggerType">触发类型 | Trigger type</param>
|
||||
/// <param name="isMiniDump">是否为 Mini Dump | Whether it is a Mini Dump</param>
|
||||
/// <returns>生成的文件完整路径,失败返回 null | Full path of generated file, null on failure</returns>
|
||||
private string? WriteDump(DumpTriggerType triggerType, bool isMiniDump)
|
||||
{
|
||||
try
|
||||
{
|
||||
// 非手动触发请求 Full Dump 时,降级为 Mini Dump | Downgrade to Mini Dump for non-manual Full Dump requests
|
||||
if (!isMiniDump && triggerType != DumpTriggerType.Manual)
|
||||
{
|
||||
_logger.Warn("非手动触发不允许生成 Full Dump,已降级为 Mini Dump:{TriggerType} | Non-manual trigger cannot generate Full Dump, downgraded to Mini Dump: {TriggerType}", triggerType);
|
||||
isMiniDump = true;
|
||||
}
|
||||
|
||||
var fileName = GenerateFileName(triggerType, DateTime.Now);
|
||||
var filePath = Path.Combine(_config.StoragePath, fileName);
|
||||
|
||||
// 确定 Dump 类型标志 | Determine dump type flags
|
||||
uint dumpType = isMiniDump
|
||||
? (uint)(MiniDumpType.MiniDumpWithDataSegs | MiniDumpType.MiniDumpWithHandleData | MiniDumpType.MiniDumpWithThreadInfo)
|
||||
: (uint)MiniDumpType.MiniDumpWithFullMemory;
|
||||
|
||||
var process = Process.GetCurrentProcess();
|
||||
|
||||
using (var fileStream = new FileStream(filePath, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
|
||||
{
|
||||
bool success = NativeMethods.MiniDumpWriteDump(
|
||||
process.Handle,
|
||||
(uint)process.Id,
|
||||
fileStream.SafeFileHandle,
|
||||
dumpType,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
var errorCode = Marshal.GetLastWin32Error();
|
||||
_logger.Error(null!, "MiniDumpWriteDump 调用失败,错误码:{ErrorCode} | MiniDumpWriteDump failed, error code: {ErrorCode}", errorCode);
|
||||
// 清理失败的文件 | Clean up failed file
|
||||
try { File.Delete(filePath); } catch { }
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Mini Dump 文件大小检查 | Mini Dump file size check
|
||||
if (isMiniDump)
|
||||
{
|
||||
var fileInfo = new FileInfo(filePath);
|
||||
if (!ValidateFileSize(fileInfo.Length, _config.MiniDumpSizeLimitMB))
|
||||
{
|
||||
_logger.Warn("Mini Dump 文件超过大小限制({SizeMB}MB),已删除:{FilePath} | Mini Dump file exceeds size limit ({SizeMB}MB), deleted: {FilePath}",
|
||||
_config.MiniDumpSizeLimitMB, filePath);
|
||||
File.Delete(filePath);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
var dumpTypeStr = isMiniDump ? "Mini" : "Full";
|
||||
_logger.Info("Dump 文件已生成:{FilePath},触发类型:{TriggerType},Dump 类型:{DumpType} | Dump file generated: {FilePath}, trigger: {TriggerType}, type: {DumpType}",
|
||||
filePath, triggerType, dumpTypeStr);
|
||||
|
||||
return filePath;
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
_logger.Error(ex, "Dump 文件写入失败:{Message} | Dump file write failed: {Message}", ex.Message);
|
||||
return null;
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
_logger.Error(ex, "Dump 文件写入权限不足:{Message} | Dump file write permission denied: {Message}", ex.Message);
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Dump 文件生成异常:{Message} | Dump file generation error: {Message}", ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#region 手动触发方法 | Manual trigger methods
|
||||
|
||||
/// <inheritdoc />
|
||||
public string? CreateMiniDump()
|
||||
{
|
||||
_logger.Info("手动触发 Mini Dump 生成 | Manually triggering Mini Dump generation");
|
||||
var filePath = WriteDump(DumpTriggerType.Manual, isMiniDump: true);
|
||||
if (filePath != null)
|
||||
{
|
||||
_logger.Info("手动 Mini Dump 已生成:{FilePath} | Manual Mini Dump generated: {FilePath}", filePath);
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string? CreateFullDump()
|
||||
{
|
||||
_logger.Info("手动触发 Full Dump 生成 | Manually triggering Full Dump generation");
|
||||
var filePath = WriteDump(DumpTriggerType.Manual, isMiniDump: false);
|
||||
if (filePath != null)
|
||||
{
|
||||
_logger.Info("手动 Full Dump 已生成:{FilePath} | Manual Full Dump generated: {FilePath}", filePath);
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 生命周期管理 | Lifecycle management
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Start()
|
||||
{
|
||||
if (_isStarted) return;
|
||||
|
||||
_logger.Info("Dump 服务启动中 | Dump service starting");
|
||||
|
||||
// 确保存储目录存在 | Ensure storage directory exists
|
||||
EnsureStorageDirectory();
|
||||
|
||||
// 订阅崩溃事件 | Subscribe to crash events
|
||||
AppDomain.CurrentDomain.UnhandledException += OnUnhandledException;
|
||||
TaskScheduler.UnobservedTaskException += OnUnobservedTaskException;
|
||||
|
||||
// 启动定时 Dump 计时器 | Start scheduled dump timer
|
||||
if (_config.EnableScheduledDump)
|
||||
{
|
||||
var intervalMs = _config.ScheduledIntervalMinutes * 60 * 1000;
|
||||
_scheduledTimer = new Timer(OnScheduledDumpCallback, null, intervalMs, intervalMs);
|
||||
_logger.Info("定时 Dump 已启用,间隔:{Interval} 分钟 | Scheduled dump enabled, interval: {Interval} minutes", _config.ScheduledIntervalMinutes);
|
||||
}
|
||||
|
||||
// 启动每日清理计时器(每24小时执行一次)| Start daily cleanup timer (every 24 hours)
|
||||
var dailyMs = 24 * 60 * 60 * 1000;
|
||||
_cleanupTimer = new Timer(OnCleanupCallback, null, dailyMs, dailyMs);
|
||||
|
||||
// 立即执行一次清理 | Execute cleanup immediately
|
||||
_cleaner.CleanExpiredFiles();
|
||||
|
||||
_isStarted = true;
|
||||
_logger.Info("Dump 服务已启动 | Dump service started");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Stop()
|
||||
{
|
||||
if (!_isStarted) return;
|
||||
|
||||
_logger.Info("Dump 服务停止中 | Dump service stopping");
|
||||
|
||||
// 取消事件订阅 | Unsubscribe from events
|
||||
AppDomain.CurrentDomain.UnhandledException -= OnUnhandledException;
|
||||
TaskScheduler.UnobservedTaskException -= OnUnobservedTaskException;
|
||||
|
||||
// 停止所有计时器 | Stop all timers
|
||||
_scheduledTimer?.Change(Timeout.Infinite, Timeout.Infinite);
|
||||
_cleanupTimer?.Change(Timeout.Infinite, Timeout.Infinite);
|
||||
|
||||
_isStarted = false;
|
||||
_logger.Info("Dump 服务已停止 | Dump service stopped");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) return;
|
||||
|
||||
Stop();
|
||||
|
||||
_scheduledTimer?.Dispose();
|
||||
_scheduledTimer = null;
|
||||
|
||||
_cleanupTimer?.Dispose();
|
||||
_cleanupTimer = null;
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 内部方法 | Internal methods
|
||||
|
||||
/// <summary>
|
||||
/// 确保存储目录存在,不存在则创建,创建失败回退默认路径
|
||||
/// Ensure storage directory exists, create if not, fallback to default on failure
|
||||
/// </summary>
|
||||
private void EnsureStorageDirectory()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(_config.StoragePath))
|
||||
{
|
||||
Directory.CreateDirectory(_config.StoragePath);
|
||||
_logger.Info("已创建存储目录:{Path} | Created storage directory: {Path}", _config.StoragePath);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "存储目录创建失败:{Path},回退到默认路径 | Storage directory creation failed: {Path}, falling back to default", _config.StoragePath);
|
||||
_config.StoragePath = DefaultStoragePath;
|
||||
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(DefaultStoragePath))
|
||||
{
|
||||
Directory.CreateDirectory(DefaultStoragePath);
|
||||
_logger.Info("已创建默认存储目录:{Path} | Created default storage directory: {Path}", DefaultStoragePath);
|
||||
}
|
||||
}
|
||||
catch (Exception fallbackEx)
|
||||
{
|
||||
_logger.Fatal(fallbackEx, "默认存储目录创建也失败:{Path} | Default storage directory creation also failed: {Path}", DefaultStoragePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 未处理异常回调 | Unhandled exception callback
|
||||
/// </summary>
|
||||
private void OnUnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||||
{
|
||||
_logger.Info("检测到未处理异常,正在生成崩溃 Dump | Unhandled exception detected, generating crash dump");
|
||||
WriteDump(DumpTriggerType.Crash, isMiniDump: true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 未观察到的 Task 异常回调 | Unobserved task exception callback
|
||||
/// </summary>
|
||||
private void OnUnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)
|
||||
{
|
||||
_logger.Info("检测到未观察的 Task 异常,正在生成崩溃 Dump | Unobserved task exception detected, generating crash dump");
|
||||
WriteDump(DumpTriggerType.Crash, isMiniDump: true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 定时 Dump 回调 | Scheduled dump callback
|
||||
/// </summary>
|
||||
private void OnScheduledDumpCallback(object? state)
|
||||
{
|
||||
_logger.Debug("定时 Dump 触发 | Scheduled dump triggered");
|
||||
WriteDump(DumpTriggerType.Scheduled, isMiniDump: true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清理回调 | Cleanup callback
|
||||
/// </summary>
|
||||
private void OnCleanupCallback(object? state)
|
||||
{
|
||||
_logger.Debug("定时清理触发 | Scheduled cleanup triggered");
|
||||
_cleaner.CleanExpiredFiles();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
|
||||
namespace XP.Common.Dump.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Dump 文件管理服务接口 | Dump file management service interface
|
||||
/// </summary>
|
||||
public interface IDumpService : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// 手动触发 Mini Dump 生成 | Manually trigger Mini Dump generation
|
||||
/// </summary>
|
||||
/// <returns>生成的 Dump 文件完整路径,失败返回 null | Full path of generated dump file, null on failure</returns>
|
||||
string? CreateMiniDump();
|
||||
|
||||
/// <summary>
|
||||
/// 手动触发 Full Dump 生成 | Manually trigger Full Dump generation
|
||||
/// </summary>
|
||||
/// <returns>生成的 Dump 文件完整路径,失败返回 null | Full path of generated dump file, null on failure</returns>
|
||||
string? CreateFullDump();
|
||||
|
||||
/// <summary>
|
||||
/// 启动服务(订阅崩溃事件、启动定时任务和清理任务)| Start service (subscribe crash events, start scheduled and cleanup tasks)
|
||||
/// </summary>
|
||||
void Start();
|
||||
|
||||
/// <summary>
|
||||
/// 停止服务(取消定时任务、取消事件订阅)| Stop service (cancel scheduled tasks, unsubscribe events)
|
||||
/// </summary>
|
||||
void Stop();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
|
||||
namespace XP.Common.Dump.Native
|
||||
{
|
||||
/// <summary>
|
||||
/// MiniDump 类型标志,用于 MiniDumpWriteDump 的 dumpType 参数
|
||||
/// MiniDump type flags for MiniDumpWriteDump dumpType parameter
|
||||
/// </summary>
|
||||
[Flags]
|
||||
internal enum MiniDumpType : uint
|
||||
{
|
||||
/// <summary>
|
||||
/// 仅包含基本信息 | Basic information only
|
||||
/// </summary>
|
||||
MiniDumpNormal = 0x00000000,
|
||||
|
||||
/// <summary>
|
||||
/// 包含数据段信息 | Include data segment information
|
||||
/// </summary>
|
||||
MiniDumpWithDataSegs = 0x00000001,
|
||||
|
||||
/// <summary>
|
||||
/// 包含完整内存信息(Full Dump 使用)| Include full memory (used for Full Dump)
|
||||
/// </summary>
|
||||
MiniDumpWithFullMemory = 0x00000002,
|
||||
|
||||
/// <summary>
|
||||
/// 包含句柄信息 | Include handle information
|
||||
/// </summary>
|
||||
MiniDumpWithHandleData = 0x00000004,
|
||||
|
||||
/// <summary>
|
||||
/// 包含线程信息 | Include thread information
|
||||
/// </summary>
|
||||
MiniDumpWithThreadInfo = 0x00001000,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
|
||||
namespace XP.Common.Dump.Native
|
||||
{
|
||||
/// <summary>
|
||||
/// Windows 原生方法 P/Invoke 声明 | Windows native method P/Invoke declarations
|
||||
/// </summary>
|
||||
internal static class NativeMethods
|
||||
{
|
||||
/// <summary>
|
||||
/// 将进程的 Mini Dump 写入指定文件 | Write a Mini Dump of the process to the specified file
|
||||
/// </summary>
|
||||
[DllImport("dbghelp.dll", SetLastError = true)]
|
||||
internal static extern bool MiniDumpWriteDump(
|
||||
IntPtr hProcess,
|
||||
uint processId,
|
||||
SafeHandle hFile,
|
||||
uint dumpType,
|
||||
IntPtr exceptionParam,
|
||||
IntPtr userStreamParam,
|
||||
IntPtr callbackParam);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user