我的 c# 应用程序创建了用于处理键盘事件的键盘钩子(许多读卡器、扫描仪和其他 POS 设备模拟键盘)。有时我的应用程序会创建没有错误的键盘钩子,但它不会触发事件并且在处理时抛出异常:
System.ComponentModel.Win32Exception (0x80004005):无法删除“应用程序”的键盘挂钩。错误 1404:无效的钩子句柄
其他日志条目是相同的错误,但它讲述了
ERROR_NOT_ALL_ASSIGNED
我无法在我的电脑上重现这个问题,也不知道我应该调查什么或谷歌。我知道:
另外,我不熟悉非托管代码和 win api。我从某个线程中获得了这段代码,并根据我的需要对其进行了修改,但在高级抽象上进行了修改。
挂钩演员:
public GlobalKeyboardHook()
{
_windowsHookHandle = IntPtr.Zero;
_user32LibraryHandle = IntPtr.Zero;
_hookProc = LowLevelKeyboardProc; // we must keep alive _hookProc, because GC is not aware about SetWindowsHookEx behaviour.
_user32LibraryHandle = LoadLibrary("User32");
if (_user32LibraryHandle == IntPtr.Zero)
{
int errorCode = Marshal.GetLastWin32Error();
throw new Win32Exception(errorCode,
$"Failed to load library 'User32.dll'. Error {errorCode}: …Run Code Online (Sandbox Code Playgroud) 我正在运行一个处理位图图像的应用程序。现在我正在寻找一种快速方法来交换“Format24bppRgb”位图图像的“红色”和“蓝色”值。在我的 C# 代码中,我的第一次尝试是使用不安全的代码片段:
var bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
ImageLockMode.ReadWrite, bmp.PixelFormat);
unsafe
{
byte* array = (byte*)bmpData.Scan0.ToPointer();
byte temp;
for (int x = 0; x < bmp.Width * bmp.Height * 3; x = x + 3) {
temp = *(array + x + 2);
*(array + x + 2) = *(array + x);
*(array + x) = temp;
}
}
Run Code Online (Sandbox Code Playgroud)
对于我使用的位图大小,这大约需要 50-70 毫秒。现在我尝试使用 pinvoke 调用在外部库(基于 C++)中完成这项工作:
[DllImport("ByteSwitch.dll")]
public static extern IntPtr ChangeRB(IntPtr data, int width, int height);
data …Run Code Online (Sandbox Code Playgroud) 有没有办法在我的C#应用程序中使用(引用)在非托管C++(不是COM库)中编写的DLL?
当我尝试从Visual Studio中引用它时,我得到'不是COM对象'错误消息.
也许有某种翻译器\路由器可以合并我的DLL参考?我不知道COM和COM互操作是如何工作的,因为我开始编程时这对我来说已经没有必要了.
谢谢.
我正在尝试实现一些涉及托管C#和非托管C ++代码之间的封送处理数组的项目。我遇到了一个问题,我在网上找到的所有解决方案似乎都无效。我对此表示感谢。
我没有提供完整的代码,而是显示了问题的非常简化的部分。尽管它看起来很大,但非常简单-只是概念上的。只是想提供尽可能多的全貌。
C ++部分:
对象
class cObject
{
public:
//...constructor, destructor...
int Method_Known_Size(double* array, int size);
int Method_Unknown_Size(double* array);
...
void FreeArray(double* p);
}
Run Code Online (Sandbox Code Playgroud)
对象.cpp
int Method_Known_Size(double* array, int size)
{
//modify array somehow..
for(int i=0; i<size; i++) array[i] = i;
}
int method_Unknown_Size(double* array)
{
int size = 9;
array = new double[size];
for(int i=0; i<size; i++) array[i] = i;
}
Run Code Online (Sandbox Code Playgroud)
(跳过Caller.h) Caller.cpp
//...callers for constructor, destructor, for releasing unmanaged memory...
extern "C" int __stdcall Run_Known_Size(cObject* pObject, double* …Run Code Online (Sandbox Code Playgroud) 我得到这个例外:
LogLoaderUnmanaged.exe 中 0x75374B32 (KernelBase.dll) 处的未处理异常:0xE0434352(参数:0x80070002、0x00000000、0x00000000、0x0000000004、0x000000004)。
当我使用此代码(Application .exe 类型项目的一部分)调用我的 CLR 项目时:
int _tmain(int argc, _TCHAR* argv[])
{
_tprintf_s(_T("Press enter to start logging messages."));
_getch();
std::string app("Application");
std::string domain("Domain");
std::string message("Message");
UnmanagedLoggerClient::LogError(Debug, app.c_str(), domain.c_str(), message.c_str());
_tprintf_s(_T("Done."));
}
Run Code Online (Sandbox Code Playgroud)
错误发生在对 LogError 的调用上,它在我的 CLR DLL 的头文件中定义如下:
#ifdef UNMANAGEDLOGGERCLIENT_EXPORTS
#define WIN32PROJECT_API __declspec(dllexport)
#else
#define WIN32PROJECT_API __declspec(dllimport)
#endif
enum UnmanagedLogLevel
{
Debug = 0,
Error = 1
};
static class WIN32PROJECT_API UnmanagedLoggerClient
{
public:
static void LogError (UnmanagedLogLevel level, const char* app, const char* domain, const …Run Code Online (Sandbox Code Playgroud) 我正在为非托管 C++ 库编写 CLR 包装器。
我从非托管库中包含了两个文件:
//MyCLIWrapper.h
#include "C:\PATH\TO\UNMANAGED\Header.h"
#include "C:\PATH\TO\UNMANAGED\Body.cpp"
Run Code Online (Sandbox Code Playgroud)
然后我正在为非托管库函数编写 CLI 实现:
//MyCLIWrapper.h
// includes ...
void MyCLIWrapper::ManagedFunction()
{
UnmanagedFunction(); // this function is called successfuly
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我的非托管函数包含对其他非托管头文件中定义的其他函数的调用。这会导致编译器链接错误。
如果我将包含添加到定义这些函数的非托管头文件中,我的错误就会得到解决。但是,有很多功能,并且需要很多包含。
有没有不同的方法来解决这个问题?
编辑: PS 我的托管代码位于单独的 Visual Studio 项目(输出 - DLL)中,并且编译设置设置为 /CLR。非托管代码位于单独的 Win32 项目(输出 - DLL)中。
此外,经过更多研究后,我得出的结论是,理论上我可以将我的 Win32 非托管项目设置为 CLR,并在其中添加我的托管类和头文件作为入口点,然后它们将全部编译为单个 DLL 文件。这可能会解决(?)链接错误。但是,我更愿意保留松散耦合以及将我的非托管项目设置为 CLR 可能引发的其他一系列问题。
编辑#2: 我引用的非托管类(body.cpp、header.h)包含所需文件,这些文件定义了导致问题的函数。但是,我的托管代码不接受非托管 body.cpp 和 header.h 中的包含。
我在我正在维护的实用程序上运行代码分析,它建议我更改它:
private static extern int ReadMenu1File(string Menu1Path);
Run Code Online (Sandbox Code Playgroud)
......对此:
private static extern int ReadMenu1File(UnmanagedType.LPWStr Menu1Path);
Run Code Online (Sandbox Code Playgroud)
...使用此措辞:"为P/Invoke字符串参数指定封送处理为了降低安全风险,将参数'Menu1Path'编组为Unicode,将DllImport.CharSet设置为CharSet.Unicode,或者将参数显式封送为UnmanagedType.LPWStr.如果需要将此字符串封装为ANSI或依赖于系统,请明确指定MarshalAs,并设置BestFitMapping = false;为了增加安全性,还要设置ThrowOnUnmappableChar = true."
...但是当我这样做时,它说:" 类型名称'LPWStr'在类型'System.Runtime.InteropServices.UnmanagedType'中不存在 "和''System.Runtime.InteropServices.UnmanagedType.LPWStr'是'字段'但用作'类型' "
代码完成没有帮助(键入"UnmanagedType."后没有建议.)也没有上下文菜单选项来添加缺失使用.
我正在尝试使用C#/ .NET 使用此本机方法获取剪贴板数据.问题是我正在破坏数据.这是我的代码:
IntPtr pointer = GetClipboardData(dataformat);
int size = Marshal.SizeOf(pointer);
byte[] buff = new byte[size];
Marshal.Copy(data, buff, 0, size);
Run Code Online (Sandbox Code Playgroud)
这是我用于GetClipboardData方法的pinvoke:
[DllImport("user32.dll")]
private static extern IntPtr GetClipboardData(uint uFormat);
Run Code Online (Sandbox Code Playgroud)
谁能告诉我哪里出错了?
我尝试使用以下代码
[DllImport("Core.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr CreateNode();
[DllImport("Core.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
public static extern void ReleaseNode(IntPtr handle);
class Node
{
IntPtr nativePtr;
public int id;
public Node(int i)
{
nativePtr = CreateNode();
id = i;
Debug.WriteLine("Constructed " + id);
}
~Node()
{
ReleaseNode(nativePtr);
Debug.WriteLine("Destructed " + id);
}
}
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 10; i++)
{
Node n = new …Run Code Online (Sandbox Code Playgroud) 我有一个非托管 C++ DLL 和一个使用 P/Invoke 进行通信的 .net 应用程序。我需要从 C++ DLL 更新 .net 应用程序中的字典。
我尝试通过以下方式做到这一点:
public delegate void MyDelegate(string address, string username);
[DllImport("MyDLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void SaveMyDelegate(MyDelegate callback);
private static SortedDictionary<string, string> dict = new SortedDictionary<string, string>();
public void save_delegate() {
SaveMyDelegate(delegate(string address, string username) {
if (username != "") {
dict.Add(address, username);
}
});
}
Run Code Online (Sandbox Code Playgroud)
在 C++ 方面我有:
typedef void (*MANAGED_CALLBACK)(string user_address, string username);
extern "C" __declspec(dllexport) void SaveMyDelegate(MANAGED_CALLBACK callback);
MANAGED_CALLBACK my_callback;
void SaveMyDelegate(MANAGED_CALLBACK callback) { …Run Code Online (Sandbox Code Playgroud) 我正在读关于Marshaling的事.我很困惑,因为在非托管代码中这意味着什么.HRESULT,DWORD和HANDLE.原文是:
您已经知道托管和非托管环境之间没有这种兼容性.换句话说,.NET不包含存在于非托管代码领域中的类型HRESULT,DWORD和HANDLE.因此,您需要找到.NET替代品或根据需要创建自己的替代品.这就是所谓的编组.