Marshal.GetActiveObject()在C#中抛出MK_E_UNAVAILABLEexception

以下vbscript代码完美地工作:

Dim App Set App = GetObject("","QuickTest.Application") App.Quit 

但是,当我将其翻译成C#代码时,如下所示:

 class Program { [STAThread] static void Main(string[] args) { object qtApp = Marshal.GetActiveObject("QuickTest.Application"); (qtApp as QuickTest.Application).Quit(); } } 

我得到了例外:

mscorlib.dll中发生未处理的“System.Runtime.InteropServices.COMException”类型exception

附加信息:(来自HRESULT的exception:0x800401E3(MK_E_UNAVAILABLE))

我不认为问题与ROT有关,因为vbscript代码有效。 那么C#代码有什么问题?

Marshal.GetActiveObject使用progID,检查你的progID,例如你可以将这个代码用于ROT中的显示对象

 using System.Collections.Generic; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; using System.Text; using Microsoft.Win32; ... class Program { private const int S_OK = 0x00000000; [DllImport("ole32.dll")] private static extern int GetRunningObjectTable(uint reserved, out IRunningObjectTable pprot); [DllImport("ole32.dll")] private static extern int CreateBindCtx(uint reserved, out IBindCtx ppbc); private static void OleCheck(string message, int result) { if (result != S_OK) throw new COMException(message, result); } private static System.Collections.Generic.IEnumerable EnumRunningObjects() { IRunningObjectTable objTbl; OleCheck("GetRunningObjectTable failed", GetRunningObjectTable(0, out objTbl)); IEnumMoniker enumMoniker; IMoniker[] monikers = new IMoniker[1]; objTbl.EnumRunning(out enumMoniker); enumMoniker.Reset(); while (enumMoniker.Next(1, monikers, IntPtr.Zero) == S_OK) { yield return monikers[0]; } } private static bool TryGetCLSIDFromDisplayName(string displayName, out string clsid) { var bBracket = displayName.IndexOf("{"); var eBracket = displayName.IndexOf("}"); if ((bBracket > 0) && (eBracket > 0) && (eBracket > bBracket)) { clsid = displayName.Substring(bBracket, eBracket - bBracket + 1); return true; } else { clsid = string.Empty; return false; } } private static string ReadSubKeyValue(string keyName, RegistryKey key) { var subKey = key.OpenSubKey(keyName); if (subKey != null) { using(subKey) { var value = subKey.GetValue(""); return value == null ? string.Empty : value.ToString(); } } return string.Empty; } private static string GetMonikerString(IMoniker moniker) { IBindCtx ctx; OleCheck("CreateBindCtx failed", CreateBindCtx(0, out ctx)); var sb = new StringBuilder(); string displayName; moniker.GetDisplayName(ctx, null, out displayName); sb.Append(displayName); sb.Append('\t'); string clsid; if (TryGetCLSIDFromDisplayName(displayName, out clsid)) { var regClass = Registry.ClassesRoot.OpenSubKey("\\CLSID\\" + clsid); if (regClass != null) { using(regClass) { sb.Append(regClass.GetValue("")); sb.Append('\t'); sb.Append(ReadSubKeyValue("ProgID", regClass)); sb.Append('\t'); sb.Append(ReadSubKeyValue("LocalServer32", regClass)); } } } return sb.ToString(); } [STAThread] public static void Main(string[] args) { Console.WriteLine("DisplayName\tRegId\tProgId\tServer"); foreach(var moniker in EnumRunningObjects()) { Console.WriteLine(GetMonikerString(moniker)); } } } 

我发现当您尝试检测的进程在没有提升权限的情况下运行时,以提升的权限(即管理模式)运行调试器/ IDE会导致此问题。

使用提升的权限运行也可以触发此问题。 多年来这似乎已经发生了变化,因此请尝试使用或不使用提升权限运行IDE或目标程序的所有排列。

截至2017年8月,为了在Visual Studio 2015调试器下获取运行的Outlook 365实例,我必须执行以下操作以避免MK_E_UNAVAILABLE错误:

  • 以管理员身份启动Outlook
  • 以管理员身份启动Visual Studio

然后,我在调试器中运行的程序能够成功运行Outlook的运行实例。