C# 中的 LoadLibrary 使用 GetErrorLast 显示烦人的错误对话框
LoadLibrary in C# shows annoying error dialog using GetErrorLast
我有一个小项目,我想在其中批量加载注册表中引用的一些库以读取一些资源。我在加载库 C:\Windows\System32\mmsys.cpl 时卡住了,它似乎有错误。错误本身不是问题,但我想防止显示任何本机错误对话框。我只想将本机代码中的异常重定向到托管代码的异常。我已经使用 .Net Framework 4.8 和 .Net Core 3.1 以及 Kernel32 中的 LoadLibrary 和 LoadLibraryEx 对此进行了测试,但没有成功。我测试了其他 *.cpl 库,它们加载正常。
预计:
加载此库导致托管代码中抛出异常 - 未显示错误对话框。
实际:
加载这个库会显示这个恼人的对话框,并在托管代码中抛出异常。
[System.Runtime.InteropServices.DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)]
private static extern System.IntPtr LoadLibrary(string lpFileName);
private static void Main(string[] args)
{
var resource = @"C:\Windows\System32\mmsys.cpl";
// var resource = @"C:\Windows\System32\timedate.cpl";
var lib = LoadLibrary(resource);
if (lib == System.IntPtr.Zero)
{
var errorCode = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
throw new System.SystemException($"System failed to load library '{resource}' with error {errorCode}");
}
}
错误对话框:
更新:
这段代码现在对我有用:
[System.Runtime.InteropServices.DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)]
private static extern System.IntPtr LoadLibrary(string lpFileName);
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern ErrorModes SetErrorMode(ErrorModes uMode);
[System.Flags]
public enum ErrorModes : uint
{
SYSTEM_DEFAULT = 0x0,
SEM_FAILCRITICALERRORS = 0x0001,
SEM_NOALIGNMENTFAULTEXCEPT = 0x0004,
SEM_NOGPFAULTERRORBOX = 0x0002,
SEM_NOOPENFILEERRORBOX = 0x8000
}
private static void Main(string[] args)
{
SetErrorMode(ErrorModes.SEM_FAILCRITICALERRORS);
var resource = @"C:\Windows\System32\mmsys.cpl";
// var resource = @"C:\Windows\System32\timedate.cpl";
var lib = LoadLibrary(resource);
if (lib == System.IntPtr.Zero)
{
var errorCode = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
throw new System.SystemException($"System failed to load library '{resource}' with error {errorCode}");
}
}
您需要先用 SEM_NOOPENFILEERRORBOX (0x8000) 调用 SetErrorMode。
详见documentation中的备注部分:
To enable or disable error messages displayed by the loader during DLL loads, use the SetErrorMode function.
我有一个小项目,我想在其中批量加载注册表中引用的一些库以读取一些资源。我在加载库 C:\Windows\System32\mmsys.cpl 时卡住了,它似乎有错误。错误本身不是问题,但我想防止显示任何本机错误对话框。我只想将本机代码中的异常重定向到托管代码的异常。我已经使用 .Net Framework 4.8 和 .Net Core 3.1 以及 Kernel32 中的 LoadLibrary 和 LoadLibraryEx 对此进行了测试,但没有成功。我测试了其他 *.cpl 库,它们加载正常。
预计: 加载此库导致托管代码中抛出异常 - 未显示错误对话框。
实际: 加载这个库会显示这个恼人的对话框,并在托管代码中抛出异常。
[System.Runtime.InteropServices.DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)]
private static extern System.IntPtr LoadLibrary(string lpFileName);
private static void Main(string[] args)
{
var resource = @"C:\Windows\System32\mmsys.cpl";
// var resource = @"C:\Windows\System32\timedate.cpl";
var lib = LoadLibrary(resource);
if (lib == System.IntPtr.Zero)
{
var errorCode = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
throw new System.SystemException($"System failed to load library '{resource}' with error {errorCode}");
}
}
错误对话框:
更新:
这段代码现在对我有用:
[System.Runtime.InteropServices.DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)]
private static extern System.IntPtr LoadLibrary(string lpFileName);
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern ErrorModes SetErrorMode(ErrorModes uMode);
[System.Flags]
public enum ErrorModes : uint
{
SYSTEM_DEFAULT = 0x0,
SEM_FAILCRITICALERRORS = 0x0001,
SEM_NOALIGNMENTFAULTEXCEPT = 0x0004,
SEM_NOGPFAULTERRORBOX = 0x0002,
SEM_NOOPENFILEERRORBOX = 0x8000
}
private static void Main(string[] args)
{
SetErrorMode(ErrorModes.SEM_FAILCRITICALERRORS);
var resource = @"C:\Windows\System32\mmsys.cpl";
// var resource = @"C:\Windows\System32\timedate.cpl";
var lib = LoadLibrary(resource);
if (lib == System.IntPtr.Zero)
{
var errorCode = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
throw new System.SystemException($"System failed to load library '{resource}' with error {errorCode}");
}
}
您需要先用 SEM_NOOPENFILEERRORBOX (0x8000) 调用 SetErrorMode。
详见documentation中的备注部分:
To enable or disable error messages displayed by the loader during DLL loads, use the SetErrorMode function.