I am creating a script which will run through a lot of the basic tasks when commissioning a new server. Now most servers have multiple NICs these days and I need to question the user (using the script) what NIC they want to assign the IP to.
At the moment I have:
$NICs = Get-WMIObject Win32_NetworkAdapterConfiguration -ComputerName $env:COMPUTERNAME | where{$_.IPEnabled -eq $true -and $_.DHCPEnabled -eq $true}
Which will put the NICs into $NICs I believe. However from here I want to print them out to the user, and then somehow assign a value to each NIC, like an index, so the user can type in, "1" or "2" so tell the script what NIC to apply the Ip configuration to which will be done like:
If($ipQuestion -eq "Y") {
$ipAddr = Read-Host "Enter IP Address: "
$subnet = Read-Host "Enter Subnet: "
$dns = Read-Host "Enter DNS: "
Write-Host "Multiple DNS servers?" -ForegroundColor Green
$multipleDNSServersQuestion = Read-Host
If($multipleDNSServersQuestion -eq 'Y'){
$dns2 = Read-Host "Enter Secondary DNS: "
}
$dGateway = Read-Host "Enter Default Gateway: "
}
$NIC.EnableStatic($ipAddr, $subnet)
$NIC.SetGateways($dGateway)
$NIC.SetDNSServerSearchOrder($dns, $dns2)
$NIC.SetDynamicDNSRegistration("TRUE")
Any ideas?
If you ensure $NICS is always an array, you can use the array index to specify each NIC. To ensure it is always an array do this:
$NICs = #(Get-WMIObject Win32_NetworkAdapterConfiguration -ComputerName $env:COMPUTERNAME | where{$_.IPEnabled -eq $true -and $_.DHCPEnabled -eq $true})
Then print out the info like so:
PS> $NICS = #(Get-WMIObject Win32_NetworkAdapterConfiguration)
PS> $NICS | Foreach {$i=-1}{$i++;$_} | ft #{n='index';e={$i}},Description,ServiceName
index Description ServiceName
----- ----------- -----------
0 WAN Miniport (L2TP) Rasl2tp
1 WAN Miniport (SSTP) RasSstp
2 WAN Miniport (IKEv2) RasAgileVpn
3 WAN Miniport (PPTP) PptpMiniport
4 WAN Miniport (PPPOE) RasPppoe
5 WAN Miniport (IP) NdisWan
6 WAN Miniport (IPv6) NdisWan
7 WAN Miniport (Network Monitor) NdisWan
8 Microsoft Kernel Debug Network Adapter kdnic
9 RAS Async Adapter AsyncMac
10 Broadcom NetXtreme Gigabit Ethernet b57nd60a
11 Microsoft ISATAP Adapter tunnel
12 Microsoft Teredo Tunneling Adapter tunnel
13 Microsoft 6to4 Adapter tunnel
14 Microsoft ISATAP Adapter tunnel
Then access each NIC like so:
$NICS[$selectedIndex]
$NICs = #(Get-WMIObject Win32_NetworkAdapterConfiguration ...)
will make $NICs an array, which can be accessed by (zero-based) index:
$NICs[0] # <-- first interface
$NICs[1] # <-- second interface
...
The way I would do it. If you have a look to the network connexions panel in the internet connexions. You can see the string the user know for his devices :
So in a dialog with the user I would give this name retreiving it with win32_NetworkAdapter joinning Win32_NetworkAdapterConfiguration with Index.
$NICs = Get-WMIObject Win32_NetworkAdapterConfiguration -ComputerName $env:COMPUTERNAME | where{$_.IPEnabled -eq $true -and $_.DHCPEnabled -eq $true}
$NICs | % {$i = (Get-WmiObject win32_NetworkAdapter -Filter "index=$($_.index)").NetConnectionID; $_} | ft #
{n='index';e={$i}},Description,ServiceName
index Description ServiceName
----- ----------- -----------
NET1 Intel(R) 82567LM Gigabit Network Conne... e1yexpress
Related
I have a function that I wrote that interrogates my local system. Just gathering whatever information I can get in a useful format. So I was wondering about a function that could interrogate other systems in this kind of way. function sys-remote <$ip-or-hostname> With that it could then try and return as much information about that system as it can. It's just an idea really, and I guess a number of points would be useful:
• With an IP address, how can we resolve the hostname in the most PowerShell'ish way?
• Whether a hostname of IP address is provided, can we resolve as much information as possible. i.e. MAC address, hostname, IP (and possibly other IP addresses if these can be visible to us)?
• Can we recover shared drives on that system so can see a list of possible shares to connect to.
• What about system information, would that always require WinRM, or can WMI or CIM suffice for most of the things in the below?
• Maybe return also a comma-separate list of whatever ports are open on that remote system if possible?
• What if the remote system is Linux. How much of the above can we reasonably obtain from a Linux system that we interrogate remotely from our Windows system (I guess that WinRM and WMI are out, but maybe CIM is still possible?)?
In general, it would be really useful to return a dump of information like this from a diagnostic point of view as would give a ton of information about a system to work from. Anything like the above (or indeed any other useful things to check for that I've not thought of here) would be really appreciated.
function sys {
$System = get-wmiobject -class "Win32_ComputerSystem"
$Mem = [math]::Ceiling($System.TotalPhysicalMemory / 1024 / 1024 / 1024)
$wmi = gwmi -class Win32_OperatingSystem -computer "."
$LBTime = $wmi.ConvertToDateTime($wmi.Lastbootuptime)
[TimeSpan]$uptime = New-TimeSpan $LBTime $(get-date)
$s = "" ; if ($uptime.Days -ne 1) {$s = "s"}
$uptime_string = "$($uptime.days) day$s $($uptime.hours) hr $($uptime.minutes) min $($uptime.seconds) sec"
$job_cpu = Start-Job -ScriptBlock { (Get-WmiObject -Class Win32_Processor).Name }
$job_cpu_cores = Start-Job -ScriptBlock { (Get-WmiObject -Class Win32_Processor).NumberOfCores }
$job_cpu_logical = Start-Job -ScriptBlock { (Get-WmiObject -Class Win32_Processor).NumberOfLogicalProcessors }
""
"Hostname: $($System.Name)"
"Domain: $($System.Domain)"
"PrimaryOwner: $($System.PrimaryOwnerName)"
"Make/Model: $($System.Manufacturer) ($($System.Model))" # "ComputerModel: $((Get-WmiObject -Class:Win32_ComputerSystem).Model)"
"SerialNumber: $((Get-WmiObject -Class:Win32_BIOS).SerialNumber)"
"PowerShell: $($PSVersionTable.PSVersion)"
"Windows Version: $($PSVersionTable.BuildVersion), Windows ReleaseId: $((Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name 'ReleaseId').ReleaseId)"
"Display Card: $((Get-WmiObject -Class:Win32_VideoController).Name)"
"Display Driver: $((Get-WmiObject -Class:Win32_VideoController).DriverVersion), Description: $((Get-WmiObject -Class:Win32_VideoController).VideoModeDescription)"
"Last Boot Time: $([Management.ManagementDateTimeConverter]::ToDateTime((Get-WmiObject Win32_OperatingSystem | select 'LastBootUpTime').LastBootUpTime)), Uptime: $uptime_string"
$IPDefaultAddress = #(Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object {$_.DefaultIpGateway})[0].IPAddress[0]
$IPDefaultGateway = #(Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object {$_.DefaultIpGateway})[0].DefaultIPGateway[0]
"Default IP: $IPDefaultAddress / $IPDefaultGateway"
Get-Netipaddress | where AddressFamily -eq IPv4 | select IPAddress,InterfaceIndex,InterfaceAlias | sort InterfaceIndex
""
Wait-Job $job_cpu | Out-Null ; $job_cpu_out = Receive-Job -Job $job_cpu
Wait-Job $job_cpu_cores | Out-Null ; $job_cpu_cores_out = Receive-Job -Job $job_cpu_cores
Wait-Job $job_cpu_logical | Out-Null ; $job_cpu_logical_out = Receive-Job -Job $job_cpu_logical
"CPU: $job_cpu_out"
"CPU Cores: $job_cpu_cores_out, CPU Logical Cores: $job_cpu_logical_out"
# Get-PSDrive | sort -Descending Free | Format-Table
gwmi win32_logicaldisk | Format-Table DeviceId, VolumeName, #{n="Size(GB)";e={[math]::Round($_.Size/1GB,2)}},#{n="Free(GB)";e={[math]::Round($_.FreeSpace/1GB,2)}}
gwmi win32_winsat | select-object CPUScore,D3DScore,DiskScore,GraphicsScore,MemoryScore,WinSPRLevel | ft # removed ,WinSATAssessmentState
get-WmiObject -class Win32_Share | ft
}
No reason to do this sort of thing from scratch. There are many existing scripts for what you are doing. Via the Microsoft powershellgallery.com.
PowerShell Script For Desktop Inventory Basic script to collect
desktop inventory.
PowerShell Hardware Inventory Script Scenario:PowerShell hardware
Inventory Script. Have you ever wanted to have an inventory without the
hassle of going to each finding the information needed to fill the
information for your inventory? It is important to keep your inventory
up to date. Every time there is a change y
DownloadGet-Inventory.ps1
You can just take your script and use Invoke-Command (Runs commands on local and remote computers.) in a PowerShell remote session to get remote computer info.
Hi All,
I was hoping if someone has done this scenario before. I'm looking for a PowerShell script to gather PC Hardware details in the local network. it's Windows 7,10 and not in DC.
Details I would like to get from each PC is
RAM (name and size)
CPU (name and size)
HDD (name and size)
Local User profiles
Is it something possible (logically I can't see how it's possible) as PC's are not in a domain.
Any suggestions would helpful
Love & Peace
My fellow humans
This should do the trick:
Add-Type -AssemblyName System.Collections
[System.Collections.Generic.List[string]]$hdd = #()
$system = Get-CimInstance CIM_ComputerSystem
$cpu = Get-CimInstance CIM_Processor
$users = Get-WmiObject -ComputerName "localhost" -Class Win32_UserAccount -Filter "LocalAccount='True'" |Select PSComputername, Name, Status, Disabled, AccountType, Lockout, PasswordRequired, PasswordChangeable, SID
$driveLetter = 'C'
$currentHdd = Get-CimInstance Win32_LogicalDisk -Filter "DeviceID = '$($driveletter):'"
while( $currentHdd.DeviceID ) {
switch( $currentHdd.DriveType ) {
3 {
$driveType = "HDD"
break;
}
5 {
$driveType = "Optical"
break;
}
default {
$driveType = "Other"
}
}
$drive = $driveletter + ': ' + $driveType + (" {0:N2}" -f ($currentHdd.Size/1GB) + " GB ") + ("{0:N2}" -f ($currentHdd.FreeSpace/1GB) + " GB ")
$hdd.Add( $drive )
$driveLetter = ([char](++([byte]([char]$driveLetter)))).ToString()
$currentHdd = Get-CimInstance Win32_LogicalDisk -Filter "DeviceID = '$($driveletter):'"
}
$ram = "{0:N2}" -f ($system.TotalPhysicalMemory/1GB) + " GB"
$cpuName = $cpu.Name
"CPU: $cpuName"
"RAM: $ram"
"Disks:"
$hdd
"Users:"
$users
This will do the trick for machines NOT on domain.
You will need:
IP Address(s)
Admin login credentials for the remote machine
Below syntax will query Windows7-Windows10 machines for RAM, CPU, HDD and User profiles:
wmic /NODE:"127.0.0.1" memorychip get capacity & wmic /NODE:"127.0.0.1" cpu list brief & wmic /NODE:"127.0.0.1" diskdrive get Name, Manufacturer, Model & wmic /NODE:"127.0.0.1" useraccount get name
For the example above, I'm simply using loopback IP (queries the local PC you are on), but you can substitute any IP address.
You can also specify your credentials to the wmic tool if needed. Learn more about wmic here:
https://learn.microsoft.com/en-us/windows/win32/wmisdk/wmic
I'm trying to get the content from the boot order list with the following command but $pr is empty and there is no error message:
$pr = Get-HPBIOSUEFIBootOrder $conObj | select -Expand UEFIBootOrder |select -Expand DeviceName| Where DeviceName -contains "*Target:0, Lun:0)"^
Where's my mistake?
When I run this:
$pr = Get-HPBIOSUEFIBootOrder $conObj | select -Expand UEFIBootOrder |select -Expand DeviceName
It returns this:
Generic USB Boot
Embedded LOM 1 Port 1 : HP Ethernet 1Gb 4-port 331i Adapter - NIC (PXE IPv6)
Embedded LOM 1 Port 1 : HP Ethernet 1Gb 4-port 331i Adapter - NIC (PXE IPv4)
Slot 3 Port 1 : HP Ethernet 10Gb 2-port 530T Adapter - NIC (PXE IPv6)
Embedded RAID 1 : Smart Array P440ar Controller - 279.43 GiB, RAID 1 Logical Drive(Target:0, Lun:1)
Windows Boot Manager
Internal USB 1 : HPE Dual 8GB MicroSD EM USB Kit - USB RAID LUN
Embedded RAID 1 : Smart Array P440ar Controller - 279.37 GiB, RAID 1 Logical Drive(Target:0, Lun:0)
Embedded FlexibleLOM 1 Port 1 : HP FlexFabric 10Gb 2-port 533FLR-T Adapter - NIC (PXE IPv6)
Embedded RAID 1 : Smart Array P440ar Controller - 279.37 GiB, RAID 1 Logical Drive(Target:0, Lun:2)
Embedded FlexibleLOM 1 Port 1 : HP FlexFabric 10Gb 2-port 533FLR-T Adapter - NIC (PXE IPv4)
Slot 3 Port 1 : HP Ethernet 10Gb 2-port 530T Adapter - NIC (PXE IPv4)
Use -like instead of -contains.
Contains should be used when you want to determine if a value is in a collection of values. Like should be used (with wildcard characters) when you want to partially match a string. This is a common PowerShell misconception.
You've also used -ExpandProperty on DeviceName after which have a collection of strings without that property name. As such you need to do this in your Where:
| Where {$_ -like "*Target:0, Lun:0)"}
$_ is a special placeholder that represents the current item in the pipeline, which with a system.string object is (by default) its string value.
Here is a bigger picture of my little project.
And what i´ve reached so far.
It will find more makings in the near future.
##
# The following Script is checking the current HPPowerProfile Setting on the local Server
# and set it to Maximum_Performance if its not already set.
#
# Also it set´s the UEFIBootOrder to HDD firts (Target:0, Lun:0)
##
# Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File C:\mysecurestring.txt
# Set Access Credentials
$username = "*******"
$password = cat C:\mysecurestring.txt | Convertto-SecureString
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username, $password
# Set ILO Hostname
$sv = hostname
$ri = $sv.replace("YY","XX")
# Connect to HPBios
$conObj = Connect-HPBIOS $ri -Credential $cred -DisableCertificateAuthentication
# Check current BootMode (depending on Boot Mode, other cmdlet´s will be executed)
$bm = $conObj | Get-HPBIOSBootMode | select -Expand BootMode
if ( $bm -eq "UEFI Mode")
{echo "UEFI"}
else
{echo "echo $bm"}
# Check current Server Power Profile
$pr = Get-HPBIOSPowerProfile $conObj | select -Expand HPPowerProfile
if (-not( $pr -eq "Maximum Performance"))
{$conObj | Set-HPBIOSPowerProfile -HPPowerProfile Maximum_Performance}
else
{echo "No change needed"}
# Find HDD and move it to Boot Order #1
$bo = Get-HPBIOSUEFIBootOrder $conObj | select -Expand UEFIBootOrder | Where DeviceName -like "*Drive(Target:0, Lun:0)" | select -Expand Index
if (-not( $bo -eq "1"))
{$conObj | Set-HPBIOSUEFIBootOrder -UEFIBootOrder "$bo,1"}
else
{echo "No change needed"}
I want to incorporate a dropdown menu that is populated with the list of available COM ports. I can't find any way to easily get the names of the available COM ports to put in the place of COM4 that creates the $port.
$port = new-Object System.IO.Ports.SerialPort COM4,19200,None,8,one
By using Win32_SerialPort I am able to easily extract COM1 and COM3.
Get-WmiObject Win32_SerialPort | Select-Object deviceid
Results:
deviceid
COM3
COM1
But my device manager shows 16 available ports from a remote serial hub.
Device Manager Snapshot
Here is what I have tried and I am able to narrow down the Name, but can't figure out how to extract just the (COM--) part.
Get-WmiObject Win32_pnpentity -Filter "Name LIKE 'devicemaster port%'" | Select-Object -Property Name
Result Screenshot
Adding a late answer because I just had a need for this...
You can use WMI ClassGuids to get the exact list (COM and LPT) that device manager shows:
$lptAndCom = '{4d36e978-e325-11ce-bfc1-08002be10318}'
get-wmiobject -Class win32_pnpentity | where ClassGuid -eq $lptAndCom | select name
Confirmed to work with a few LPT / COM extension cards (Brain Boxes / Exar), using Windows 8.1 up to server 2019 (Powershell 4 onwards).
The full list of ClassGuids is here:
https://learn.microsoft.com/en-us/windows-hardware/drivers/install/system-defined-device-setup-classes-available-to-vendors
Here is a more up-to-date solution to get the COM-port details:
cls
$portList = get-pnpdevice -class Ports -ea 0
$portCount = 0
if ($portList) {
$now = get-date
foreach($device in $portList) {
$id = $device.InstanceId
if ($device.Present) {
$date = $now
} else {
$info = Get-PnpDeviceProperty -InstanceId $id
$latest = $info | ?{$_.KeyName -eq "DEVPKEY_Device_LastRemovalDate"}
$date = [datetime]$latest.Data
}
$age = $now-$date
if ($age.Days -lt 14) {
"port name : $name"
"last active: $date"
""
$portCount++
}
}
}
"number of active COM-port devices in last 14 days: $portCount"
Leaving some work to you to figure out, but based on your Result Screenshot you can do something like this:
$ports = #()
$ports += 'devicemaster port (COM1)'
$ports += 'devicemaster port (COM2)'
$ports += 'devicemaster port (COM3)'
$ports += 'devicemaster port (COM4)'
$ports | % {
if ($_ -match "devicemaster port \((.*)\)") {
$matches[1]
}
}
with that object, assuming you store that in '$ports'. You may need to use '$ports.Name'...
Possibly see regex101.com for how the regex works.
In the following code, the $ipAddress stores both the IPV4 and IPV6. I only want the IPV4 displayed, is there anyway this can be done? Maybe with a split?
Also, the subnet mask prints 255.255.255.0 64 - where is this rogue 64 coming from?
Code:
ForEach($NIC in $env:computername) {
$intIndex = 1
$NICInfo = Get-WmiObject -ComputerName $env:computername Win32_NetworkAdapterConfiguration | Where-Object {$_.IPAddress -ne $null}
$caption = $NICInfo.Description
$ipAddress = $NICInfo.IPAddress
$ipSubnet = $NICInfo.IpSubnet
$ipGateWay = $NICInfo.DefaultIPGateway
$macAddress = $NICInfo.MACAddress
Write-Host "Interface Name: $caption"
Write-Host "IP Addresses: $ipAddress"
Write-Host "Subnet Mask: $ipSubnet"
Write-Host "Default Gateway: $ipGateway"
Write-Host "MAC: $macAddress"
$intIndex += 1
}
Subnets work differently for IPv6, so the rogue 64 you are seeing is the IPv6's subnet mask - not the IPv4's.
The prefix-length in IPv6 is the equivalent of the subnet mask in IPv4. However, rather than being expressed in 4 octets like it is in IPv4, it is expressed as an integer between 1-128. For example: 2001:db8:abcd:0012::0/64
See here: http://publib.boulder.ibm.com/infocenter/ts3500tl/v1r0/index.jsp?topic=%2Fcom.ibm.storage.ts3500.doc%2Fopg_3584_IPv4_IPv6_prefix_subnet_mask.html
In order to remove it you can try the following (massive assumption made that IPv4 always comes first, but in all my experimenting it hasn't come second yet ;))
ForEach($NIC in $env:computername) {
$intIndex = 1
$NICInfo = Get-WmiObject -ComputerName $env:computername Win32_NetworkAdapterConfiguration | Where-Object {$_.IPAddress -ne $null}
$caption = $NICInfo.Description
#Only interested in the first IP Address - the IPv4 Address
$ipAddress = $NICInfo.IPAddress[0]
#Only interested in the first IP Subnet - the IPv4 Subnet
$ipSubnet = $NICInfo.IpSubnet[0]
$ipGateWay = $NICInfo.DefaultIPGateway
$macAddress = $NICInfo.MACAddress
Write-Host "Interface Name: $caption"
Write-Host "IP Addresses: $ipAddress"
Write-Host "Subnet Mask: $ipSubnet"
Write-Host "Default Gateway: $ipGateway"
Write-Host "MAC: $macAddress"
$intIndex += 1
}
Hope this helps!