简体   繁体   中英

Creating a basic C++ .dll for p/invoke in 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.

PROBLEM

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.

DETAILS

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.

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.

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.

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

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.

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

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

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.

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.

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.

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

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.

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.

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 )

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.

In 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM