<# This script will set the IP configuration for the primary IPV4 enabled adapter. The initial release of this script will only support 1 adapter. I have used the Win32_NetworkAdapterConfiguration WMI class to provide full backward compatibility for Operating Systems and PowerShell versions. In my opinion this makes the script more flexible and useful. This version of the script simply sets 4 values: - IP Address - Subnet Mask - Default Gateway - DNS Server Search Order The script is hardcoded to: - Disable NetBIOS over TCP/IP, which in this day and age this should be a best practice! - Enable the "Register this connection's address in DNS", which is default. - Disable the "Use this connection's addresses in DNS", which is default. - However, this script will set this to Enable for Windows 7/2008R2, as I often find that these Operating System versions don't always register themselves in DNS without it. To use in an MDT/SCCM Task Sequence you must set the following Task Sequence variables: - OSDAdapterCount - OSDAdapter0EnableDHCP - OSDAdapter0IPAddressList - OSDAdapter0SubnetMask - OSDAdapter0Gateways - OSDAdapter0DNSServerList Syntax Examples: - No need to pass parameters if running from an MDT/SCCM Task Sequence. Set-IPV4Address.ps1 - Set a fixed IP Address and DNS servers Set-IPV4Address.ps1 -IPAddress:192.168.1.21 -SubnetMask:255.255.255.0 -DefaultGateway:192.168.1.1 -DNSServerSearchOrder:192.168.1.11,192.168.2.11 - Enable DHCP Set-IPV4Address.ps1 -EnableDHCP Notes: - To list all the properties of the Win32_NetworkAdapterConfiguration WMI class type: Get-WmiObject Win32_NetworkAdapterConfiguration | Get-Member -MemberType Properties | Format-List - To list all the methods of the Win32_NetworkAdapterConfiguration WMI class type: Get-WmiObject Win32_NetworkAdapterConfiguration | Get-Member -MemberType Methods | Format-List Script Name: Set-IPV4Address.ps1 Release 1.4 Written by Jeremy@jhouseconsulting.com 29/12/2014 Modified by Jeremy@jhouseconsulting.com 16/01/2022 #> #------------------------------------------------------------- Param ([Switch]$EnableDHCP,[String]$IPAddress,[String]$SubnetMask,[String]$DefaultGateway,[Array]$DNSServerSearchOrder) # Set Powershell Compatibility Mode Set-StrictMode -Version 2.0 # Enable verbose output $VerbosePreference = 'Continue' #------------------------------------------------------------- Function IsTaskSequence([switch] $verbose) { # This code was taken from a discussion on the CodePlex PowerShell App Deployment Toolkit site. # It was posted by mmashwani. # The only issue with this function is that it writes terminating errors to the transcription log, which looks # rather ugly. So this function will eventually be updated so that it checks for the existenace of the relevant # snapins (Get-PSSnapin) and assemblies ([AppDomain]::CurrentDomain.GetAssemblies()) that have been loaded. # References: # - https://richardspowershellblog.wordpress.com/2007/09/30/assemblies-loaded-in-powershell/ # - http://learningpcs.blogspot.com.au/2012/06/powershell-v2-test-if-assembly-is.html Try { [__ComObject]$SMSTSEnvironment = New-Object -ComObject Microsoft.SMS.TSEnvironment -ErrorAction 'SilentlyContinue' -ErrorVariable SMSTSEnvironmentErr } Catch { # The Microsoft.SMS.TSEnvironment assembly is not present. } If ($SMSTSEnvironmentErr) { Write-Verbose "Unable to load ComObject [Microsoft.SMS.TSEnvironment]. Therefore, script is not currently running from an MDT or SCCM Task Sequence." -verbose:$verbose Return $false } ElseIf ($null -ne $SMSTSEnvironment) { Write-Verbose "Successfully loaded ComObject [Microsoft.SMS.TSEnvironment]. Therefore, script is currently running from an MDT or SCCM Task Sequence." -verbose:$verbose Return $true } } #------------------------------------------------------------- $invalidChars = [io.path]::GetInvalidFileNamechars() $datestampforfilename = ((Get-Date -format s).ToString() -replace "[$invalidChars]","-") # Get the script path $ScriptPath = {Split-Path $MyInvocation.ScriptName} $ScriptName = [System.IO.Path]::GetFilenameWithoutExtension($MyInvocation.MyCommand.Path.ToString()) $Logfile = "$ScriptName-$($datestampforfilename).txt" $logPath = "$($env:windir)\Temp" If ((IsTaskSequence -verbose:$false)) { $tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment $logPath = $tsenv.Value("LogPath") } $logfile = "$logPath\$Logfile" try { # The Microsoft.BDD.TaskSequencePSHost.exe (TSHOST) does not support # transcription, so we wrap this in a try catch to prevent errors. Start-Transcript $logFile } catch { Write-Verbose "This host does not support transcription" } #------------------------------------------------------------- # Use PowerShell to Find Operating System Version # You can use "[System.Environment]::OSVersion.Version", or the PInvoke method as per the following Scripting Guy article: # http://blogs.technet.com/b/heyscriptingguy/archive/2014/04/25/use-powershell-to-find-operating-system-version.aspx Function Get-OSVersion { $signature = @" [DllImport("kernel32.dll")] public static extern uint GetVersion(); "@ Add-Type -MemberDefinition $signature -Name "Win32OSVersion" -Namespace Win32Functions -PassThru } $os = [System.BitConverter]::GetBytes((Get-OSVersion)::GetVersion()) $majorVersion = $os[0] $minorVersion = $os[1] $build = [byte]$os[2],[byte]$os[3] $buildNumber = [System.BitConverter]::ToInt16($build,0) [float]$OSVersion = $majorVersion.ToString() + "." + $minorVersion.ToString() #------------------------------------------------------------- If ((IsTaskSequence -verbose:$false)) { Write-Verbose "Reading Task Sequence variables" } Else { Write-Verbose "Reading script parameters" } Write-Verbose "**********************" $MissingVariables = $False If ((IsTaskSequence -verbose:$false)) { $AdapterCount = $tsenv.Value("OSDAdapterCount") } Else { $AdapterCount = 1 } If ((IsTaskSequence -verbose:$false)) { If ($TSEnv:OSDAdapter0EnableDHCP) { # We need to use the .Net System.Convert ToBoolean method to convert a # TRUE or FALSE string value into a TRUE or FALSE boolean value. $EnableDHCP = [System.Convert]::ToBoolean($tsenv.Value("OSDAdapter0EnableDHCP")) } } Else { If ($EnableDHCP.IsPresent) { $EnableDHCP = $True } Else { $EnableDHCP = $False } } If ((IsTaskSequence -verbose:$false)) { If ($TSEnv:OSDAdapter0IPAddressList) { # OSDAdapter0IPAddressList can be an array. We only accept the first value. If (($tsenv.Value("OSDAdapter0IPAddressList") | Measure-Object).Count -gt 1) { $IPAddress = $tsenv.Value("OSDAdapter0IPAddressList")[0] } Else { $IPAddress = $tsenv.Value("OSDAdapter0IPAddressList") } } Else { Write-Verbose "The OSDAdapter0IPAddressList TS variable is missing" $MissingVariables = $True } } Else { If (([String]::IsNullOrEmpty($IPAddress)) -AND $EnableDHCP -eq $False) { Write-Verbose "IP Address required" $MissingVariables = $True } } If ((IsTaskSequence -verbose:$false)) { If ($TSEnv:OSDAdapter0SubnetMask) { # OSDAdapter0SubnetMask can be an array. We only accept the first value. If (($tsenv.Value("OSDAdapter0SubnetMask") | Measure-Object).Count -gt 1) { $SubnetMask = $tsenv.Value("OSDAdapter0SubnetMask")[0] } Else { $SubnetMask = $tsenv.Value("OSDAdapter0SubnetMask") } } Else { Write-Verbose "The OSDAdapter0SubnetMask TS variable is missing" $MissingVariables = $True } } Else { If (([String]::IsNullOrEmpty($SubnetMask)) -AND $EnableDHCP -eq $False) { Write-Verbose "Subnet Mask required" $MissingVariables = $True } } If ((IsTaskSequence -verbose:$false)) { If ($TSEnv:OSDAdapter0Gateways) { # OSDAdapter0Gateways can be an array. We only accept the first value. If (($tsenv.Value("OSDAdapter0Gateways") | Measure-Object).Count -gt 1) { $DefaultGateway = $tsenv.Value("OSDAdapter0Gateways")[0] } Else { $DefaultGateway = $tsenv.Value("OSDAdapter0Gateways") } } Else { Write-Verbose "The OSDAdapter0Gateways TS variable is missing" $MissingVariables = $True } } Else { If (([String]::IsNullOrEmpty($DefaultGateway)) -AND $EnableDHCP -eq $False) { Write-Verbose "Default Gateway required" $MissingVariables = $True } } If ((IsTaskSequence -verbose:$false)) { If ($TSEnv:OSDAdapter0DNSServerList) { # OSDAdapter0DNSServerList is an array of DNS Servers listed by their # IP Addresses. $DNSServerSearchOrder = $tsenv.Value("OSDAdapter0DNSServerList") } Else { Write-Verbose "The OSDAdapter0DNSServerList TS variable is missing" $MissingVariables = $True } } Else { If ((($DNSServerSearchOrder | Measure-Object).Count -eq 0) -AND $EnableDHCP -eq $False) { Write-Verbose "DNS Server List required" $MissingVariables = $True } } # Register this connection's address in DNS # Set to True by default #$FullDNSRegistrationEnabled = $tsenv.Value("OSDAdapter0EnableFullDNSRegistration") $FullDNSRegistrationEnabled = $True # Use this connection's addresses in DNS # Set to False by default #$DynamicDNSRegistration = $tsenv.Value("OSDAdapter0EnableDNSRegistration") #if ($OSVersion -gt 6.1) { $DynamicDNSRegistration = $False #} Else { # $DynamicDNSRegistration = $True #} # DNS Suffix for this connection. # This is typically left blank. It Shouldn't be needed. #$OSDAdapter0DNSSuffix = "" # Always disable NetBIOS over TCP/IP. # You can only set this back to 0 (default) is DHCP is enabled. #$TcpipNetbiosOptions = $tsenv.Value("OSDAdapter0TCPIPNetBiosOptions") $TcpipNetbiosOptions = 2 # Primary DNS suffix of this computer. This is a computer wide setting. # NEVER set this for a domain joined computer. #$OSDDNSDomain # DNS Suffix Search Order. This is a computer wide setting. # It shouldn't be needed #OSDDNSSuffixSearchOrder If ($MissingVariables) { Write-Verbose "Required variables are missing. The script is now exiting!" try { # The Microsoft.BDD.TaskSequencePSHost.exe (TSHOST) does not support # transcription, so we wrap this in a try catch to prevent errors. Stop-Transcript } catch { Write-Verbose "This host does not support transcription" } Exit } Write-Verbose "**********************" Write-Verbose "Using the following script parameters:" If ($EnableDHCP -eq $False) { Write-Verbose "- IPAddress: $IPAddress" Write-Verbose "- SubnetMask: $SubnetMask" Write-Verbose "- DefaultGateway: $DefaultGateway" Write-Verbose "- DNSServerSearchOrder: $DNSServerSearchOrder" } Else { Write-Verbose "- EnableDHCP: $EnableDHCP" } Write-Verbose "- FullDNSRegistrationEnabled: $FullDNSRegistrationEnabled" Write-Verbose "- DynamicDNSRegistration: $DynamicDNSRegistration" Write-Verbose "- TcpipNetbiosOptions: $TcpipNetbiosOptions" #------------------------------------------------------------- Function Get-Primary-NIC-IPV4-Address { # This function will get the IPV4 address of the primary NIC. $ExistingIPV4Address = Get-WMIObject win32_NetworkAdapterConfiguration | Where-Object { $_.IPEnabled -eq $true } | Foreach-Object { $_.IPAddress } | Where-Object { $_ -notmatch 'fe80' } | Foreach-Object { [IPAddress]$_ } | Where-Object { $_.AddressFamily -eq 'Internetwork' } | Foreach-Object { $_.IPAddressToString } Return $ExistingIPV4Address } Function Set-Primary-NIC-IPV4-Config { Param ([String]$IdentifyNIC,[String]$Action) $NIC = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter "IPEnabled=true" -ComputerName . | where {$_.IPAddress -eq $IdentifyNIC} If ($NIC -ne $NULL) { $CurrentDHCPEnabled = $NIC.DHCPEnabled $CurrentIPAddress = ($NIC.IPAddress[0]) $CurrentSubnetMask = $NIC.IPSubnet[0] $CurrentDefaultGateway = $NIC.DefaultIPGateway[0] $CurrentDNSDomain = $NIC.DNSDomain $CurrentDNSDomainSuffixSearchOrder = $NIC.DNSDomainSuffixSearchOrder $CurrentDNSServerSearchOrder = $NIC.DNSServerSearchOrder # Register this connection's address in DNS $CurrentFullDNSRegistrationEnabled = $NIC.FullDNSRegistrationEnabled # Use this connection's addresses in DNS. # Note that this can only be enabled if "Register this connection's address in DNS" is enabled. $CurrentDynamicDNSRegistration = $NIC.DomainDNSRegistrationEnabled $CurrentTcpipNetbiosOptions = $NIC.TcpipNetbiosOptions Write-Verbose "**********************" If ($Action -eq "Set") { Write-Verbose "Existing Configuration:" } If ($Action -eq "Get") { Write-Verbose "New Configuration:" } Write-Verbose "- DHCP Enabled: $CurrentDHCPEnabled" Write-Verbose "- IP Address: $CurrentIPAddress" Write-Verbose "- Subnet Mask: $CurrentSubnetMask" Write-Verbose "- Default Gateway: $CurrentDefaultGateway" Write-Verbose "- DNS Domain: $CurrentDNSDomain" Write-Verbose "- DNS Domain Suffix Search Order: $CurrentDNSDomainSuffixSearchOrder" Write-Verbose "- DNS Servers: $CurrentDNSServerSearchOrder" Write-Verbose "- Register this connection's address in DNS: $CurrentFullDNSRegistrationEnabled" Write-Verbose "- Use this connection's addresses in DNS: $CurrentDynamicDNSRegistration" Write-Verbose "- NetBIOS Setting: $CurrentTcpipNetbiosOptions (0 = Default, 1 = Enabled, 2 = Disabled)" If ($Action -eq "Set") { Write-Verbose "**********************" Write-Verbose "Applying New Configuration..." If ($EnableDHCP -eq $False) { #$NIC.EnableStatic($IPAddress, $SubnetMask) | Out-Null #$NIC.SetGateways($DefaultGateway) | Out-Null #$NIC.SetDNSServerSearchOrder($DNSServerSearchOrder) | Out-Null } Else { $NIC.EnableDHCP() | Out-Null $NIC.SetDNSServerSearchOrder() | Out-Null } $NIC.SetDynamicDNSRegistration($FullDNSRegistrationEnabled,$DynamicDNSRegistration) | Out-Null $NIC.SetTcpipNetbios($TcpipNetbiosOptions) | Out-Null $SleepTimeInSeconds = 10 If ($EnableDHCP -eq $False) { Write-Verbose "- Sleeping for $SleepTimeInSeconds seconds whilst the IP address applies." } Else { Write-Verbose "- Sleeping for $SleepTimeInSeconds seconds whilst it gets an IP address from DHCP." } Start-Sleep -seconds $SleepTimeInSeconds } $NIC = $NULL } } $IdentifyNIC = Get-Primary-NIC-IPV4-Address If ($IdentifyNIC -ne $NULL) { Set-Primary-NIC-IPV4-Config -IdentifyNIC:$IdentifyNIC -Action:Set } Else { Write-Verbose "An IP enabled NIC with an IPV4 address could not be found." } $IdentifyNIC = Get-Primary-NIC-IPV4-Address If ($IdentifyNIC -ne $NULL) { Set-Primary-NIC-IPV4-Config -IdentifyNIC:$IdentifyNIC -Action:Get } Else { Write-Verbose "An IP enabled NIC with an IPV4 address could not be found." } Write-Verbose "**********************" # Push the current location onto a location stack and then change the current location to the location specified Push-Location "$env:SystemRoot\System32" # Force the computer to re-register with DNS to update its host record. ipconfig /registerdns | Out-Null Write-Verbose "Re-registering with DNS to update the host record" # Change the current location back to the location most recently pushed onto the stack, which will be defined by the $ScriptPath variable Pop-Location try { # The Microsoft.BDD.TaskSequencePSHost.exe (TSHOST) does not support # transcription, so we wrap this in a try catch to prevent errors. Stop-Transcript } catch { Write-Verbose "This host does not support transcription" }