Powershell Switch-Statement doesn't change value - windows

This is the Powershell script I wrote:
$varCompList = Get-ADComputer -Filter "Name -like '*Name of Computers*'" -Properties OperatingSystemVersion | select DNSHostName, OperatingSystemVersion
foreach ($System in $varCompList){
$Restult=switch ($System.OperatingSystemVersion){
"10.0 (20348)"{"Server 2022"}
"10.0 (19042)"{"Server 2019 20H2"}
"10.0 (18363)"{"Server 2019 1909"}
"10.0 (17763)"{"Server 2019 1809"}
"10.0 (14393)"{"Server 2016"}
}
}
echo $varCompList
It displays all the Servers like it should but the OperatingSystemVersion is still displayed as 10.0 (14393).
What am I missing?

You're currently assigning the mapped OS names to a variable, but you never use it for anything and you never update the original input object.
Instead of assigning the result to a variable, assign it to the OperatingSystemVersion property on each object instead:
foreach ($System in $varCompList){
$System.OperatingSystemVersion = switch ($System.OperatingSystemVersion){
"10.0 (20348)"{"Server 2022"}
"10.0 (19042)"{"Server 2019 20H2"}
"10.0 (18363)"{"Server 2019 1909"}
"10.0 (17763)"{"Server 2019 1809"}
"10.0 (14393)"{"Server 2016"}
default { $_ }
}
}
The default case will ensure you preserve the original version string for any computer that doesn't have any of the listed versions installed.

Related

How to display the installed applications in alphabetical order of application name using winget?

Using winget,
winget list command displays the list of the applications currently installed in my computer, but it doesn't display the applications in alphabetical order of application name just like in the control panel,
Is there a way to display the installed applications in alphabetical order of application name using winget?
Note: The two images are from different machines.
Thanks.
As Demetrius mentioned in his comment, there isn't an ability to sort built into the client currently. However, in your screenshot I see you are using PowerShell. You can use PowerShell variables and commands to effectively sort the output. By chaining a few commands together, it is possible to re-create the table. This seemed to work for me -
$a=winget list;$a|select -First 3;$a|select -Skip 3|Sort-Object|select -First 9
I was trying to see if there was a parameter/option to accompany the winget command, and really wanted to just comment on the answer by Trenly; I had been using a similar piped command (just shorter), so he should still get the credit!
However, apparently, I must have a certain reputation score to even comment on his (or any other) answer... Yet, I can provide an answer without any rating whatsoever; go figure. So, the shorter version, similar to his answer, but without the unnecessary nested piping:
winget list|Sort-Object
You can check for ConvertFrom-FixedColumnTable function at here to convert the result of winget list to a table.
I created a function winget_list_OrderBy in order to make it simple:
function winget_list_OrderBy {
<#
.EXAMPLE
winget_list_OrderBy
.EXAMPLE
winget_list_OrderBy -OrderBy 'Name' -Arguments "--id=Git.Git"
#>
[CmdletBinding()]
param (
[Parameter(ValueFromPipeline)]
[string[]]
$OrderBy = 'Name', # $OrderBy can be equal to 'Name'/'Id'/'Version'/'Source' (and 'Available' if exist).
[Parameter(ValueFromPipeline)]
[string[]]
$Arguments = ''
)
# Backup the original [Console]::OutputEncoding
$encoding = [Console]::OutputEncoding
# Make PowerShell interpret winget.exe's output as UTF-8
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new()
(winget list $Arguments) -match '^(\p{L}|-)' | # filter out progress-display lines
ConvertFrom-FixedColumnTable | # parse output into objects
Sort-Object $OrderBy | # sort by the ID property (column)
Format-Table # display the objects in tabular format
# Restore the original [Console]::OutputEncoding afterwards
[Console]::OutputEncoding = $encoding
}
Usage is simple: winget_list_OrderBy -OrderBy $OrderBy -Arguments $Arguments or winget_list_OrderBy.
thoughts on this? It may need a little clean up, but I just converted the results to an object Array.
$apps = #("Microsoft Visual Studio Code", "Microsoft Visual Studio Code Insiders", "Visual Studio Community 2022")
$global:foundapps = [System.Collections.Generic.List[object]]::new()
foreach ($app in $apps) {
$Applist = winget search $app
$header = $Applist[1]
$nameposition = $header.indexof('Name')
$idPosition = $header.indexof('Id')
$versionPosition = $header.indexof('Version')
$sourceposition = $header.indexof('Source')
$name = $header.substring($nameposition, $idPosition).replace(' ', '')
$id = $header.substring($idPosition, ($versionPosition - $idPosition)).replace(' ', '')
$iVersiond = $header.substring($versionPosition, ($sourceposition - $versionPosition)).replace(' ', '')
$source = $header.substring($sourceposition, ($header.length - $sourceposition)).replace(' ', '')
$appstoadd = $Applist | select-object -skip 3
foreach ($AppToAdd in $appstoadd) {
$foundapps.Add([PSCustomObject] #{
"Name" = $AppToAdd.substring($nameposition, $idPosition).replace(' ', '')
"Version" = $AppToAdd.substring($versionPosition, ($sourceposition - $versionPosition)).replace(' ', '')
"ID" = $AppToAdd.substring($idPosition, ($versionPosition - $idPosition)).replace(' ', '')
"Source" = $AppToAdd.substring($sourceposition, ($header.length - $sourceposition)).replace(' ', '')
})
}
}
$foundapps |fl

I want to search for values in a Table created with Powershell

So i have the following code to generate the entire Windows Update History:
$Session = New-Object -ComObject "Microsoft.Update.Session"
$Searcher = $Session.CreateUpdateSearcher()
$historyCount = $Searcher.GetTotalHistoryCount()
$Searcher.QueryHistory(0, $historyCount) | Select-Object Title, Description, Date,
#{name="Operation"; expression={switch($_.operation){
1 {"Installation"}; 2 {"Uninstallation"}; 3 {"Other"}
}}}
My question is how can i search in this table for updates containing KB. So for instance i want to know if the update KB4052623 has been installed. How can i write a simple piece of code to tell me KB4052326 has been found in the output of above code? Thanks in advance.
You need to assign the array returned by QueryHistory to a variable, then loop through that array to get the objects. Probably easiest to use Regex to find the KB numbers.
This code just list the found KB numbers, but you should be able test it as needed. Also, you may want to check the Description for KB numbers as well, it may tell you that it replaces old KB numbers or other important info.
$Session = New-Object -ComObject "Microsoft.Update.Session"
$Searcher = $Session.CreateUpdateSearcher()
$historyCount = $Searcher.GetTotalHistoryCount()
$MSUpdateHistory = $Searcher.QueryHistory(0, $historyCount) | Select-Object Title, Description, Date,
#{name="Operation"; expression={switch($_.operation){
1 {"Installation"}; 2 {"Uninstallation"}; 3 {"Other"}
}}}
$MSUpdateHistory | ForEach-Object {
if ($_.Title -match '(?<KBNum>KB\d+)') {
Write-Host "Found $($Matches.KBNum)"
#$_.Description
#$_.Date
#$_.Operation
}
}

Powershell function not returning output correctly

I have a Powershell function that formats out put from another function I have to gather version, path and file information based on some registry queries. It seems all the data is being stored to one variable and only printing one line altogether. Below is my code, the output and an explanation of what I need in the desired output.
Code:
function getOffice()
{
$list = new-object System.Collections.Generic.List[PSCustomObject];
$found_paths = #();
$final_paths = #();
$uninstall_keys = getRegistrySubkeys "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" '\\Office[\d+.*]';
if ($uninstall_keys -ne $null)
{
foreach ($key in $uninstall_keys)
{
$product_name = getRegistryValue $key "DisplayName";
$version = getRegistryValue $key "DisplayVersion";
$base_install_path = getRegistryValue $key "InstallLocation";
$full_install_path = (Get-ChildItem -Directory -LiteralPath $base_install_path | Where-Object Name -match '^Office\d{1,2}\D?').FullName;
$found_paths += ,$full_install_path;
$exes = #("MSOCF.DLL", "access.exe", "word.exe", "wordCnv.exe", "WordViewer.exe", "Excel.exe", "ExcelCnv.exe", "ExcelViewer.exe", "PowerPoint.exe",
"PowerPointViewer.exe", "PowerPointCnv.exe", "Publisher.exe", "Project.exe", "OneNote.exe", "InfoPath.exe Groove.exe", "FrontPage.exe",
"SharePointDesigner.exe", "Visio.exe", "VisioViewer.exe", "Lync.exeOutlook.exe", "WINPROJ.EXE");
foreach($path in $found_paths)
{
foreach($exe in $exes)
{
$found_files = Get-Item ([System.IO.Path]::Combine($path, $exe)) -EA Ignore;
$found_file = $found_files.Name;
if ($found_file)
{
$office = makeFileResult $found_file, $path, $version, $product_name, $version;
$list.Add($office);
$list
}
}
}
}
}
}
function makeFileResult($name, $path, $file_version, $product_name, $product_version)
{
return [PSCustomObject]#{
path = $path;
file = $name;
product_version = $product_version;
product_name = $product_name;
file_version = $file_version;
};
}
getOffice
Output:
path :
file : {MSOCF.DLL, C:\Program Files\Microsoft Office\Office15, 15.0.4569.1506, Microsoft Project Standard 2013...}
product_version :
product_name :
file_version :
path :
file : {WINPROJ.EXE, C:\Program Files\Microsoft Office\Office15, 15.0.4569.1506, Microsoft Project Standard 2013...}
product_version :
product_name :
file_version :
path :
file : {MSOCF.DLL, C:\Program Files\Microsoft Office\Office15, 15.0.4569.1506, Microsoft Project Standard 2013...}
product_version :
product_name :
file_version :
path :
file : {WINPROJ.EXE, C:\Program Files\Microsoft Office\Office15, 15.0.4569.1506, Microsoft Project Standard 2013...}
product_version :
product_name :
file_version :
I am not sure why all the data is only being stored in the `file` key here.
I am not sure why all the data is only being stored in the file key here.
Desired Output:
path : C:\Program Files\Microsoft Office\Office15
file : MSOCF.DLL
product_version : 15.0.4569.1506
product_name : Microsoft Project Standard 2013
file_version : 15.0.4569.1506
path : C:\Program Files\Microsoft Office\Office15
file : WINPROJ.EXE
product_version : 15.0.4569.1506
product_name : Microsoft Project Standard 2013
file_version : 15.0.4569.1506
Seems silly, but remove the commas and only have spaces when making the function call makeFileResult.
$office = makeFileResult $found_file $path $version $product_name $version
Since the parameters in the function call have no type defined, PowerShell will do it's best to "guess" what type you mean. The commas in between the variables end up being interpreted as a string array instead of a string like you are expecting. You can see this when you get the type:
PS C:\> $office.file.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
The spaces make the function call be evaluated like a traditional cmd call, with the Arg[] string array.
I personally would read about advanced Parameters and add named parameters which would make it easier to make sure everything gets logged in a consistent way.

How to change the loop Powershell content from the csv file automatically?

I want to change the loop PowerShell content from the CSV file automatically, is there someone know how to achieve the goal?
I want to run the loop PowerShell as below,I export the AD Group Members UPN with CSV file like One#contoso.com. I want to change the Userlist with the UPN automatically because there have more than 1000 members in the group and I have to change the upn from one#contoso.com to 'one#contoso.com',it’s easy to make a miss, is there has a smart way can achieve the goal,thanks.
Export-ADGroupmember UPN:
Get-ADGroupmember -identity adgroup | % { get-aduser $_.samaccountname | select userprincipalname } | export-csv upn.csv -notypeinformation
Loop PowerShell:
Loop PowerShell:
$UserList = #(
'One#contoso.com'
'Two#contoso.com'
'Three#contoso.com'
'Four#contoso.com'
'Five#contoso.com'
)
foreach ($UL_Item in $UserList)
{
$ARAGU_Params = #{
TenantName = "contoso"
HostPoolName = "contosoHostPool"
AppGroupName = "Desktop Application Group"
UserPrincipalName = $UL_Item
}
Add-RdsAppGroupUser #ARAGU_Params
}
You cant change content in your $UserList .More precisely, it is possible but affect the performance since You will need to read from the file and break it into segments. The best way is to download all users at once.You can do it like this:
$UserList=Get-ADGroupmember -identity adgroup | % { get-aduser $_.samaccountname | select userprincipalname }
foreach ($UL_Item in $UserList)
{
$ARAGU_Params = #{
TenantName = "contoso"
HostPoolName = "contosoHostPool"
AppGroupName = "Desktop Application Group"
UserPrincipalName = $UL_Item.userprincipalname
}
Add-RdsAppGroupUser #ARAGU_Params
}

LoadPercentage win32_processor Windows Powershell

I have written the following code for a Powershell script:
while($true){
$os= Get-Ciminstance Win32_OperatingSystem
$cpu=Get-WmiObject win32_processor
$cpuUsage=($cpu.LoadPercentage)
$os | Select #{Name = "CPU usage"; Expression = {$cpuUsage}},
#{Name = "FreeGB"; Expression = {[math]::Round($_.FreePhysicalMemory/1mb, 2)}}
}
These are a sample from the outputs I'm getting:
LoadPercentage:2
LoadPercentage:0
LoadPercentage:1
LoadPercentage:
LoadPercentage:7
LoadPercentage:10
LoadPercentage:8
LoadPercentage:
LoadPercentage:2
I don't understand why sometimes null values are being generated. Is this a flaw within the function itself or is there something wrong with my code? Has this ever happened to anyone before?
Thank you

Resources