Feedback

C# - Laufende COM-Objekte abfragen

Veröffentlicht von am 03.05.2007
(2 Bewertungen)
Viele bekannte Anwendungen (z.B. Excel, Word, Access, Outlook oder Visual Studio) bieten Automatisierungsmöglichkeiten über COM-Schnittstellen. Manchmal möchte man eine bereits geöffnete Instanz einer solchen Anwendung fernsteuern. Wenn nun z.B. aber gleich mehrere Excel-Sheets gleichzeitig geöffnet sind? Wie findet man die richtige Instanz?

Das geht über die "Running Object Table". Dort werden laufende Objekte registiert, die als COM-Server fungieren. Jedes laufende Objekt bekommt einen Namen. Oft ist es der Dateiname des Dokuments oder eine GUID (Das hängt von der Anwendung ab).

Das folgende Snippet gibt alle laufenden COM-Objekte aus der Running Object Table zurück und kann direkt auf die einzelnen Objekte über ihren Namen zugreifen.
GFU-Schulungen  [Anzeige]

C# Komplett

Sie kennen sich in objektorientierter Programmierung aus. Sie schreiben C++ oder Java? Und nun stehen Sie vor der Aufgabe, in C# Anwendungen zu erstellen. Das C# Komplett-Seminar verschafft Ihnen umfassende Programmierkenntnisse in dieser Sprache. Nach der Schulung entwickeln Sie selbständig Anwendungen mit C#. Sie kennen die Datentypen und Klassenbibliotheken der objektorientierten Programmiersprache C#. Der Komplettkurs setzt bei den Grundlagen von C# ein. Sie arbeiten mit Variablen und konvertieren Typen. Multithreading, Delegates, Generics sind nach dem Seminar für Sie kein Geheimnis mehr.

ASP.NET Core und Angular Komplett für .NET-Entwickler

Sie  lernen in drei (3) Tagen wie man mit  ASP.NET Core und den Technologien  MVC, Entity Framework, WebAPI und  Razor professionelle sowie moderne  Web-Anwendungsarchitekturen aufbaut.  Die Schulung ist der perfekte  Einstieg um insbesondere datengetriebene  und präsentationsorientierte  Applikationen auf Basis der robusten und  skalierbaren ASP.NET Core  Plattform zu erstellen. Nach der Veranstaltung kennen Sie die Konzepte von Angular und können Angular in neue und bestehende ASP.NET-Anwendungen einsetzen.

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;

namespace Rainbird.Tools.COMInterop
{
    /// <summary>
    /// Ermöglicht .NET-Anwendungen direkten Zugriff auf die Running Object Table (Tabelle mit allen momentan laufenden COM-Objekte)
    /// </summary>
    public class RunningObjectTable
    {
        /// <summary>
        /// Privater Standardkonstruktor.
        /// </summary>
        private RunningObjectTable() { }

        // Win32-API-Aufruf zum lesen der ROT
        [DllImport("ole32.dll")]
        private static extern int GetRunningObjectTable(uint reserved, out IRunningObjectTable pprot);

        // Win32-API-Aufruf zum erstellen von Bindungen
        [DllImport("ole32.dll")]
        private static extern int CreateBindCtx(uint reserved, out IBindCtx pctx);

        /// <summary>
        /// Gibt einen Verweis auf eine laufendes COM-Objekt anhand ihres Anzeigenamens zurück.
        /// </summary>
        /// <param name="objectDisplayName">Anzeigename einer COM-Instanz</param>
        /// <returns>Verweis auf COM-Objekt, oder null, wenn kein COM-Objekt mit dem angegbenen Namen läuft</returns>
        public static object GetRunningCOMObjectByName(string objectDisplayName)
        {
            // ROT-Schnittstelle
            IRunningObjectTable runningObjectTable = null;

            // Moniker-Auflistung
            IEnumMoniker monikerList = null;

            try
            {
                // Running Object Table abfragen und nichts zurückgeben, wenn keine COM-Objekte laufen
                if (GetRunningObjectTable(0, out runningObjectTable) != 0 || runningObjectTable == null) return null;

                // Moniker abfragen
                runningObjectTable.EnumRunning(out monikerList);

                // An den Anfang der Auflistung springen
                monikerList.Reset();

                // Array für Moniker-Abfrage erzeugen
                IMoniker[] monikerContainer = new IMoniker[1];

                // Zeiger auf die Anzahl der tatsächlich abgefragten Moniker erzeugen
                IntPtr pointerFetchedMonikers = IntPtr.Zero;

                // Alle Moniker durchlaufen
                while (monikerList.Next(1, monikerContainer, pointerFetchedMonikers) == 0)
                {
                    // Objekt für Bindungsinformationen
                    IBindCtx bindInfo;

                    // Variable für den Anzeigenamen des aktuellen COM-Objekts
                    string displayName;

                    // Bindungsobjekt erzeugen
                    CreateBindCtx(0, out bindInfo);

                    // Anzeigename des COM-Objekts über den Moniker abfragen
                    monikerContainer[0].GetDisplayName(bindInfo, null, out displayName);

                    // Bindungsobjekt entsorgen
                    Marshal.ReleaseComObject(bindInfo);

                    // Wenn der Anzeigename mit dem gesuchten übereinstimmt ...
                    if (displayName.IndexOf(objectDisplayName) != -1)
                    {
                        // Variable für COM-Objekt
                        object comInstance;

                        // COM-Objekt über den Anzeigenamen abrfragen
                        runningObjectTable.GetObject(monikerContainer[0], out comInstance);

                        // COM-Objekt zurückgeben
                        return comInstance;
                    }
                }
            }
            catch
            {
                // Nichts zurückgeben
                return null;
            }
            finally
            {
                // Ggf. COM-Verweise entsorgen
                if (runningObjectTable != null) Marshal.ReleaseComObject(runningObjectTable);
                if (monikerList != null) Marshal.ReleaseComObject(monikerList);
            }
            // Nichts zurückgeben
            return null;
        }

        /// <summary>
        /// Gibt eine Liste mit Anzeigenamen aller momentan laufenden COM-Objekte zurück.
        /// </summary>
        /// <returns>Liste mit Anzeigenamen</returns>
        public static IList<string> GetRunningCOMObjectNames()
        {
            // Auflistung der Anzeigenamen erzeugen
            IList<string> result = new List<string>();

            // Informationsobjekt der laufenden COM-Instanzen
            IRunningObjectTable runningObjectTable = null;

            // Moniker-Auflistung
            IEnumMoniker monikerList = null;

            try
            {
                // Running Object Table abfragen und nichts zurückgeben, wenn keine COM-Objekte laufen
                if (GetRunningObjectTable(0, out runningObjectTable) != 0 || runningObjectTable == null) return null;

                // Moniker abfragen
                runningObjectTable.EnumRunning(out monikerList);

                // An den Anfang der Auflistung springen
                monikerList.Reset();

                // Array für Moniker-Abfrage erzeugen
                IMoniker[] monikerContainer = new IMoniker[1];

                // Zeiger auf die Anzahl der tatsächlich abgefragten Moniker erzeugen
                IntPtr pointerFetchedMonikers = IntPtr.Zero;

                // Alle Moniker durchlaufen
                while (monikerList.Next(1, monikerContainer, pointerFetchedMonikers) == 0)
                {
                    // Objekt für Bindungsinformationen
                    IBindCtx bindInfo;

                    // Variable für den Anzeigenamen des aktuellen COM-Objekts
                    string displayName;

                    // Bindungsobjekt erzeugen
                    CreateBindCtx(0, out bindInfo);

                    // Anzeigename des COM-Objekts über den Moniker abfragen
                    monikerContainer[0].GetDisplayName(bindInfo, null, out displayName);

                    // Bindungsobjekt entsorgen
                    Marshal.ReleaseComObject(bindInfo);

                    // Anzeigenamen der Auflistung zufügen
                    result.Add(displayName);
                }
                // Auflistung zurückgeben
                return result;
            }
            catch
            {
                // Nichts zurückgeben
                return null;
            }
            finally
            {
                // Ggf. COM-Verweise entsorgen
                if (runningObjectTable != null) Marshal.ReleaseComObject(runningObjectTable);
                if (monikerList != null) Marshal.ReleaseComObject(monikerList);
            }
        }
    }
}

Kommentare zum Snippet

 

Logge dich ein, um hier zu kommentieren!