在C#中为p/invoke创建基本的C++ .dll

Cie*_*iel 4 c# c++ pinvoke

我是一名C#程序员,不幸的是由于年龄和经验,我没有机会在我的学习中有机会完成编程的C++时代 - 这对我来说是多么神秘和新鲜.这里并没有真正讨论学习这种与否的重要性,但我需要一些应该是一件小事的帮助.

问题

我需要帮助将我的C++代码打包成.dll.我没有与C++的经验和我有困难的大量制造工作.dll文件,我可以P /从(调用Visual Studio 2010中).请继续阅读以获取更多详细信息以及我要打包的代码.

细节

我有一些代码需要在非托管环境中运行.在正常情况下,简单的p/invoke适用于此任务.连线一些[ImportDll],你很高兴.最糟糕的情况我有时可以使用编组.然而,由于我还没有真正发现的原因,我目前的任务似乎不可能.

我试图从一个owner drawn list box旧的非托管C++应用程序中读取一些数据,并从中获取文本.我已经看到了几个如何执行此操作的示例 - 但它们是旧的VB6代码.

我发现了C++等价物,但这对我来说也不合适.即使使用p/invoke,内存移动以及它需要如何操作似乎也有很多麻烦.这个过程非常简单.

我需要创建一个简单的C++ .dll来运行我在非托管代码中需要的方法,并用结果填充变量.

虽然这听起来很蠢,但我不知道该怎么做.我试过在Visual Studio中运行简单的C++向导(使用Visual Studio 2010),我只是没有运气.我希望有人可以帮助我解决这个问题,也许可以解释发生了什么,这样我就可以从中学习.

这是我需要放入的代码.dll.

意图是hListWnd作为一个IntPtrC#传递,index将是一个简单的Int32,outputResult并将进入任何必要的使这项工作.在其他p/invoke情况下,我已经看到了这一点System.Text.StringBuilder,但我愿意使用任何东西来使这项工作正确.

void GetListItemData( HWND hListWnd, long index, char *outputResult )
{
    int result;
    DWORD processID;
    HANDLE hProcess;
    char *itemData;
    char sDataRead[5];
    DWORD bytes;
    DWORD lListItemHold, lListItemDataHold;
    *outputResult=0;

    if( hListWnd )
    {
        GetWindowThreadProcessId( hListWnd, &processID );

        hProcess=OpenProcess( 0x10|0xf0000|PROCESS_VM_READ, 0, processID );

        if( hProcess )
        {
            lListItemHold=(DWORD)SendMessage( hListWnd, LB_GETITEMDATA, index-1, 0 );
            lListItemHold=lListItemHold+24;

            result=ReadProcessMemory( hProcess, (void *)lListItemHold, &sDataRead, 4, &bytes );
            if( !result )
            {
                RaiseWinErr();
            }

            memcpy( &lListItemDataHold, &sDataRead, 4 );
            lListItemDataHold=lListItemDataHold+6;

            ReadProcessMemory( hProcess, (void *)lListItemDataHold, outputResult, 16, &bytes );

            CloseHandle( hProcess );
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如果有人可以帮助我,拜托,我在这里乞讨.这对我来说已成为一个非常令人沮丧的问题.我试图在C#中使用RtlMoveMemoryReadProcessMemoryp/invoke 重现这一点,但无济于事.我一直在寻找日子和日子,并继续拿出死的结果.我知道有些代码没有多大意义(我曾经让人们问我为什么要求它+6和它是什么+24等等),绝对的事实是我不完全知道.我所知道的是所有者绘制的列表框上有一些图形,这些偏移的目的是检查绘制图形区域之外的数据,因为它的实际结构List Item是未知的.

我尝试过的另一种方法是IAccessible使用Accessibility.dll库检索我的项目.这也证明没有结果.我也尝试过ManagedWinApipinvoke.net,那里的图书馆没有任何成功.

我知道这段代码有效.它只是在C#中不起作用.我的理论是使用a [DllImport]在C#中调用它会给我想要的结果.

再次感谢任何人提供的帮助.

Pup*_*ppy 6

第三个参数需要是一个byte [],编组为char*,大小为16.

如果您检查ReadProcessMemory的文档,它需要一个缓冲区和一个大小,并且此函数将大小传递为16个字节.这意味着您将需要一个16字节的数组.运行时应该非常乐意编组一个大小为16的byte [].注意不要将C++ char与C#char混合使用 - C#char实际上是Windows上的C++ wchar_t.C++ char是C#的字节.

并不是说我对这些函数的工作方式有任何实际的想法 - 我只是追踪了第三个参数的用法,它实际上只传递给了ReadProcessMemory,其参数清楚地记录在案.

要打包成.dll(假设你没有其他内容可以进入.dll),你想在开头添加一些东西,要求C++编译器不要破坏名称并为你导出它,产生这个作为第一线

extern "C" __declspec(dllexport) void GetListItemData( HWND hListWnd, long index, char *outputResult )
Run Code Online (Sandbox Code Playgroud)

您只需要一个C++源文件,没有标题,并编译为DLL(它在项目设置中).除了函数和任何您需要的包含之外,您不需要任何代码.

在C#中

[System.Runtime.InteropServices.DllImport(
    DLLPath,
    CallingConvention = CallingConvention.Cdecl
)]
private static extern void GetListItemData(
    System.IntPtr hWnd,
    System.Int32 index,
    [MarshalAs(UnmanagedType.LPArray)]byte[] buffer
);
Run Code Online (Sandbox Code Playgroud)

不幸的是,您可以确保缓冲区的大小足够大.