Powershell - need to change only Subnet and GW for specific NIC - powershell

I have a situation where I need to change the Subnet and Gateway for about 170 servers but leave the IP address alone. It seems like this would be simple but the problem is that many of these servers have more than one interface on them so I have to be selective about which one is being changed.
Luckily I've named all my interfaces with a standard convention so I can select the interface I need, however since its Windows 2008r2 I'm using WMI.
Here is what my problem is: To collect information about the interface name I have to use NetConnectionID which is included in Win32_NetworkAdapter, but to actually make changes to the interface I have to use Win32_NetworkAdapterConfiguration which doesn't include the ability to select the interface based upon the name.
So what I am trying to do us is use the Index property which is in both collections to tie the information together. I first filter Win32_NetworkAdapter based upon the interface name, obtain the index value, and then attempt to select the correct interface from Win32_NetworkAdapterConfiguration so that I can change the required subnet mask and gateway.
Below is my script; the very specific area that is causing the problem is the section where I try to get the Where{$.Index -eq $Index} to work with a variable. If I set the statement to Where{$.Index -eq 10) it works, but if I try to use the variable of $Index it fails.
Here is my code:
$index = gwmi Win32_NetworkAdapter -Filter "NetConnectionID='Swizzlan'" | Select-Object - Property Index
$NICs = gwmi Win32_NetworkAdapterConfiguration -computername . | where{$_.Index -eq $Index}
Foreach($NIC in $NICs) {
$ip = ($NIC.IPAddress[0])
$gateway = "192.168.1.1"
$subnet = "255.255.252.0"
$NIC.EnableStatic($ip, $subnet)
$NIC.SetGateways($gateway)
}
Can anyone tell me how to solve this problem? After hours and hours of searching has not turned up the solution to me and I know it has to be something simple.

Win32_NetworkAdapter value "DeviceID" is equivalent to Win32_NetworkAdapterConfiguration value "Index".
So, in your code try:
$deviceID = gwmi Win32_NetworkAdapter -Filter "NetConnectionID='Swizzlan'" | Select-Object - Property DeviceID
$NICs = gwmi Win32_NetworkAdapterConfiguration -computername . | where{$_.Index -eq $deviceID.DeviceID}
$deviceID.DeviceID is used because the first line returns a PSobject. Another way to do this would be as follows:
$Adapter = gwmi Win32_NetworkAdapter -Filter "NetConnectionID='Swizzlan'"
$NICs = gwmi Win32_NetworkAdapterConfiguration -computername . | where{$_.Index -eq $Adapter.DeviceID}

Related

Select network interface to be used for getting IP information using WMI

I'm creating a script that finds and displays IP configuration information. I have managed to create the variables to get the information and to display it:
$ip = (Get-WmiObject -Class win32_networkadapterconfiguration -Filter "index = '12'").IPAddress[0]
$subnet = (Get-WmiObject -Class win32_networkadapterconfiguration -Filter "index = '12'").IPSubnet[0]
$gateway = (Get-WmiObject -Class win32_networkadapterconfiguration -Filter "index = '12'").DefaultIPGateway
$dns = (Get-WmiObject -Class win32_networkadapterconfiguration -Filter "index = '12'").DNSServerSearchOrder
write-host
write-host
write-host "IP address is: $ip"
write-host "Subnet Mask is: $subnet"
write-host "Default Gateway is: $gateway"
write-host "DNS is: $dns"
I'm filtering the interface by index number, which for my case the number is 12 for the right interface. I want to prompt the user with a list of network interfaces. Get-NetAdapter command should not be used because it doesn't work on PowerShell v2. The user must be able to see current interfaces including descriptions and be able to select one netowrk adapter interface. The selected interface must be put into a variable i.e. $interface. The variable must output the corresponding adapter index number. After that, I am able to place the variable in the filter command like: -Filter "index = '$interfaceindexnumber'" which should normally display IP information for the selected interface.
Feel free to use a different filter if you believe index number is not the right solution for this case. Please, make sure to use commands that work with PowerShell v2.
Thank You!
Based on the description of what you are trying to do, which is to allow a user to select an interface that is later used to provide information to you or your script, I took your script and scrubbed it a little bit as well as added in Out-GridView which is great for presenting information to a user. All of these commands should work in PowerShell v2.
I started out by doing just one WMI query and storing it in a variable. Then I pass filtered information to the Out-GridView cmdlet for the user to select whichever interface they want or need to select. I chose to only show the user Description, IPAddress, and Index to prevent too much confusion.
After the user makes the selection, it is assigned to $interface. To extract the full information that was originally queried from win32_networkadapterconfiguration I used the index number of the users selection to filter against $AllNetInterfaces. This could be simplified by just passing all of the information to the Out-GridView to begin with, but again since you plan on having users make selections and such, less is more.
Finally, I call the properties of the object without using the "Write-Host" function because at this point I am validating that it worked and I am not really sure what you are going to do with it later on.
$AllNetInterfaces = Get-WmiObject -Class win32_networkadapterconfiguration -Property *
$Interface = $AllNetInterfaces | Select Description, IPAddress, Index | Out-GridView -Title "Available Network Adapters" -OutputMode Single
$Interface = $AllNetInterfaces | ? {$_.Index -match $Interface.Index}
$Interface.IPAddress[0]
$Interface.IPSubnet[0]
$Interface.DefaultIPGateway
$Interface.DNSServerSearchOrder
If what you are trying to do is show the user the IP information without using ipconfig, then you could use the Out-GridView cmdlet once again, like this:
$Interface | Select IPAddress, IPSubnet, DefaultIPGateway, DNSServerSearchOrder | Out-GridView -Title "IP Info for: $($Interface.Description)"
Get-WmiObject -Class win32_networkadapterconfiguration | Select Index, #{n="IP"; e={$_.ipaddress[0]}}, #{n="Subnet"; e={$_.IPSubnet[0]}}, Description | Format-Table -AutoSize
[int]$ifindex = Read-Host "Select Network Adapter by Index Number"
$adapters = Get-WmiObject -Class win32_networkadapterconfiguration -Filter "index = '$ifindex'"
foreach ($adapter in $adapters){
$ip = $adapter.IPAddress[0]
$subnet = $adapter.IPSubnet[0]
$gateway = $adapter.DefaultIPGateway
$dns = $adapter.DNSServerSearchOrder
}
$ip
$subnet
$gateway
$dns

Powershell on 2012 PrintServer searching for printer port with certain subnets

I am interning at a company and we need to redefine our client's printer IP schema. I'm fairly green with powershell and I am using Powershell ISE and when I use:
Get-PrinterPort
I get the full list as expected. However, if I am looking for any printer ports within the subnet set of 192.168.228.*, I have used the following:
$IPAddress = Get-WmiObject -Class Win32_TCPIPPrinterPort | Where-Object ({$_.Name.Split('.').index[-1]} -eq '228')
$IPAddress = Get-WmiObject -Class Win32_TCPIPPrinterPort | Where-Object ({$_.Name.Split('.')} -match '192.168.228*')
$IPAddress = Get-WmiObject -Class Win32_TCPIPPrinterPort | Where-Object ({$_.Name.Split('.').index[-1]} -match '228')
Nothing will display. I have tried many variations of the -match, -icontains, -contains, -like and several others that will search for the partial IP address
$IPAddress = Get-WmiObject -Class Win32_TCPIPPrinterPort | Where-Object ({$_.Name.Split('.')} -match '*228')
I have also modified the script to:
Get-WmiObject -Class Win32_TCPIPPrinterPort -OutVariable allIPs
foreach ($splitIP in $allIPs -split '.' ){
$splitIP = $allIPs -split '.'
sort $splitIP[2] -Unique -OutVariable uniqueSubnetIP
}
$uniqueSubnetIP
This is the output I get from the above code
Ultimately, I want to filter through each of the subnet IPs and locate the ones where the last octet are outside the schema and automate a process to put them in range like this:
< 192.268.***.50 || > 192.168.***.60
Any help you can offer is really appreciated; I've spent days trying to figure this out.
First, I wouldn't consider $printerport.name to be reliable for detecting subnets; use $printerport.hostaddress instead.
Get-WMIObject -Class Win32_TCPIPPrinterPort | Where-Object {($_.HostAddress -split '\.')[2] -eq 228} appears to return the printerport objects in the subnet you want - for a different subnet, just change the 228 to whatever the appropriate value is.
The -split operator takes a regular expression, so the . must be escaped, \.. The operation will result in an array of four items, representing the octets of the IP address of the port. The third octet is in #()[2]; you can test other octets similarly by changing the [2] to [0], [1], or [3].

Powershell - how to replace OS Version number with String

I am querying remote servers for their operating system. I know that I can return the Version, but I want to replace these values with the friendly name. The code I have so far is:
$Computer = (gc c:\servers.txt)
$BuildVersion = Get-WmiObject -Class Win32_OperatingSystem -Property Version, CSName -ComputerName $Computer -ErrorAction SilentlyContinue
$Build=$BuildVersion.version
If ({$BuildVersion.Version -match "5.2.3790"})
{$Build="2003"}
Elseif ({$BuildVersion.Version -match "6.1.7601"})
{$Build="2008"}
Elseif ({$BuildVersion.Version -like "6.3.9600"})
{$Build="2012"}
But this doesn't seem to work and only returns "2003" regardless. Please help, I'm fairly new to PS and coding.
thanks
The problem is your if statements. Putting the Boolean expression inside squiggly brackets makes it a script block, and that's going to get cast as a string before being cast as a Boolean. Strings cast to Booleans always evaluate to true unless they're empty.
PS C:\> {$BuildVersion.Version -match "5.2.3790"}
$BuildVersion.Version -match "5.2.3790"
PS C:\> ({$BuildVersion.Version -match "5.2.3790"}) -as [bool]
True
PS C:\> $BuildVersion.Version -match "5.2.3790"
False
PS C:\> ($BuildVersion.Version -match "5.2.3790") -as [bool]
False
So what you're running is essentially:
if ([bool]'$BuildVersion.Version -match "5.2.3790"') [...]
And that's always going to be true.
Try:
$Computer = (gc c:\servers.txt)
$BuildVersion = Get-WmiObject -Class Win32_OperatingSystem -Property Version, CSName -ComputerName $Computer -ErrorAction SilentlyContinue
$Build=$BuildVersion.version
If ($BuildVersion.Version -match "5.2.3790")
{
$Build = "2003"
}
Elseif ($BuildVersion.Version -match "6.1.7601")
{
$Build = "2008"
}
Elseif ($BuildVersion.Version -like "6.3.9600")
{
$Build = "2012"
}
Bottom line is that squiggly brackets are not parentheses and you can't use them like they are.
However, there's also a major logic error here. You're potentially fetching an array for $BuildVersion because you're reading from a file, but then you treat it like a single value. You never loop through $BuildVersion. However, I do not have enough information about what you're actually trying to do with your script (like what you do with $Build) to be able to fix that.
I originally said this, but I've since changed my mind
The reason this is only returning 2003 is that you're only running your If code on a single entry in the list.
Wrong
As TessellatingHeckler says, the reason your if wasn't working is that you had too many curly braces, so PowerShell wasn't actually evaluating your logic.
However, you still need to step through each of the computers to do what you're trying to do. We'll do that by adding in a ForEach loop. I also went ahead and replaced your If {} logic with a Switch statement, which I think is easier to understand for a scenario like this with multiple clauses. If's just get way too verbose.
Finally, I'm assuming you want to output the results too, so I added a custom object here, which is just a way of choosing which properties we want to display.
$Computer = (gc c:\servers.txt)
ForEach ($system in $computer){
$BuildVersion = Get-WmiObject -Class Win32_OperatingSystem -Property Version, CSName -ComputerName $system -ErrorAction SilentlyContinue
$Build=$BuildVersion.version
switch ($build){
"5.2.3790" {$Build="2003"}
"6.1.7601" {$Build="2008"}
"6.3.9600" {$Build="2012"}
}
#output results
[pscustomobject]#{Server=$system;OSVersion=$build;CSName=$buildVersion.CSname}
}#EndOfForEach
Output
>Server OSVersion CSName
------ --------- ------
dc2012 2012 DC2012
sccm1511 2012 SCCM1511
You can use this:
Get-WmiObject -Class Win32_OperatingSystem | Select-Object -ExpandProperty Caption
Additionally you can see everything this WMI object holds like this:
Get-WmiObject -Class Win32_OperatingSystem | fl *
Edit: if you want to remove some text from the string, you can use -replace:
(Get-WmiObject -Class Win32_OperatingSystem |
Select-Object -ExpandProperty Caption) -replace "Microsoft Windows Server ",""

WMI Object with another object as property ( how to pass an object as input parameter)

Hi
I have 2 Wmi object with one of them being a property of the other.
here is my code.
$connections = get-wmiobject -class 'HNet_Connection' -Namespace 'root\Microsoft\HomeNet' ;
$connectioName = 'ethernet';
#Write-Host $connections;
foreach ($connection in $connections)
{
if ( $connection.Name -eq $connectioName)
{
$connectionx = $connection;
Write-Host $connectionx;
}
}
$connectionproperties = get-wmiobject -class 'HNet_Connectionproperties' -Namespace 'root\Microsoft\HomeNet' ;
}
So I have the connection object now I want to use it as input parameter to find the associated connection properties and I have no Idea how to do it. I don't want to parse anything; I can do some parsing on the string but for sure there should be a way to use this object as is.
Any input on how to use object in the where ( simple WQL query instead of power shell)
select * from something where something.otherobject = otherobject;
something like above.
Any ideas.
Thanks.
So the quick answer is yes, or at least as far as I understand your question the answer is yes.
Get-WmiObject has a -filter parameter that you can use to input a WQL query. As an Example:
$service = Get-WmiObject Win32_service -Filter "Name = 'Bits'"
Get-WmiObject Win32_process -Filter "ProcessID = $($service.ProcessId)"
The $() symbol indicates a subexpression I use it in this case to expand out the ProcessID property on the Service variable.

powershell how to remove `{}#` from output. Is there a special command to do it?

I entered gwmi win32_product | select -property name | select -first 1 and output to a file. My result was #{name=Google Talk Plugin}.
How can I get rid of #{}, and name. I only want it to show Google Talk Plugin?
#{} means your exporting an object with properties. Try the -ExpandProperty parameter in Select-Object. You could also combine both select-object commands, like:
gwmi win32_product | select -expandproperty name -first 1
I ran into a problem similar with
$drive = Get-WmiObject Win32_LogicalDisk -ComputerName $servername | Select-Object DeviceID
$drive comes up as #{DeviceID=C:}, #{DeviceID=D:}, ...
Here is my brute force hack at it.
The second Trim statement was because for some reason if I put it in the first Trim it starts to Trim the letters in the Drive =D: becomes :
enter code here
$Asdrive = #() #declared before to get rid of null pointer issue, also to tell PS this is an array not a string
#Write-Host "Trimming for Get-WmiObject"
for($i=0;$i -lt $drive.length; $i++) {
[string]$sdrive = $drive[$i]
[string]$sdrive1 = $sdrive.Trim("#","{","}","D","e","v","i","c","e","I","D")
[string]$sdrive2 = $sdrive1.Trim("=")
$Asdrive += $sdrive2
}
If you're running at least Version 3, you can also use the member enumeration feature and then array slicing to take the first one, instead of using select:
(gwmi win32_product).name[0]
I add some code as I found this question with google.
Frode F. solution is the best one.
If you write out something like:
Get-ADComputer -Filter * -SearchBase $OU | Select-Object Name
you get a proper List of all Computers in an OU. You can also pipe that to a CVS/HTML file and its still nice.
| Export-CSV "mylist.csv"
But if you store it into a variable (array) every name will be wrapped in #{}.
In my case I needed computer names in a variable. Here is the solution thanks to Frodo:
$computerList = Get-ADComputer -Filter * -SearchBase $OU | Select-Object -ExpandProperty Name
Hope it helps someone.
(would add it as comment under the right solution, but I don't have enough reputation to do so)