История:
Я написал многопоточное приложение в Win32, которое я начинаю с кода С#, используя класс Process
из пространства имен System.Diagnostics
.
Теперь, в коде С#, я хочу получить имя/символ начального адреса каждого потока, созданного в приложении Win32, чтобы я мог записывать информацию, связанную с потоком, такую как использование ЦП, в базу данных. В основном, код С# запускает несколько экземпляров приложения Win32, контролирует их, при необходимости убивает, а затем регистрирует информацию/ошибку/исключения/причину/etc в базе данных.
С этой целью я обернул два API Win32: SymInitialize
и SymFromAddr
в программном API, написанном мной, как указано ниже:
extern "C"
{
//wraps SymInitialize
DllExport bool initialize_handler(HANDLE hModue);
//wraps SymFromAddr
DllExport bool get_function_symbol(HANDLE hModule, //in
void *address, //in
char *name); //out
}
И затем вызовите эти API из кода С#, используя pinvoke. Но это не работает, и GetLastError
дает 126
код ошибки, что означает:
Указанный модуль не найден
Я передаю Process.Handle
как hModule
для обеих функций; initialize_handler
, похоже, работает, но get_function_symbol
не работает; он дает указанную выше ошибку. Я не уверен, передаю ли я правильную ручку. Я попытался передать следующие дескрипторы:
Process.MainWindowHandle
Process.MainModule.BaseAddress
Оба сбой выполняются на самом первом этапе (т.е. при вызове initialize_handler
). Я передаю Process.Threads[i].StartAddress
в качестве второго аргумента, и это, по-видимому, является причиной сбоя, поскольку ProcessThread.StartAddress
представляется адресом функции RtlUserThreadStart
, не адресом конкретной функции запуска к приложению. MSDN говорит об этом:
Каждый поток Windows фактически начинает выполнение в системной заданной функции, а не в приложении. Исходный адрес для основного потока, следовательно, тот же (как он представляет адрес функции, поставляемой системой) для каждого процесса Windows в системе. Однако свойство StartAddress позволяет получить адрес начальной функции, специфичный для вашего приложения.
Но он не говорит, как получить адрес функции startinbg, специфичный для приложения, используя ProcessThread.StartAddress.
Вопрос:
Моя проблема сводится к тому, чтобы получить начальный адрес потока win32 из другого приложения (написанного на С#), как только я его получу, я также получу имя, используя вышеупомянутые API. Итак, как получить начальный адрес?
Я проверил свой API поиска символов из кода на С++. Он отлично работает, чтобы разрешить адрес символу, если задан правильный адрес для начала.
Вот мои объявления p/invoke:
[DllImport("UnmanagedSymbols.dll", SetLastError = true, CallingConvention= CallingConvention.Cdecl)]
static extern bool initialize_handler(IntPtr hModule);
[DllImport("UnmanagedSymbols.dll", SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
static extern bool get_function_symbol(IntPtr hModule, IntPtr address, StringBuilder name);