c# - 检查 COM+ 应用程序是否已经在运行?

标签 c# com+

是否有可能在 C# (4.0) 中获取同一个盒子上已安装的 Com+ 应用程序的列表,然后检索每个应用程序的状态(运行/关闭)?

我可以找到启动/停止的方法,但不能检索状态。

最佳答案

我认为 COM+ 管理组件只允许您查询“静态”配置属性(例如 Identity、IsEnabled),不允许您查询 COM+ 的动态属性(例如 PID)。

我发现做你想做的事情的唯一方法是使用 COMSVCSLib(COM+ 服务类型库)。

更新:根据@Vagaus 的评论,我们可以使用COM+ 管理组件或COM+ 服务类型库!

在文章 Comonitor - A COM+ Monitor 的帮助下.我拼凑了一些使用 COM+ 服务类型库的代码:

public static bool IsComPlusApplicationRunning(string appName)
{
    int appDataSize = Marshal.SizeOf(typeof(COMSVCSLib.appData));
    Type appDataType = typeof(COMSVCSLib.appData);

    uint appCount;
    IntPtr appDataPtr = IntPtr.Zero;    

    GCHandle gh = GCHandle.Alloc(appDataPtr, GCHandleType.Pinned);
    IntPtr addressOfAppDataPtr = gh.AddrOfPinnedObject();

    COMSVCSLib.IGetAppData getAppData = null;
    COMSVCSLib.TrackerServer tracker = null;

    try
    {
        tracker = new COMSVCSLib.TrackerServerClass();
        getAppData = (COMSVCSLib.IGetAppData)tracker;

        getAppData.GetApps(out appCount, addressOfAppDataPtr);
        appDataPtr = new IntPtr(Marshal.ReadInt32(addressOfAppDataPtr));

        for (int appIndex = 0; appIndex < appCount; appIndex++)
        {
            COMSVCSLib.appData appData = (COMSVCSLib.appData)Marshal.PtrToStructure(
                new IntPtr(appDataPtr.ToInt32() + (appIndex * appDataSize)),
                appDataType);

            string currentAppName = GetPackageNameByPID(appData.m_dwAppProcessId);

            if (string.Compare(currentAppName, appName, StringComparison.OrdinalIgnoreCase) == 0)
            {
                Console.WriteLine("Application " + appName + " is running with PID " + appData.m_dwAppProcessId);
                return true;
            }            
        }
    }
    finally
    {
        Marshal.FreeCoTaskMem(appDataPtr);

        if (tracker != null)
        {
            Marshal.ReleaseComObject(tracker);
        }

        gh.Free();
    }

    return false;
}

private static string GetPackageNameByPID(uint PID)
{
    COMSVCSLib.MtsGrp grpObj = new COMSVCSLib.MtsGrpClass();

    try
    {
        object obj = null;
        COMSVCSLib.COMEvents eventObj = null;

        for (int i = 0; i < grpObj.Count; i++)
        {
            try
            {
                grpObj.Item(i, out obj);

                eventObj = (COMSVCSLib.COMEvents)obj;

                if (eventObj.GetProcessID() == PID)
                {
                    return eventObj.PackageName;
                }
            }
            finally
            {
                if (obj != null)
                {
                    Marshal.ReleaseComObject(obj);
                }
            }
        }
    }
    finally
    {
        if (grpObj != null)
        {
            Marshal.ReleaseComObject(grpObj);
        }
    }

    return null;
}


但我们也可以使用 COM+ 管理组件(这看起来更简单)来做同样的事情:

public static bool IsComPlusApplicationRunning(string appName)
{
    COMAdmin.COMAdminCatalog catalog = new COMAdmin.COMAdminCatalogClass();

    COMAdmin.ICatalogCollection appCollection = (COMAdmin.ICatalogCollection)catalog.GetCollection("Applications");
    appCollection.Populate();

    Dictionary<string, string> apps = new Dictionary<string, string>();
    COMAdmin.ICatalogObject catalogObject = null;

    // Get the names of the applications with their ID and store for later
    for (int i = 0; i < appCollection.Count; i++)
    {
        catalogObject = (COMAdmin.ICatalogObject)appCollection.get_Item(i);
        apps.Add(catalogObject.get_Value("ID").ToString(), catalogObject.Name.ToString());
    }

    appCollection = (COMAdmin.ICatalogCollection)catalog.GetCollection("ApplicationInstances");
    appCollection.Populate();

    for (int i = 0; i < appCollection.Count; i++)
    {
        catalogObject = (COMAdmin.ICatalogObject)appCollection.get_Item(i);

        if (string.Compare(appName, apps[catalogObject.get_Value("Application").ToString()], StringComparison.OrdinalIgnoreCase) == 0)
        {
            Console.WriteLine(appName + " is running with PID: " + catalogObject.get_Value("ProcessID").ToString());
            return true;
        }
    }

    return false;
}

关于c# - 检查 COM+ 应用程序是否已经在运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3726609/

相关文章:

java - com4j 与 jacob 从 Java 调用 COM 方法

wpf - 托管 WPF 和 native 代码互操作。 WPF 托管在 ServicedComponent 中

c# - 使用 C# 类库作为 COM+ 服务器应用程序

C#:为什么 ShowDialog().ToString() 不返回预期的字符串?

c# - 从 url 中获取参数

c# - 使用反射获取特定键的字典完整路径

c# - 组件服务 COM+ C# 不太对劲?

c# - 如何在注入(inject)的类上调用泛型方法而不通知泛型类型的父类?

c# - 如何确定 C# 中方法参数的适当类型?

C++ COM+ 方法参数推导