PowerShell Scripting with WMI Part 2

PowerShell Tutorial 11 - Part 2: Scripting with Windows Management Instrumentation (WMI) - Methods


Part 1 introduced us to WMI. We learned how to ‘find’ classes and examine their properties and methods. Hope you downloaded and familiarized yourself with WMI CIM Studio, as it is a great tool to have. We also learned how to find WMI Classes when working in PowerShell. Tutorial 11 Part 1 was about gathering data by enumerating properties within a WMI Class. In Part 2 of the PowerShell Tutorial for WMI, we are going to be using Methods to make changes in our environment. The example scripts make changes to the environment, I highly recommend running any script in a test environment before applying them in your production environment.

Working with Methods

Example 1.

Here’s where the fun begins… The Big Boss has come to your office after you have successfully implemented DHCP on your network. You figure he’s there to give you a “big” pat on the back and an even “bigger” raise (wishful thinking). The reality is, the desktop group is complaining because they don’t want to re-configure each workstation from static IP to DHCP. It’s not that they have an underlying hatred for DHCP, they just don’t want to physically visit all 4000 workstations to make the change - I don’t blame them… You look the Boss right in the eye and give him your standard answer, “NO PROBLEM” - I’ll take care of it. After all you are becoming a PowerShell GURU and you are no stranger to managing complex environments.

1. First step, what WMI Class are we going to use to accomplish this task? Using WMI CIM Studio, I did a search for “Network.” I found the Class “Win32_NetworkAdapterConfiguration” which has a method called “EnableDHCP” - Looks like a winner to me. Another important thing to note, this Class also has a property called “IPEnabled” which provides a boolean data type (True or False). The importance of this property will be apparent as we build the script.
2. I’m going test the script on my local workstation, so I verify that my NIC is setup as static:

PowerShell IP Address Config

DHCP Properties

3. Here is the script code that will change the NIC settings to “Obtain an IP address automatically”

$NICs = Get-WmiObject Win32_NetworkAdapterConfiguration `
| Where {$_.IPEnabled -eq “TRUE”}
foreach($NIC in $NICs) {$NIC.EnableDHCP()}

So what is the script doing?

  • The first line stores the results of our WMI query in a variable called $NICs.
  • It also utilizes the Property “IPEnabled” to filter active IP configured Network Adapters. This enables us to skip any disconnected, virtual, and/or non-IP configured NICs; such as NetBUI, IPX/SPX, AppleTalk, etc…
  • We then use a foreach loop to iterate each item in the collection and use the “EnableDCHP” method to configure the NIC as a DHCP client.
PowerShell Training - DHCP settings

IP Set To DHCP

You should see the following result:

PowerShell Training - IPCONFIG

ipconfig Results

4. Let’s verify we’ve received and IP address from DHCP. If you don’t have a DHCP server assigning addresses on your network, just follow the steps as we go. My address has changed from 192.168.171.42 (my static IP range) to 192.168.171.78 which is in my DHCP address pool, cool success! Okay… so we’re half way there with our code.

PowerShell Training - DNS Setting

DNS Changed to DHCP

5. The next step is to change the DNS setting to “Obtain DNS server address automatically.” We want to change this so that we can utilize the DNS Scope Options created on the DHCP server. This was not a simple feat in VBScript, as we could not pass a “NULL” or and Empty String as we did with EnableDHCP(). Using PowerShell we are able to pass a “NULL” to the SetDNSServerSearchOrder method which sets the DHCP option. We are only adding one line to our script code $NIC.SetDNSServerSearchOrder()

$NICs = Get-WMIObject Win32_NetworkAdapterConfiguration `
| where{$_.IPEnabled -eq “TRUE”}
Foreach($NIC in $NICs) {
$NIC.EnableDHCP()
$NIC.SetDNSServerSearchOrder()
}

Running the code should yield the following results:

Do an “ipconfig /all” to verify the DNS server settings as well as other scope options are available. You should also see DHCP Lease Obtain and Expires infomation.

Example 2.

I’m not going to leave you hanging, let’s say we want to use methods of the “Win32_NetworkAdapterConfiguration” Class to change to static IP or you wish to make changes in a static IP environment.

Let’s examine all the methods available to us:

Get-WmiObject Win32_NetworkAdapterConfiguration `
| Get-Member -MemberType Methods | Format-List

Here is a list of the Methods that are available to this Class:

  • DisableIPSec
  • EnableDHCP
  • EnableIPSec
  • EnableStatic
  • ReleaseDHCPLease
  • RenewDHCPLease
  • SetDNSDomain
  • SetDNSServerSearchOrder
  • SetDynamicDNSRegistration
  • SetGateways
  • SetIPConnectionMetric
  • SetIPXFrameTypeNetworkPairs
  • SetTcpipNetbios
  • SetWINSServer
  • ConvertFromDateTime
  • ConvertToDateTime
  • Delete
  • GetType
  • Put

Looking at the list, there are a number of methods we can use to remotely configure machines. Granted, the workstation is available on the network.

I’m going to share a script that is going to set the IP address, subnet mask, gateway, DNS, and WINS servers. But before I do a special note: Data Types, I bring it up again because knowing which “Data Type” is expected will help when using Methods. For example, let’s look at the Definitions for SetDynamicDNSRegistration and SetWINSServer Methods.

Name : SetDynamicDNSRegistration
Definition : System.Management…(System.Boolean FullDNSRegistrationEnabled…)

Right away you should notice that the Method uses a boolean argument (TRUE or FALSE). If you look at this setting graphically (Network Adapter properties - TCP/IP settings - Advanced Settings - DNS tab - Check box near the bottom) you will see that this setting is a check box. When checked the boolean value = TRUE, unchecked = FALSE.

In the real-world: A call comes in stating that a workstation was moved to another network subnet, when pinging its FQDN or doing a reverse DNS lookup it yields the old IP address. User can’t use application because network application requires name resolution (it can happen). You enumerate the “FullDNSRegistrationEnabled” property and it comes back with a setting of “FALSE.” Quickly you run the “FullDNSRegistrationEnabled(”TRUE”)” Method to resolve the issue. You’re a star!!!

Name :SetWINSServer
Definition: System.Management..(System.String WinsPrimaryServer, …)

Take note that this Method requires a text string data type. By now I’m sure we all know what a text string is.

Here is the script code:

$NICs = Get-WMIObject Win32_NetworkAdapterConfiguration `
| where{$_.IPEnabled -eq “TRUE”}
Foreach($NIC in $NICs) {
$NIC.EnableStatic(”192.168.171.42″, “255.255.255.0″)
$NIC.SetGateways(”192.168.171.1″)
$DNSServers = “198.102.234.125″,”198.102.234.126″
$NIC.SetDNSServerSearchOrder($DNSServers)
$NIC.SetDynamicDNSRegistration(”TRUE”)
$NIC.SetWINSServer(”198.102.234.125″, “198.102.234.126″)
}
PowerShell Training - IP Static Config

Setting Static IP

Results:
IP Address, Subnet Mask, Default Gateway, DNS Servers configured

PowerShell Training - DNS Registration Enabled

Register Check Box Enabled

Register this connection’s addresses in DNS enabled.

PowerShell Training - WINS Configured

WINS Configuration

WINS Configured.

Let’s take a closer look at the code:

$NICs = Get-WMIObject Win32_NetworkAdapterConfiguration `
| where{$_.IPEnabled -eq “TRUE”}

The first line of code creates a variable called $NICs and holds all the properties and methods for the “Win32_NetworkAdapterConfiguration” Class “where” the Network Adapter is IP Enabled. The “where” filter allows us to choose only real network adapters apposed to virtual and/or non-IP based NICs.

Foreach($NIC in $NICs) {

}

We now use a “Foreach” loop to iterate the $NICs collection.

$NIC.EnableStatic(”192.168.171.42″, “255.255.255.0″)
$NIC.SetGateways(”192.168.171.1″)
$DNSServers = “198.102.234.125″,”198.102.234.126″
$NIC.SetDNSServerSearchOrder($DNSServers)
$NIC.SetDynamicDNSRegistration(”TRUE”)
$NIC.SetWINSServer(”198.102.234.125″, “198.102.234.126″)

Within the foreach loop, we take an instance and use methods to assign values. Looking above we used the Method EnableStatic() to assign an IP address and subnet mask. Note: the IP address are integers but they have been encased in quotes as the Method requires a text string value. Also, each entry is separated by a comma.

$DNSServers = “198.102.234.125″,”198.102.234.126″
$NIC.SetDNSServerSearchOrder($DNSServers)

These two lines of code are interesting, as I ran into trouble with the “SetDNSServerSearchOrder” method. I attempted to use the following but it would only allow me to set the preferred DNS server - SetDNSServerSearchOrder(”198.102.234.125″, “198.102.234.126″)
I thought it would work the same as setting the WINS servers, but look at the differences in each method’s definition:
SetWINSServer
(System.String WINSPrimaryServer, System.String WINSSecondaryServer)

SetDNSServerSearchOrder
(System.String[] DNSServerSearchOrder)

Looking up the “SetDNSServerSearchOrder” method on the Microsoft Developer site it states:
The SetDNSServerSearchOrder WMI class method uses an array of string elements to set the server search order.

Okay… an array of string elements. We’ve worked with arrays, we know how to build them. Look at the code again:

$DNSServers = “198.102.234.125″,”198.102.234.126″
$NIC.SetDNSServerSearchOrder($DNSServers)

The first line creates an array and assigns values to the variable $DNSServers.
The second line uses the SetDNSServer… method and uses the values in $DNSServer.

Fun stuff right?!?
This is a good example of understanding which DataTypes are expected. Since I was puzzled by the definition, I looked up the Method on Microsoft Developers site and found the answer - phew!!!

Example 3.

In this example I’m going to show you how to format your hard drive… just kidding! But, if that were a task for you to complete, you should feel comfortable at this point with locating the WMI Class required and the Methods to do the job.

We are going to have a little fun, in this example were are going to use the “Win32_OperatingSystem” class to re-boot computers.

  1. Verify which Methods are available:
    Get-WmiObject Win32_OperatingSystem | Get-Member -MemberType Method | Format-List
  2. Available Methods:
    • Reboot
    • SetDateTime
    • Shutdown
    • Win32Shutdown

    Not much to it, we’ll use the “Reboot” Method to re-boot the computer. Don’t do it now, I’m just showing the code at this time.

  3. Local Re-boot code:
    $colItems = Get-WmiObject Win32_OperatingSystem
    Foreach($Item in $colItems){
    $Item.Reboot()
    }

    If you are a local Admin and you get the following error: “Privilege not held” there is a bug in .NET 1.0 SP3.

  4. The evil remote reboot. I just have to state this disclaimer: “Use this script only to resolve issues, do not use it to flame your fellow coworkers.” With that said, here is code to connected to a remote PCServer and reboot it. Save and run the code as RemBoot.ps1. The Code Prompts for the computer name you wish to reboot:
    $strComputer = Read-Host “Enter Computer Name”
    $colItems = Get-WmiObject Win32_OperatingSystem -ComputerName “$strComputer”
    Foreach($Item in $colItems) {
    $Item.Reboot()
    }

Okay… we could go on for days with examples on how to use Methods of a WMI Class. My goal of the WMI tutorials are to show you how to find Classes and discover which Properties and Methods are available. This is enough to get you up and working with WMI. There is also a really cool “FREE” tool for scripting with WMI (WMI Explorer) that comes from “ThePowerShellGuy” website. I’ve made the tool available in the new PowerShellPro Forums. Get It, you will love it!!!

In the Next tutorial we are going to talk about creating reports, and I get to rant about Microsoft (just a little). I’m also going to show you what I consider the proper PowerShell syntax for WMI…

Email This Page To A Friend Email This Page To A Friend

Comments

By Matt Duguid on April 29th, 2008 at 9:10 pm

I am interested to see how to pass the IP ADDRESS and SUBNET in as powershell variables.

Do you mean something like this:

$ipaddress = “10.0.0.1″
$subMask = “255.0.0.0″
$NIC.EnableStatic($ipaddress, $subMask)

-or-
$ipaddress = Read-Host “Enter the IP Address”
$subMask = Read-Host “Enter Subnet Mask”
$GW = Read-Host “Enter Default Gateway”

Etc…

By Christian BARDOU on June 27th, 2008 at 5:22 am

Hi Jesse ?,

In the “Foreach” loop of the example 2, i don’t understand how the IP address can be different for each instance of $NICs collection ?

Regards

The example provided assumes that only one nic in the system is IP enabled. Which is the case for a majority of workstations within most networking environments. If you have a special case where you have workstation that have multiple nics that require separate IP address, then you would set up a filter to connect to the nic of your choice. If you do a get-member on the wmi object there are many properties you can choose to filter. Since we are looking for a unique property I tend to use the MAC address of the nic. I want to change and customize the filter as follows:
$NICs = Get-WmiObject Win32_NetworkAdapterConfiguration `
| Where {$_.MACAddress -eq “3E:6D:10:34:22:3D”}

This filter assures me that I am connecting to the NIC I wish to make changes too. That way if I have two nics in the system, I’m only making changes to the one I choose…

By Palle Grassmé on December 10th, 2008 at 4:54 am

Is it possible to prepend the primary and secondary WINS server addresses to the existing WINS settings?

 

Leave a Comment