Powershell – Import certificates on remote servers

Standard

A while back I was tasked with importing some certificates on all our web servers. I didn’t like the idea of doing this manually on hundreds of servers so I decided I had to write a script which could help me with this job. The problem was that I couldn’t find any “easy” way of importing certificates on remote servers. It is possible with some commercial tools and also with windows 2012 R2 and powershell v4 but none of these options were available to me. Furthermore I wanted to have a script which was generic and could be used on all windows servers regardless of version. This led me to create this powershell script which I will go over for you now.

The script loops through the servers in the “servers.txt” file (you must create this file and put it in the script directory) and basically works as outlined in these steps:
1. The certificate is copied to the remote server
2. A custom mini-scipt for importing the certificate is created and copied to the remote server.
3. The mini-script is invoked by using psexec and imported into the desired certificate store.
4. The certificate and mini-script are deleted on the remote server after use.
5. The result of the certificate import is checked.

A log file with relevant information is created when the script is run, making it possible to confirm the successful import later on.
The script is divided into three sections – variables, functions and script main.

Variables

#VARIABLES
$scriptpath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptpath
$RemoteCertDir = "c:\temp\certs\" #temporary file location on remote server
$logfile = "$dir\logs\" + "cert-bulkimport_" + $(get-date -Format "yyyy-MM-dd_HH-mm-ss") + ".log"
$servers = gc "$dir\servers.txt"
$psexec = "$dir\psexec.exe"
#parameters
$DebugPreference = "continue" #comment out to disable debug info
$certRootStore = "localmachine"
$certStore = "My"
$Cert = "$dir\certs\some_cert.pfx" #certificate to import
$CertPW = "Password" #password for certificate to import
$CertCN = "some.domain.com" #common name of certificate to import

The first two lines of code –
$scriptpath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptpath

are really practical as it gives me an object $dir which always points to where the script was run. This makes the script more robust as I can freely move the script around and run it from many locations without having to change any paths in the script.
$logfile is the path of the log file which will be created for each script run. The file name will contain a time stamp to avoid overwriting the file.
$servers is an array populated by running Get-Content on the “servers.txt” file.
$psexec is the path to psexec.exe (place it in the same directory as the script).
The parameters section is really important and you need to fill these variables with the specific information about your certificate and which store to import them to. The descriptions in the code comments should explain how to do this.

Functions

1. Function Log-Entry

function log-entry {
    param(
        $message
    )
    $time = Get-date
    Add-Content -Path $logfile -Value "$time`t$message"
}

This function takes a parameter “message” and appends it to the log file with a timestamp. I use it to easily write to the log file throughout the script.

2. Function RemoteCopy-Certificate

function RemoteCopy-Certificate {
    param(
        $server
    )
    $copyresult = $false
    $RemoteDir = "\\$server\" + $RemoteCertDir.replace(":","$")	
    Write-Debug "Creating directory $RemoteDir"
    log-entry -message "Creating directory $RemoteDir"	
    New-Item -ItemType "directory" $RemoteDir -Force
    $RemoteCertPath = $RemoteDir + (gci $Cert).Name	
    Write-Debug "Copying $Cert to $RemoteDir"
    log-entry -message "Copying $Cert to $RemoteDir"	
    Copy-Item -Path $Cert -Destination $RemoteCertPath -Force
    if (Test-Path -Path $RemoteCertPath) {
        $CopyResult = $true		
        Write-Debug "Copy of $Cert to $RemoteDir succeeded."
        log-entry -message "Copy of $Cert to $RemoteDir succeeded." 
    }
    else {
        $CopyResult = $false 		
        Write-Debug "Error - Copy of $Cert to $RemoteDir failed."
        log-entry -message "Error - Copy of $Cert to $RemoteDir failed."
    }
    return $CopyResult
}

This function creates a temp directory on the remote server and copies the certificate to there. It then checks if the certificate is there and returns $true if the copy was successful.

3. Function Create-ImportScript

function Create-ImportScript {
    param(
        $server
    )
    $ScriptCreateResult = $false
    $RemoteScriptPath = "\\$server\" + $RemoteCertDir.Replace(":","$") + "import-pfx.ps1"    
    $CertPath = "'" + $RemoteCertDir + (gci $Cert).Name + "'"    
    $crtPass = "'" + $CertPW + "'"
    $SB = @"
`n
`$crt = new-object System.Security.Cryptography.X509Certificates.X509Certificate2
`$crt.import($certPath,$crtPass,"Exportable,PersistKeySet")
`$store = new-object System.Security.Cryptography.X509Certificates.X509Store(`'$certStore`',`'$certRootStore`') 
`$store.open("MaxAllowed") 
`$store.add(`$crt) 
`$store.close()
"@
    log-entry -message "Creating import script $RemoteScriptPath"
    Write-Debug "Creating import script $RemoteScriptPath`:$SB`n"	
    $SB | Out-File $RemoteScriptPath -force
    if (Test-Path -Path $RemoteScriptPath) {
        $ScriptCreateResult = $true		
        Write-Debug "Creation of $RemoteScriptPath succeeded."
        log-entry -message "Creation of $RemoteScriptPath succeeded." 
    }
    else {
        $ScriptCreateResult = $false		
        Write-Debug "Error - Creation of $RemoteScriptPath failed."
        log-entry -message "Error - Creation of $RemoteScriptPath failed."
    }
    return $ScriptCreateResult    
}

Here, a custom powershell mini import script is created. Basically the mini script comes from the multi-line string $SB which is redirected to create a .ps1 file. The function then checks if the file was created on the remote server and returns $true for a successful result.

4. Function Invoke-Importscript

function Invoke-Importscript {
    param(
        $server
    )
    $ImportScriptPath = $RemoteCertDir + "import-pfx.ps1"
    $arg1 = "/acceptEula"
    $arg2 = "\\$server"
    $arg3 = "cmd /c"
    $arg4 = "`"echo .|powershell -file $ImportScriptPath`""	
    Write-Debug "invoking remote import script on $server"   
    log-entry -message "invoking remote import script on $server"	
    Start-Process -Wait -FilePath $psexec -ArgumentList "$arg1 $arg2 $arg3 $arg4"
}

This function runs the mini script on the remote server and imports the certificate into the chosen store. Psexec.exe is used to invoke the script on the remote server.

5. Function Remove-TempFiles

function Remove-TempFiles {
    param(
        $server
    )
    $RemoteScriptDir = "\\$server\" + $RemoteCertDir.Replace(":","$")	
    Write-Debug "Removing temporary cert and script files from $RemoteScriptDir"
    log-entry -message "Removing temporary cert and script files from $RemoteScriptDir"	
    gci -Recurse -Path $RemoteScriptDir | Remove-Item
}

As we don’t want to leave any certs or scripts behind after we are done I wrote this function to remove these files after the cert has been imported.

6. Function List-RemoteCerts

function List-RemoteCerts {
    param(
        $server
    )
    $ro = [System.Security.Cryptography.X509Certificates.OpenFlags]"ReadOnly"
    $lm = [System.Security.Cryptography.X509Certificates.StoreLocation]"LocalMachine"
    $store = new-object System.Security.Cryptography.X509Certificates.X509Store("\\$server\$CertStore", $lm)
    $store.Open($ro)
    return $store.Certificates
}

This function lists the certificates on the remote server. I use this function in the next function Confirm-CertImport.

7. Function Confirm-CertImport

function Confirm-CertImport {
    param(
        $server
    )
    Write-Debug "Checking if certificate import on $server was successful."
    log-entry -message "Checking if certificate import on $server was successful."	
    $IsCertThere = $false    
    $MyCerts = List-RemoteCerts -server $server        
    $MyCerts | % {	
        Write-Debug "Found certificate: $($_.Subject)"		
        if ($_.Subject -like "*$CertCN*") {		
            Write-Debug "*************Certificate match for $CertCN found!)"			
            $IsCertThere = $true
        }
    }
    return $IsCertThere       
}

Here I loop through the certificates found on the remote server. If the certificate we just attempted to import is found a result of $true is returned.

Script Main

#SCRIPT MAIN
new-item -itemtype "file" $logfile -force | out-null #create the log file for this script execution
Write-Debug "Script run started."
log-entry -message "Script run started."
$servers | % { #loop through the servers which we will import the certificate to
    Write-Debug "Starting cert import on $_".ToUpper()
    log-entry "Starting cert import on $_".ToUpper()
    $copyResult = RemoteCopy-Certificate -server $_ # Find out if the copy of the cert to the server was successful
    if ($copyResult) {   #If the copy of the certificate to the server succeeded then proceed.     
        $ScriptCreateResult = Create-ImportScript -server $_ #Find out if the script was created and copied to the server successfully
        if ($ScriptCreateResult) { #if the script was created/copied to the server successfully then proceed.
            Invoke-Importscript -server $_ #import the certificate into the specified store
            Remove-TempFiles -server $_ #Remove temp files such as the cert and import script
            $CertImportResult = Confirm-CertImport -server $_ #check that the cert was imported successfully and write the result to the log.
            if ($CertImportResult) {
                Write-Debug "Success! $CertCN was successfully imported on $_"
                log-entry -message "Success! $CertCN was successfully imported on $_"
            }
            else {
                Write-Debug "Error! Import of $CertCN on $_ failed."
                log-entry -message "Error! Import of $CertCN on $_ failed."
            }
        }
    }
    Write-Debug "-------------------------------------------------------------------------------------------------------------------------"
    log-entry "`n`n"
}

The script main starts with creating the log file used for the script run. I then loop through the $servers array and with some nested IF sentences run the functions described above.
When the script run has completed, the certificate will be imported on the servers specified in the “servers.txt” file and you will have a log file with the import results available.
I hope you find the script useful. Enjoy!!
I have copied in the full script below.

##################################################################################################################
##RemoteImport-Certificate.ps1
##Description: 		Script imports a certificate into all remote servers specified in the 
#+                  "servers.txt" inputlist.
#+					Fill out the "parameters" section according to your needs before running!
##Created by:		Noam Wajnman
##Creation Date:	March 17, 2014
###################################################################################################################
#VARIABLES
$scriptpath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptpath
$RemoteCertDir = "c:\temp\certs\" #temporary file location on remote server
$logfile = "$dir\logs\" + "cert-bulkimport_" + $(get-date -Format "yyyy-MM-dd_HH-mm-ss") + ".log"
$servers = gc "$dir\servers.txt"
$psexec = "$dir\psexec.exe"
#parameters
$DebugPreference = "continue" #comment out to disable debug info
$certRootStore = "localmachine"
$certStore = "My"
$Cert = "$dir\certs\some_cert.pfx" #certificate to import
$CertPW = "Password" #password for certificate to import
$CertCN = "some.domain.com" #common name of certificate to import
#FUNCTIONS
function log-entry {
    param(
        $message
    )
    $time = Get-date
    Add-Content -Path $logfile -Value "$time`t$message"
}
function RemoteCopy-Certificate {
    param(
        $server
    )
    $copyresult = $false
    $RemoteDir = "\\$server\" + $RemoteCertDir.replace(":","$")	
    Write-Debug "Creating directory $RemoteDir"
    log-entry -message "Creating directory $RemoteDir"	
    New-Item -ItemType "directory" $RemoteDir -Force
    $RemoteCertPath = $RemoteDir + (gci $Cert).Name	
    Write-Debug "Copying $Cert to $RemoteDir"
    log-entry -message "Copying $Cert to $RemoteDir"	
    Copy-Item -Path $Cert -Destination $RemoteCertPath -Force
    if (Test-Path -Path $RemoteCertPath) {
        $CopyResult = $true		
        Write-Debug "Copy of $Cert to $RemoteDir succeeded."
        log-entry -message "Copy of $Cert to $RemoteDir succeeded." 
    }
    else {
        $CopyResult = $false 		
        Write-Debug "Error - Copy of $Cert to $RemoteDir failed."
        log-entry -message "Error - Copy of $Cert to $RemoteDir failed."
    }
    return $CopyResult
}
function Create-ImportScript {
    param(
        $server
    )
    $ScriptCreateResult = $false
    $RemoteScriptPath = "\\$server\" + $RemoteCertDir.Replace(":","$") + "import-pfx.ps1"    
    $CertPath = "'" + $RemoteCertDir + (gci $Cert).Name + "'"    
    $crtPass = "'" + $CertPW + "'"
    $SB = @"
`n
`$crt = new-object System.Security.Cryptography.X509Certificates.X509Certificate2
`$crt.import($certPath,$crtPass,"Exportable,PersistKeySet")
`$store = new-object System.Security.Cryptography.X509Certificates.X509Store(`'$certStore`',`'$certRootStore`') 
`$store.open("MaxAllowed") 
`$store.add(`$crt) 
`$store.close()
"@
    log-entry -message "Creating import script $RemoteScriptPath"
    Write-Debug "Creating import script $RemoteScriptPath`:$SB`n"	
    $SB | Out-File $RemoteScriptPath -force
    if (Test-Path -Path $RemoteScriptPath) {
        $ScriptCreateResult = $true		
        Write-Debug "Creation of $RemoteScriptPath succeeded."
        log-entry -message "Creation of $RemoteScriptPath succeeded." 
    }
    else {
        $ScriptCreateResult = $false		
        Write-Debug "Error - Creation of $RemoteScriptPath failed."
        log-entry -message "Error - Creation of $RemoteScriptPath failed."
    }
    return $ScriptCreateResult    
}
function Invoke-Importscript {
    param(
        $server
    )
    $ImportScriptPath = $RemoteCertDir + "import-pfx.ps1"
    $arg1 = "/acceptEula"
    $arg2 = "\\$server"
    $arg3 = "cmd /c"
    $arg4 = "`"echo .|powershell -file $ImportScriptPath`""	
    Write-Debug "invoking remote import script on $server"   
    log-entry -message "invoking remote import script on $server"	
    Start-Process -Wait -FilePath $psexec -ArgumentList "$arg1 $arg2 $arg3 $arg4"
}
function Remove-TempFiles {
    param(
        $server
    )
    $RemoteScriptDir = "\\$server\" + $RemoteCertDir.Replace(":","$")	
    Write-Debug "Removing temporary cert and script files from $RemoteScriptDir"
    log-entry -message "Removing temporary cert and script files from $RemoteScriptDir"	
    gci -Recurse -Path $RemoteScriptDir | Remove-Item
}
function List-RemoteCerts {
    param(
        $server
    )
    $ro = [System.Security.Cryptography.X509Certificates.OpenFlags]"ReadOnly"
    $lm = [System.Security.Cryptography.X509Certificates.StoreLocation]"LocalMachine"
    $store = new-object System.Security.Cryptography.X509Certificates.X509Store("\\$server\$CertStore", $lm)
    $store.Open($ro)
    return $store.Certificates
}
function Confirm-CertImport {
    param(
        $server
    )
    Write-Debug "Checking if certificate import on $server was successful."
    log-entry -message "Checking if certificate import on $server was successful."	
    $IsCertThere = $false    
    $MyCerts = List-RemoteCerts -server $server        
    $MyCerts | % {	
        Write-Debug "Found certificate: $($_.Subject)"		
        if ($_.Subject -like "*$CertCN*") {		
            Write-Debug "*************Certificate match for $CertCN found!)"			
            $IsCertThere = $true
        }
    }
    return $IsCertThere       
}
#SCRIPT MAIN
new-item -itemtype "file" $logfile -force | out-null #create the log file for this script execution
Write-Debug "Script run started."
log-entry -message "Script run started."
$servers | % { #loop through the servers which we will import the certificate to
    Write-Debug "Starting cert import on $_".ToUpper()
    log-entry "Starting cert import on $_".ToUpper()
    $copyResult = RemoteCopy-Certificate -server $_ # Find out if the copy of the cert to the server was successful
    if ($copyResult) {   #If the copy of the certificate to the server succeeded then proceed.     
        $ScriptCreateResult = Create-ImportScript -server $_ #Find out if the script was created and copied to the server successfully
        if ($ScriptCreateResult) { #if the script was created/copied to the server successfully then proceed.
            Invoke-Importscript -server $_ #import the certificate into the specified store
            Remove-TempFiles -server $_ #Remove temp files such as the cert and import script
            $CertImportResult = Confirm-CertImport -server $_ #check that the cert was imported successfully and write the result to the log.
            if ($CertImportResult) {
                Write-Debug "Success! $CertCN was successfully imported on $_"
                log-entry -message "Success! $CertCN was successfully imported on $_"
            }
            else {
                Write-Debug "Error! Import of $CertCN on $_ failed."
                log-entry -message "Error! Import of $CertCN on $_ failed."
            }
        }
    }
    Write-Debug "-------------------------------------------------------------------------------------------------------------------------"
    log-entry "`n`n"
}
Advertisements

Powershell – Set static DNS on remote servers

Standard

Recently I was tasked with the job of changing the DNS search order on all the windows servers we use in my company. Since I didn’t want to change it manually by going into the TCP/IP settings of the NIC on each server I decided to write a script to help me do this.

I am working in a sensitive production environment so I needed to not only change the settings but also check that the changes were made successfully on all servers. To accomplish this I added some functionality to the script to confirm that the changes were made and write all the information to a log file. This log file could then be reviewed later for errors.

I have built the script in three different sections – variables, functions and script main. To begin with I will quickly explain the variables section.

VARIABLES

I don’t like working with too many absolute paths in my scripts because one needs to change them if they are moved to another computer or location. Therefore I use the following code so I always have an object pointing to the script directory.

$scriptpath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptpath

When used, $dir will always point to the directory where the script was run. $log_dir specifies the path to a directory names /logs which will be used later on.

The script takes input from a file called “servers.txt” which must be placed in the script directory. $servers is an array created and populated by running Get-Content on “servers.txt”. The parameters section contains the $dns1, $dns2, $dns3 objects which will be set on the servers listed in “servers.txt” – remember to fill these out with the appropriate values before running the script.

#VARIABLES
$DebugPreference = "continue"
$scriptpath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptpath
$log_dir = "$dir\logs"
$servers = @(gc "$dir\servers.txt")
#parameters - Add the desired DNS servers below
[string]$dns1 = "192.168.1.2"
[string]$dns2 = "192.168.1.3"
[string]$dns3 = "192.168.1.4"

That covers the variables section – now to the functions. The script is built on four different functions which I will go over now.

FUNCTIONS

1. Function Create-Log

function Create-Log {
	$time = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
	$logFilePath = "$log_dir\SetStaticDNS_$time.log"
	New-Item -ItemType File $logFilePath -Force
}
 

This little function simply creates a logfile in $dir\logs\ which will be used by the script to record the results of attempting to change the DNS settings on each server.

2. Function Write-ToLog

function Write-ToLog {
	param (
		[string]$message
		)
	$time = Get-Date
	$logEntryStr = "$time`t" + $message
	$logEntryStr | Out-File -Append $logFilePath -Width 400
}
 

Write-ToLog takes a parameter “message” and appends it to the log file with a time stamp

3. Get-ActiveNicIP

function Get-ActiveNicIP {
 	param (
 		[Parameter(Mandatory=$true)][string]$computer
 	)
 	Write-ToLog -message "Getting IP of 'active' interface on $computer ..."
 	$conx = Test-Connection -ComputerName $computer -Count 1
 	$ActiveIP = $conx.IPV4Address.IPAddressToString
 	Write-ToLog -message "Active IP on $computer is $ActiveIP"
 	return $ActiveIP
}

Some servers can have several NICs/Teams in use and I wanted to make sure that I only change the DNS settings on the NIC which answers to the hostname of the server. Get-ActiveNicIP simply pings the server given as the parameter “computer” and returns the IP which answers.

4. Function Set-StaticDNS

function Set-StaticDNS {
	param (
		[Parameter(Mandatory=$true)][string]$computer,
		[Parameter(Mandatory=$true)][string]$ActiveIP
	)
	Write-ToLog -message "Attempting to set DNS search order on computer 	$computer on the interface with the IP $ActiveIP"
	#get dns info via WMI
	$wmi = Get-WmiObject win32_networkadapterconfiguration -filter "ipenabled = 'true'" -ComputerName $computer | ? { $_.IPAddress -match $ActiveIP }
	#set dns search order via WMI
	$wmi.SetDNSServerSearchOrder($DnsSearchOrder)
	#confirm that dns search order was set to desired value.
	$StrdnsSearchOrder = $dnsSearchOrder | Out-String
	$wmi2 = Get-WmiObject win32_networkadapterconfiguration -filter "ipenabled = 'true'" -ComputerName $computer | ? { $_.IPAddress -match $ActiveIP }
	$StrWmiDnsSearchOrder = $wmi2.DNSServerSearchOrder | Out-String
	if ($StrWmiDnsSearchOrder -eq $StrdnsSearchOrder) {
	Write-ToLog -message "Setting the DNS search order was successful. Value is now $dnsSearchOrder"
	}
	else {
		Write-ToLog -message "Error - Setting the DNS search order failed!"
	}
}

The Set-Static DNS function takes a computer and an IP as parameters and then uses WMI to change the DNS search order on the NIC.
That covers the functions – now to the script main.

SCRIPT MAIN

#SCRIPT MAIN
clear
$dnsSearchOrder = @()
$dnsSearchOrder += @($dns1)
$dnsSearchOrder += @($dns2)
$dnsSearchOrder += @($dns3)
$logFilePath = Create-Log
Write-ToLog -message "Starting script Set-StaticDNS.ps1...."
Write-ToLog -message "Setting DNS search order on all servers in 'servers.txt' to $dnsSearchOrder"
Write-ToLog -message "----------------------------------------------------------------------------------------------------------`n`n"
$servers | % {
	$ActiveIP = Get-ActiveNicIP -computer $_
	Set-StaticDNS -computer $_ -ActiveIP $ActiveIP
}
Write-ToLog -message "`n`n----------------------------------------------------------------------------------------------------------"
Write-ToLog -message "Script run ended."

The script main simply loops through the $servers array and runs the Get-ActiveNipIP and Set-StaticDNS functions on each server.
That should explain how the script works. I have copied in the full script below.
Enjoy!

################################################################################################
##Script:		Set-StaticDNS.ps1
##
##Description:		Sets the DNS search order on the servers given as input in servers.txt
#+			to the IP addresses specified in the parameters section.
##Created by:		Noam Wajnman
##Creation Date: December 9, 2013
################################################################################################
#FUNCTIONS
function Create-Log {
	$time = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
	$logFilePath = "$log_dir\SetStaticDNS_$time.log"
	New-Item -ItemType File $logFilePath -Force
}
function Write-ToLog {
	param (
		[string]$message
	)
	$time = Get-Date
	$logEntryStr = "$time`t" + $message
	$logEntryStr | Out-File -Append $logFilePath -Width 400
}
function Get-ActiveNicIP {
	param (
		[Parameter(Mandatory=$true)][string]$computer
	)
	Write-ToLog -message "Getting IP of 'active' interface on $computer ..."
	$conx = Test-Connection -ComputerName $computer -Count 1
	$ActiveIP = $conx.IPV4Address.IPAddressToString
	Write-ToLog -message "Active IP on $computer is $ActiveIP"
	return $ActiveIP
}
function Set-StaticDNS {
	param (
		[Parameter(Mandatory=$true)][string]$computer,
		[Parameter(Mandatory=$true)][string]$ActiveIP
	)
	Write-ToLog -message "Attempting to set DNS search order on computer $computer on the interface with the IP $ActiveIP"
	#get dns info via WMI
	$wmi = Get-WmiObject win32_networkadapterconfiguration -filter "ipenabled = 'true'" -ComputerName $computer | ? { $_.IPAddress -match $ActiveIP }
	#set dns search order via WMI
	$wmi.SetDNSServerSearchOrder($DnsSearchOrder)
	#confirm that dns search order was set to desired value.
	$StrdnsSearchOrder = $dnsSearchOrder | Out-String
	$wmi2 = Get-WmiObject win32_networkadapterconfiguration -filter "ipenabled = 'true'" -ComputerName $computer | ? { $_.IPAddress -match $ActiveIP }
	$StrWmiDnsSearchOrder = $wmi2.DNSServerSearchOrder | Out-String
	if ($StrWmiDnsSearchOrder -eq $StrdnsSearchOrder) {
		Write-ToLog -message "Setting the DNS search order was successful. Value is now $dnsSearchOrder"
	}
	else {
		Write-ToLog -message "Error - Setting the DNS search order failed!"
	}
}
#VARIABLES
$DebugPreference = "continue"
$scriptpath = $MyInvocation.MyCommand.Path
$dir = Split-Path $scriptpath
$log_dir = "$dir\logs"
$servers = @(gc "$dir\servers.txt")
#parameters - Add the desired DNS servers below
[string]$dns1 = "192.168.1.2"
[string]$dns2 = "192.168.1.3"
[string]$dns3 = "192.168.1.4"
#SCRIPT MAIN
clear
$dnsSearchOrder = @()
$dnsSearchOrder += @($dns1)
$dnsSearchOrder += @($dns2)
$dnsSearchOrder += @($dns3)
$logFilePath = Create-Log
Write-ToLog -message "Starting script Set-StaticDNS.ps1...."
Write-ToLog -message "Setting DNS search order on all servers in 'servers.txt' to $dnsSearchOrder"
Write-ToLog -message "----------------------------------------------------------------------------------------------------------`n`n"
$servers | % {
	$ActiveIP = Get-ActiveNicIP -computer $_
	Set-StaticDNS -computer $_ -ActiveIP $ActiveIP
}
Write-ToLog -message "`n`n----------------------------------------------------------------------------------------------------------"
Write-ToLog -message "Script run ended."