2011-10-12 7 views
13

でMK_E_UNAVAILABLE例外をスローMarshal.GetActiveObject()は次のVBScriptコードは、罰金prefectly作品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))

vbscriptコードが動作するため、問題はROTに関連していないと思います。では、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()関数は、C#のそれと同じようにROTを検索しませんか? – 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またはターゲットプログラムのいずれかを実行して、昇格された特権の有無にかかわらずすべての順列を試してみてください。管理者

  • スタートとして

    • Outlookを起動:Visual Studioの2015デバッガで展望365の実行中のインスタンスを取得するために、私はMK_E_UNAVAILABLEエラーを回避するには、以下の操作を行う必要がありました2017年8月の時点で

      、 Visual Studioの管理者

    デバッガで実行されているプログラムが、実行中のOutlookインスタンスを正常に取得できました。

  • 関連する問題