Determining internet connection using Powershell - powershell

Is there a simple cmdlet I can run in PowerShell to determine if my Windows machine is connected to the internet through Ethernet or through the wireless adapter? I know you can determine this on the GUI, I just want to know how this can be managed in PowerShell.

The PowerShell cmdlet Get-NetAdapter can give you a variety of info about your network adapters, including the connection status.
Get-NetAdapter | select Name,Status, LinkSpeed
Name Status LinkSpeed
---- ------ ---------
vEthernet (MeAndMahVMs) Up 10 Gbps
vEthernet (TheOpenRange) Disconnected 100 Mbps
Ethernet Disconnected 0 bps
Wi-Fi 2 Up 217 Mbps
Another option is to run Get-NetAdapterStatistics which will show you stats only from the currently connected device, so we could use that as a way of knowing who is connected to the web.
Get-NetAdapterStatistics
Name ReceivedBytes ReceivedUnicastPackets SentBytes SentUnicastPackets
---- ------------- ---------------------- --------- ------------------
Wi-Fi 2 272866809 323449 88614123 178277
Better Answer
Did some more research and found that if an adapter has a route to 0.0.0.0, then it's on the web. That leads to this pipeline, which will return only devices connected to the web.
Get-NetRoute | ? DestinationPrefix -eq '0.0.0.0/0' | Get-NetIPInterface | Where ConnectionState -eq 'Connected'
ifIndex InterfaceAlias AddressFamily InterfaceMetric Dhcp ConnectionState
------- -------------- ------------- --------------- ------- ---------------
17 Wi-Fi 2 IPv4 1500 Enabled Connected

Get-NetConnectionProfile
will return something like this for each connected network adapter using the Network Connectivity Status Indicator (the same indicator as used in the properties of a network device):
Name : <primary DNS suffix>
InterfaceAlias : Ethernet
InterfaceIndex : 9
NetworkCategory : DomainAuthenticated
IPv4Connectivity : Internet
IPv6Connectivity : LocalNetwork
Name : <primary DNS suffix>
InterfaceAlias : WiFi
InterfaceIndex : 12
NetworkCategory : DomainAuthenticated
IPv4Connectivity : Internet
IPv6Connectivity : LocalNetwork
You should be able to use the IPv4Connectivity or IPv6Connectivity to give you a true/false value what you want. The following will check if Windows thinks any network device is connected to the Internet via either IPv4 or IPv6:
$AllNetConnectionProfiles = Get-NetConnectionProfile
$AllNetConnectionProfiles.IPv4Connectivity + $AllNetConnectionProfiles.IPv6Connectivity -contains "Internet"

I wrote a function that does this. It should work on all versions of PowerShell, but I have not tested it on XP / Server 2003.
function Test-IPv4InternetConnectivity
{
# Returns $true if the computer is attached to a network that has connectivity to the
# Internet over IPv4
#
# Returns $false otherwise
# Get operating system major and minor version
$strOSVersion = (Get-WmiObject -Query "Select Version from Win32_OperatingSystem").Version
$arrStrOSVersion = $strOSVersion.Split(".")
$intOSMajorVersion = [UInt16]$arrStrOSVersion[0]
if ($arrStrOSVersion.Length -ge 2)
{
$intOSMinorVersion = [UInt16]$arrStrOSVersion[1]
} `
else
{
$intOSMinorVersion = [UInt16]0
}
# Determine if attached to IPv4 Internet
if (($intOSMajorVersion -gt 6) -or (($intOSMajorVersion -eq 6) -and ($intOSMinorVersion -gt 1)))
{
# Windows 8 / Windows Server 2012 or Newer
# First, get all Network Connection Profiles, and filter it down to only those that are domain networks
$IPV4ConnectivityInternet = [Microsoft.PowerShell.Cmdletization.GeneratedTypes.NetConnectionProfile.IPv4Connectivity]::Internet
$internetNetworks = Get-NetConnectionProfile | Where-Object {$_.IPv4Connectivity -eq $IPV4ConnectivityInternet}
} `
else
{
# Windows Vista, Windows Server 2008, Windows 7, or Windows Server 2008 R2
# (Untested on Windows XP / Windows Server 2003)
# Get-NetConnectionProfile is not available; need to access the Network List Manager COM object
# So, we use the Network List Manager COM object to get a list of all network connections
# Then we check each to see if it's connected to the IPv4 Internet
# The GetConnectivity() method returns an integer result that can be bitwise-enumerated
# to determine connectivity.
# See https://msdn.microsoft.com/en-us/library/windows/desktop/aa370795(v=vs.85).aspx
$internetNetworks = ([Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]"{DCB00C01-570F-4A9B-8D69-199FDBA5723B}"))).GetNetworkConnections() | `
ForEach-Object {$_.GetNetwork().GetConnectivity()} | Where-Object {($_ -band 64) -eq 64}
}
return ($internetNetworks -ne $null)
}

Test-Connection -ComputerName $servername
Where $servername is a web address. Use the -Quiet switch to return true/false.

Related

How do I permanently set a static IP Address in Windows 10 using PowerShell for my automated OS build process?

When I started learning how to do this by watching videos, I learned about IP address InterfaceIndexes. I learned that I can't set an IP Address without knowing the IP Address's InterfaceIndex first. That seemed to be different on every computer I look at and seemed to be random. Then, I learned that you can use an IP Address Alias. On a fresh Windows install, it seemed that the IP Address Alias Ethernet0 was going to be a constant that I could rely on. So, with my primitive PowerShell skills, I thought I could reach out and grab the PC's IP Address and check to see if it matched what it was supposed to be. If it wasn't, wipe out whatever Ethernet0 is, and create a new IP Address with the alias of Ethernet0. Of course the first time I did this it worked perfectly and I moved on. I had a static IP address called Ethernet0 with the specified IP address. I just went in and looked and I have 2 available NICs. One is called "Ethernet" and the other is "Ethernet2". Nether of them have a static IP Address. I'm assuming the PC wants to set random alias names upon a restart? I'm a little confused on what happened. Of course when I run my method again, I get an error that says "No InterfaceAlias equal to ethernet0", so my code doesn't work. I'm obviously way off on how I should be approaching this. I want to do a fresh install and run a configuration script to set everything up without any GUI interaction. I don't work in an enterprise domain type of environment, and have to create my own process. Please help further my PowerShell wisdom, as only a Padawan I am.
function SetIp {
$ipv4 = (Test-Connection -ComputerName $env:COMPUTERNAME -Count 1) .IPV4Address.IpAddressToString
if($ipv4 -eq "my.ip.add.res") {
Write-Host "Do Nothing as the IP has already been set"
}
else {
Remove-NetIPAddress -InterfaceAlias ethernet0
New-NetIPAddress -IPAddress my.ip.add.res -InterfaceAlias ethernet0 -PrefixLength 16
Write-Host "IP Address has been set"
}
}
You can see all the available info about the NetIPInterface objects with Get-NetIPInterface | Select * -First 1. Some useful properties are ConnectionState,AddressFamily, or Dhcp. For example, try something like this to find valid ones:
Get-NetIPInterface | Where {
$_.ConnectionState -eq 'Connected' -and
$_.AddressFamily -eq 'IPV4' -and
$_.InterfaceAlias -like 'Eth*' -and
# check if in your local subnet
($_.DHCP -eq 'Enabled' -or ($_|Get-NetIPAddress).IPv4Address -like '1.2.3.*')
}
You can run into all sorts of things though, so it depends on how controlled your environment is:
Wifi and/or Ethernet are connected
Second Ethernet, or laptop dock creates new net interfaces
VPN software creates a new 'Ethernet' interface
If you need to ask a user for input, you could do it with gridview:
$Selected = Get-NetIPInterface |
? {$_.AddressFamily -eq 'IPV4' -and $_.InterfaceAlias -notlike 'Loopback*'} |
Select IFIndex,InterfaceAlias,ConnectionState |
# Ask the user to select the interface
Out-GridView -Title 'Please select the correct interface' -OutputMode Single
Set-NetIPInterface -InterfaceIndex $Selected.ifIndex -AddressFamily IPv4 ## etc...
That said, just setting up DHCP to handle this will almost always be easier. DHCP reservations are generally just as good as static IPs for user machines

List all services in PowerShell

There are some services in Windows (such as http and USBStor) which are not listed when you view Services, or when running the Get-Service cmdlet. What is the simplest way to list all services, even the hidden or unlisted ones?
For example, the http and USBStor services are not enumerated when listing services, but they can be accessed directly by name:
PS C:\Windows\System32> Get-Service | Where-Object {"http","usbstor","spooler" -contains $_.Name}
Status Name DisplayName
------ ---- -----------
Running Spooler Print Spooler
PS C:\Windows\System32> Get-Service "http","usbstor","spooler"
Status Name DisplayName
------ ---- -----------
Running http HTTP Service
Running spooler Print Spooler
Stopped usbstor USB Mass Storage Driver
This might not be the most elegant way of getting all the services (hidden per say), but this will give you all the services along with ones these are dependent on.
Get-Service -RequiredServices | select -Unique DisplayName | ? {$_.DisplayName -like "Http*" }
Try 'Get-CimInstance'.
Such functions (Get-Service) delivered by Microsoft rely on and use CIM/Win32 classes.
(Get-Service only shows Windows services. 'HTTP' is a system driver.)
Get-CimInstance 'CIM_Service'

Why is Get-DnsClientServerAddress | select AddressFamily output not IPv4 and IPv6

When I type the cmdlet Get-DnsClientServerAddress I get all the interfaces my PC has like for example
InterfaceAlias Interface Address ServerAddresses
Index Family
-------------- --------- ------- ---------------
Ethernet 7 IPv4 {10.10.15.40, 10.10.25.44}
So when I type in Get-DnsClientServerAddress | where AddressFamily -Like "4" I would expect to see the Ethernet Adapter.
But for any reason it didn't show up. So I typed Get-DnsClientServerAddress | select AddressFamily and what I got was
AddressFamily
-------------
2
23
2
23
Can anyone explain this to me ?
As you found, the AddressFamily is categorised internally using a (not obvious) numbering scheme, where IPv4 addresses are type '2'. This comes from the underlying WMI type (MSFT_DNSClientServerAddress) and is not an issue with PowerShell.
The default display helps you out by translating this to IPv4, etc, but you can't filter on that as it's for display only. You can, however, still filter if you use the correct value:
Get-DnsClientServerAddress | Where-Object AddressFamily -Like 2
This formatting of data for display purposes happens all the time in PowerShell and is acheived through Format.ps1xml files. For example, compare the output of the Working Set values from Get-Process in table and list format:
PS C:\> Get-Process powershell
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
------- ------ ----- ----- ------ -- -- -----------
662 31 97928 110256 1.27 11452 2 powershell
PS C:\> Get-Process powershell | Format-List *
Handles : 705
VM : 2204040044544
WS : 113082368
PM : 100356096
NPM : 31512
The property (itself added by PowerShell for convenience) is called WS, but is shown as WS(K) in the table and the actual value is stored in bytes, but is displayed in KB, so some manipulation is going on for the default output.
Following from my comment, I would use Get-NetIPAddress instead.
Get-NetIPAddress -InterfaceAlias "Ethernet" | Select-Object FamilyAddress

VMWare PowerCLI Get DiskUsage of powered off vm's

I'm creating a script that gets all vm's and shows the DiskSpace. THe Problem is, that if a vm is powered off, it won't show the uesed Space of a disk.
Here are two examples: First one with an VM that is powered on:
PowerCLI C:\> Get-VM sluwv0039
Name PowerState Num CPUs MemoryGB
---- ---------- -------- --------
sluwv0039 PoweredOn 2 4.000
PowerCLI C:\> $VM = Get-VM sluwv0039
PowerCLI C:\> $VM.guest.disks
CapacityGB FreeSpaceGB Path
---------- ----------- ----
49.997 5.417 C:\
Example two where the VM is powered off:
PowerCLI C:\> Get-VM sluwv0012
Name PowerState Num CPUs MemoryGB
---- ---------- -------- --------
sluwv0012 PoweredOff 4 8.000
PowerCLI C:\> $VM = Get-VM sluwv0012
PowerCLI C:\> $VM.guest.disks
PowerCLI C:\>
Note: The Last line is the output. There is no "CapacityGB" etc.
Correct, that property is reading from the guest file system to see how much space is left on the partition. In your case, the C:\ drive. If the VM is off, there's no way for PowerCLI to find that property.
Alternatively, you could look at the $vm.ExtensionData.Summary.Storage properties and do some rough conversions. Note: the output of those are in byte, so you'll want to convert them to GB. Example: $tempVM.ExtensionData.Summary.Storage.Committed / 1GB
It won't be exact, but it will be better than no output at all.
here is example of script to show vm specification:
Get-Vm | Select-Object Name,PowerState,VMHost,NumCPU,MemoryGB,ProvisionedSpaceGB,#{N="HostName";E={#($.guest.HostName)}},#{N="Gateway";E={#($.ExtensionData.Guest.IpStack.IpRouteConfig.IpRoute.Gateway.IpAddress[0])}},#{N="DNS";E={$.ExtensionData.Guest.IpStack.DnsConfig.IpAddress}},#{N="IPAddress";E={#($.guest.IPAddress -like "192.168.*")}},#{N="Nics";E={#($.guest.Nics)}},#{N="Datastore";E={#($ | Get-DataStore)}},#{N="Disks";E={#($.guest.Disks)}},Version,#{N="State";E={#($.guest.State)}},#{N="OS";E={#($_.guest.OSFullName)}}
the sample output is like this:
Name State VMHost NumCpu MemoryGB PowerState ProvisionedSpaceGB Version IPAddress HostName OS Nics Disks VMwareTools Gateway DNS
test Running 192.168.32.100 2 1 PoweredOn 43.1085147 v8 192.168.122.1 Elenoon Ubuntu Linux (64-bit) Network adapter 1:VM Network Network adapter 2:local : : Capacity:17167286272, FreeSpace:14212493312, Path:/ Capacity:15188623360, FreeSpace:15154872320, Path:/media/files Capacity:10724835328, FreeSpace:10672824320, Path:/var/log Capacity:973770752, FreeSpace:690139136, Path:/boot guestToolsRunning 127.0.0.1
hope to be useful ;)

qwinsta /server:somesrv equivalent in Powershell?

When I run the qwinsta /server:somesrv command in cmd I can get a listing of all the current RDP sessions that are logged into a particular Windows server.
SESSIONNAME USERNAME ID STATE TYPE DEVICE
console 0 Conn wdcon
rdp-tcp 65536 Listen rdpwd
rdp-tcp#594 tom1 1 Active rdpwd
rdp-tcp#595 bob1 2 Active rdpwd
Is it possible to get a list like this on a remote server from Powershell so that the data can be used elsewhere?
There are multiple alternatives:
Use the Terminal Services PowerShell Module. Easy solution.
Writing a powershell wrapper that parses the output of qwinsta to objects. Easy solution. See example below
Use the Cassia.DLL .Net wrapper to access the native APIs that qwinsta runs behind the scene. This is the class that the TS Module uses. More difficult, but will have the benefit of being customized to your needs.
Go crazy and use the Native Methods that Cassia.DLL accesses using P/Invoke (wtsapi32.dll, kernel32.dll, winsta.dll). Hard and overcomplicated.
PowerShell-wrapper for qwinsta
function Get-TSSessions {
param(
$ComputerName = "localhost"
)
qwinsta /server:$ComputerName |
#Parse output
ForEach-Object {
$_.Trim() -replace "\s+",","
} |
#Convert to objects
ConvertFrom-Csv
}
Get-TSSessions -ComputerName "localhost" | ft -AutoSize
SESSIONNAME USERNAME ID STATE TYPE DEVICE
----------- -------- -- ----- ---- ------
services 0 Disc
console Frode 1 Active
rdp-tcp 65537 Listen
#This is objects, so we can manipulate the results to get the info we want. Active sessions only:
Get-TSSessions -ComputerName "localhost" | ? { $_.State -eq 'Active' } | ft -AutoSize SessionName, UserName, ID
SESSIONNAME USERNAME ID
----------- -------- --
console Frode 1
I used to use Terminal Services PowerShell Module (now in codeplex archive), but it was two years ago. I can't put my hand on it, but it also exists a function on gitshub or another site that embeded QWinsta/RmWinsta.