The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 2,224 other followers

Archive for the ‘PowerShell’ Category

Windows command prompt: decrementing loop

Posted by jpluimers on 2020/12/30

I needed a decrementing loop on the Windows command prompt, but that seems very hard from batch files without programming your own kind of while loop:

PowerShell to the rescue to loop back from and including 463 down to and including 290:

PowerShell -Command "for ($i=463; $i -ge 290; $i--) { Write-Host "Value " $i}"

This outputs:

Value 463
Value 462
Value 291
Value 290

In a similar way, you can execute a cmd command, but then you need to be careful on how to pass parameters: the \" is important to you can have quotes within quoted strings..

PowerShell -Command "for ($i=463; $i -ge 290; $i--) { & echo \"Value $i\"}"

gives this:

Value 463
Value 462
Value 291
Value 290

Read the rest of this entry »

Posted in Batch-Files, CommandLine, Console (command prompt window), Development, PowerShell, PowerShell, Scripting, Software Development, Windows | 1 Comment »

On Windows 7 and 8.x too: Completely disable Windows 10 telemetry collection – twm’s blog

Posted by jpluimers on 2020/12/10

From [WayBack] Completely disable Windows 10 telemetry collection – twm’s blog:

So I don’t forget: According to an article in c’t magazine, disabling the “DiagTrack” service (“Connected User Experience and Telemetry”) will completely disable user tracking in Windows 10. They also say that they did not see any negative effects.

Source: [WayBack] Telefonierverbot in c’t 01/2019 page 172 (in German)

I saw at least one system where the service is not shown when you run Services.msc: it did not list DiagTrack, nor Connected User Experience and Telemetry. How awful is that!

The service can also be installed non older Windows versions: [WayBack] Just found DiagTrack running in Services – Tips and Tricks

Sometimes, it gets re-enabled. I think this happens during major Windows updates.

To inspect, stop and disable

Run all commands from the console the below bold commands. The non-bold text was the output on my system. If instead of the cmd.exe console, you run a PowerShell console, then remove the bits PowerShell -Command " and " at the start and end of each command.

The first command does not require an Administrative (UAC Elevated) command prompt; the last one does.

However, the first command, needs the | Select-Object * bit as otherwise most of the fields will not be displayed, excluding for instance StartType.

powershell -Command "Get-Service -Name DiagTrack | Select-Object *"

Name                : DiagTrack
RequiredServices    : {RpcSs}
CanPauseAndContinue : False
CanShutdown         : True
CanStop             : True
DisplayName         : Connected User Experiences and Telemetry
DependentServices   : {}
MachineName         : .
ServiceName         : DiagTrack
ServicesDependedOn  : {RpcSs}
ServiceHandle       :
Status              : Running
ServiceType         : Win32OwnProcess
StartType           : Automatic
Site                :
Container           :

On an Administrative command-prompt:

powershell -Command "Set-Service -Name DiagTrack -StartUpType Disabled"
powershell -Command "Get-Service -Name DiagTrack | Stop-Service"

Two notes:

Read the rest of this entry »

Posted in Batch-Files, CommandLine, Development, Power User, PowerShell, PowerShell, Scripting, Software Development, Windows | Leave a Comment »

powershell – Format-Table forgets some properties, but Format-List shows them all. Why? – Stack Overflow

Posted by jpluimers on 2020/11/12

Reminder to self: finish the script that initiated this 2013 question (yes ages ago!) [WayBack] powershell – Format-Table forgets some properties, but Format-List shows them all. Why? – Stack Overflow.

The question was based on code I was really happy I saved in the WayBack machine: WayBack: how-to: Print/List installed programs/applications sorted by date | Tech Off | Forums | Channel 9

So here the question and the answer.


Given the below PowerShell 3 script, Format-Table does not list all properties as columns (it skips NoRemove), but Format-List does, and you can force the properties to be there using Select-Object.

Out-GridView behaves the same as Format-Table and also skips NoRemove

Why is that?

Note: this is from a much less restricted Where-Object clause, where it looks like Format-Tabledoes inspect more than just the first object in the array to guess the columns.

The example comes from Channel 9 how-to: Print/List installed ​programs/ap​plications sorted by date which forgot to initialize the first Get-ItemProperty (gp) as an array so you got an error like this:

Method invocation failed because [Microsoft.Win32.RegistryKey] doesn't
contain a method named 'op_Addition'.

Example code:

$nonUninstallableSoftwareRegistryKeys = (@(Get-Item HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*)) + 
(Get-Item HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*) + 
(Get-Item HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*) | 
  Where-Object { $_.ValueCount -eq 1 }

$nonUninstallableSoftwareRegistryKeys | Get-Member

$nonUninstallableSoftwareRegistryNameValues = $nonUninstallableSoftwareRegistryKeys | 

$nonUninstallableSoftwareRegistryNameValues | Get-Member

$nonUninstallableSoftwareRegistryNameValues |

$nonUninstallableSoftwareRegistryNameValues |

$nonUninstallableSoftwareRegistryNameValues |
  Select-Object SystemComponent, NoRemove, PSPath, PSParentPath, PSChildName, PSProvider |

I used GetType().FullName and Get-Member to inspect the underlying types.

$nonUninstallableSoftwareRegistryKeys starts with all installed software (user, system x64 and system x86) filtered by registry keys having only 1 value (empirically those are the ones you cannot uninstall).

The first part of the output shows that $nonUninstallableSoftwareRegistryKeys is a System.Object[] of type Microsoft.Win32.RegistryKey with all the right members. Hence the ability to perform a Where-Object filter on the ValueCount property even though the code-completion does not show that.

$nonUninstallableSoftwareRegistryKeys exposes also a few PowerShell “Extended Type System” NoteProperty properties including Property that contain the registry Name/Value pairs under the key and a bunch of PS* coming from the registry provider.

$nonUninstallableSoftwareRegistryNameValues is also a System.Object[] but now of typeSystem.Management.Automation.PSCustomObject because of the Get-ItemProperty which expands the Name/Value pairs in the Property of each $nonUninstallableSoftwareRegistryKeysitem into properties. For the first item in my output, it adds the SystemComponent property. For the second item it adds NoRemove. And it adds a bunch of PS* coming from the registry provider.

Format-Table output:

SystemComponent PSPath                                                                                                                                    PSParentPath                        
--------------- ------                                                                                                                                    ------------                        
              1 Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\Connection Manager             Microsoft.PowerShell.Core\Registr...
                Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\WIC                            Microsoft.PowerShell.Core\Registr...
              1 Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Connection Manager Microsoft.PowerShell.Core\Registr...
                Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\WIC                Microsoft.PowerShell.Core\Registr...

Format-List output:

SystemComponent : 1
PSPath          : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\Connection Manager
PSParentPath    : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall
PSChildName     : Connection Manager
PSProvider      : Microsoft.PowerShell.Core\Registry

NoRemove     : 1
PSPath       : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\WIC
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall
PSChildName  : WIC
PSProvider   : Microsoft.PowerShell.Core\Registry

SystemComponent : 1
PSPath          : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Connection Manager
PSParentPath    : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall
PSChildName     : Connection Manager
PSProvider      : Microsoft.PowerShell.Core\Registry

NoRemove     : 1
PSPath       : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\WIC
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall
PSChildName  : WIC
PSProvider   : Microsoft.PowerShell.Core\Registry

Select-Object output:

SystemComponent NoRemove PSPath                                                                                                                                    PSParentPath               
--------------- -------- ------                                                                                                                                    ------------               
              1          Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\Connection Manager             Microsoft.PowerShell.Cor...
                1        Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall\WIC                            Microsoft.PowerShell.Cor...
              1          Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Connection Manager Microsoft.PowerShell.Cor...
                1        Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\WIC                Microsoft.PowerShell.Cor...

Edit: my environment

PS C:\Users\Developer> Get-CimInstance Win32_OperatingSystem | Select-Object Version, Caption | Format-List

Version : 6.2.9200
Caption : Microsoft Windows 8 Pro

Name                           Value                                                                                                                                                          
----                           -----                                                                                                                                                          
PSVersion                      3.0                                                                                                                                                            
WSManStackVersion              3.0                                                                                                                                                            
CLRVersion                     4.0.30319.18051                                                                                                                                                
BuildVersion                   6.2.9200.16628                                                                                                                                                 
PSCompatibleVersions           {1.0, 2.0, 3.0}                                                                                                                                                
PSRemotingProtocolVersion      2.2   

These 2 return the same table:

$nonUninstallableSoftwareRegistryNameValues |

$nonUninstallableSoftwareRegistryNameValues |
  Format-Table *                                                                                                                                                         

Answer 1

If you don’t specify the property names or ‘*’ for all of them, Format-Table will print by default just the first 4 (the default value of $FormatEnumerationLimit), not ure why you get only three in the ft output. Format-List will show all only when the type of objects doesn’t have a format view for Format-List.


I did a $nonUninstallableSoftwareRegistryNameValues | Format-Table * which also skips NoRemove. Something fishy is going on here.

And if you add -Force?

This also fails: $nonUninstallableSoftwareRegistryNameValues | Format-Table * -Force

I can see all properties when piping to fl (without -force) and with ft *.

What OS and PS version do you run? I’ve added mine to my question.

Answer 2

Did you try the following?

$nonUninstallableSoftwareRegistryNameValues |
  Select-Object SystemComponent, NoRemove, PSPath, PSParentPath, PSChildName, PSProvider |
  Format-Table -Wrap


That works (it is almost the same as the last entry in my example), but why can’t Format-Table figure this out by itself? Or maybe phrased differently: what criteria does Format-Table to determine which columns to pick?


Posted in .NET, CommandLine, Development, PowerShell, PowerShell, Scripting, Software Development | Leave a Comment »

Installing Windows software with Chocolatey: a few notes

Posted by jpluimers on 2020/10/28

I will limit myself to software that needs Administrative elevation in order to be installed. This is the default use-case for Chocolatey. It is way way easier than installing software all by hand, but there are a few things you need to know, hence these notes.

Administrative elevation

Since the default use case is installing software that requires Administrative elevation during install, Chocolatey needs to run with Administrative privileges in order to perform these installs.

If you were hoping for a way around this (for instance by having a client/service architecture), then just stop here.

Even though such a structure could technically be created, getting it stable and working it correctly with a truckload of software to be installed (much of which not available as packages during Chocolatey development in the first place) is a task too big.

Think of the size of the Windows Installer team at Microsoft to get installers working in the first place, the extra effort needed by Chocolatey volunteers to get the installers working from the console, then another much more complex layer of getting them running from inside a service and communicating everything back and forth to a non-elevated command prompt would be a nightmare.

I won’t even mention the security steps involved to ensure the non-elevated command prompt has enough rights to send installation instructions to the elevated service.

So the first step is to have an elevated command prompt for Chocolatey.

Being elevated, and Chocolatey needing to download installers requires a local temporary place for them.

By default, that place is %Temp%\chocolatey of the administrative user that elevated the Chocolatey command prompt.

This directory can grow quite big, so dir, so – since there is no choco cleanup yet [WayBack] you need to either:

Install Chocolatey itself

Either the direct one below, or the more secure one (so you can inspect the intermediate [WayBackinstall.ps1) at [WayBack] Installation using PowerShell from cmd.exe:

@echo off
SET DIR=%~dp0%
::download install.ps1
%systemroot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "((new-object net.webclient).DownloadFile('','%DIR%install.ps1'))"
::run installer
%systemroot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '%DIR%install.ps1' %*"

If you want to get rid of it, use [WayBack] Uninstallation.

Besides the one above and below, there are many more [WayBack] Installation: more install options

Output of direct install as Administrator (disclaimers apply):

C:\WINDOWS\system32>powershell -NoProfile -ExecutionPolicy Bypass -Command "[System.Net.WebRequest]::DefaultWebProxy.Credentials = [System.Net.CredentialCache]::DefaultCredentials; iex ((New-Object System.Net.WebClient).DownloadString(''))" && SET PATH="%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"
Getting latest version of the Chocolatey package for download.
Getting Chocolatey from
Downloading 7-Zip commandline tool prior to extraction.
Extracting C:\Users\JEROEN~1\AppData\Local\Temp\chocolatey\chocInstall\ to C:\Users\JEROEN~1\AppData\Local\Temp\chocolatey\chocInstall...
Installing chocolatey on this machine
Creating ChocolateyInstall as an environment variable (targeting 'Machine')
  Setting ChocolateyInstall to 'C:\ProgramData\chocolatey'
WARNING: It's very likely you will need to close and reopen your shell
  before you can use choco.
Restricting write permissions to Administrators
We are setting up the Chocolatey package repository.
The packages themselves go to 'C:\ProgramData\chocolatey\lib'
  (i.e. C:\ProgramData\chocolatey\lib\yourPackageName).
A shim file for the command line goes to 'C:\ProgramData\chocolatey\bin'
  and points to an executable in 'C:\ProgramData\chocolatey\lib\yourPackageName'.

Creating Chocolatey folders if they do not already exist.

WARNING: You can safely ignore errors related to missing log files when
  upgrading from a version of Chocolatey less than 0.9.9.
  'Batch file could not be found' is also safe to ignore.
  'The system cannot find the file specified' - also safe.
chocolatey.nupkg file not installed in lib.
 Attempting to locate it from bootstrapper.
PATH environment variable does not have C:\ProgramData\chocolatey\bin in it. Adding...
WARNING: Not setting tab completion: Profile file does not exist at 'C:\Users\jeroenAdministrator\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1'.
Chocolatey (choco.exe) is now ready.
You can call choco from anywhere, command line or powershell by typing choco.
Run choco /? for a list of functions.
You may need to shut down and restart powershell and/or consoles
 first prior to using choco.
Ensuring chocolatey commands are on the path
Ensuring chocolatey.nupkg is in the lib folder

Installing packages


If you run out of SSD or VM disk space, you can try compress using compact /c /s *.* in these directories:

  • C:\ProgramData\Package Cache
  • C:\ProgramData\Microsoft\VisualStudio\Packages
  • C:\ProgramData\Microsoft\ClickToRun\ProductReleases

Further reading


PS: always watch the output and logs!

Read the rest of this entry »

Posted in Chocolatey, CommandLine, Conference Topics, Conferences, Development, Event, Power User, PowerShell, PowerShell, Scripting, Software Development, Windows | Leave a Comment »

PowerShell: checking minimum version

Posted by jpluimers on 2020/08/13

Nowadays, often your PowerShell code uses features unavailable in older PowerShell versions. When running it on a version that is too old, you usually get an error message, for instance like this:

Unable to find type [Ordered]: make sure that the assembly containing this type is loaded.

Back in the days, this was a new feature introduced in PowerShell 3.0: [WayBack] Use cases of [ordered], the new PowerShell 3.0 feature – Stack Overflow

It is way friendlier to show a message indicating the version is too old in stead of throwing this error.

That’s where the # Requires Version 3.0 directive comes in: [WayBackabout_Requires | Microsoft Docs.

Adding this line to the top of a script gives output like this on a stock Windows 7 SP1 system that has PowerShell 2.0:

# PowerShell -f List-Delphi-Installed-Packages.ps1
The script ‘List-Delphi-Installed-Packages.ps1’ cannot be run because it contained a “#requires” statement at line 1 for Windows PowerShell version 3.0. The version required by the script does not match the currently running version of Windows PowerShell version 2.0.
+ CategoryInfo : ResourceUnavailable: (List-Delphi-Installed-Packages.ps1:String) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : ScriptRequiresUnmatchedPSVersion

Note that PowerShell 3.0 is also the minimum version for debugging it in Visual Studio Code (which means you do not have to use PowerShell ISE any more; it is still there , but so far behind as a development tool that many prefer Visual Studio Code):


Posted in CommandLine, Development, PowerShell, PowerShell, Scripting, Software Development | Leave a Comment »

%d bloggers like this: