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);
После завершения GetProcessInfo
сразу вылетает программа, причём без ошибок. В чём проблема понять не могу, т.к. вроде как импортирую правильно (если убрать GetModuleFileNameEx
и malloc
, заменив заполнение значения пустой строкой, всё будет работать хорошо).
Вот решение с библиотекой на C++/CLI.
Положите в этой библиотеке в заголовочном файле следующие определения:
#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;
}
};
}
О том, как создавать сигнатуры методов для C++/CLI, можно посмотреть, например, здесь.
В C#-части выберите таргет с конкретной битностью (x86 или x64). Подключите часть на C++/CLI как project reference.
В C#-коде вызывайте:
InteropLibrary.ProcInf pi = new InteropLibrary.ProcInf() { ProcessId = 1234 };
if (InteropLibrary.ProcessHelper.GetProcessInfo(pi))
{
...
Вот вроде бы и всё.
Не забудьте: если в вашем проекте есть неуправляемый код, вы привносите в него undefined behaviour и все остальные «прелести» нативного доступа к памяти. Поэтому будьте предельно осторожны с нативными функциями. (Например, вы неправильно подсчитали размер буфера, нативное программирование таких ошибок не прощает.)
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Разрабатывается чат вконтакте, который поддерживает медиавложенияБыл написан обращённый список ListView, поддерживающий виртуализацию данных...
Мне нужно, чтобы переходя на любой роут моего приложения koa всегда передавал файл indexhtml, т
имеется ту ду лист, создается заметка, которая в формате li#draggable > p добавляется в ul в колонку PENDINGхочу реализовать drag&drop, чтобы заметки из колонки...