你可以使用Go语言来指定调用WMI时的命名空间。

huangapple go评论85阅读模式
英文:

How can I use the go language to specify the namespace of wmi when calling wmi?

问题

我可以帮你翻译代码部分,以下是翻译好的内容:

我被要求使用Go语言获取本地计算机的一些计算机配置,例如CPU型号和内存大小,但在获取某些配置时遇到了问题。

当我获取基本的CPU信息时,我使用以下代码,它能正常工作,因为Win32_Processor来自root\cimv2

type cpuInfo struct {
	Name          string
	NumberOfCores uint32
	ThreadCount   uint32
	Architecture  uint32
}

func getCPUInfo() {

	var cpuinfo []cpuInfo

	err := wmi.Query("Select * from Win32_Processor", &cpuinfo)
	if err != nil {
		return
	}
	fmt.Printf("Cpu info =", cpuinfo)
	fmt.Println()
}

但是当我需要获取一些特殊信息时,例如网络适配器是否为物理网络适配器,硬盘是SSD还是HDD,我需要使用MSFT_NetAdapterMSFT_PhysicalDisk,它们的命名空间不是root\cimv2,而是来自root\StandardCimv2\root\microsoft\windows\storage

当我使用以下代码获取这些信息时,返回的值为空:

type networkInfo struct {
	Name              string
	DriverDescription string
	InterfaceName     string
}

func getNetworkInfo() {

	var networkinfo []networkInfo
	query := wmi.CreateQuery(&networkinfo, "Select * from MSFT_NetAdapter where Virtual=false")
	err := wmi.QueryNamespace(query, &networkinfo, "Root\\StandardCimv2")
	if err != nil {
		return
	}
	fmt.Printf("Network Info=", networkinfo)
	fmt.Println()
}

当我使用C#调用这个类时,我能正确获取到所需的信息:

var objectSearcher = new ManagementObjectSearcher("root\\StandardCimv2", $@"select DriverDescription, Name, InterfaceName, InterfaceType, NdisPhysicalMedium from MSFT_NetAdapter where ConnectorPresent=1"); //Physical adapter

foreach (var managementObject in objectSearcher.Get())
{
    var interfaceName = managementObject["InterfaceName"]?.ToString();
    var interfaceType = Convert.ToUInt32(managementObject["InterfaceType"]);
    var ndisPhysicalMedium = Convert.ToUInt32(managementObject["NdisPhysicalMedium"]);
    var driverDescription = managementObject["DriverDescription"]?.ToString();
    var name = managementObject["Name"]?.ToString();

    if (!string.IsNullOrEmpty(interfaceName) &&
        interfaceType == 6 &&       
        (ndisPhysicalMedium == 0 || ndisPhysicalMedium == 14))   //802.3
    {
        Console.WriteLine("Name:" + name);
        Console.WriteLine("DriverDescription:" + driverDescription);
        Console.WriteLine("InterfaceName:" + interfaceName);
    }
}

请问我应该如何在Go语言中指定命名空间来调用所需的类?

英文:

I was asked to use the Go language to obtain some computer configurations of the local computer, such as CPU model and memory size,but there was a problem when getting some configurations.

When I get the basic CPU information, I use the following code, which works well because Win32_ Processor from root\cimv2

type cpuInfo struct {
	Name          string
	NumberOfCores uint32
	ThreadCount   uint32
	Architecture  uint32
}

func getCPUInfo() {

	var cpuinfo []cpuInfo

	err := wmi.Query("Select * from Win32_Processor", &cpuinfo)
	if err != nil {
		return
	}
	fmt.Printf("Cpu info =", cpuinfo)
	fmt.Println()
}

But when I need to obtain some special information, such as whether the network card is a physical network card, whether the hard disk is SSD or HDD, I need to use MSFT_ NetAdapter and MSFT_ PhysicalDisk, whose namespaces are not root\cimv2,They come from root\StandardCimv2 and \root\microsoft\windows\storage.
When I use the following code to obtain this information, the returned value is null

type networkInfo struct {
	Name              string
	DriverDescription string
	InterfaceName     string
}

func getNetworkInfo() {

	var networkinfo []networkInfo
	query := wmi.CreateQuery(&networkinfo, "Select * from MSFT_NetAdapter where Virtual=false")
	err := wmi.QueryNamespace(query, &networkinfo, "Root\\StandardCimv2")
	if err != nil {
		return
	}
	fmt.Printf("Network Info=", networkinfo)
	fmt.Println()
}

When I use C# to call this class, I get the information I need correctly

var objectSearcher = new ManagementObjectSearcher("root\\StandardCimv2", $@"select DriverDescription, Name, InterfaceName, InterfaceType, NdisPhysicalMedium from MSFT_NetAdapter where ConnectorPresent=1"); //Physical adapter

foreach (var managementObject in objectSearcher.Get())
{
    var interfaceName = managementObject["InterfaceName"]?.ToString();
    var interfaceType = Convert.ToUInt32(managementObject["InterfaceType"]);
    var ndisPhysicalMedium = Convert.ToUInt32(managementObject["NdisPhysicalMedium"]);
    var driverDescription = managementObject["DriverDescription"]?.ToString();
    var name = managementObject["Name"]?.ToString();

    if (!string.IsNullOrEmpty(interfaceName) &&
        interfaceType == 6 &&       
        (ndisPhysicalMedium == 0 || ndisPhysicalMedium == 14))   //802.3
    {
        Console.WriteLine("Name:" + name);
        Console.WriteLine("DriverDescription:" + driverDescription);
        Console.WriteLine("InterfaceName:" + interfaceName);
    }
}

How should I use the Go language to specify the namespace to call the class I need?

答案1

得分: 1

你正在错误地使用wmi.CreateQuery()函数。请查看https://github.com/StackExchange/wmi/blob/v1.2.1/wmi.go#L566上的参数描述。
你需要在getNetworkInfo()函数中替换你的查询语句:

query := wmi.CreateQuery(&networkinfo, "Virtual=false", "MSFT_NetAdapter")
err := wmi.QueryNamespace(query, &networkinfo, "Root\\StandardCimv2")

而在wmi.QueryNamespace()函数中,写Root或root没有任何区别。我已经验证过了。

英文:

You are using the function wmi.CreateQuery() incorrectly. See the parameters description on https://github.com/StackExchange/wmi/blob/v1.2.1/wmi.go#L566.
You must replace your query in getNetworkInfo():

query := wmi.CreateQuery(&networkinfo, "Virtual=false", "MSFT_NetAdapter")
err := wmi.QueryNamespace(query, &networkinfo, "Root\\StandardCimv2")

And it makes absolutely no difference whether to write Root or root in wmi.QueryNamespace(). I checked.

答案2

得分: 0

感谢@AlexandrKamenev!我确定我得到了我想要的答案。使用QueryNamespace()方法来指定命名空间:

直接使用QueryNamespace()方法:

err := wmi.QueryNamespace("Select * from MSFT_PhysicalDisk", &diskMediaTypeInfo, "root\\Microsoft\\Windows\\Storage")

使用CreateQuery()和QueryNamespace()方法:

query := wmi.CreateQuery(&networkinfo, "WHERE Virtual=false", "MSFT_NetAdapter")
err := wmi.QueryNamespace(query, &networkinfo, "root\\StandardCimv2")

它可以工作!

英文:

Thank @AlexandrKamenev!I'm sure I got the answer I wanted.Use the QueryNamespace() method to specify namespace:

Directly use QueryNamespace() method:

err := wmi.QueryNamespace("Select * from MSFT_PhysicalDisk", &diskMediaTypeInfo, "root\\Microsoft\\Windows\\Storage")

Use CreateQuery() with QueryNamespace() method

query := wmi.CreateQuery(&networkinfo, "WHERE Virtual=false", "MSFT_NetAdapter")
err := wmi.QueryNamespace(query, &networkinfo, "root\\StandardCimv2")

it works!

huangapple
  • 本文由 发表于 2023年2月21日 12:04:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/75516204.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定