user4951
user4951

Reputation: 33138

How can we make this code run with option strict on?

Public Class Form1  
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        lblSystemSerialNumbers.Text = SystemSerialNumber()
        lblCpuIds.Text = CpuId()
    End Sub

    Private Function SystemSerialNumber() As String
        ' Get the Windows Management Instrumentation object.
        Dim wmi As Object = GetObject("WinMgmts:")

        ' Get the "base boards" (mother boards).
        Dim serial_numbers As String = ""
        Dim mother_boards As Object = wmi.InstancesOf("Win32_BaseBoard")
        For Each board As Object In mother_boards
            serial_numbers &= ", " & board.SerialNumber
        Next board
        If serial_numbers.Length > 0 Then serial_numbers = serial_numbers.Substring(2)

        Return serial_numbers
    End Function

    Private Function CpuId() As String
        Dim computer As String = "."
        Dim wmi As Object = GetObject("winmgmts:" & _
            "{impersonationLevel=impersonate}!\\" & _
            computer & "\root\cimv2")
        Dim processors As Object = wmi.ExecQuery("Select * from Win32_Processor")

        Dim cpu_ids As String = ""
        For Each cpu As Object In processors
            cpu_ids = cpu_ids & ", " & cpu.ProcessorId
        Next cpu
        If cpu_ids.Length > 0 Then cpu_ids = cpu_ids.Substring(2)

        Return cpu_ids
    End Function
End Class

This code will retrieve the CPU id and the motherboard id. How do I ensure that this will work even when option strict is on.

Why this could be a problem?

Well, let's see. The type of wmi is Object. That wmi do not necessarily support methods like InstancesOf, and SerialNumber

So how can we pull this out?

I think object that we got from GetObject is not just pure object. I think we should ctype or direct cast it to a more appropriate type. That more appropriate type will support methods like InstancesOf, SerialNumber, etc.

However what are the appropriate types?

Upvotes: 0

Views: 180

Answers (1)

Steve
Steve

Reputation: 216353

You could use the ManagementObjectSearcher from the WMI classes hosted inside the System.Management.dll assembly.
(And you need to add the appropriate reference).

In this way you could write the SystemSerialNumber as

Private Function SystemSerialNumber(computer As String) As String

    Dim wmi = New ManagementObjectSearcher(computer & "\root\cimv2", "select * from Win32_BaseBoard")

    Dim boards = New List(Of String)()
    For Each board In wmi.Get()
        Dim temp = board.Properties("SerialNumber").Value?.ToString()
        If Not String.IsNullOrEmpty(temp) Then
            boards.Add(temp)
        End If
    Next board
    Return String.Join(", ", boards)
End Function

The CpuId function is a bit more complex because you want to set the Impersonate flags but it is still possible to write a method around the NET wrapper classes for WMI interfaces

Private Function CpuId(computer As String) As String
    Dim cpu = New List(Of String)()

    Dim options = New ConnectionOptions()
    options.Impersonation = System.Management.ImpersonationLevel.Impersonate

    Dim scope = New ManagementScope(computer & "\root\cimv2", options)
    scope.Connect()

    Dim query = New ObjectQuery("Select * from Win32_Processor")
    Dim wmi = New ManagementObjectSearcher(scope, query)
    For Each m As ManagementObject In wmi.Get()
        Dim temp = m.Properties("ProcessorId").Value?.ToString()
        If Not String.IsNullOrEmpty(temp) Then
            cpu.Add(temp)
        End If
    Next
    Return String.Join(", ", cpu)
End Function

Upvotes: 2

Related Questions