背景介绍
用Mircrsoft Visual Studio 启动程序代码时,System.Runtime.InteropServices.Marshal.GetLastWin32Error()报如下错误:
“System.ComponentModel.Win32Exception”类型的未经处理的异常在 System.Windows.Forms.Keyboard.exe 中发生
其他信息: 找不到指定的模块。
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto,
CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, int dwThreadId);
private const int WH_MOUSE_LL = 14;
private const int WH_KEYBOARD_LL = 13;
private delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
private IntPtr KeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
return IntPtr.Zero;
}
public int Test()
{
try
{
KeyboardHookProcedure = new HookProc(KeyboardHookProc);
//get executing assembly
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
if (assembly == null) return -1;
//Get all modules as part of this assembly
System.Reflection.Module[] modules = assembly.GetModules();
if (modules == null || modules.Length <= 0) return -1;
//Get the first module among all modules
System.Reflection.Module module = modules[0];
if (module == null) return -1;
//Get the instance handle of the specified module
IntPtr hMod = System.Runtime.InteropServices.Marshal.GetHINSTANCE(module);
if (hMod == IntPtr.Zero)
{
int errorCode = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
throw new System.ComponentModel.Win32Exception(errorCode);
}
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, hMod, 0);
if (hKeyboardHook == IntPtr.Zero)
{
int errorCode = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
throw new System.ComponentModel.Win32Exception(errorCode);
}
return 0;
}
catch (Exception exp)
{
}
return -1;
}
分析原因
在Micrsoft Visual Studio 2013 调试运行的时 System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0] 获取的全路径为:[ProjectDirectory]\bin\[SolutionConfigurationName]\[AssemblyName].exe;然而在Micrsoft Visual Studio 调试实际运行的程序全路径为:[ProjectDirectory]\bin\[SolutionConfigurationName]\[AssemblyName].vshost.exe,于是System.Runtime.InteropServices.Marshal.GetHINSTANCE(module);去获取正在运行实例地址的时候报错,因为在任务管理器里面找不到正在运行的[AssemblyName].exe程序。
- [ProjectDirectory]: 工程所在文件夹;
- [SolutionConfigurationName]: 解决方案配置文件名称,如“Debug”、“Release”等;
- [AssemblyName]:程序集名称。
解决方案
将 System.Runtime.InteropServices.Marshal.GetHINSTANCE(System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0])
替换成 GetModuleHandle(System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName)
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
public static extern IntPtr GetModuleHandle(string name);
[System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto,
CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, int dwThreadId);
private const int WH_MOUSE_LL = 14;
private const int WH_KEYBOARD_LL = 13;
private delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
private IntPtr KeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
return IntPtr.Zero;
}
public int Test()
{
try
{
KeyboardHookProcedure = new HookProc(KeyboardHookProc);
//get current process
System.Diagnostics.Process process = System.Diagnostics.Process.GetCurrentProcess();
if (process == null) return -1;
//get process main module
System.Diagnostics.ProcessModule processModule = process.MainModule;
if (processModule == null) return -1;
//get process main module name
string moduleName = processModule.ModuleName;
if (string.IsNullOrEmpty(moduleName)) return -1;
//get process main module handle
IntPtr hMod = GetModuleHandle(moduleName);
if (hMod == IntPtr.Zero)
{
int errorCode = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
throw new System.ComponentModel.Win32Exception(errorCode);
}
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProcedure, hMod, 0);
if (hKeyboardHook == IntPtr.Zero)
{
int errorCode = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
throw new System.ComponentModel.Win32Exception(errorCode);
}
return 0;
}
catch (Exception exp)
{
}
return -1;
}