В моей программе я использую таблицу Running Object (ROT), чтобы гарантировать, что работает только один экземпляр моей программы. Поскольку я "наследую" этот код от разработчика, который, к сожалению, покинул компанию, я бедный парень, чтобы решить проблемы. Код работает отлично, но у нас есть 3 клиента (из 39 000), которые получат AccessDeniedException
. Каждый клиент запускает программное обеспечение в пользовательском режиме.
Любые предложения, что может быть неправильным?
bool retVal = false;
IMoniker[] arrMoniker = new IMoniker[1];
IBindCtx bindCtx = null;
string displayName;
int hResult;
int mkSys;
Guid clsidRot;
bool guidCompare = false;
IntPtr number = IntPtr.Zero;
moreObjectsListed = false;
objectFromRot = null;
try
{
// check the objects in the running object table for fitting the specified class id
while ((retVal == false) && (0 == enumMoniker.Next(1, arrMoniker, number)))
{
hResult = CreateBindCtx(0, out bindCtx);
if (hResult == 0)
{
arrMoniker[0].IsSystemMoniker(out mkSys);
if (mkSys == 4)
{
try
{
// the display name is the class id of the object in the table
// --> AccessDeniedException raises here <--
arrMoniker[0].GetDisplayName(bindCtx, null, out displayName);
clsidRot = new Guid(displayName.Substring(1));
guidCompare = clsidRot.Equals(clsid);
}
catch(Exception) {}
// an object with fitting class id was found
if (guidCompare == true)
{
rot.IsRunning(arrMoniker[0]);
rot.GetObject(arrMoniker[0], out objectFromRot);
retVal = true;
}
}
}
}
}
finally
{
if (arrMoniker[0] != null)
{
moreObjectsListed = true;
Marshal.ReleaseComObject(arrMoniker[0]);
}
if (bindCtx != null)
{
Marshal.ReleaseComObject(bindCtx);
}
}
Изменить: Вот запрошенный код для регистрации объекта в ROT:
internal static extern uint RegisterActiveObject([MarshalAs(UnmanagedType.IUnknown)]object pIUnknown, ref Guid refclsid, uint flags, out uint pdwRegister);
internal const uint ActiveObjectStrong = 0;
...
NativeMethods.RegisterActiveObject(this, ref guid, NativeMethods.ActiveObjectStrong, out this.runningObjectTableRegisteredId);
Изменить 2:
Прежде всего, большой EXCUSE для всех исследователей, мы не получаем AccessDeniedException, это System.UnauthorizedAccessException(HRESULT: 0x80070005 (E_ACCESSDENIED)).
Во-вторых, ответы на вопросы "следователя" Кена Бриттайна: - SharePoint не находится в миксе - Я пытаюсь запросить правильный объект из ROT - Еще одна подсказка может быть, что одна из 3 проблем (кроме 39 000, работающих правильно) запускает приложения на WTS (сервер терминалов Windows)
Изменить 3:
Вот стоп-тракт одного из этих исключений: (я перевел stacktrace, потому что он был на немецкой машине)
System.UnauthorizedAccessException: Access denied (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
at System.Runtime.InteropServices.ComTypes.IRunningObjectTable.EnumRunning(IEnumMoniker& ppenumMoniker)
at Datev.Framework.DirectStart.RunningObjectTableClientManager..ctor()
Остальная часть трассировки стека находится в нашем коде. В этом случае можно отметить, что исключение возникает в конструкторе нашего RunningObjectTableClientManager. Вот код этого конструктора:
private IRunningObjectTable rot;
private IEnumMoniker enumMoniker;
public RunningObjectTableClientManager()
{
int retVal = GetRunningObjectTable(0, out this.rot);
if (retVal == 0)
{
rot.EnumRunning(out this.enumMoniker);
}
}