2011-10-12 103 views
13

下面的VBScript代码工作prefectly罚款:Marshal.GetActiveObject()抛出C#MK_E_UNAVAILABLE例外

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(); 
    } 
} 

我得到的异常:

类型'System.Runtime.InteropServices.COMException'发生在mscorlib.dll中的未处理的异常

附加信息:(从HRESULT异常:0x800401E3(MK_E_UNAVAILABLE))

我不认为这个问题是关系到ROT,因为VBScript代码工作。那么C#代码有什么问题?

回答

10

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)); 
     } 
    } 
} 
+1

谢谢!我用你的代码来列出ROT中的对象,发现列表中没有任何QuickTest相关的对象。但奇怪的是,VBScript代码仍然有效! vbscript的GetObject()函数不会查找ROT,因为它是C#对应的吗? – TomCaps

+1

http://msdn.microsoft.com/en-us/library/kdccchxa%28v=vs.85%29.aspx MSDN GetObject 1st remark: “如果路径名是零长度字符串(”“),GetObject返回一个新的指定类型的对象实例“,所以你的VBScript创建QuickTest.Application的新实例,并且你在C#中的代码必须像 var qtApp = new QuickTest.Application(); ... – MishaU

+0

我将C#代码更改为var qtApp = new QuickTest.Application();它的工作原理!非常感谢你! – TomCaps

29

用于显示对象这个代码,我发现,运行与提升的权限(即管理模式)调试器/ IDE可能引起这个问题,当你试图检测过程没有提升的权限运行。

+2

傻了,我没有看到你的评论。所以我一直在努力尝试,直到它开始尝试从受限制的命令提示符运行我的程序。它的工作。然后我来到这里添加我最新发现的知识,并且我看到了您的评论。好吧。干杯! –

0

该问题也可以由而不是以提升的权限运行来触发。这似乎在多年以来一直在改变,因此请尝试使用或不使用提升权限运行IDE或目标程序的所有排列组合。

截至2017年8月,以获得在Visual Studio 2015年调试器下的Outlook 365的运行实例,我不得不做以下,以避免MK_E_UNAVAILABLE错误:

  • 启动Outlook作为管理员
  • 开始Visual Studio作为管理员

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

相关问题