Обмен некоторой информацией со всеми библиотеками DLL, вовлеченными в процесс - PullRequest
1 голос
/ 21 апреля 2010

У нас есть корпоративная система, в которой есть много процессов (EXE, сервисы, DCOM-серверы, приложения COM +, ISAPI, оснастки MMC), которые используют многие COM-компоненты. Недавно мы наблюдали сбои в некоторых развертываниях клиентов, но нам трудно найти причину.

Чтобы отследить проблему, мы дополнили весь источник инструкциями регистрации, где происходят ошибки.

Чтобы определить, какие журналы были получены от каких процессов, код журнала C ++ (скомпилированный во все компоненты) использует имя EXE-файла для присвоения имени журналу. Это хорошо в некоторых случаях, но не во всех - приложения COM +, оснастки ISAPI и MMC имеют системные имена EXE, а журналы чередуются.

Я видел этот пост о разделах общих данных , который может помочь, но я не понимаю, кто решает, что происходит в разделе общего доступа. Можно ли как-то гарантировать, что определенный фрагмент кода будет записан в раздел с общим доступом, прежде чем кто-либо еще его прочитает?

Или есть лучшее решение этой проблемы?

Ответы [ 2 ]

1 голос
/ 11 мая 2010

Для синхронизации нескольких процессов записи в общий раздел вам понадобится какой-нибудь IPC, например События Windows, мьютексы, сокеты. Каждый из ваших модулей вызывает CreateMutex и передает фиксированное имя, которое разделяют все модули. Затем модули вызывают WaitForSingleObject, чтобы ждать и запрашивать мьютекс - когда один из них получает его, он может читать / записывать раздел с общим доступом, пока все остальные модули ждут. Когда это сделано, он вызывает ReleaseMutex, чтобы позволить другому модулю идти.

Сказав все это лично, я бы продолжил с лог-файлами. Я предполагаю, что ваша проблема в том, что для библиотек DLL вы основываете имя файла журнала на имени EXE родительского процесса, а не на собственном имени библиотеки DLL?

Вы можете получить собственное имя библиотеки DLL, сохранив дескриптор экземпляра DLL, переданный в DllMain, и затем используя его с GetModuleFileName. Обратите внимание, что это работает и для EXE, если вы оставили дескриптор экземпляра как NULL.

// global variable to store DLL handle (or it stays NULL if this is an EXE)
HINSTANCE hDllHandle=NULL;

BOOLEAN WINAPI DllMain( IN HINSTANCE hInstance, 
     IN DWORD     nReason, 
     IN LPVOID    Reserved )
{
  hDllHandle = hInstance;
  return TRUE;

}

<snip>

void Log(LPSTR lpszMsg)
{
    WCHAR szMyModuleName[MAX_PATH]={0};

    // if hDllHandle is still NULL (e.g. this is an EXE) it returns the process name
    // if non-NULL, it returns our DLL name
    GetModuleFileName(hDllHandle, szMyModuleName, MAX_PATH);

    fprintf(LOGFILE, "[%s] %s\n", szMyModuleName, lpszMsg);

     ....<snip>....
}
0 голосов
/ 08 июня 2010

Использование общего раздела в DLL (раздел с флагами RWS) не решает вашу главную проблему. Если вам нужна общая память для быстрой связи между процессами, вы можете использовать файлы, отображенные в память (см., Например, http://msdn.microsoft.com/en-us/library/ms810613.aspx), и иметь больший контроль над созданием и использованием общей памяти.

Чтобы получить больше информации о процессе, который загрузил вашу DLL, вы можете дополнительно зарегистрировать командную строку приложения (например, функция GetCommandLine()). Вы увидите что-то вроде «C: \ Windows \ system32 \ mmc.exe C: \ Windows \ system32 \ services.msc» или «C: \ Windows \ system32 \ mmc.exe C: \ Windows \ system32 \ azman.msc» для оснастки MMC.

Чтобы увидеть больше информации о процессе вызова, вы можете StackWalk64 (см. http://msdn.microsoft.com/en-us/library/ms680650(VS.85).aspx) функцию. См. http://stackwalker.codeplex.com/ или http://www.codeproject.com/KB/threads/StackWalker.aspx для хорошего примера кода.

...