在我的程序中,我使用运行对象表 (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:
首先对所有调查人员来说是一个很大的借口,我们没有得到 AccessDeniedException 它是一个 System.UnauthorizedAccessException (HRESULT: 0x80070005 (E_ACCESSDENIED))。
其次,“调查员”Ken Brittain 的问题的答案:-SharePoint不在其中-我愿意向 ROT 请求正确的对象-另一个提示可能是 3 个问题中的 1 个(除了 39,000 个正常工作)正在运行WTS(Windows 终端服务器)上的应用程序
编辑3:
这是其中一个异常的堆栈跟踪:(我已经翻译了堆栈跟踪,因为它在德国机器上)
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);
}
}