创建的p基本的C ++ .dll文件/调用在C# [英] Creating a basic C++ .dll for p/invoke in C#

查看:128
本文介绍了创建的p基本的C ++ .dll文件/调用在C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是一个C#程序员,不幸的是,由于年龄和经验,我没有得到去通过C的机会++编程时代在我学习的奢侈品 - 与其说它是神秘的,新的我。不是真的在这里辩论学习这种与否的重要性,但我需要一些帮助,什么应该是一件小事。

I am a C# programmer, and unfortunately due to both age and experience, I did not have the luxury of getting the chance to go through the C++ era of programming in my learning - so much of it is mysterious and new to me. Not really here to debate the importance of learning such or not, but I am in need of some help with what should be a trivial matter.

我需要我的包装的C ++代码转换成一个.dll援助。我没有与C ++的经验和我有困难了很大的制作工作.dll文件,我可以P /调用从(的Visual Studio 2010 的)。请继续阅读更多的细节和我试图打包代码。

I need assistance in packaging my C++ code into a .dll. I do not have experience with C++ and am having a great deal of difficulty making a working .dll that I can p/invoke from (Visual Studio 2010). Please keep reading for more details and for the code I am trying to package.

我有一些代码需要在非托管的环境中运行。在正常情况下,一个简单的P / Invoke适合这项任务。线材一些 [ImportDll] ,你是好去。最坏的情况下,我可以有时使用编组。然而,对于我还没有真正找到原因,这似乎并不可能跟我现在的任务。

I have some code that needs to run in an unmanaged environment. Under normal circumstances, a simple p/invoke is suitable for this task. Wire up some [ImportDll] and you're good to go. Worst case scenario I can sometimes use Marshalling. However for reasons that I have yet to really discover, this does not seem possible with my present task.

我想从所有者绘制的列表框这是一个古老的非托管C提出++应用程序读取一些数据,并从它那里得到的文本。我已经看到了如何做到这一点的几个例子 - 但他们在旧的VB6代码。

I am trying to read some data from an owner drawn list box that was made in an old unmanaged C++ application, and get the text from it. I have seen several examples of how to do this - but they are in older VB6 code.

我已经发现了C ++相当,但这也是不适合我。即使P /调用,似乎有很多麻烦的内存运动以及它如何需要操作。这个过程是非常简单的。

I have discovered the C++ equivalent, but this too is unsuitable for me. Even with p/invoke, there seems to be a lot of trouble with the moving of memory and how it needs to operate. The process is pretty simplistic.

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

I need to create a simple C++ .dll that runs the method I need in unmanaged code, and populates a variable with the result.

一样傻乎乎的这听起来,我不知道如何做到这一点。我曾尝试只是通过简单的C ++向导在Visual Studio中运行(使用Visual Studio 2010),我只是没有运气。我希望有人能帮助我走过这一点,或许可以解释这是怎么回事,所以我可以借鉴一下。

As dumb as this sounds, I do not know how to do this. I have tried just running through the simple C++ Wizards in Visual Studio (using Visual Studio 2010) and I'm just not having luck. I was hoping someone could help me walk through this, and perhaps explain what is going on so I can learn from it.

下面是我需要放到一个代码的.dll

Here is the code I need to place into a .dll.

我们的目的是为 hListWnd 的IntPtr 在C#中,首页将是一个简单的的Int32 outputResult 将去什么时,只需要完成这项工作。在其他的P / Invoke的情况下,我已经看到了这与 System.Text.StringBuilder 做的,但我愿意是任何,以努力使这个工作的权利。

The intention is for hListWnd to be passed as an IntPtr in C#, index will be a simple Int32, and outputResult will go to whatever is neccessary to make this work. In other p/invoke situations, I have seen this done with System.Text.StringBuilder, but I am willing to work with anything to make this work right.

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 );
        }
    }
}

如果有人能帮助我,请,我在这里乞讨。这已经成为一个非常令人沮丧的问题对我来说。我曾尝试使用 RtlMoveMemory ReadProcessMemory 的P / Invoke重现这在C#,但无济于事。我查了好多天,并继续拿出死者的结果。我知道有些代码不使一个很大的意义(我有别人问我为什么它是要求 +6 ,什么 +24 是,等),绝对的事实是,我没有的完全知道。我所知道的是,在所有者绘制的列表框使用它的一些图形和这些偏移的目的是研究超越图形区域绘制所在的数据,因为实际结构项目是未知的。

If anyone can help me, please, I am begging here. This has become a very frustrating problem for me. I have tried to reproduce this in C# using RtlMoveMemory and ReadProcessMemory p/invoke, but to no avail. I have been hunting for days and days, and continue to come up with dead results. I know that some of the code does not make a lot of sense (I've had people ask me why it is requiring the +6 and what the +24 is, etc), and the absolute truth is that I don't entirely know. What I do know is that the owner drawn list box employs some graphics on it, and the purpose of these offsets is to examine the data beyond where the graphic area is drawn, because the actual structure of the List Item is unknown.

我试图检索我的项目作为另一种方法是的IAccessible 使用辅助功能。 DLL 库。这也证明了不结果。我也曾尝试 ManagedWinApi 从pinvoke.net和库有没有证明任何成功。

Another method I have tried is retrieving my item as an IAccessible using the Accessibility.dll library. This too proved fruitless. I have also tried ManagedWinApi from pinvoke.net and the libraries there did not prove any success.

我知道这代码工作。它只是没有在C#中工作。我的理论是,使用函数[DllImport] 来调用它在C#会给我想要的结果。

I know this code works. It just doesn't work in C#. My theory is that using a [DllImport] to invoke it in C# will give me the desired result.

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

Thanks again for any help anyone provides.

推荐答案

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

The third parameter needs to be a byte[], marshalled as a char*, of size 16.

如果您检查ReadProcessMemory的文档,它需要一个缓冲和大小,与此功能传递的大小为16个字节。这意味着您将需要一个16字节数组。运行时应该是心甘情愿名帅一个byte []大小16.小心不要混淆C ++的char与C#煤焦C#中的char实际上是Windows上的C ++ wchar_t的。 C ++的char是C#的字节。

If you check the documentation for ReadProcessMemory, it takes a buffer and a size, and this function passes the size as 16 bytes. This means that you will need a 16-byte array. The runtime should be perfectly happy to marshal a byte[] of size 16. Be careful not to mix C++ char with C# char- the C# char is actually a C++ wchar_t on Windows. The C++ char is C#'s byte.

这并不是说我有多么的工程─我刚才跟踪的第三个参数的使用功能,它实际上只被传递任何实际的想法到ReadProcessMemory,参数为这是很清楚的记载。

Not that I have any actual idea about how that functions works- I just traced the usage of the third parameter and it only actually gets passed to ReadProcessMemory, the parameters for which are quite clearly documented.

要打包成一个.dll(假设你没有别的去到该.dll文件),要上添加几件事情要一开始就问C ++编译器不要裂伤的名称,将其导出为你生产这个作为第一行

To package into a .dll (assuming you have nothing else to go into that .dll), you want to add a couple things on to the beginning to ask the C++ compiler not to mangle the name and to export it for you, producing this as the first line

extern "C" __declspec(dllexport) void GetListItemData( HWND hListWnd, long index, char *outputResult )

您将只需要一个C ++源文件,无头,并编译为DLL(这是在项目设置)。你不需要任何代码以外的功能以及任何包含您所需要的。

You'll only need one C++ source file, no headers, and compile as DLL (it's in the project settings). You won't need any code except the function and any includes that you need.

在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
);



不幸的是,这是由你来确保缓冲区足够的大小。

Unfortunately, it's up to you to make sure that buffer is of sufficient size.

这篇关于创建的p基本的C ++ .dll文件/调用在C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆