WMI:通过InstrumentationManager向WMI存储库注册程序集.RegisterAssembly



我正在尝试用C#(3.5版)编写WMI提供程序。它将是一个dll,我可以安装到GAC中,它通过管道与正在运行的服务通信。由于服务上有一个自定义的更新程序机制,我想用WMI存储库以编程方式注册和注销提供程序,而不是使用installutil.exe。

为了隔离我的问题并一次解决一个问题,我从以下链接开始使用示例提供程序:https://msdn.microsoft.com/en-us/library/cc268228.aspx.我可以将其构建为DLL,将其插入GAC(gacuti.exe),并通过InstallUtil.exe将其注册到WMI存储库。通过powershell对其进行的查询可以正常工作,当我使用wbemtest.exe时,我可以在其命名空间下看到其类。

但是,当我使用为使用InstrumentationManager编写的单独应用程序时,我尝试向WMI存储库注册程序集时失败了。RegisterAssembly。

下面是我尝试基于上面的示例以程序方式安装DLL。我非常感谢任何关于示例的指导或说明,这些示例显示了如何以这种方式实现提供者dll。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;
using System.Management.Instrumentation;
using System.Configuration.Install;
//using System.EnterpriseServices.Internal;
namespace wmi_register_tool
{
    class Program
    {
        static void Main(string[] args)
        {
            bool installing = true;
            string asmPath = "";
            if (!ParseInput(args, ref installing, ref asmPath))
            {
                PrintUsage();
                return;
            }
            Assembly myAssem = Assembly.Load(File.ReadAllBytes(asmPath));
            Console.WriteLine(myAssem.FullName);
            Console.WriteLine("Types contained in " + asmPath + " assembly");

            foreach (Type oType in myAssem.GetTypes())
            {
                Console.WriteLine("t" + oType.Name);
            }
            //Publish p = new Publish();
            //p.RegisterAssembly(myAssem);
            AssemblyInstaller wmi_installer = new AssemblyInstaller(myAssem, null);
            Console.WriteLine("--------------> Starting AssemblyInstaller.Install()");
            wmi_installer.Install(null);
            Console.WriteLine("--------------> Done with AssemblyInstaller.Install()");
            Console.WriteLine("--------------> Starting AssemblyInstaller.Commit()");
            wmi_installer.Commit(null);
            Console.WriteLine("--------------> Done with AssemblyInstaller.Commit()");
            try
            {
                Console.WriteLine("--------------> Starting Instrumentation.RegisterAssembly()");
                //Instrumentation.RegisterAssembly(myAssem);
                InstrumentationManager.RegisterAssembly(myAssem);
                Console.WriteLine("--------------> Done with Instrumentation.RegisterAssembly()");
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception Caught: {0}", e);
                Console.WriteLine("Exception Message: " + e.Message);
            }
        }
        static bool ParseInput(string[] args, ref bool installing, ref string asmPath)
        {
            if (args.Length < 2 || args[0].Equals("/h") || args[0].Equals("-h"))
            {
                return false;
            }
            asmPath = args[1];
            if (args[0].Equals("-i"))
            {
                installing = true;
                return true;
            }
            else if(args.Equals("-u"))
            {
                installing = false;
                return true;
            }
            return false;
        }
        static void PrintUsage()
        {
            System.Console.WriteLine("wmi_register_tool.exe nt-i <filename>nt-u <filename>");
        }
    }
}

我在它似乎成功的地方得到了以下输出,但在WMI存储库中找不到任何东西,所以RegisterAssembly一定没有成功插入它。

C:wmi_testing>"C:Program Files (x86)Microsoft SDKsWindowsv7.0ABingacutil.exe" /i WmiServic
eHost.dll
Microsoft (R) .NET Global Assembly Cache Utility.  Version 3.5.30729.1
Copyright (c) Microsoft Corporation.  All rights reserved.
Assembly successfully added to the cache
C:wmi_testing>wmi_register_tool.exe -i WmiServiceHost.dll
WmiServiceHost, Version=1.0.0.3, Culture=neutral, PublicKeyToken=3cd934646523c30c
Types contained in WmiServiceHost.dll assembly
        SERVICE_STATUS_PROCESS
        SCM_ACCESS
        SERVICE_ACCESS
        SC_STATUS_TYPE
        ServiceHandle
        SCM
        MyInstall
        Win32_Process
        WIN32ServiceHost
        <EnumerateServiceHosts>d__0
--------------> Starting AssemblyInstaller.Install()
Installing assembly 'C:WindowsassemblyGAC_MSILWmiServiceHost1.0.0.3__3cd934646523c30cWmiServiceHost.dll'.
Affected parameters are:
   assemblypath = C:WindowsassemblyGAC_MSILWmiServiceHost1.0.0.3__3cd934646523c30cWmiServiceHost.dll
   logfile = C:WindowsassemblyGAC_MSILWmiServiceHost1.0.0.3__3cd934646523c30cWmiServiceHost.InstallLog
Installing WMI Schema: Started
Registering assembly: WmiServiceHost_SN_3cd934646523c30c_Version_1.0.0.3
Ensuring that namespace exists: rootMicrosoftWmiNet
Ensuring that class exists: rootMicrosoftWmiNet:WMINET_Instrumentation
Ensuring that class exists: CREATING  rootMicrosoftWmiNet:WMINET_Instrumentation
Ensuring that class exists: rootMicrosoftWmiNet:WMINET_InstrumentedNamespaces
Ensuring that class exists: CREATING  rootMicrosoftWmiNet:WMINET_InstrumentedNamespaces
Ensuring that class exists: rootMicrosoftWmiNet:WMINET_Naming
Ensuring that class exists: CREATING  rootMicrosoftWmiNet:WMINET_Naming
Ensuring that namespace exists: rootdefault
Ensuring that class exists: rootdefault:WMINET_Instrumentation
Ensuring that class exists: CREATING  rootdefault:WMINET_Instrumentation
Ensuring that class exists: rootdefault:WMINET_InstrumentedAssembly
Ensuring that class exists: CREATING  rootdefault:WMINET_InstrumentedAssembly
Ensuring that class exists: rootdefault:MSFT_DecoupledProvider
Ensuring that class exists: CREATING  rootdefault:MSFT_DecoupledProvider
Ensuring that class exists: rootdefault:WMINET_ManagedAssemblyProvider
Ensuring that class exists: CREATING  rootdefault:WMINET_ManagedAssemblyProvider
Installing WMI Schema: Finished
--------------> Done with AssemblyInstaller.Install()
--------------> Starting AssemblyInstaller.Commit()
See the contents of the log file for the C:WindowsassemblyGAC_MSILWmiServiceHost1.0.0.3__3cd934646523c30cWmiServic
eHost.dll assembly's progress.
The file is located at C:WindowsassemblyGAC_MSILWmiServiceHost1.0.0.3__3cd934646523c30cWmiServiceHost.InstallLog.
Committing assembly 'C:WindowsassemblyGAC_MSILWmiServiceHost1.0.0.3__3cd934646523c30cWmiServiceHost.dll'.
Affected parameters are:
   assemblypath = C:WindowsassemblyGAC_MSILWmiServiceHost1.0.0.3__3cd934646523c30cWmiServiceHost.dll
   logfile = C:WindowsassemblyGAC_MSILWmiServiceHost1.0.0.3__3cd934646523c30cWmiServiceHost.InstallLog
   logtoconsole =
--------------> Done with AssemblyInstaller.Commit()
--------------> Starting Instrumentation.RegisterAssembly()
--------------> Done with Instrumentation.RegisterAssembly()
C:wmi_testing>

编辑:我试着更换Instrumentation。RegisterAssembly使用了以下代码,它再次毫无例外地运行完成,但它向控制台输出了更多信息,表明事情进展顺利。最后结果是一样的,我无法使用wbemtest.exe在WMI存储库中找到我的命名空间。

string[] installArgs = new String[] {
    "//logfile=",
    "//LogToConsole=false",
    "//ShowCallStack",
    myAssem.Location,
};
System.Configuration.Install.
ManagedInstallerClass.InstallHelper(installArgs);

在我试图让RegisterAssembly函数完成这项工作时,我错过了在搜索潜在依赖项时实现目标的事实。AssemblyInstaller。安装和组装安装程序。提交函数已成功将我的提供程序插入WMI存储库。我不确定RegisterAssembly是否删除了它和/或弄乱了条目,或者我是否只是通过持续测试弄乱了WMI存储库,但当我将测试VM重置为干净状态并使用一些新行运行代码时,AssemblyInstaller之后会导致异常。提交并在RegisterAssembly之前,我注意到我的提供程序已正确插入WMI存储库,并且我可以通过powershell查询它。

以下是在我手动将DLL放入GAC后成功将其安装到WMI存储库中的主要内容。

    static void Main(string[] args)
    {
        bool installing = true;
        string asmPath = "";
        if (!ParseInput(args, ref installing, ref asmPath))
        {
            PrintUsage();
            return;
        }
        Assembly myAssem = Assembly.Load(File.ReadAllBytes(asmPath));
        Console.WriteLine(myAssem.FullName);
        AssemblyInstaller wmi_installer = new AssemblyInstaller(myAssem, null);
        wmi_installer.Install(null);
        wmi_installer.Commit(null);
    }

为了完整起见,我将提供另一个版本,它可以在尝试之前卸载并检查程序集是否可以安装。

    static void Main(string[] args)
    {
        bool installing = true;
        bool installable = false;
        string asmPath = "";
        if (!ParseInput(args, ref installing, ref asmPath))
        {
            PrintUsage();
            return;
        }
        IDictionary mySavedState = new Hashtable();
        Assembly myAssem = Assembly.Load(File.ReadAllBytes(asmPath));
        Console.WriteLine(myAssem.FullName);
        AssemblyInstaller wmi_installer = new AssemblyInstaller(myAssem, null);
        if (installing)
        {
            try
            {
                AssemblyInstaller.CheckIfInstallable(asmPath);
                installable = true;
            }
            catch (Exception)
            {
                installable = false;
            }
            if (installable)
            {
                mySavedState.Clear();
                try
                {
                    wmi_installer.Install(mySavedState);
                    wmi_installer.Commit(mySavedState);
                }
                catch (Exception)
                {
                    wmi_installer.Rollback(mySavedState);
                }
            }
        }
        else
        {
            try
            {
                wmi_installer.Uninstall(null);
            }
            catch (Exception e)
            {
                Console.WriteLine("Uninstall failed due to: " + e.Message);
            }
        }
    }

最新更新