Merge Powershell Output - Get-VM, Get-VHD - powershell

I would like to export some Server Statistics from a Failover Cluster System.
My plan is to show with the Get-VHD command all VHD used on the VMs on my host.
So I was Trying to use:
Get-VM | select-object VMID |get-vhd |ft
This gives me a list the
"ComputerName, Path, VHDFormat,VHDType,FileSize,MinimumSize, LogicalSectorSize, PhysicalSectorSize"
Sadly the ComputerName is not the VMName but just the Name of the Host.
Now when I run the Get-VM command I get the Name and here it is actually the VMName.
Is there a nice way to get the real VMnames in the Output of Get-VHD?
I am fairly new to Powershell and I could not find a solution that worked... Most of the "sniplets" found here did not work at all or did not return the VMname...
Thank you for your suggestions =)
Sorry, I think my Title is not that well described, I was not sure how this funktion is called.

Untested, but you could use a ForEach-Object loop and capture the Name property from the Get-VM cmdlet. Then go on with Get-VHD and combine the output:
Get-VM | ForEach-Object {
$name = $_.Name
$_ | Get-VHD | Select-Object #{Name = 'Name'; Expression = {$name}}, *
} | Format-Table -AutoSize

Related

Getting list of specific attributes for all Hyper-V VMs on Windows Server

Let's start off on the right foot. I'm not looking for someone to write the script discussed below for us. What I'd like is a pointer or pointers that can quickly get me up to speed on just the PowerShell parts I need in order to accomplish this task without first becoming an expert in PowerShell and then in use of Get-VM. That said, please read on.
We are attempting to do a virtual machine inventory on several VM hosts in a network of computers. To that end, we would like to write a script that writes a .CSV file containing the host name, and specific attributes for each VM defined on that host. So, for example:
HostName, VMName, ComputerName, ID, Maximum memory, Minimum meomry, ...
VMH1, VM1, DATACENTER1, 54324ebe-f167-..., 1099511627776, 536870912, ...
and so on, for each VM under this host... and we'd run the command on each of our hosts to get the inventory into files we could merge for an enterprise view.
Where I need help, is with PowerShell scripting. I'm highly skilled with KornShell and many other scripting languages, but I've avoided PS all these years. Now the piper is at my door.
Trying to understand how to tie these two things together:
I can get a list of VMs with the
Get-VM | ft Name
Given a VM, I can get the details I want with
Get-VM <vmname> |
Select-Object Name, etc...
I believe I'd need to pipe the command into the command, but that's not working for me. And then once that's done, need to manipulate the output so that %COMPUTERNAME% is at the front of the output, so a simple Export-Csv won't work for us either.
Again, I don't want this to be a "here's my homework - do it for me" entry; just looking for pointers.
THanks for your time.
All of what you are after are in the examples in the PowerShell Help Files for that cmdlet.
# Get specifics for a module, cmdlet, or function
(Get-Command -Name Get-VM).Parameters
(Get-Command -Name Get-VM).Parameters.Keys
Get-help -Name Get-VM -Examples
# Results
<#
Get-VM -ComputerName Server1 |
Where-Object {$_.State -eq 'Running'}
Get-ClusterGroup |
Where {$PSItem.GroupType -eq 'VirtualMachine' } |
Get-VM
#>
Get-help -Name Get-VM -Full
Get-help -Name Get-VM -Online
As for your code in the comment section, this ...
Get-VM |
ForEach-Object Get-VM |
Select-Object *
and/or this ...
Get-VM |
ft Name|
ForEach-Object Get-VM |
Select-Object *
... both are syntactically wrong. If you use the PowerShell_ISE or VSCode editor they would immediately flag these as errors. If you are prone to staying in the console host, then use the Invoke-ScriptAnalyzer cmdlet to check your code and Trace-Command to see all it is doing. See the help file for details.
(Get-Command -Name Invoke-ScriptAnalyzer).Parameters
(Get-Command -Name Invoke-ScriptAnalyzer).Parameters.Keys
Get-help -Name Invoke-ScriptAnalyzer -Examples
Get-help -Name Invoke-ScriptAnalyzer -Full
Get-help -Name Invoke-ScriptAnalyzer -Online
(Get-Command -Name Trace-Command).Parameters
(Get-Command -Name Trace-Command).Parameters.Keys
Get-help -Name Trace-Command -Examples
Get-help -Name Trace-Command -Full
Get-help -Name Trace-Command -Online
Thus should be this
Get-VM |
ForEach-Object {
$PSItem |
Select-Object -Property '*'
}
Never do '*' for all properties, unless that is what you really want. Always select only what you need.
To see all the properties of on the first VM, just to this
(Get-VM)[0] |
Select-Object -Property '*'
To see all the properties of all the VM's, just remove the [0].
You easily leverage the Out-GtidView cmdlet for selecting VM and viewing details.
(Get-VM)[0] |
Select-Object -Property '*' |
Out-GridView -Title 'Showing Virtual Machines'
see:
https://mcpmag.com/articles/2016/02/17/creating-a-gui-using-out-gridview.aspx
https://spiderzebra.com/2020/05/26/utilizing-powershell-out-gridview-as-a-gui-alternative
https://mikefrobbins.com/2014/09/11/creating-a-simplistic-gui-interface-with-out-gridview
Lastly, you are also saying, you want a list of VMHosts, that you are then trying to get the VM Guest off those hosts. That is not what Get-VM is for.
If your VMHosts are Windows Servers, joined to your domain, you'd use Get-ADComputer to get a list of VMHost names (however you have them named), then pass that to Get-VM to get the guests.
Example:
Get-ADComputer -Identity 'VMHost*' |
ForEach-Object {Get-VM -ComputerName $PSitem}
If they are not windows machines, use your chosen method to get that hostname, then pass that to Get-VM.
Doing this on my local Hyper-V machine
$env:COMPUTERNAME, 'Localhost' |
ForEach {
Get-VM -ComputerName $PSItem |
Select-Object -Property Name, State, Status, Version
}
# Results
<#
Name State Status Version
---- ----- ------ -------
WS2K16 Off Operating normally 9.0
...
#>
$env:COMPUTERNAME, 'Localhost' |
ForEach-Object {
$VMHostName = $PSItem
Get-VM -ComputerName $VMHostName |
Select-Object -Property #{
Name = 'VMHost'
Expression = {$VMHostName }
}, Name, State, Status, Version |
Export-Csv -Path 'D:\Temp\VMGuestReport.Csv' -Append
}
Import-Csv -Path 'D:\Temp\VMGuestReport.Csv' |
Format-Table -AutoSize
# Results
<#
VMHost Name State Status Version
------ ---- ----- ------ -------
SRV1 WS2K16 Off Operating normally 9.0
...
Localhost WS2K16 Off Operating normally 9.0
...
#>

How do i Filter the DHCP Lease information that i export

I just wrote a powershell script that will export dhcp lease information but i want to export specific information like export only IP and mac addresses in the dhcp. Instead of exporting every lease information. The one line of code i have written that exports everything is bellow.
Get-DhcpServerv4Lease -ComputerName "HW2009-11" | Export-Csv -Path ("C:\log\new.csv")
To adress only certain properties of an object, you can use Select-Object. This way you can only choose the ipand mac-address like this:
Get-DhcpServerv4Lease -ComputerName "HW2009-11" | Select-Object -Property IP, mac-address
You can then pipe this to Export-Csv and it will create a .csv file with only those properties:
Get-DhcpServerv4Lease -ComputerName "HW2009-11" | Select-Object -Property IP, mac-address | Export-Csv -Path "C:\log\new.csv"
If you don't know the specific properties of an object, you can just pipe the command to Get-Member:
Get-DhcpServerv4Lease | Get-Member

Access Script property

I am looking to run a DNS lookup for a local server, select both the hostname and IP address and output to a text file.
[System.Net.Dns]::GetHostEntry('server1') |
Select-Object 'HostName', 'IPAddressToString' |
Out-File -Path 'c:\temp\DnsIpAddress.txt'
I can access HostName but cannot select IPAddressToString. I can
access IPAddressToString if I save the results to a variable this way:
$result.AddressList.IpAddressToString
Can I use Select-Object to select hostname and IPAddressToString? Or should I do this another way?
Use a calculated property with Select-Object:
[System.Net.Dns]::GetHostentry('server1') |
Select-Object HostName,#{Name = 'IPAddress';Expression={$_.AddressList.IPAddressToString}} |
Out-File -Path 'C:\temp\DnsIpAddress.txt'
It may also be worth mentioning that there's a cmdlet Resolve-DnsName that may yield more "PowerShelly" code:
Resolve-DnsName -name www.stackoverflow.com | Select-Object Name,IPAddress

Powershell split items into text file into multiple variables

I am trying to run a software script against my servers, to see exactly what software is installed and what version. I have the list of the servers stored in a text file "SystemList.txt" that is formatted like you see below.
SERVER001
SERVER002
SERVER003
SERVER004
I need to pull the server names out of the file and use them in my csv that I need to look like this:
Here is the code:
$computers = Get-Content -path
D:\Users\stephen.lyons.sa\Documents\SystemList\SystemList.txt
Foreach($computer in $computers)
{
$computer
$env:COMPUTERNAME
Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*
|Select-Object Displayname, DisplayVersion, Publisher, InstallDate | Out-
file \\txusocts002\d$\APSO\Steve\Test\$env:COMPUTERNAME.csv
}
Perhaps I am missing something, but would this meet your CSV file need?
Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\* |
Select-Object -Property DisplayName,DisplayVersion,Publisher,InstallDate |
Export-Csv -Path my.csv

Get startup type of Windows service using PowerShell

How can I get the Windows service startup type using PowerShell and not using WMI?
I looked inside the Get-Service command, and it does not provide something to display the "startup type".
With PowerShell version 4:
You can run a command as given below:
Get-Service | select -property name,starttype
WMI is the way to do this.
Get-WmiObject -Query "Select StartMode From Win32_Service Where Name='winmgmt'"
Or
Get-WmiObject -Class Win32_Service -Property StartMode -Filter "Name='Winmgmt'"
In PowerShell you can use the command Set-Service:
Set-Service -Name Winmgmt -StartupType Manual
I haven't found a PowerShell command to view the startup type though. One would assume that the command Get-Service would provide that, but it doesn't seem to.
You can use also:
(Get-Service 'winmgmt').StartType
It returns just the startup type, for example, disabled.
As far as I know there is no “native” PowerShell way of getting this information. And perhaps it is rather the .NET limitation than PowerShell.
Here is the suggestion to add this functionality to the version next:
https://connect.microsoft.com/PowerShell/feedback/details/424948/i-would-like-to-see-the-property-starttype-added-to-get-services
The WMI workaround is also there, just in case. I use this WMI solution for my tasks and it works.
Once you've upgraded to PowerShell version 5 you can get the startup type.
To check the version of PowerShell you're running, use $PSVersionTable.
The examples below are for the Windows Firewall Service:
For the local system
Get-Service | Select-Object -Property Name,Status,StartType | where-object {$_.Name -eq "MpsSvc"} | Format-Table -auto
For one remote system
Get-Service -ComputerName HOSTNAME_OF_SYSTEM | Select-Object -Property MachineName,Name,Status,StartType | where-object {$_.Name -eq "MpsSvc"} | Format-Table -auto
For multiple systems (must create the systems.txt)
Get-Service -ComputerName (Get-content c:\systems.txt) | Select-Object -Property MachineName,Name,Status,StartType | where-object {$_.Name -eq "MpsSvc"} | Format-Table -auto
Use:
Get-Service BITS | Select StartType
Or use:
(Get-Service -Name BITS).StartType
Then
Set-Service BITS -StartupType xxx
[PowerShell 5.1]
If you update to PowerShell 5 you can query all of the services on the machine and display Name and StartType and sort it by StartType for easy viewing:
Get-Service |Select-Object -Property Name,StartType |Sort-Object -Property StartType
You can also use the sc tool to set it.
You can also call it from PowerShell and add additional checks if needed.
The advantage of this tool vs. PowerShell is that the sc tool can also set the start type to auto delayed.
# Get Service status
$Service = "Wecsvc"
sc.exe qc $Service
# Set Service status
$Service = "Wecsvc"
sc.exe config $Service start= delayed-auto
It is possible with PowerShell 4.
Get-Service *spool* | select name,starttype | ft -AutoSize
screenshot
By default StartType is not shown by Get-Service, but you can always explicitly ask for it:
Get-Service | select StartType,DisplayName | sort StartType,DisplayName
Use Get-Service | Get-Member to see all available fields.