2011-10-12 30 views
13

El siguiente código de VBScript obras prefectamenta bien:Marshal.GetActiveObject() lanza una excepción MK_E_UNAVAILABLE en C#

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

Pero cuando se traducen en código C# de la siguiente manera:

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

tengo la excepción :

Se produjo una excepción no controlada del tipo 'System.Runtime.InteropServices.COMException' en mscorlib.dll

Información adicional: (Excepción de HRESULT: 0x800401e3 (MK_E_UNAVAILABLE))

No creo que el problema está relacionado a la pudrición, porque el código VBScript funciona. Entonces, ¿qué está mal con el código C#?

Respuesta

10

Marshal.GetActiveObject use progID, verifique su ID prog, p. Ej. usted podría utilizar este código para los objetos de visualización en 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

gracias! Utilicé su código para listar objetos en ROT, encontrando que no hay ningún objeto relacionado con QuickTest en la lista. ¡Pero, curiosamente, el código de vbscript aún funciona! ¿La función GetObject() de vbscript no busca el ROT como lo hace la contraparte C#? – TomCaps

+1

http://msdn.microsoft.com/en-us/library/kdccchxa%28v=vs.85%29.aspx MSDN GetObject primera observación: "Si pathname es una cadena de longitud cero (" "), GetObject returns una nueva instancia de objeto del tipo especificado. ", por lo que su VBScript creará una nueva instancia de QuickTest.Application, y su código en C# tiene que ser como var qtApp = new QuickTest.Application(); ... – MishaU

+0

Cambié el código de C# en var qtApp = new QuickTest.Application(); ¡y funciona! ¡muchas gracias! – TomCaps

29

me encontré con que ejecuta el depurador/IDE con privilegios elevados (es decir, el modo de administrador) puede causar este problema cuando el proceso que está intentando detectar es correr sin privilegios elevados .

+2

Tonto, yo no vi tu comentario. Así que lo intenté y lo intenté hasta que se me ocurrió intentar ejecutar mi programa desde un símbolo del sistema restringido. Y funcionó. Y luego vine aquí para agregar mi conocimiento recién descubierto, y vi tu comentario. Oh bien. ¡Aclamaciones! –

0

El problema también puede ser provocado por no ejecutándose con privilegios elevados. Esto parece haber cambiado a lo largo de los años, así que pruebe todas las permutaciones de ejecutar el IDE o el programa de destino con o sin privilegios elevados.

En agosto de 2017, para obtener la instancia en ejecución de Perspectivas 365 bajo el Visual Studio 2015 depurador, que tenía que hacer lo siguiente para evitar el error MK_E_UNAVAILABLE:

  • de inicio de Outlook como administrador
  • de inicio Visual Studio como administrador

Mi programa ejecutándose en el depurador fue capaz de obtener la instancia en ejecución de Outlook con éxito.

Cuestiones relacionadas