Powershell does not create CSV if there is no data to export in Azure - azure

I am trying to export VM data from Azure and below script is working perfect if subscription has VMs however it does create a .csv if there is no data (VMs) and I need that even if there is no data powershell should create a blank csv. Below is my script which is working fine if subscription has VMs created in it.
function create($path) {
$exists = Test-Path -path $path
Write-Host "tried the following path: $path, it" $(If ($exists) {"Exists"} Else {"Does not Exist!"})
if (!($exists)) { New-Item $path -itemType Directory }
}
# reading file contents
$subs_file = "C:\Scrpting\Subscriptions\Subscriptions.xlsx"
$azSubs = Import-Excel $subs_file
$azSubs
$output_folder = "C:\audit-automation"
# creating folder for outputing data
create("$output_folder")
# New-Item $output_folder -itemType Directory
# iterating over subscriptions
ForEach ( $sub in $azSubs ) {
# sub
$azsub = $sub.Subscription
# app
$app = $sub.Application
$azsub
$app
# creating folder to save data for apps
# New-Item $output_folder\$app -itemType Directory
# setting config for azure
Set-AzContext -SubscriptionName $azsub
# GET VM INFO
$vms = Get-AzVM
$vmrg = Get-AzVM | Select-Object "ResourceGroupName"
$nics = get-AzNetworkInterface | Where-Object { $_.VirtualMachine -NE $null }
# creating folder to save
# New-Item $output_folder\$app\vm_info -itemType Directory
create("$output_folder\$app")
ForEach ($nic in $nics) {
$info = "" | Select VMName, ResourceGroupName, OS, PrivateIPAddress, PublicIPAddress, SubscriptionID, Status, NICName
$vm = $vms | ? -Property Id -eq $nic.VirtualMachine.id
$info.NICName = $nic.Name
$info.VMName = $vm.Name
$info.SubscriptionID = $azsub
$info.ResourceGroupName = $vm.ResourceGroupName
$info.PrivateIPAddress = $nic.IpConfigurations.PrivateIpAddress
$PublicIPAddress =
(Az vm list-ip-addresses --name $vm.Name --resource-group $vm.ResourceGroupName | ConvertFrom-Json).virtualMachine.network.publicIpAddresses.ipaddress
$info.PublicIPAddress = if ($null -eq $PublicIPAddress ) { "Not Assigned" } else { $PublicIPAddress }
$info.OS = $vm.StorageProfile.osDisk.osType
$info.Status = ((Get-AzVM -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name -Status).Statuses[1]).code
$info | Export-Csv -Path $output_folder\$app\$app-vm_data$((Get-Date).ToString("yyyy-MM-dd")).csv -Append
}}

You can remove the function create and replace that with just the one line $null = New-Item $output_folder -ItemType Directory -Force.
On file system, the -Force makes the cmdlet return either the DirectoryInfo object of an existing folder or create a new folder and return that.
(don't use this on registry keys!)
Next, if you capture the output you want in the CSV file first, it is easy enough to check if there is output or not and if not, write an empty csv file (only the headers will be in there)
Something like this:
# reading file contents
$subs_file = "C:\Scrpting\Subscriptions\Subscriptions.xlsx"
$azSubs = Import-Excel $subs_file
#$azSubs
$output_folder = "C:\audit-automation"
# creating folder for outputing data
$null = New-Item $output_folder -ItemType Directory -Force
# iterating over subscriptions
foreach($sub in $azSubs) {
# sub
$azsub = $sub.Subscription
# app
$app = $sub.Application
$azsub
$app
# setting config for azure
Set-AzContext -SubscriptionName $azsub
# GET VM INFO
$vms = Get-AzVM
$vmrg = Get-AzVM | Select-Object "ResourceGroupName"
$nics = Get-AzNetworkInterface | Where-Object { $null -ne $_.VirtualMachine }
# creating folder to save
$null = New-Item (Join-Path -Path $output_folder -ChildPath $app) -ItemType Directory -Force
# capture the output of the foreach loop
$result = foreach ($nic in $nics) {
$info = "" | Select VMName, ResourceGroupName, OS, PrivateIPAddress, PublicIPAddress, SubscriptionID, Status, NICName
$vm = $vms | ? -Property Id -eq $nic.VirtualMachine.id
$info.NICName = $nic.Name
$info.VMName = $vm.Name
$info.SubscriptionID = $azsub
$info.ResourceGroupName = $vm.ResourceGroupName
$info.PrivateIPAddress = $nic.IpConfigurations.PrivateIpAddress
$PublicIPAddress = (Az vm list-ip-addresses --name $vm.Name --resource-group $vm.ResourceGroupName |
ConvertFrom-Json).virtualMachine.network.publicIpAddresses.ipaddress
$info.PublicIPAddress = if ($null -eq $PublicIPAddress ) { "Not Assigned" } else { $PublicIPAddress }
$info.OS = $vm.StorageProfile.osDisk.osType
$info.Status = ((Get-AzVM -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name -Status).Statuses[1]).code
# output the object to be collected in variable $result
$info
}
# test if you actually have data now in the $result variable
if (!#($result.Count)) {
# no data; create an empty csv with just the headers
$result = "" | Select VMName, ResourceGroupName, OS, PrivateIPAddress, PublicIPAddress, SubscriptionID, Status, NICName
}
$outFile = Join-Path -Path $output_folder -ChildPath ('{0}\{0}-vm_data{1:yyyy-MM-dd}.csv' -f $app, (Get-Date))
$result | Export-Csv -Path $outFile -NoTypeInformation
}

add outside the loop, since $vms may be empty
if (!($vms)){
$info = "" | Select VMName, ResourceGroupName, OS, PrivateIPAddress, PublicIPAddress, SubscriptionID, Status, NICName
$info | Export-Csv -Path $output_folder\$app\$app-vm_data$((Get-Date).ToString("yyyy-MM-dd")).csv -Append
}

Related

How to get specifi list of Virtual Machine Status from Azure using powershell from Excel sheet

I am pretty much new to PowerShell and we have customer requirement that they will share Azure VM details in Excel sheet with below columns.
we have to get VM Status details from all the subscriptions & ResourceGroup using the Powershell script.
Outuput:
I am able to perform for single RSG and VM values by using the below code
$SubscriptionName = Get-AzSubscription -SubscriptionId $subscriptionId
$RG = "rgp-use2-prd-bioportalbiopeople1"
$RSGName = Get-AzResourceGroup -Name $RG
$VMs = Get-AzVM -Name "vmbppapiv1prd02"
$VMState = (Get-AzVM -Name $VM -ResourceGroupName $RG -Status).Statuses
$vmOutput = $VMs | ForEach-Object {
[PSCustomObject]#{
"Resource Group Name" = $RSGName.ResourceGroupName
"Subscription Name" = $SubscriptionName.Name
"VM Name" = $_.Name
"VM Type" = $_.StorageProfile.osDisk.osType
"VM Statss" = ($VMState | where code -Like 'PowerState/*')[0].DisplayStatus
}
}
$vmOutput | Format-Table -AutoSize
$vmOutput | export-csv C:\Projects\data.csv
I can't test this myself, but you will have to create nested loops to get the details for all subscriptions and resourcegroups.
Something like this:
$subscriptions = Get-AzSubscription -TenantId "aaaa-aaaa-aaaa-aaaa" # enter the tenant ID here
$VMs = Get-AzVM -Name "vmbppapiv1prd02"
$vmOutput = foreach ($vm in $VMs) {
foreach ($subscription in $subscriptions) {
Set-AzContext -SubscriptionId $subscription.Id
(Get-AzResourceGroup).ResourceGroupName | ForEach-Object {
$vmState = (Get-AzVM -Name $vm.Name -ResourceGroupName $_ -Status).Statuses
[PSCustomObject]#{
"Resource Group Name" = $_
"Subscription Name" = $Subscription.Name
"VM Name" = $vm.Name
"VM Type" = $vm.StorageProfile.osDisk.osType
"VM Status" = ($vmState | where code -Like 'PowerState/*')[0].DisplayStatus
}
}
}
}
$vmOutput | Format-Table -AutoSize
$vmOutput | Export-Csv -Path 'C:\Projects\data.csv' -NoTypeInformation

How To fix "add-member : Cannot add a member with the name "" because a member with that name already exists"

I need to list multiple FTP connexion on LogicApp service and export this list on csv file. This export is use for see if the SSL protocol connexion is activate or not. My script generate this error.
add-member : Cannot add a member with the name "FTP" because a member with that name already exists. To overwrite the member anyway, add the Force parameter to your command.
LogicApp FTP connexion :
https://learn.microsoft.com/en-us/azure/connectors/connectors-create-api-ftp
I need to add these FTP connections in this format on excel :
format need
$LogicApp_temp = $null
$LogicApp_obj = #()
$LogicApp_temp = new-object PSObject
$FTPAll = Get-AzResource -ResourceGroupName $RG -ResourceType Microsoft.Web/connections
foreach ( $FTPAlls in $FTPAll ) {
$FTPName = $FTPAlls.name
$FTPName1 = Get-AzResource -ResourceGroupName $RG -ResourceType Microsoft.Web/connections -Name $FTPName
foreach ($FTPName2 in $FTPName1) {
$FTPcheckType = $FTPName2.Properties.api.name
if ( $FTPcheckType -eq "ftp") {
$FTPSSL1 = $FTPName1.Properties.parameterValues.isSSL
}
else {
}
$LogicApp_temp | add-member -MemberType NoteProperty -Name "FTP" -Value "$FTPName2.Properties.displayName $FTPSSL1"
}
}
$LogicApp_obj += $LogicApp_temp
Write-Output "LogicApp Name : $Name Ressource Group : $RG OK"
# CSV Exports :
$LogicApp_obj | Export-Csv $csvPath -Append -NoTypeInformation
thank you in advance for your help
Because the PSObject property just could be set one value at one time, if you use the -Force, it will overwrite the value before.
If you want to get the .csv file like the format you provided, we could just append every string like joyftp True first.
My working sample:
$RG = "<resource group name>"
$LogicApp_obj = #()
$value = ""
$FTPAll = Get-AzResource -ResourceGroupName $RG -ResourceType Microsoft.Web/connections
foreach ( $FTPAlls in $FTPAll ) {
$FTPName = $FTPAlls.name
$FTPName1 = Get-AzResource -ResourceGroupName $RG -ResourceType Microsoft.Web/connections -Name $FTPName
foreach ($FTPName2 in $FTPName1) {
$FTPcheckType = $FTPName2.Properties.api.name
$displayname = $FTPName2.Properties.displayName
$LogicApp_temp = New-Object -TypeName PSObject
if ( $FTPcheckType -eq "ftp") {
$FTPSSL1 = $FTPName1.Properties.parameterValues.isSSL
$value += "$displayname $FTPSSL1 | "
$LogicApp_temp | add-member -MemberType NoteProperty -Name "FTP" -Value "$value" -Force
}
}
}
Write-Output "LogicApp Name : $Name Ressource Group : $RG OK"
# CSV Exports :
$LogicApp_temp | Export-Csv -Path "C:\Users\joyw\Desktop\ftp.csv" -NoTypeInformation
The .csv file:

Merge Storage Account Name and SKU with VM Name in Powershell

I want to add StorageAccountName and its SKU to my report, this is the code I'm having now:
VMs = Get-AzureRmVM -Status
$vmOutput = $VMs | ForEach-Object {
[PSCustomObject]#{
"VM Name" = $_.name
"Private IP" =""
"VM Type" = $_.StorageProfile.osDisk.osType
"VM Profile" = $_.HardwareProfile.VmSize
"Environment" = $_.Tags.Environment
"Application" = $_.Tags.Application
"Decommission Date" = $_.Tags.Decomission
"OS Disk Size" = $_.StorageProfile.OsDisk.DiskSizeGB
"Data Disks Total Size" = ($_.StorageProfile.DataDisks.DiskSizeGB | Measure -Sum).Sum
"Data Disks Amount" = ($_.StorageProfile.DataDisks | Measure ).Count
"Managed OS Disk" = ($_.StorageProfile.OSDisk.ManagedDisk | Measure).Count
"Managed Data Disks" = ($_.StorageProfile.DataDisks.ManagedDisk | Measure).Count
"Powerstate" = $_.PowerState
}
}
$nics = get-azurermnetworkinterface | where VirtualMachine -NE $null
$ips =#{}
foreach($nic in $nics){
$vm = $VMs | Where-Object -Property id -EQ $nic.VirtualMachine.id
$prv = $nic.IpConfigurations | select-object -ExpandProperty PrivateIpAddress
$ips.Add($vm.Name,$prv)
}
foreach($vm in $vmOutput)
{
if($ips.ContainsKey($vm."VM Name"))
{
$vm."Private IP"=$ips[$vm."VM Name"]
}
}
$vmOutput | sort "Environment", "VM Type", "VM Profile", "Application" | export-csv VMReport.csv -delimiter ";" -force -notypeinformation
I tried to do it more less the same way IP addresses were implemented into this code, but it's much harder than I expected, as Get-AzureRmStorageAccount cmdlet doesn't store VirtualMachine.Id property like Get-AzureRMNetworkInterface cmdlet does.
Any ideas how can I merge it into one table? Is there any key upon which I can join both information? What I want to achieve is to add StorageAccountName and SKUName columns into the $vmOutput table.
Update:
$sat =#{}
$OutFile = "..."
#part1
foreach ($vmdetails in $VMs)
{
$ResourceGroupName=$vmdetails.ResourceGroupName
$VMName=$vmdetails.name
$storage=$vmdetails.StorageProfile.OsDisk.Vhd.Uri
$DataDiks=$vmdetails.StorageProfile.OsDisk.Name
$ss=$storage.split('/')[2]
$OSStorageAccountName=$ss.split('.')[0]
$DiskType="OSDisk"
$StroageAccountLocation=($StroageAccDetail | where {$_.StorageAccountName -eq $OSStorageAccountName }).location
$StorageAccountType=($StroageAccDetail | where {$_.StorageAccountName -eq $OSStorageAccountName }).AccountType
"$sub,$ResourceGroupName,$VMName,$DataDiks,$DiskType,$OSStorageAccountName" | Out-File -FilePath $OutFile -Append
$vmdatadisks=$vmdetails.StorageProfile.DataDisks
if($vmdatadisks -ne $null){
foreach($vmDatadsik in $vmdatadisks)
{
$vmDatadsikss=$vmDatadsik.vhd.uri
$DiskType="DataDisk"
$ss=$vmDatadsikss.split('/')[2]
$DataDiks=$vmDatadsik.Name
$dataStorageAccountName=$ss.split('.')[0]
"$sub,$ResourceGroupName,$VMName,$DataDiks,$DiskType,$OSStorageAccountName" | Out-File -FilePath $OutFile -Append
}
}
}
#part2
$VMs = Get-AzureRmVM -ResourceGroupName "..." -Name "..."
$storageAccountName = $VMs.StorageProfile.OsDisk.Vhd.Uri.Split("/")[2].Split(".")[0]
Get-AzureRmStorageAccount -StorageAccountName $storageAccountName -ResourceGroupName "..."
Please correct me if I'm misunderstanding you.
Assume the sku you refer to the account storage's sku, you can also add placeholders in the $vmOutput for SA Name and SKUName.
$VMs = Get-AzureRmVM -Status
$vmOutput = $VMs | ForEach-Object {
[PSCustomObject]#{
"VM Name" = $_.name
"ResourceGroupName" =$_.ResourceGroupName #you must include this parameter
"storage" = $_.StorageProfile.OsDisk.Vhd.Uri #you must include this parameter
#your other property
#add placeholder for SA Name and SKUName like below
"StorageAccountName" =""
"StorageAccountSKUName" =""
}
}
Then, iterate all the vms in $vmoutput, and find the related storage account and sku, then add value to the $vmoutput:
foreach($v in $vmOutput){
$resourceGroups = $v.ResourceGroupName
$storage=$v.storage
if($storage -ne $null)
{
$ss=$storage.split('/')[2]
$OSStorageAccountName=$ss.split('.')[0]
$s1 = Get-AzureRmStorageAccount -ResourceGroupName $resourceGroups -StorageAccountName $OSStorageAccountName
#add the value to $vmoutput
$v.StorageAccountName =$OSStorageAccountName
$v.StorageAccountSKUName=$s1.Sku.name
}
else
{
$v.StorageAccountName ="no value"
$v.StorageAccountSKUName="no value"
}
}

How to export Virtual Machine Names and IP Addresses from within multiple azure subscriptions

I have been able to export out VM Names and IP Addresses from within a single azure subscription using the following script.
$report = #()
$vms = get-azvm
$nics = get-aznetworkinterface | ?{ $_.VirtualMachine -NE $null}
foreach($nic in $nics)
{
$info = "" | Select VmName, ResourceGroupName, HostName, IpAddress
$vm = $vms | ? -Property Id -eq $nic.VirtualMachine.id
$info.VMName = $vm.Name
$info.ResourceGroupName = $vm.ResourceGroupName
$info.IpAddress = $nic.IpConfigurations.PrivateIpAddress
$info.HostName = $vm.OSProfile.ComputerName
$report+=$info
}
$report | Export-Csv -Path "c:\Azure\VMIPs.csv"
However I have tried using the below to export the same data from an azure account that has multiple subscriptions but all I get is a blank CSV file.
$report = #()
$vms = get-azvm
$azureSubs = get-azsubscription
$azureSubs.foreach{
Select-AzSubscription $_ # << change active subscription
$nics = get-aznetworkinterface | ?{ $_.VirtualMachine -NE $null}
foreach($nic in $nics)
{
$info = "" | Select VmName, ResourceGroupName, HostName, IpAddress
$vm = $vms | ? -Property Id -eq $nic.VirtualMachine.id
$info.VMName = $vm.Name
$info.ResourceGroupName = $vm.ResourceGroupName
$info.IpAddress = $nic.IpConfigurations.PrivateIpAddress
$info.HostName = $vm.OSProfile.ComputerName
$report+=$info
}
}
$report | Export-Csv -Path "c:\Azure\VMIPs.csv"
Can anyone assist?
I think you need to move Get-AzVm right after the Select-AzSubscription? because right now you only get vms once (in default subscription)
$azureSubs.foreach{
Select-AzSubscription $_ # << change active subscription
$nics = get-aznetworkinterface | ?{ $_.VirtualMachine -NE $null}
$vms = get-azvm
...
}

Azure VM OS Build - Powershell

I am trying to create a powershell command to loop through all my Azure subscriptions and get the OS build number of the VMs
param(
# Specify the location of the audit file
$csvFilePath = "C:\agentAudit.csv"
)
cls
$ErrorActionPreference = 'Stop'
Write-Host "Validating Azure Accounts..."
try{
$subscriptionList = Get-AzureRmSubscription | Sort SubscriptionName
}
catch {
Write-Host "Reauthenticating..."
Login-AzureRmAccount | Out-Null
$subscriptionList = Get-AzureRmSubscription | Sort SubscriptionName
}
if (Test-Path $csvFilePath) {
Remove-Item -Path $csvFilePath
}
foreach($subscription in $subscriptionList) {
Select-AzureRmSubscription -SubscriptionId $subscription.SubscriptionId | Out-Null
Write-Output "`n Working on subscription: $($subscription.SubscriptionName) `n"
$vms = Get-AzureRmVM -WarningAction Ignore
foreach ($vm in $vms) {
$VMs = Get-AzureRmVM
$vmlist = #()
$VMs | ForEach-Object {
$VMObj = New-Object -TypeName PSObject
$VMObj | Add-Member -MemberType Noteproperty -Name "VM Name" -Value $_.Name
$VMObj | Add-Member -MemberType Noteproperty -Name "OS type" -Value $_.StorageProfile.ImageReference.Sku
$VMObj | Add-Member -MemberType Noteproperty -Name "OS Offer" -Value $_.StorageProfile.ImageReference.Offer
$VMObj | Add-Member -MemberType Noteproperty -Name "OS Publisher" -Value $_.StorageProfile.ImageReference.Publisher
$VMObj | Add-Member -MemberType Noteproperty -Name "OS Version" -Value $_.StorageProfile.ImageReference.Version
$vmlist += $VMObj
}
$vmlist
}
}
I am pretty new to to Powershell and still learning to understand and write PS
Long time back i created a script for generating the Azure inventory. May be this can help you. You just need to tweak it a bit
Add-AzureRmAccount
$SubscriptionNames = "Prototypes","Development"
foreach($SubscriptionName in $SubscriptionNames)
{
try
{
Select-AzureRmSubscription -SubscriptionName $SubscriptionName
$VMinventory = Get-AzurermVM -ErrorAction Stop
$OutputPath = "C:\VMInventoryRM-" + $SubscriptionName + ".csv"
$report=#()
foreach ($vm in $VMinventory)
{
$VMinfo = " " | select Powerstate, Location, VMSize
# Display
write-host($vm.Name)
$vmStatus = $null
$Location = $null
$VMSize = $null
$vmStatus = (get-azurermvm -Name $vm.Name -ResourceGroupName $vm.ResourceGroupName -Status).Statuses[1].Code
$Location = $vm.Location
$VMSize = $vm.HardwareProfile.VmSize
$VMinfo.Powerstate = $vmStatus
$VMinfo.Location = $Location
$VMinfo.VMSize = $VMSize
$Report += $VMinfo
$i++
}
$Report | export-csv $OutputPath -NoTypeInformation
}
catch
{}
}
I found the answer in the below technet article
function Get-WindowsVersion {
<#
.SYNOPSIS
List Windows Version from computer. Compatible with PSVersion 3 or higher.
.DESCRIPTION
List Windows Version from computer. Compatible with PSVersion 3 or higher.
.PARAMETER ComputerName
Name of server to list Windows Version from remote computer.
.PARAMETER SearchBase
AD-SearchBase of server to list Windows Version from remote computer.
.PARAMETER History
List History Windows Version from computer.
.PARAMETER Force
Disable the built-in Format-Table and Sort-Object.
.NOTES
Name: Get-WindowsVersion.psm1
Author: Johannes Sebald
Version: 1.2.5
DateCreated: 2016-09-13
DateEdit: 2018-07-11
.LINK
https://www.dertechblog.de
.EXAMPLE
Get-WindowsVersion
List Windows Version on local computer with built-in Format-Table and Sort-Object.
.EXAMPLE
Get-WindowsVersion -ComputerName pc1
List Windows Version on remote computer with built-in Format-Table and Sort-Object.
.EXAMPLE
Get-WindowsVersion -ComputerName pc1,pc2
List Windows Version on multiple remote computer with built-in Format-Table and Sort-Object.
.EXAMPLE
Get-WindowsVersion -SearchBase "OU=Computers,DC=comodo,DC=com" with built-in Format-Table and Sort-Object.
List Windows Version on Active Directory SearchBase computer.
.EXAMPLE
Get-WindowsVersion -ComputerName pc1,pc2 -Force
List Windows Version on multiple remote computer and disable the built-in Format-Table and Sort-Object.
.EXAMPLE
Get-WindowsVersion -History with built-in Format-Table and Sort-Object.
List History Windows Version on local computer.
.EXAMPLE
Get-WindowsVersion -ComputerName pc1,pc2 -History
List History Windows Version on multiple remote computer with built-in Format-Table and Sort-Object.
.EXAMPLE
Get-WindowsVersion -ComputerName pc1,pc2 -History -Force
List History Windows Version on multiple remote computer and disable built-in Format-Table and Sort-Object.
#>
[cmdletbinding()]
param (
[parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
[string[]]$ComputerName = "localhost",
[string]$SearchBase,
[switch]$History,
[switch]$Force
)
if ($($PsVersionTable.PSVersion.Major) -gt "2") {
# SearchBase
if ($SearchBase) {
if (Get-Command Get-AD* -ErrorAction SilentlyContinue) {
if (Get-ADOrganizationalUnit -Filter "distinguishedName -eq '$SearchBase'" -ErrorAction SilentlyContinue) {
$Table = Get-ADComputer -SearchBase $SearchBase -Filter *
$ComputerName = $Table.Name
}
else {Write-Warning "No SearchBase found"}
}
else {Write-Warning "No AD Cmdlet found"}
}
# Loop 1
$Tmp = New-TemporaryFile
foreach ($Computer in $ComputerName) {
if (Test-Connection -ComputerName $Computer -Count 1 -ErrorAction SilentlyContinue) {
try {
$WmiObj = Get-WmiObject Win32_OperatingSystem -ComputerName $Computer
}
catch {
Write-Warning "$Computer no wmi access"
}
if ($WmiObj) {
# Variables
$WmiClass = [WmiClass]"\\$Computer\root\default:stdRegProv"
$HKLM = 2147483650
$Reg1 = "SOFTWARE\Microsoft\Windows NT\CurrentVersion"
$Reg2 = "SYSTEM\Setup"
if ($History) {$KeyArr = ($WmiClass.EnumKey($HKLM, $Reg2)).snames -like "Source*"} else {$KeyArr = $Reg1}
# Loop 2
foreach ($Key in $KeyArr) {
if ($History) {$Reg = "$Reg2\$Key"} else {$Reg = $Key}
$Major = $WmiClass.GetDWordValue($HKLM, $Reg, "CurrentMajorVersionNumber").UValue
$Minor = $WmiClass.GetDWordValue($HKLM, $Reg, "CurrentMinorVersionNumber").UValue
$Build = $WmiClass.GetStringValue($HKLM, $Reg, "CurrentBuildNumber").sValue
$UBR = $WmiClass.GetDWordValue($HKLM, $Reg, "UBR").UValue
$ReleaseId = $WmiClass.GetStringValue($HKLM, $Reg, "ReleaseId").sValue
$ProductName = $WmiClass.GetStringValue($HKLM, $Reg, "ProductName").sValue
$ProductId = $WmiClass.GetStringValue($HKLM, $Reg, "ProductId").sValue
$InstallTime1 = $WmiClass.GetQWordValue($HKLM, $Reg, "InstallTime").UValue
$InstallTime2 = ([datetime]::FromFileTime($InstallTime1))
# Variables Windows 6.x
if ($Major.Length -le 0) {$Major = $WmiClass.GetStringValue($HKLM, $Reg, "CurrentVersion").sValue}
if ($ReleaseId.Length -le 0) {$ReleaseId = $WmiClass.GetStringValue($HKLM, $Reg, "CSDVersion").sValue}
if ($InstallTime1.Length -le 0) {$InstallTime2 = ([WMI]"").ConvertToDateTime($WmiObj.InstallDate)}
# Add Points
if (-not($Major.Length -le 0)) {$Major = "$Major."}
if (-not($Minor.Length -le 0)) {$Minor = "$Minor."}
if (-not($UBR.Length -le 0)) {$UBR = ".$UBR"}
# Output
$Output = New-Object -TypeName PSobject
$Output | Add-Member -MemberType NoteProperty -Name ComputerName -Value $Computer.toUpper()
$Output | Add-Member -MemberType NoteProperty -Name ProductName -Value $ProductName
$Output | Add-Member -MemberType NoteProperty -Name WindowsVersion -Value $ReleaseId
$Output | Add-Member -MemberType NoteProperty -Name WindowsBuild -Value "$Major$Minor$Build$UBR"
$Output | Add-Member -MemberType NoteProperty -Name ProductId -Value $ProductId
$Output | Add-Member -MemberType NoteProperty -Name InstallTime -Value $InstallTime2
$Output | Export-Csv -Path $Tmp -Append
}
}
}
else {Write-Warning "$Computer not reachable"}
}
# Output
if ($Force) {Import-Csv -Path $Tmp} else {Import-Csv -Path $Tmp | Sort-Object -Property ComputerName, WindowsVersion | Format-Table -AutoSize}
}
else {Write-Warning "PSVersion to low"}
}
https://gallery.technet.microsoft.com/scriptcenter/Get-WindowsVersion-can-0726c5d4#
Thank You Johannes Sebald

Resources