У меня есть C++ прежней версии "механизм решения", который я уже перенес как незавершенный COM-объект для использования клиентскими приложениями, которые только требуют единственного "механизма решения".
Однако у меня теперь есть клиентское приложение, которое требует нескольких "механизмов решения". К сожалению, базовый унаследованный код имеет достаточно глобальных данных, одиночных элементов и ужасов поточной обработки, что данный имеющиеся ресурсы не возможно иметь несколько экземпляров его незавершенный одновременно.
То, что я надеюсь, - то, что некоторая добрая душа может сказать мне о некотором волшебстве COM, где с зеркальным отражением нескольких настроек реестра возможно иметь отдельный сервер COM из процесса (отдельный процесс операционной системы) для каждого экземпляра COM-объекта, который требуют.
Я нахожусь в удаче?
Да, это возможно. Ключ в том, чтобы зарегистрировать ваш кокласс, вызвав CoRegisterClassObject, и OR в значении REGCLS_SINGLEUSE в параметре flags
.
Если ваш проект является проектом ATL 7. 0+, вы можете сделать это, переопределив CAtlExeModuleT::PreMessageLoop(), который отвечает за регистрацию объекта класса, следующим образом:
HRESULT CATLHacksModule::PreMessageLoop(int nShow)
{
HRESULT hr = RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE);
if (hr == S_OK)
{
if (m_bDelayShutdown && !StartMonitor())
{
hr = E_FAIL;
}
}
else
{
m_bDelayShutdown = false;
}
return hr;
}
Для блокировки экземпляра EXE потребуется кокласс "master", похожий на интерфейс "Application". Найдите вызов CoRegisterClassObject() для его фабрики. И измените аргумент REGCLS на REGCLS_SINGLEUSE.
Это автоматически отменит регистрацию фабрики классов, как только к ней подключится первый клиент. Вызов CoCreateInstance() для этой фабрики снова запускает новый экземпляр сервера. Я думаю.
Я почти уверен, что это невозможно. Внепроцессный COM-сервер должен глобально зарегистрировать объекты класса, которые он предоставляет (через CoRegisterClassObject); часть этой регистрации - GUID класса. Очевидно, вы не можете зарегистрировать один и тот же GUID дважды.