Set-IpAddress.ps1
<#
.SYNOPSIS Set-IPAddress allows you to set an IP address, subnet mask, gateway, and DNS servers for a network adapter. .DESCRIPTION Set-IPAddress allows you to set an IP address, subnet mask, gateway, and DNS servers for a network adapter. Windows 8/2012 and above have built-in cmdlets for Set-NetIPAddress, but any downlevel clients and servers are stuck with netsh. This script can still be used for Windows 8/2012 and above since the WMI methods are still available. Requires: * Write-Log - https://gallery.technet.microsoft.com/scriptcenter/Write-Log-PowerShell-999c32d0 * Send-Log - https://gallery.technet.microsoft.com/scriptcenter/Send-Log-PowerShell-f4de1581 .NOTES Created by: Jason Wasser Modified: 11/23/2015 01:47:23 PM Changelog: * Set $PSDefaultParameterValues for Write-Log * Moved sleep to the End section to save time. TODO: * Do we even want to attempt to feed computer names or just assume locally? This would require more testing and working with remote wmi. Plus changing an IP address of a remote computer during the script would not work well. * Re-enable DHCP .EXAMPLE Set-IPAddress -NetworkAdapterName "Local Area Connection" -IPAddress 192.168.1.50 -SubnetMask 255.255.255.0 -Gateway 192.168.1.1 -DNSServers 192.168.1.1,8.8.8.8 Sets the IP address, subnet mask, gateway, and DNS servers for Local Area Connection. .EXAMPLE Set-IPAddress -NetworkAdapterName "Local Area Connection" -IPAddress 192.168.1.50 -SubnetMask 255.255.255.0 Sets the IP address and subnet mask for Local Area Connection. .EXAMPLE Set-IPAddress -NetworkAdapterName "Local Area Connection" -IPAddress 192.168.1.50 -SubnetMask 255.255.255.0 -ReplaceExisting $false Adds the IP address and subnet mask to Local Area Connection keeping the existing IP configuration. #> function Set-IPAddress { [CmdletBinding()] #[OutputType([int])] Param ( # Network Interface Name [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=0)] [Alias("NIC")] [string]$NetworkAdapterName, # IP address [Parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true, Position=1)] [ipaddress[]]$IPAddress, # Subnet Mask [Parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true, Position=2)] [Alias('Netmask')] [ipaddress[]]$SubnetMask, # Gateway [Parameter(Mandatory=$false,Position=3)] [ipaddress]$Gateway, # DNS Server(s) [Parameter(Mandatory=$false,Position=4)] [ipaddress[]]$DNSServers, # Default to replace existing IP configuration. [Parameter(Mandatory=$false)] [bool]$ReplaceExisting=$true, # Path to log file [Parameter(Mandatory=$false)] [String]$LogFileName="C:\Logs\SetIPAddress.log", # Include to send copy of log via email [Parameter(Mandatory=$false)] [switch]$SendLog, # Email Parameters [string]$SmtpServer = "smtp.domain.com", [string]$ToAddress = "it.distro@domain.com", [string]$FromAddress = "automaton@domain.com", [string]$Subject = "Automaton Alert $(get-date -Format "MM/dd/yyyy HH:mm") - Set-StaticIPAddress for $($env:COMPUTERNAME)", [string]$MessageBody = "Please see attached.`n`nSincerely,`nYour friendly AutoMaton.", [int]$Port = 25, [System.Management.Automation.PSCredential]$Credential = [System.Management.Automation.PSCredential]::Empty ) Begin { # Set Default Log Path for Write-Log $PSDefaultParameterValues = @{"Write-Log:Path"="C:\Logs\SetIPAddress.log"} # Worker Function that actually changes the IP configuration. function Set-IP { # IP Address and Subnet Mask if ($IPAddress) { if (!$SubnetMask) { Write-Log "Subnet Mask was not provided." -LogPath $LogFileName -Level Error return } else { Write-Log "Setting IP Address(es) for $($NetworkAdapter.NetConnectionID)`: $IPAddress" -LogPath $LogFileName Write-Log "Subnet Mask(s): $SubnetMask" -LogPath $LogFileName $StaticIPResult = $NetworkConfig.EnableStatic($IPAddress, $SubnetMask) if ($StaticIPResult.ReturnValue -ne 0) { Write-Log "Error setting IP: $($StaticIPResult.ReturnValue)" -Level Error } } } else { # No IP address specified. Write-Log "No IP address specified." } # Gateway if ($Gateway) { Write-Log "Setting Gateway: $Gateway" $GatewayResult = $NetworkConfig.SetGateways($Gateway, 1) if ($GatewayResult.ReturnValue -ne 0) { Write-Log "Error setting gateway: $($GatewayResult.ReturnValue)" -Level Error } } else { # No gateway specified Write-Log "No gateway specified." } # DNS if ($DNSServers) { Write-Log "Setting DNS: $DNSServers" $DNSResult = $NetworkConfig.SetDNSServerSearchOrder(@($DNSServers)) if ($DNSResult.ReturnValue -ne 0) { Write-Log "Error setting DNS: $($DNSResult.ReturnValue)" -Level Error } } else { # No DNS Specified Write-Log "No DNS specified." } # After making the change we should log the new configuration. $NetworkConfig = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter "Index = $($NetworkAdapter.Index)" Write-Log "New IP Configuration: $($NetworkConfig.IPAddress)" Write-Log "New Subnet Configuration: $($NetworkConfig.IPSubnet)" Write-Log "New Gateway Configuration: $($NetworkConfig.DefaultIPGateway)" Write-Log "New DNS Configuration: $($NetworkConfig.DNSServerSearchOrder)" } # Begin Logging Write-Log "--------------------------------------------" Write-Log "Beginning $($MyInvocation.InvocationName) on $($env:COMPUTERNAME) by $env:USERDOMAIN\$env:USERNAME" } Process { # Get the network adapter that matches the provided name. Wildcards are supported, but for safety we can only match one adapter. # Although it is better to filter left, I chose to use Where to filter the network adapter name # to be able to use standard wildcards for quicker shorthand (i.e. -NIC *local*). #$NetworkAdapter = Get-WmiObject -Class win32_NetworkAdapter -Filter "NetConnectionID like '$NetworkAdapterName'" -ErrorAction Stop $NetworkAdapter = Get-WmiObject -Class win32_NetworkAdapter -ErrorAction Stop | Where-Object -FilterScript {$_.NetConnectionID -like "$NetworkAdapterName"} if ($NetworkAdapter) { if ($NetworkAdapter.Count -gt 1) { Write-Log "More than one network adapter matches $NetworkAdapterName" -Level Error } else { #$NetworkConfig = Get-WmiObject -class Win32_NetworkAdapterConfiguration -Filter "IpEnabled = 'True' and Index = $($NetworkAdapter.Index)" $NetworkConfig = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter "Index = $($NetworkAdapter.Index)" # By default we will replace the existing IP configuration with what was supplied. if ($ReplaceExisting) { Set-IP } else { # If we want to keep the existing IP address configuration, the $ReplaceExisting must be false. # This would be used if the user wished to add an additional IP address to an adapter. # We have to read the current IP address and subnet mask and then add it. # Reading the current IP address(es) may return a IPv6 which cannot be assigned through # the current WMI method. We need to strip out any IPv6 addresses and their corresponding # subnet masks. $CurrentIPAddress = @() $CurrentSubnet = @() $CurrentIPAddress += $NetworkConfig.IPAddress | Where-Object {($_ -as [ipaddress]).AddressFamily -eq "InterNetwork"} Write-Log "Current IP Address(es): $CurrentIPAddress" foreach ($Address in $CurrentIPAddress) { $CurrentSubnet += $NetworkConfig.IPSubnet[[array]::IndexOf($NetworkConfig.IPAddress, $Address)] } Write-Log "Current Subnet(s): $CurrentSubnet" # Composite arrays of existing IP address(es) and additional IP address(es). $IPAddress = $CurrentIPAddress + $IPAddress $SubnetMask = $CurrentSubnet + $SubnetMask Set-IP } } } # No matching network adapter found. else { Write-Log "Unable to find a network adapter named $NetworkAdapterName" -Level Error } } End { # Adding a pause to allow the network card to apply the new settings. Write-Log "Pausing to allow the network card to apply the new settings." Start-Sleep -Seconds 5 # Clean up Write-Log "$($MyInvocation.InvocationName) complete." Write-Log "--------------------------------------------" # Send the user a copy of the log if requested. if ($SendLog) { # Creating anonymous credential if ($Credential.Username -eq $null) { $SecurePassword = ConvertTo-SecureString -String 'anonymous' -AsPlainText -Force $Credential = New-Object System.Management.Automation.PSCredential('anonymous',$SecurePassword) } Send-Log -Path $LogFileName -SmtpServer $SmtpServer -ToAddress $ToAddress -FromAddress $FromAddress -Subject $Subject -Username $Username -Password $Password -Port $Port } # Rotate Log file if (Test-Path $LogFileName) { $TimeStamp = Get-Date -Format "yyyyMMddhhmmss" $LogFilePath = Get-ChildItem -Path $LogFileName Rename-Item $LogFileName -NewName "$($LogFilePath.BaseName)-$TimeStamp.log" } } } |