Exporting and Importing WMI Filters with PowerShell: Part 2, Import
Now that we're through Exporting and Importing WMI Filters with PowerShell: Part 1, Export, the import process can begin. Let's do a quick review of what will be imported. Since WMI filters are domain-specific, we only required three attributes for each WMI filter from the source domain: Name, Description, and Query. Our backup file ($BackupFile from Part 1 of this blog) contains a tab-delimited list of WMI filters. Here's a same of that file:
Name | Description | Query |
Manufacturer Dell | Find all computer manufactured by Dell | 1;3;10;62;WQL;root\CIMv2;Select * from WIN32_ComputerSystem where Manufacturer = "DELL"; |
Installed Memory > 1Gb | Finds all computer with more than 1 Gb of RAM | 1;3;10;74;WQL;root\CIMv2;Select * from WIN32_ComputerSystem where TotalPhysicalMemory >= 1073741824; |
The backup file can be imported into Excel for easy modification of any particular field or the removal of filters by deleting the corresponding row in the backup file. The following script uses the backup file to create new WMI filters in the destination domain (the script is also attached as Import_All_WMI_Filters.ps1):
param([String]$BackupFile) if ([String]::IsNullOrEmpty($BackupFile)){ write-host -ForeGroundColor Red "BackupFile is a required parameter. Exiting Script.`n" return} import-module ActiveDirectory $Header = "Name","Description","Filter"$WMIFilters = import-csv $BackupFile -Delimiter "`t" -Header $Header #The code below this line was modified to work with the file import code above this line. The original code can be found here. $defaultNamingContext = (get-adrootdse).defaultnamingcontext$configurationNamingContext = (get-adrootdse).configurationNamingContext$msWMIAuthor = "Administrator@" + [System.DirectoryServices.ActiveDirectory.Domain]::getcurrentdomain().name foreach ($WMIFilter in $WMIFilters){$WMIGUID = [string]"{"+([System.Guid]::NewGuid())+"}"$WMIDN = "CN="+$WMIGUID+",CN=SOM,CN=WMIPolicy,CN=System,"+$defaultNamingContext$WMICN = $WMIGUID$WMIdistinguishedname = $WMIDN$WMIID = $WMIGUID $now = (Get-Date).ToUniversalTime()$msWMICreationDate = ($now.Year).ToString("0000") + ($now.Month).ToString("00") + ($now.Day).ToString("00") + ($now.Hour).ToString("00") + ($now.Minute).ToString("00") + ($now.Second).ToString("00") + "." + ($now.Millisecond * 1000).ToString("000000") + "-000" $msWMIName = $WMIFilter.Name$msWMIParm1 = $WMIFilter.Description + " "$msWMIParm2 = $WMIFilter.Filter $Attr = @{"msWMI-Name" = $msWMIName;"msWMI-Parm1" = $msWMIParm1;"msWMI-Parm2" = $msWMIParm2;"msWMI-Author" = $msWMIAuthor;"msWMI-ID"=$WMIID;"instanceType" = 4;"showInAdvancedViewOnly" = "TRUE";"distinguishedname" = $WMIdistinguishedname;"msWMI-ChangeDate" = $msWMICreationDate; "msWMI-CreationDate" = $msWMICreationDate} $WMIPath = ("CN=SOM,CN=WMIPolicy,CN=System,"+$defaultNamingContext) New-ADObject -name $WMICN -type "msWMI-Som" -Path $WMIPath -OtherAttributes $Attr} |
Let's take a closer look at what is going on in this script.
It starts by requiring the administrator to provide the $BackupFile parameter. If the parameter is not provided, the script exits and notifies the administrator.
param([String]$BackupFile) if ([String]::IsNullOrEmpty($BackupFile)){ write-host -ForeGroundColor Red "BackupFile is a required parameter. Exiting Script.`n" return} |
Next, we import the Active Directory Modules for PowerShell and populate the $WMIFilters variable with a full collection of WMI filters from the source domain along with the Name, Description, and Query for each filter described earlier. The headers are also inserted to allow for easy identification later in the script.
import-module ActiveDirectory $Header = "Name","Description","Filter"$WMIFilters = import-csv $BackupFile -Delimiter "`t" -Header $Header |
Now we enter a for loop processing each row in the $BackupFile. In order to create the new WMI filter object (msWMI-Som objectClass), we'll need a new Globally Unique Identifier (GUID) stored in $WMIGUID. Using the GUID, we store the Distinguished Name (DN) in the $WMIDN variable. We'll also need the Container Name ($WMICN). The Container for WMI filters in Active Directory is represented by the GUID. The DN of the new WMI filter is then stored for later use in $WMIdistinguishedname. Finally, the GUID is stored for later use in $WMIID.
foreach ($WMIFilter in $WMIFilters){$WMIGUID = [string]"{"+([System.Guid]::NewGuid())+"}"$WMIDN = "CN="+$WMIGUID+",CN=SOM,CN=WMIPolicy,CN=System,"+$defaultNamingContext$WMICN = $WMIGUID$WMIdistinguishedname = $WMIDN$WMIID = $WMIGUID |
The next section prepares more variables for use later in the script. $now stores the current date/time (UTC). $msWMICreationDate stores the date/time in a converted format for storage in the msWMI-CreationDate attribute of the WMI filter. Finally, the Name, Description, and Query of the WMI filter are stored in $msWMIName, $msWMIParm1, and $msWMIParm2 variables, respectively.
$now = (Get-Date).ToUniversalTime()$msWMICreationDate = ($now.Year).ToString("0000") + ($now.Month).ToString("00") + ($now.Day).ToString("00") + ($now.Hour).ToString("00") + ($now.Minute).ToString("00") + ($now.Second).ToString("00") + "." + ($now.Millisecond * 1000).ToString("000000") + "-000" $msWMIName = $WMIFilter.Name$msWMIParm1 = $WMIFilter.Description + " "$msWMIParm2 = $WMIFilter.Filter |
The last two variables we'll need to create the WMI filter are $Attr and $WMIPath. $Attr represents all the attributes required for creating a WMI filter object in Active Directory. $WMIPath identifies the DN of the location where WMI filters are stored in Active Directory.
$Attr = @{"msWMI-Name" = $msWMIName;"msWMI-Parm1" = $msWMIParm1;"msWMI-Parm2" = $msWMIParm2;"msWMI-Author" = $msWMIAuthor;"msWMI-ID"=$WMIID;"instanceType" = 4;"showInAdvancedViewOnly" = "TRUE";"distinguishedname" = $WMIdistinguishedname;"msWMI-ChangeDate" = $msWMICreationDate; "msWMI-CreationDate" = $msWMICreationDate} $WMIPath = ("CN=SOM,CN=WMIPolicy,CN=System,"+$defaultNamingContext) |
The final line in the script is what creates the new WMI filter object. The parameters passed to the "New-ADObject" command are as follows:
- -name: The Container Name of the WMI filter in Active Directory (not the friendly name)
- -type: The objectClass for WMI filters (msWMI-Som)
- -Path: The DN of the location where WMI filters are stored in Active Directory
- -OtherAttributes: The attributes required to create the new WMI filter object
New-ADObject -name $WMICN -type "msWMI-Som" -Path $WMIPath -OtherAttributes $Attr} |
That does it for the import script. There is one special note to be made during the import process: There is no error checking. Also, if you have existing WMI filters in your domain with names that conflict with the names of the WMI filter you are importing using this script, new WMI filters with the same friendly name will be created (your existing ones will not be updated or impacted in any way). Still, I recommend working out those conflicts before running the import script or the conflicting names can eventually lead to confusion when administering WMI filter links and filters.
My next series of scripts will provide administrators with a way, using PowerShell, to perform bulk imports of Group Policy Object and perform automated linking of previously-linked WMI filters to those GPO's. Sounds exciting, right?
Disclaimer: The information on this site is provided "AS IS" with no warranties, confers no rights, and is not supported by the authors or Microsoft Corporation. Use of included script samples are subject to the terms specified in the Terms of Use .
Comments
- Anonymous
August 26, 2015
I get the error: "New-ADObject : Cannot validate argument on parameter 'OtherAttributes'. The argument is null or an element of the argument collection contains a null value.".... so perhaps there is a newer version of the file somewhere?