私のプログラムでは、Running Object Table (ROT) を使用して、プログラムのインスタンスが 1 つだけ実行されるようにしています。私は残念ながら会社を去った開発者からそのコードを「継承」しているため、問題を解決するのは貧しい人です。コードは問題なく動作しますが、39,000 のうち 3 人の顧客が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)) です。
次に、「調査者」ケン・ブリテンの質問に対する回答: - SharePointは混同されていません- ROT から正しいオブジェクトを要求することを確信しています - もう 1 つのヒントは、おそらく 3 つの問題のうちの 1 つ (39,000 が正常に動作していること以外) が実行されていることです。 WTS (Windows ターミナル サーバー) 上のアプリ
編集3:
これらの例外の 1 つのスタック トレースを次に示します。
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);
}
}