我正在尝试用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);
}
}
}