Powershell, get ip4v address of VM - powershell

I'm new to powershell and I"m trying to get just the IPv4 address of a vm and save it as a string.
I can get all network attributes like so:
PS C:\Windows\system32> get-vm | select -ExpandProperty networkadapters | select vmname, macaddress, switchname, ipaddres
sses
VMName MacAddress SwitchName IPAddresses
------ ---------- ---------- -----------
foobar vSwitch {192.0.2.1, fe80::84a...
I can get both the v4 and the v6 ip address
PS C:\Windows\system32> $IP = ( GEt-VM -ComputerName $HVCOMPUTERNAME -VMName $HVNAME | Get-VMNetworkAdapter).IpAddresses
PS C:\Windows\system32> $IP
192.0.2.1
fe80::d47e:
----------
How can I get just the v4 address as a string?
Update
It looks like there is no object property that just includes the v4 address
PS C:\Windows\system32> GEt-VM -ComputerName $HVCOMPUTERNAME -VMName $HVNAME | Get-VMNetworkAdapter | Format-List -Property *
IovWeight : 0
IovQueuePairsRequested : 1
IovQueuePairsAssigned : 0
IovInterruptModeration : Default
IovUsage : 0
ClusterMonitored : True
VirtualFunction :
IsLegacy : False
IsManagementOs : False
IsExternalAdapter : False
Id : Microsoft:xxxxxxxxxxx
AdapterId : xxxxxxxxxxx
DynamicMacAddressEnabled : True
MacAddress : 00155D5B9B14
MacAddressSpoofing : Off
SwitchId : xxxxxxxxxxx
Connected : True
PoolName :
SwitchName : vSwitch
AclList : {}
ExtendedAclList : {}
IsolationSetting : Microsoft.HyperV.PowerShell.VMNetworkAdapterIsolationSetting
CurrentIsolationMode : Vlan
RoutingDomainList : {}
DhcpGuard : Off
RouterGuard : Off
PortMirroringMode : None
IeeePriorityTag : Off
VirtualSubnetId : 0
DynamicIPAddressLimit : 0
StormLimit : 0
AllowTeaming : Off
VMQWeight : 100
IPsecOffloadMaxSA : 512
VmqUsage : 0
IPsecOffloadSAUsage : 0
VFDataPathActive : False
VMQueue :
MandatoryFeatureId : {}
MandatoryFeatureName : {}
VlanSetting : Microsoft.HyperV.PowerShell.VMNetworkAdapterVlanSetting
BandwidthSetting :
BandwidthPercentage : 0
TestReplicaPoolName :
TestReplicaSwitchName :
StatusDescription : {OK}
Status : {Ok}
IPAddresses : {192.0.2.1, fe80::xxxxxxxxxxx}
ComputerName : xxxxxxxxxxx
Name : Network Adapter
IsDeleted : False
VMId : xxxxxxxxxxx
VMName : foobar
VMSnapshotId : 00000000-0000-0000-0000-000000000000
VMSnapshotName :
Key :

You can just filter out any IP that has ":" in it, as such:
$IP | ?{$_ -notmatch ':'}

Assuming there is only 1 V4 address, and that the v4 address is the first output, do:
$IP = ( GEt-VM -ComputerName $HVCOMPUTERNAME -VMName $HVNAME | Get-VMNetworkAdapter).IpAddresses | Select-String -List 1

IPAddresses looks like an array or list and you only want the first one so try:
$IP = ( GEt-VM -ComputerName $HVCOMPUTERNAME -VMName $HVNAME | Get-VMNetworkAdapter).IpAddresses[0]

Related

How can I use a variable as Application Pool name?

The following code gives me the default app pool, converted to string. When I pass this variable
$appPoolName = Get-IISAppPool | Select-Object Name | Where-Object {$_.Name -like "Default" } | Out-String
(Get-IISAppPool $appPoolName).processmodel.username
I get the following error
Why not just do this:
$appPoolName = (Get-IISAppPool | Where-Object Name -Match 'Default').Name
(Get-IISAppPool $appPoolName).processmodel
# Results
<#
IdentityType : ApplicationPoolIdentity
IdleTimeout : 00:20:00
IdleTimeoutAction : Terminate
LoadUserProfile : True
MaxProcesses : 1
PingingEnabled : True
PingInterval : 00:00:30
PingResponseTime : 00:01:30
Password :
ShutdownTimeLimit : 00:01:30
StartupTimeLimit : 00:01:30
UserName :
...
#>

How Get All Camera Devices ID From PowerShell

I am trying to get all camera devices ID and respective names using PowerShell command line. I tried several commands, but nothing has done what I am aiming. Below my "best" approach:
Get-CimInstance Win32_PnPEntity | where caption -match 'camera'
output
Caption : Remote Desktop Camera Bus
Description : UMBus Enumerator
InstallDate :
Name : Remote Desktop Camera Bus
Status : OK
Availability :
ConfigManagerErrorCode : 0
ConfigManagerUserConfig : False
CreationClassName : Win32_PnPEntity
DeviceID : UMB\UMB\1&841921D&0&RDCAMERA_BUS
ErrorCleared :
ErrorDescription :
LastErrorCode :
PNPDeviceID : UMB\UMB\1&841921D&0&RDCAMERA_BUS
PowerManagementCapabilities :
PowerManagementSupported :
StatusInfo :
SystemCreationClassName : Win32_ComputerSystem
SystemName : DESKTOP
ClassGuid : {4d36e97d-e325-11ce-bfc1-08002be10318}
CompatibleID :
HardwareID : {UMB\UMBUS}
Manufacturer : Microsoft
PNPClass : System
Present : True
Service : umbus
PSComputerName :
I know, for example, that generally the integrated camera has a name "integrated camera" with a ID "0". But this is not what is being shown.
Get-CimInstance Win32_PnPEntity | ? { $_.service -eq "usbvideo" } | Select-Object -Property PNPDeviceID, Name

Get Drive letter from Volume ID

I want to use drive letter instead of Volume ID like below. How can I do that ?
Thanks,
My output :
VolumeName OriginatingMachine InstallDate
\\?\Volume{3c0a6eed-1b4c-4e90-a25b-8af1af46e368}\ app01.contoso.com 4/13/2021 6:03:34 PM
\\?\Volume{de5c18ac-56e1-4efa-afb4-abaf476a99a9}\ app01.contoso.com 4/13/2021 6:03:34 PM
My desired output :
VolumeName OriginatingMachine InstallDate
E: app01.contoso.com 4/13/2021 6:03:34 PM
X: app01.contoso.com 4/13/2021 6:03:34 PM
Command:
Get-CimInstance Win32_ShadowCopy | Where InstallDate -lt ([datetime]::Now.AddDays(-5)) | Select-Object VolumeName,OriginatingMachine,InstallDate
Get-CimInstance Win32_ShadowCopy output :
Caption :
Description :
InstallDate : 9/17/2021 9:22:06 PM
Name :
Status :
ClientAccessible : False
Count : 11
DeviceObject : \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1234
Differential : True
ExposedLocally : False
ExposedName :
ExposedPath :
ExposedRemotely : False
HardwareAssisted : False
ID : {3C8DAB36-F083-4C68-84BA-E339B8A18AF3}
Imported : False
NoAutoRelease : True
NotSurfaced : False
NoWriters : False
OriginatingMachine : app01.contoso.com
Persistent : True
Plex : False
ProviderID : {B5946137-7B9F-4925-AF80-51ABD60B20D5}
ServiceMachine : app01.contoso.com
SetID : {D3D15CE2-9FFC-4A22-B03C-77D7FCB7D40E}
State : 12
Transportable : False
VolumeName : \\?\Volume{85e62cfa-2e9c-4a46-af5a-f0748acd60b6}\
PSComputerName :
The Win32_ShadowCopy command returns Win32_ShadowCopy objects, which have a number of fields all described here.
Some of the fields provided in ShadowCopy happen to match other WMI Classes which have info about Drive Letters, namely the VolumeName field. This field happens to also be present on both the ShadowCopy and Win32_Volume class, the latter of which has the drive letter property we need!
All we have to do is lookup all of the shadow copies, then lookup all of the volumes on the machine, then we can loop through the copies to find the matching volumes. If you have some really complex mounting logic, you'll need to add some extra logic though in the foreach section.
So we would make a quick little function to do this lookup for us, which would look like this:
function Get-Win32ShadowVolumeDiskInfo{
$shadowCopies = Get-CimInstance Win32_ShadowCopy
$volumes = Get-CimInstance Win32_Volume
$returnObject = #()
foreach ($copy in $shadowCopies){
$matchingVolume = $volumes | Where DeviceID -eq $copy.VolumeName
$returnObject += [PSCustomObject]#{
VolumeName=$matchingVolume.Name;
OriginatingMachine = $copy.OriginatingMachine;
InstallDate = $copy.InstallDate}
}
$returnObject
}

Select-String showing a line that does not exist on the original output

I am trying to discover which IP and interface a Windows machine is using to communicate with another machine.
This is the command that I am executing:
Find-NetRoute -RemoteIpAddress 192.168.1.10 | Select-String -Pattern "IPAddress"
And this is the response:
MSFT_NetIPAddress (Name = ";C?8;#B8:8;::55?55;55;", CreationClassName = "", SystemCreationClassName = "", SystemName = "")
I do not understand this output because the output of Find-NetRoute without the Select-String is this:
IPAddress : 192.168.0.100
InterfaceIndex : 4
InterfaceAlias : Wi-Fi
AddressFamily : IPv4
Type : Unicast
PrefixLength : 24
PrefixOrigin : Dhcp
SuffixOrigin : Dhcp
AddressState : Preferred
ValidLifetime : 01:10:34
PreferredLifetime : 01:10:34
SkipAsSource : False
PolicyStore : ActiveStore
Caption :
Description :
ElementName :
InstanceID : :8:8:8:9:55>55;C<8;#B8:8<?>55;
AdminDistance :
DestinationAddress :
IsStatic :
RouteMetric : 0
TypeOfRoute : 3
AddressFamily : IPv4
CompartmentId : 1
DestinationPrefix : 0.0.0.0/0
InterfaceAlias : Wi-Fi
InterfaceIndex : 4
InterfaceMetric : 50
NextHop : 192.168.0.254
PreferredLifetime : 02:00:00
Protocol : NetMgmt
Publish : No
State : Alive
Store : ActiveStore
ValidLifetime : 02:00:00
PSComputerName :
ifIndex : 4
Is Select-String really supposed to work similar to "grep" on Windows Powershell?
Aside from | findstr /i, here's another probably not that convenient workaround. You could shorten -stream to -s.
Find-NetRoute -RemoteIpAddress 192.168.1.10 | Out-String -Stream | Select-String ipaddress
IPAddress : 192.168.0.100
You can search property names with select-object:
Find-NetRoute -RemoteIpAddress 192.168.1.10 | select *address*
I wish I could search the property values like this, but unfortunately it doesn't work:
Find-NetRoute -RemoteIpAddress 192.168.1.10 | where * -match 192
I suppose this works, but it outputs all the properties anyway. At least it only outputs matching objects.
Find-NetRoute -RemoteIpAddress 192.168.1.10 | where { $_ -match '192' }
[pscustomobject]#{name='joe';address='here'},
[pscustomobject]#{name='james';address='there'} | where { $_ -match 'th' }
name address
---- -------
james there
EDIT:
I came up with a "search-object" script that only returns the properties (and methods) that match, by name or value:
# search-object.ps1
param ($pattern)
begin {
$hash = #{}
}
process {
$obj = $_
$obj | Get-Member | foreach name |
foreach {
$name = $_
$value = $obj.$name
if ($name -match $pattern -or $value -match $pattern) {
$hash += #{$name = $value}
}
}
[pscustomobject]$hash
}
For example:
get-process cmd | search-object cmd
Modules : {System.Diagnostics.ProcessModule (cmd.exe), System.Diagnostics.ProcessModule
(ntdll.dll), System.Diagnostics.ProcessModule (KERNEL32.DLL),
System.Diagnostics.ProcessModule (KERNELBASE.dll),
System.Diagnostics.ProcessModule (msvcrt.dll)}
Path : C:\Windows\System32\cmd.exe
MainModule : System.Diagnostics.ProcessModule (cmd.exe)
ProcessName : cmd
Name : cmd
MainWindowTitle : cmd
Find-NetRoute -RemoteIpAddress 192.168.1.10 | search-object ipaddress
IPAddress
---------
192.168.0.100
When "Grepping" in PS I tend to lean on findstr.
Try this:
find-netroute -remoteipaddress 10.0.0.1 | findstr "IPAddress"
For me (thats my gateway IP) it returns:
IPAddress : 10.0.0.136
And just an FYI, yes, your syntax gave me the same data from InstanceID.
Here's what I think is happening. As #Lee_Dailey states, Select-String works with [String] instances. Find-NetRoute outputs [CimInstance] instances...
PS> Find-NetRoute -RemoteIpAddress 192.168.1.10 | ForEach-Object { $_.PSObject.TypeNames[0] }
Microsoft.Management.Infrastructure.CimInstance#ROOT/StandardCimv2/MSFT_NetIPAddress
Microsoft.Management.Infrastructure.CimInstance#ROOT/StandardCimv2/MSFT_NetRoute
...so some transformation to [String] needs to take place so the text can be searched. If you run this...
PS> Find-NetRoute -RemoteIpAddress 192.168.1.10 | ForEach-Object { [String] $_ }
MSFT_NetIPAddress (Name = ";C?8;#B8:8;::55?55;55;", CreationClassName = "", SystemCreationClassName = "", SystemName = "")
MSFT_NetRoute (InstanceID = ":8:8:8:9:55>55;C<8;#B8:8<?>55")
...you get the [String] representation of a MSFT_NetIPAddress and MSFT_NetRoute [CimInstance] instances. If you tack the original Select-String command onto that...
PS> Find-NetRoute -RemoteIpAddress 10.10.10.10 | ForEach-Object { [String] $_ } | Select-String -Pattern IPAddress
MSFT_NetIPAddress (Name = ";C?8;#B8:8;::55?55;55;", CreationClassName = "", SystemCreationClassName = "", SystemName = "")
...you get the original output, which is missing the MSFT_NetRoute line. The CIM class name MSFT_NetIPAddress is matched by the pattern IPAddress, which is why that line is present in the output.
My first thought was that it is not casting input objects to [String] but calling ToString() on them, and that is what the documentation suggests...
Inputs
System.Management.Automation.PSObject
You can pipe any object that has a ToString method to Select-String.
...but if I do that I get different text for the MSFT_NetIPAddress instance...
PS> Find-NetRoute -RemoteIpAddress 192.168.1.10 | ForEach-Object { $_.ToString() }
192.168.0.100
MSFT_NetRoute (InstanceID = ":8:8:8:9:55>55;C<8;#B8:8<?>55")
If you look through that documentation there are some mentions of its similarity to or getting it to work like grep and findstr. The issue here, though, is the input text it was searching was not what you thought it would be; the text you saw in your console from a bare Find-NetRoute command was not the same text that would get passed to Select-String via the pipeline.
By the way, if your intention was to just filter the output down to that first IPAddress property that is displayed by Find-NetRoute -RemoteIpAddress 192.168.1.10 then instead of searching the full text for IPAddress you could just "search" for matching property (sub)names with Select-Object...
PS> Find-NetRoute -RemoteIpAddress 192.168.1.10 | Select-Object -Property '*IPAddress*'
IPAddress
---------
192.168.0.100

Receiving invalid data via WMI

I've had a script running for the better half of a year now that checks for disk space, should it be low it sends out an email been working just fine.
Today I received an alert saying that that Disk space was at 0gb.. I logged into the server and had about 30gbs available.
Part of code that checks the space.
[decimal]$thresholdspace = 5
$tableFragment= Get-WMIObject -ComputerName $computer Win32_LogicalDisk `
| select __SERVER, DriveType, VolumeName, Name, #{n='Size (Gb)' ;e={"{0:n2}" -f ($_.size/1gb)}},#{n='FreeSpace (Gb)';e={"{0:n2}" -f ($_.freespace/1gb)}}, #{n='PercentFree';e={"{0:n2}" -f ($_.freespace/$_.size*100)}} `
| Where-Object {$_.DriveType -eq 3 -and [decimal]$_.PercentFree -lt [decimal]$thresholdspace}
So I opened up an ISE session and did the following.
$computer = 'Server_01'
Get-WMIObject -ComputerName $computer Win32_LogicalDisk | select __SERVER, DriveType, VolumeName, Name,FreeSpace
and it responded with:
__SERVER : Server_01
DriveType : 2
VolumeName :
Name : A:
FreeSpace :
__SERVER : Server_01
DriveType : 3
VolumeName :
Name : C:
FreeSpace : 31372767232
__SERVER : Server_01
DriveType : 5
VolumeName :
Name : E:
FreeSpace :
So I then ran the part of my code that is getting space and it returned with the following:
__SERVER : Server_01
DriveType : 3
VolumeName :
Name : C:
Size (Gb) : 0.00
FreeSpace (Gb) : 0.00
PercentFree :
So I ran the simple WMI query and it responded with no data..
__SERVER : Server_01
DriveType : 2
VolumeName :
Name : A:
FreeSpace :
__SERVER : Server_01
DriveType : 3
VolumeName :
Name : C:
FreeSpace :
__SERVER : Server_01
DriveType : 5
VolumeName :
Name : E:
FreeSpace :
Any idea as to why I'm getting invalid or what appears to be incomplete data? I've never seen anything like this, and have not ran into this issue at all before. Nothing has changed on either server it is running from.