C ++ DLL:

#include "stdafx.h" #include "windows.h" #include "psapi.h" #include "stdlib.h" typedef struct PROCINF { DWORD dwPID; LPWSTR lpMainModName; } *LPPROCINF; extern "C" __declspec(dllexport) void GetProcessInfo(LPPROCINF lppi) { HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, lppi->dwPID); if (hProcess == NULL) return; MessageBox(NULL, L"GET MAIN MOD NAME", NULL, NULL); // // Get process main module name. // lppi->lpMainModName = (LPWSTR)malloc(MAX_PATH * sizeof(wchar_t)); GetModuleFileNameEx((HMODULE)hProcess, NULL, lppi->lpMainModName, MAX_PATH * sizeof(wchar_t)); CloseHandle(hProcess); } 

C #:

  [StructLayout(LayoutKind.Sequential)] struct PROCINF { public uint dwPID; [MarshalAs(UnmanagedType.LPWStr)] public string lpMainModName; } [DllImport("my.dll", CallingConvention = CallingConvention.Cdecl)] static extern void GetProcessInfo(ref PROCINF info); // ... PROCINF pinfo = new PROCINF(); pinfo.dwPID = 3604; GetProcessInfo(ref pinfo); MessageBox.Show("PID: " + pinfo.dwPID + Environment.NewLine + "Main module: " + pinfo.lpMainModName); 

After the completion of GetProcessInfo , the program immediately crashes, and without errors. What is the problem I can not understand, because it seems to be importing correctly (if you remove GetModuleFileNameEx and malloc , replacing filling the value with an empty string, everything will work fine).

  • one
    If dll is yours, I would advise you to write it in C ++ / CLI and provide a managed interface immediately. - VladD
  • Malloc seems to be a problem, the small values ​​cannot be passed across the DLL's boundary (because no one knows how to get them back). - VladD
  • And what do you propose for a replacement? - D .Stark
  • If you want, I will write as a response, a solution in C ++ / CLI. - VladD
  • To find out the cause of the crash, try setting the Break on Exceptions flag (Shift-Alt-E in the studio), with both C ++ Exceptions and CLR Exceptions: blogs.msdn.microsoft.com/devops/2015/02/23/… and run the program in debug mode (F5). - Sergey Slepov

1 answer 1

Here is the solution with a C ++ / CLI library.

  1. Add a C ++ / CLI library to the project. In Visual Studio 2017, this is called the “CLR class library”.
  2. Put the following definitions in this library in the header file:

     #pragma once #include "windows.h" #include "psapi.h" using namespace System; namespace InteropLibrary { public ref class ProcInf { public: UInt16 ProcessId; String^ MainModuleName; }; public ref class ProcessHelper abstract sealed // аналог статического класса { public: static Boolean GetProcessInfo(ProcInf^ lppi) { HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, lppi->ProcessId); if (hProcess == NULL) return false; wchar_t moduleName[MAX_PATH + 1]; // размер в символах, поэтому не удваиваем его auto nameSize = GetModuleFileNameEx( (HMODULE)hProcess, NULL, moduleName, MAX_PATH); if (nameSize > 0) lppi->MainModuleName = gcnew String(moduleName, 0, nameSize); CloseHandle(hProcess); return nameSize > 0; } }; } 

    How to create method signatures for C ++ / CLI, you can see, for example, here .

  3. In C # parts, select a target with a specific bit depth (x86 or x64). Connect the part on C ++ / CLI as project reference.

  4. In C # code, call:

     InteropLibrary.ProcInf pi = new InteropLibrary.ProcInf() { ProcessId = 1234 }; if (InteropLibrary.ProcessHelper.GetProcessInfo(pi)) { ... 

That seems to be all.


Don't forget: if there is unmanaged code in your project, you bring undefined behavior and all the other “delights” of native memory access into it. Therefore, be extremely careful with native functions. (For example, you incorrectly calculated the size of the buffer, the native programming of such errors does not forgive.)

  • Comments are not intended for extended discussion; conversation moved to chat . - PashaPash