C# GetActiveObject()在C中引发MK_E_不可用异常#

C# GetActiveObject()在C中引发MK_E_不可用异常#,c#,com-interop,C#,Com Interop,以下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"

以下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”的未处理异常

其他信息:(来自HRESULT的异常:0x800401E3(MK_E_不可用))


我认为这个问题与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<IMoniker> 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));
        }
    }
}  
使用System.Collections.Generic;
使用System.Runtime.InteropServices;
使用System.Runtime.InteropServices.ComTypes;
使用系统文本;
使用Microsoft.Win32;
...
班级计划
{
私有常量int S_OK=0x00000000;
[DllImport(“ole32.dll”)]
私有静态外部int GetRunningObjectTable(uint保留,out IRunningObjectTable pprot);
[DllImport(“ole32.dll”)]
私有静态外部int CreateBindCtx(uint保留,out IBindCtx ppbc);
私有静态无效检查(字符串消息,int结果)
{
如果(结果!=S_正常)
抛出新的COMException(消息、结果);
}
私有静态System.Collections.Generic.IEnumerable EnumRunningObjects()
{           
IrunningObjectTableOBJTBL;
OleCheck(“GetRunningObjectTable失败”,GetRunningObjectTable(0,out objTbl));
IEnumMoniker enumMoniker;
IMoniker[]名字=新IMoniker[1];
objTbl.EnumRunning(超出enumMoniker);
enumMoniker.Reset();
while(enumMoniker.Next(1,名字对象,IntPtr.Zero)==S_OK)
{
收益率别名[0];
}
}
私有静态bool TryGetCLSIDFromDisplayName(字符串displayName,输出字符串clsid)
{
var bBracket=displayName.IndexOf(“{”);
var eBracket=displayName.IndexOf(“}”);
如果((b帧>0)和&(eBracket>0)和&(eBracket>b帧))
{
clsid=displayName.Substring(bBracket,eBracket-bBracket+1);
返回true;
}
其他的
{
clsid=string.Empty;
返回false;
}   
}
私有静态字符串ReadSubKeyValue(字符串keyName、注册表项key)
{
var subKey=key.OpenSubKey(keyName);
if(子键!=null)
{
使用(子键)
{
var value=subKey.GetValue(“”);
返回值==null?字符串。空:value.ToString();
}
}
返回字符串。空;
}
私有静态字符串GetMonitorString(IMoniker名字对象)
{
IBindCtx-ctx;
OleCheck(“CreateBindCtx失败”,CreateBindCtx(0,out ctx));
var sb=新的StringBuilder();
字符串显示名;
GetDisplayName(ctx,null,out displayName);
某人附加(显示名称);
sb.追加('\t');
字符串clsid;
if(TryGetCLSIDFromDisplayName(displayName,out clsid))
{
var regClass=Registry.ClassesRoot.OpenSubKey(“\\CLSID\\”+CLSID);
if(regClass!=null)
{
使用(regClass)
{
sb.Append(regClass.GetValue(“”);
sb.追加('\t');
sb.Append(ReadSubKeyValue(“ProgID”,regClass));
sb.追加('\t');
sb.Append(ReadSubKeyValue(“LocalServer32”,regClass));
}
}
}
使某人返回字符串();
}
[状态线程]
公共静态void Main(字符串[]args)
{
Console.WriteLine(“DisplayName\tRegId\tProgId\tServer”);
foreach(EnumRunningObjects()中的变量名字对象)
{
Console.WriteLine(GetMonikerString(名字对象));
}
}
}  

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

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

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

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

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

谢谢!我使用您的代码列出ROT中的对象,发现列表中没有任何与QuickTest相关的对象。但奇怪的是,vbscript代码仍然有效!vbscript的GetObject()函数是否不像C#对应函数那样查找ROT?MSDN GetObject第一句话:“如果路径名为零长度字符串(“”),GetObject将返回指定类型的新对象实例。”,因此VBScript创建QuickTest.Application的新实例,而C#中的代码必须类似于var qtApp=new QuickTest.Application()。。。我将C#代码更改为var qtApp=new QuickTest.Application();而且它有效!非常感谢你!如果没有ProgID怎么办?我真傻,我没有看到你的评论。所以我一直在尝试,直到我意识到要尝试在受限命令提示符下运行我的程序。它成功了。然后我来这里补充我新发现的知识,我看到了你的评论。哦,好吧。干杯