Windows Server Inventory Report Script

To help us IT identifying certain configurations on a server and possible misconfigurations I have made a PowerShell script which creates a…

To help us IT identifying certain configurations on a server and possible misconfigurations I have made a PowerShell script which creates a complete overview of the current server configuration and exports it as a single HTML file.

In this post I will explain how to use it and how the script works.

jv-media-3866-047721edba6f.png

An example of the output of the script.


Where to download this script?

For the fast pass, my script can be downloaded here:

Download script from GitHub


What does the Server Inventory script do?

The script I have made creates a full system configuration report which shows us a lot of information:

  • Generic System information
  • Network information
  • Firewall configuration and Ports
  • Storage information
  • Applications
  • Server roles, SQL and IIS configuration
  • Services
  • Configured shares
  • Installed printers

I have uploaded this script to the PowerShell Gallery for quick and easy installation/use. You can download and install the script by typing this into your PowerShell window:

POWERSHELL
Install-Script JV-ServerInventoryReport

At the question for the untrusted repository, answer “Yes to all” (A).

jv-media-3866-73da7b39246d.png

Now the script is installed, and we can execute it by running:

POWERSHELL
JV-ServerInventoryReport

This immediately runs the script and saves the output to your desktop folder.


How to use the script manually

To use the script, we need to do some steps. You can do it in your own way, but I show the most easiest way to run the script without compromising system security.

First download the script from GitHub:

Download script from GitHub

Click on the blue button above. You now are on the GitHub page of the script.

jv-media-3866-49e7d848560d.png

Click on “Code” and then “Download ZIP”.

Now place the files on the server where you want to execute the script.

jv-media-3866-7b76c7b8117c.png

Unzip the ZIP file.

Open Powershell ISE as administrator.

jv-media-3866-4baa015038fe.png

After opening PowerShell ISE and after authenticating, open the script.

jv-media-3866-a00421852055.png

Review the script to understand what it does. This is always a good recommendation before executing unknown scripts.

After reviewing, run the following command to temporarily disable the PowerShell execution policy:

POWERSHELL
Set-ExecutionPolicy Unrestricted -Scope Process

This disables the default PowerShell execution policy for only the duration of your PowerShell window. After closing PowerShell, every other window will have this enabled again.

Then run the script by clicking the “Play” button:

jv-media-3866-e70383784fc0.png

The script will run. This takes about 30 seconds. After it has been succesfully completed, the HTML-file will be placed on the desktop (or other location if you specify this while running).

POWERSHELL
PS C:\Users\justin-admin> Set-ExecutionPolicy Unrestricted -Scope Process

PS C:\Users\justin-admin> C:\Users\justin-admin\Downloads\JV-ServerInventoryReport-main\JV-ServerInventoryReport.ps1
Script made by...
     _           _   _        __     __            _   _  _
    | |_   _ ___| |_(_)_ __   \ \   / /__ _ __ ___| |_(_)(_)_ __   ___ _ __
 _  | | | | / __| __| | '_ \   \ \ / / _ \ '__/ __| __| || | '_ \ / _ \ '_ \
| |_| | |_| \__ \ |_| | | | |   \ V /  __/ |  \__ \ |_| || | | | |  __/ | | |
 \___/ \__,_|___/\__|_|_| |_|    \_/ \___|_|  |___/\__|_|/ |_| |_|\___|_| |_|
                                                       |__/
Report written to: C:\Users\justin-admin\Desktop\Server-Inventory_20250821_101816.html
jv-media-3866-361f5c88aa16.png

Then you can open this file with your favorite webbrowser and review the information.


Summary

This script provides a great and simple overview of the full server configuration. It places everything in nice and clear tables, while still granting access to the raw outputs it used to markup the tables.

Everything is placed in nice and clear tabs so information is categorized, and the information can be easily exported.

I hope my script is helpful for you and thank you for viewing.

Sources

These sources helped me by writing and research for this post;

  1. https://learn.microsoft.com/en-us/powershell/scripting/learn/ps101/09-functions?view=powershell-7.5
  2. https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/convertto-html?view=powershell-7.5

Β 

End of the page πŸŽ‰

You have reached the end of the page. You can navigate through other blog posts as well, share this post on X, LinkedIn and Reddit or return to the blog posts collection page. Thank you for visiting this post.

If you think something is wrong with this post or you want to know more, you can send me a message to one of my social profiles at: https://justinverstijnen.nl/about/

Go back to Blog homepage

If you find this page and blog very useful and you want to leave a donation, you can use the button below to buy me a beer. Hosting and maintaining a website takes a lot of time and money. Thank you in advance and cheers :)

Buy me a beer

The terms and conditions apply to this post.

Remove Roaming Profile folders with PowerShell (force)

This guide uses and describes a PowerShell script that removes a roaming profile folder by taking ownership, fixing permissions and attributes, and using a robocopy fallback if delete fails due to several possible reasons.

What this script does

This script tries to clean and delete a folder which I have used in the past to remove Roaming Profile folders from Active Directory. These folders are heavily secured as personal data might reside in it. It can also contain files with more than 260 characters and as we already know by now, Windows doesn’t like that. This script therefore manages to do the following steps:

  1. Changes ownership (takeown`)
  2. Changes permissions (icacls) for the logged in administrator to actually get access to the folder if not having already
  3. Removes protected file attributes (attrib)
  4. If normal delete fails, it uses a robocopy fallback to make the folder empty

Requirements

  • Run PowerShell or PowerShell ISE as Administrator
  • Local machine access (SMB share not supported)
  • Update these two variables before actuallyrunning:
    • $fullPath = the folder you want to clean/remove
    • $emptydir = where the script creates a temporary empty folder
  • Be sure you are pointing to the correct folder as this script deletes contents without creating backups

Step 1: Download the script

Let’s start with downloading the script from my GitHub page:

Download script from GitHub

Click on “Code” and then “Download ZIP”.

jv-media-8506-2a23ca53a3ed.png

Now you have to put the script on the computer/server where the roaming profile folder is.


Step 2: Open and edit the script prior to execution

Before we run the script, we need to change the parameters. Let’s open PowerShell ISE as Administrator on the destination server for a nice split window of editing and execution of the script.

jv-media-3616-d4b54450c379.png

Then open the just downloaded file:

jv-media-8506-19d45d799598.png

Then we need to change the folder on Line 2:

  • $fullPath = “D:\Path\To\Profiles”

This must become the actual path on your machine you can’t remove through the GUI. Let’s say my own Roaming Profile on D:\RoamingProfiles\justinverstijnen.V6. Navigate to the folder, and then do a right click on that folder while holding down the Shift button. This brings up an option to copy the full path.

jv-media-8506-442434aaf0c6.png

Paste that value in the variable on Line 2:

jv-media-8506-2f57a056a6d5.png

You can also change the value on Line 4 to change the temporary directory needed for the fallback method. This folder is cleaned before the script is finished.


Step 3: Running the script

Before we can actually run the script, great chance that the machine has an PowerShell execution policy active which it has by default. Run this command to bypass this for the duration of this window:

PowerShell
Set-ExecutionPolicy Unrestricted -Scope Process -Force

Paste the command into the blue execution part and hit Enter.

jv-media-8506-cc3aa7182f5e.png

Now we are ready to execute the script to delete the bothering folder. Click on the “Play” button in the menu bar:

jv-media-8506-4ab8aa159681.png

The script will exactly tell you what its doing at every moment, giving you insights on what files are permanently deleted.

jv-media-8506-f6f122ec4c99.png


Step 4: Check the results

After the script has finished, let’s check with the GUI File Explorer what has happened with the folder:

jv-media-8506-3176752715d7.png

The folder is now completely gone and not bothering us anymore, which is great. You can use it for deleting more profiles by changing the variable on Line 2 to a new profile in case you need this.


Summary

  • The script is designed to remove a folder and its contents , even when permissions, too long file lengths (260 chars) or attributes make deletion hard.
  • It first tries a normal delete (Remove-Item), then:
    • if the folder still exists, it uses a robocopy fallback to mirror an empty folder over the target (so the target becomes empty)
    • if an error happens, it also uses the robocopy fallback and then tries again to remove what is left
  • The script makes changes to permissions and ownership of the target folder (because of takeown and icacls).
  • Because this is destructive, only run it when you are sure $fullPath is correct.

Thank you for reading this post and I hope it was helpful!

Sources

These sources helped me by writing and research for this post;

  1. https://learn.microsoft.com/powershell/module/microsoft.powershell.management/remove-item
  2. https://learn.microsoft.com/windows-server/administration/windows-commands/takeown

Β 

End of the page πŸŽ‰

You have reached the end of the page. You can navigate through other blog posts as well, share this post on X, LinkedIn and Reddit or return to the blog posts collection page. Thank you for visiting this post.

If you think something is wrong with this post or you want to know more, you can send me a message to one of my social profiles at: https://justinverstijnen.nl/about/

Go back to Blog homepage

If you find this page and blog very useful and you want to leave a donation, you can use the button below to buy me a beer. Hosting and maintaining a website takes a lot of time and money. Thank you in advance and cheers :)

Buy me a beer

The terms and conditions apply to this post.

Clean files on a schedule with Powershell script

Sometimes in IT, we have software or solutions that need to to save temporary files in your filesystem. Let’s say, a feed with logs or…

Sometimes in IT, we have software or solutions that need to to save temporary files in your filesystem. Let’s say, a feed with logs or CSV files that are saved, logs or back-ups like the Bartender software. The software itself doesn’t have a solution to clean up those files and after 2 years, the size can be massive.

To let this files clean on schedule I have created a Powershell script which cleans those files in specific folders after they are not modified in *specfied* days . You can define the folders and number of days at the parameters section of the script.


The clean script

The Powershell script for cleaning up files is on my GitHub page:

Download PowerShell script

It starts with a parameter to define the amount of days you want to retain the files. It checks this at the last write time to the file.

After that, it defines the folders where it must check for files with no exclusion of file extensions. It removes all files and folders in the defined folders.


What does the script do?

The script is meant for cleaning specific files after X days. A great example of it in practice is if you have Bartender installed on a server. Bartender will every day save deleted database records to a file without it even bothering cleaning it up. After 2 years, such folder can be over 25GB’s. With this script, it only keeps 30 versions of the file. Assuming we have more retention on our backups, we don’t need any more than that.

The script works in this way:

  1. Ensuring it runs as Administrator
  2. Enable logging
    • Saves a log file in the same directory with 5MB limit by default (can be adjusted to your needs)
  3. Searching for the files to be cleaned, which are older than the specified days
  4. Deleting the files and logging them for reference

Script parameters for customization

At the beginning of the script, we can set some parameters for customization of the script. The rest of the script can be as-is to ensure it still runs.

I will refer to the line numbers of the script on GitHub:

  • Line 14: Specify the number of days to keep files (typing 30 will keep files for 30 days)
  • Line 15: Specify the paths. As this is an array, it must be comma-seperated except the last one. Keep this in mind. You can add as many folders as you want but be aware to not put in critical folders
  • Line 21: Specify the maximum size of the log file. It will remove lines at the start of the file so the latest information is always available

jv-media-262-29e335edfd63.png


Installing the clean script automatically

For installation with Task Scheduler I included an installation script that, by default, configures a task in the Windows Task Scheduler that runs it;

  • Every first day of the month
  • At hour 03:00

If these settings are great for you, you can leave them as-is.

The Installation script creates a folder in C:\ named “Scripts” if not already there and places the cleaning script there.

Installation

Click on the blue button above. You now are on the Github page of the script.

jv-media-262-bd5120723e6c.png

Click on “Code” and then “Download ZIP”.

Then place the files on the server where you want to install the script.

jv-media-262-2f7eeaef8810.png

Open Powershell ISE as administrator.

Now open the “Install” script.

jv-media-262-52f60dcc58a7.png

Review it’s default settings and if you feel at home in PowerShell, review the rest of the script to understand what it does.

jv-media-262-ba06ebf0a588.png

You can change the schedule very easily by changing the runtime: 0:00 till 23:59 and the day of month to specify the day number of the month (1-31).

After your schedule is ready, let’s ensure we temporarily bypass the Execution Policy by typing the command in the blue window below:

POWERSHELL
Set-ExecutionPolicy Unrestricted -Scope Process

This way the execution policy stays enabled but for this session only it’s been lowered. When you close the window, you have to type this again before be able to run scripts.

Execute the command, and when prompted to lower the policy, click Yes.

Now execute the Install script by clicking the green “Run” button:

jv-media-262-5d8c5132c234.png

After executing the script, we get the message that the task has been created succesfully:

jv-media-262-796cf0e8b1c6.png

Let’s check this in the Windows Task Scheduler:

jv-media-262-15f532958450.png

As you can see, the script is succesfully installed to Task Scheduler. This ensures it runs every first of the month at 03:00 (or at your own defined schedule). Also, the script has been placed in C:\Scripts for a good overview of the scripts of the system.


Using the script manually/demonstration

For demonstration of the clean script, I created a second, simple script that creates 100 dummy files in the C:\Temp directory. This with last write times between 15 and 365 days ago.

POWERSHELL
$targetFolder = "C:\Temp"
New-Item -ItemType Directory -Force -Path $targetFolder | Out-Null

1..100 | ForEach-Object {
    $fileName = "TestFile_$($_)_$(Get-Random -Minimum 1000 -Maximum 9999).txt"
    $filePath = Join-Path $targetFolder $fileName
    New-Item -ItemType File -Path $filePath -Force | Out-Null

    # Generate a random past date between 15 and 365 days ago
    $daysAgo = Get-Random -Minimum 15 -Maximum 365
    $randomDate = (Get-Date).AddDays(-$daysAgo)
    (Get-Item $filePath).LastWriteTime = $randomDate
    (Get-Item $filePath).CreationTime = $randomDate
}

After executing the script from my GitHub page, the files older than 30 days only must be removed while files between the 15 and 30 days must be retained.

Setting the PowerShell Execution Policy

Before we can run any of the scripts, we have to do a one-time bypass for the Powershell Execution Policy by typing the command in the blue window below:

POWERSHELL
Set-ExecutionPolicy Unrestricted -Scope Process

This way the execution policy stays enabled but for this session only it’s been lowered. When you close the window, you have to type this again before be able to run scripts.

Execute the command, and when prompted to lower the policy, click Yes.

Running the dummy files script

Now we can run the script itself by clicking the green “Play” button.

jv-media-262-76a0868abc22.png

Now we have a folder with 100 files with random last write times:

jv-media-262-45d854205010.png

If we would execute the cleanup script, only the files from 18-6-2025 and newer will be retained.

Review the parameters on line 12 to 20, change them to your needs and then execute the script. I have changed the Paths to C:\Temp only.

jv-media-262-254abcf4ca57.png

The script will now delete every file older than the specified days:

jv-media-262-6de48e1650e3.png

Let’s take a look at the folder:

jv-media-262-814012720169.png

All cleared now and only versions younger than 30 days are retained.

In the Script directory, a file is created, containing all the filenames it has removed:

jv-media-262-1fd571205bb5.png

jv-media-262-fd1602bd51a6.png


Summary

This Powershell script can help cleaning up files in specific folders. mostly i use this for maintenance on servers where software is installed without proper retention settings of their temporary files. This script helps keeping your disks clean and indirectly improves the availability of your infrastructure.

Thank you for reading this guide and I hope this was helpful.

Sources

These sources helped me by writing and research for this post;

  1. https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/get-childitem?view=powershell-7.5
  2. https://learn.microsoft.com/en-us/powershell/scripting/learn/ps101/09-functions?view=powershell-7.5

Β 

End of the page πŸŽ‰

You have reached the end of the page. You can navigate through other blog posts as well, share this post on X, LinkedIn and Reddit or return to the blog posts collection page. Thank you for visiting this post.

If you think something is wrong with this post or you want to know more, you can send me a message to one of my social profiles at: https://justinverstijnen.nl/about/

Go back to Blog homepage

If you find this page and blog very useful and you want to leave a donation, you can use the button below to buy me a beer. Hosting and maintaining a website takes a lot of time and money. Thank you in advance and cheers :)

Buy me a beer

The terms and conditions apply to this post.

How to completely hide language bar/selector Windows 11

One of the small things I experienced in one of the updates for Windows 11 (24H2) is that the language bar/selector get’s automatically…

One of the small things I experienced in one of the updates for Windows 11 (24H2) is that the language bar/selector get’s automatically visible on the Windows taskbar. In previous versions of Windows, this was only available when using multiple keyboard languages.

Because this can get very annoying, I researched on how to disable this button to clean up our taskbar and only use it for the applications and space we need.

jv-media-4730-9c5068dbeb67.png


Cause of appearance

In most cases, this button will appear automatically when more than 1 language is installed in Windows. However, after one of the updates for 24H2, it appeared for me on multiple PC’s. Especially the PC’s which were installed with the Dutch language.

When using the Dutch language, we also have to configure “United States International” as keyboard layout, or we get issues with some of the symbols.


How I removed the button

Initially, I started with browsing on the internet how to disable this button ans they all pointed to this registry key:

  • Computer\HKEY_CURRENT_USER\Software\Microsoft\CTF\LangBar

And set the value for “ShowStatus” to 3. However, this didn’t work for me, but you can try this by running this command in PowerShell:

POWERSHELL
Set-ItemProperty -Path "HKCU:\Software\Microsoft\CTF\LangBar" -Name "ShowStatus" -Value 3

The way I finally manage to disable the button is to run these commands.

First run this command. This disables the Input manager which loads the language switcher:

POWERSHELL
New-ItemProperty -Path "HKCU:\Software\Microsoft\CTF" -Name DisableThreadInputManager -PropertyType DWord -Value 1 -Force

Then run this command to disable the startup item for the Text Services Framework:

POWERSHELL
reg delete "HKCU\Software\Microsoft\Windows\CurrentVersion\Run" /v "ctfmon.exe" /f

Summary

Because I want to share how I solved the problem doesn’t mean you should actually do this. Running these commands can interrupt some of your systems’ functions or other components. So only run them if you are familiar with your computer and be able to be up and running within an hour in case this happens.

If you managed to run the commands, I hope I helped you to get rid of this annoying bar :).

Β 

End of the page πŸŽ‰

You have reached the end of the page. You can navigate through other blog posts as well, share this post on X, LinkedIn and Reddit or return to the blog posts collection page. Thank you for visiting this post.

If you think something is wrong with this post or you want to know more, you can send me a message to one of my social profiles at: https://justinverstijnen.nl/about/

Go back to Blog homepage

If you find this page and blog very useful and you want to leave a donation, you can use the button below to buy me a beer. Hosting and maintaining a website takes a lot of time and money. Thank you in advance and cheers :)

Buy me a beer

The terms and conditions apply to this post.

Initial Installation script for Windows Azure VMs

When deploying Windows VMs in Azure, we get the default settings. This means we get a 12-hour clock, standard UTC/Zulu timezone and such…

When deploying Windows VMs in Azure, we get the default settings. This means we get a 12-hour clock, standard UTC/Zulu timezone and such. For users like us in the Netherlands we want to change this but not by hand.

For this purpose I built this script. It sets the timezone for Western Europe and sets the clock to 24-hour system. It also does some bonusses like responding to ping and disabling the IE Enhanced Security as it’s mostly server focussed. We don’t change the Windows language and this stays English.


Where to download this script?

For the fast pass, my script can be downloaded here:

Download script from GitHub


What does the Initial server installation script do?

The script itself has 6 steps:

  1. Ensuring it runs as Administrator
  2. Enable logging
    • Saves a log file in the same directory and with 100KB limit
  3. Setting the timezone to Western Euopean time (Amsterdam time)
  4. Setting regional settings for 24 hours clock
  5. Disables IE Enhanced Security
  6. Enables response to ping for local networks
  7. Reboots the server

Using the initial server installation script

To use the script, we must first download it from the Github page:

jv-media-3616-cc79aadbe302.png

Click on “Code” and then “Download ZIP”.

Now place the script on the machine where it must run, If not already done so.

To run this in the most user-friendly way possible, open the PowerShell ISE as administrator:

jv-media-3616-d4b54450c379.png

Type in your credentials and advance.

Now open the script by using the “Open” function:

jv-media-3616-c9cbad0236b0.png

Before we can run, we must change the Powershell Execution policy temporarily. We can do this by typing the command in the blue window below:

POWERSHELL
Set-ExecutionPolicy Unrestricted -Scope Process

This way the execution policy stays enabled but for this session only it’s been lowered. When you close the window, you have to type this again before be able to run scripts.

Execute the command, and when prompted to lower the policy, click Yes.

Now we are ready to execute the script. Double check the parameters section (Line 13 to 18) of the script to ensure this complies with your desired settings.

jv-media-3616-eb61e387156a.png

Then run the script:

jv-media-3616-3a4f47e6e796.png

This shows that the script runs and sets every setting correctly. After running correctly, the server will instantly reboot to apply all settings:

jv-media-3616-97e8e90de29a.png


Summary

This is a great script to use for installing Windows Servers on initial. These are some settings we must do by hand normally but we can now to with a simple script. Also setting the correct timezone can sometimes be stupid as the timezone may roll back to the Azure default. This script ensures this doesn’t happen.

Thank you for reading the post and I hope the script is useful.

Sources

These sources helped me by writing and research for this post;

  1. https://learn.microsoft.com/en-us/windows/win32/intl/table-of-geographical-locations
  2. https://learn.microsoft.com/en-us/powershell/module/international/set-culture?view=windowsserver2025-ps
  3. https://learn.microsoft.com/en-us/powershell/module/international/set-culture?view=windowsserver2025-ps

Β 

End of the page πŸŽ‰

You have reached the end of the page. You can navigate through other blog posts as well, share this post on X, LinkedIn and Reddit or return to the blog posts collection page. Thank you for visiting this post.

If you think something is wrong with this post or you want to know more, you can send me a message to one of my social profiles at: https://justinverstijnen.nl/about/

Go back to Blog homepage

If you find this page and blog very useful and you want to leave a donation, you can use the button below to buy me a beer. Hosting and maintaining a website takes a lot of time and money. Thank you in advance and cheers :)

Buy me a beer

The terms and conditions apply to this post.

Disk cleaning script on Windows Azure VMs

On Windows Servers, a critical point is maintaining the disk space. If a disk fills up to the end, several errors can occur and impacting…

On Windows Servers, a critical point is maintaining the disk space. If a disk fills up to the end, several errors can occur and impacting the end-users experience of your applications. Something we definitely not want.

To help reducing this chance, I have created a PowerShell script that cleans up your server using built in tools of Windows. In this post, I will explain what the script does, how to install it and how to use it.


Where do download this script?

For the fast pass, my script can be downloaded here:

Download script from GitHub


What does the disk cleanup script do?

The script I have made focusses primarily on cleaning up some folders we don’t need for the server to work. This consists of:

  • Windows Update download cache of already installed updates
  • TEMP folders
  • Unused drivers
  • Unused Event logs
  • Google Chrome browsing cache
  • Microsoft Edge browsing cache
  • Recycle bins

The script itself has 6 steps:

  1. Ensuring it runs as Administrator
  2. Enable logging
    • Saves a log file in the same directory and with 100KB limit
  3. Running Windows Cleanmgr-tool
  4. Simulating the Cleanmgr tool for all other local drives
  5. Deleting unused device drivers
  6. Removing cache for Chrome and Edge
  7. Rebooting the server.

How to install the Disk cleaning script Automatically

For installation with Task Scheduler I included an installation script that, by default, configures a task in the Windows Task Scheduler that runs it;

  • Every first day of the month
  • At hour 03:00

If these settings are great for you, you can leave them as-is.

The Installation script creates a folder in C:\ named “Scripts” if not already there and places the cleaning script there.

Installation

Click on the blue button above. You now are on the Github page of the script.

jv-media-1276-124a84eaa9eb.png

Click on “Code” and then “Download ZIP”.

Now place the files on the server where you want to install the script.

jv-media-1276-ddcc9123190d.png

Unzip the file and then we can run the “Install” script. This must be run as administrator and temporarily without Execution Policy.

Open Powershell ISE as administrator.

jv-media-1276-abb9c2951099.png

Now open the “Install” script.

jv-media-1276-2af30938721b.png

Review it’s default settings and if you feel at home in PowerShell, review the rest of the script to understand what it does.

jv-media-1276-f3c0b123c54a.png

You can change the schedule very easily by changing the runtime: 0:00 till 23:59 and the day of month to specify the day number of the month (1-31).

After your schedule is ready, let’s ensure we temporarily bypass the Execution Policy by typing the command in the blue window below:

POWERSHELL
Set-ExecutionPolicy Unrestricted -Scope Process

This way the execution policy stays enabled but for this session only it’s been lowered. When you close the window, you have to type this again before be able to run scripts.

Execute the command, and when prompted to lower the policy, click Yes.

jv-media-1276-6339e6e403bb.png

Now execute the Install script by clicking the green “Run” button:

jv-media-1276-0c76057f8ec1.png

After executing the script, we get the message that the task has been created succesfully:

jv-media-1276-1f68c43db92c.png

Let’s check this in the Windows Task Scheduler:

jv-media-1276-c97dc8c16bfa.png

As you can see, the script is succesfully installed to Task Scheduler. This ensures it runs every first of the month at 03:00 (or at your own defined schedule). Also, the script has been places in C:\Scripts for a good overview of the scripts of the system.


How to install the Disk cleaning script manually

If you want to define your own schedule and script location, it can be better to install the script yourself or only using it when you need it.

Click on the blue Download button at the beginning of the page.

jv-media-1276-124a84eaa9eb.png

Click on “Code” and then “Download ZIP”.

Then place the ZIP file on the server where you want to install the disk cleanup script.

Move the script to the right location

Select the script and place it in your preferred location. My advice is to not install this in a user profile, but in a location accessible for all users. Like C:\Scripts.

jv-media-1276-f1add1017f51.png

I have placed the scipt into the correct folder. If you also want the script to run on a schedule, open up the “Task Scheduler” (taskschd.msc).

Creating the scheduled task

jv-media-1276-1df7d56f3806.png

Do a “Right-mouse click” on the empty space and click on “Create New Task…”.

jv-media-1276-348875edb112.png

Give the task a name and description that alings with your documentation.

Then change the user to “SYSTEM” to run this in SYSTEM context for the highest privileges:

jv-media-1276-c6c18f9fa7db.png

Then check the “Run with highest privileges” and select the highest OS possible in the “Configure for” dropdown menu.

Configure script trigger

Go to the “Triggers” tab and add a new trigger.

jv-media-1276-fafe7b477e51.png

Select “Monthly” and select all months. Then change the “Days” field to 1 to run it on the first day.

Now the page looks like this:

jv-media-1276-8e35e0f371e5.png

Configure script action

Click “OK” and go to the “Actions” tab. Create a new action.

In the “Program/Script” field, type in the following:

POWERSHELL
powershell.exe

In the “Add arguments (optional):” field, type in the following:

POWERSHELL
-ExecutionPolicy Bypass -File C:\Scripts\JV-ServerPeriodicDiskCleanup.ps1
jv-media-1276-e54f48edbd99.png

Now click on “OK” twice to create the task.

Testing the task

Now we can manually run the task to ensure it runs on a schedule too. Right click the task and click on “Run” to start the task.

jv-media-1276-33d36f0fd528.png

As we can see, the script runs succesfully as it still runs after 30 seconds. This means the task and permissions are correct.

jv-media-1276-0a1b4dc58c68.png

The script can take up to several hours when cleaning everything, depending on the server size.

In the folder of the script, a log file is created:

jv-media-1276-2acc74f58076.png


Summary

I think it’s a great way to use scripts like these once per month on your server. We can better be pro-actively cleaning up our servers than waiting till some issue occurs. However, my advice is to not run this script too often. Once or twice per month is good enough.

We IT guys’ work is to minimize disruptions and ensure end users don’t need to call us. If we IT guys are completely invisible and users think: “What are those guys even doing?”, then we do your jobs correctly.

Thank you for reading this post and I hope it was helpful.

Sources

These sources helped me by writing and research for this post;

  1. https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/cleanmgr

Β 

End of the page πŸŽ‰

You have reached the end of the page. You can navigate through other blog posts as well, share this post on X, LinkedIn and Reddit or return to the blog posts collection page. Thank you for visiting this post.

If you think something is wrong with this post or you want to know more, you can send me a message to one of my social profiles at: https://justinverstijnen.nl/about/

Go back to Blog homepage

If you find this page and blog very useful and you want to leave a donation, you can use the button below to buy me a beer. Hosting and maintaining a website takes a lot of time and money. Thank you in advance and cheers :)

Buy me a beer

The terms and conditions apply to this post.

Get Device serial number on Windows 11 24H2 and up

With Windows 24H2 and the deprecation of WMIC, a easy command to find your devices’ serial number is gone. However, we can still look this up with Powershell.

To get your device’s serial number, use the following command in Windows PowerShell:

POWERSHELL
Get-WmiObject win32_bios | select SerialNumber

Its as simple as that!

Β 

End of the page πŸŽ‰

You have reached the end of the page. You can navigate through other blog posts as well, share this post on X, LinkedIn and Reddit or return to the blog posts collection page. Thank you for visiting this post.

If you think something is wrong with this post or you want to know more, you can send me a message to one of my social profiles at: https://justinverstijnen.nl/about/

Go back to Blog homepage

If you find this page and blog very useful and you want to leave a donation, you can use the button below to buy me a beer. Hosting and maintaining a website takes a lot of time and money. Thank you in advance and cheers :)

Buy me a beer

The terms and conditions apply to this post.

How to upload PowerShell script to Gallery with Github Actions

When using the PowerShell Gallery to upload and publish your scripts and PowerShell modules to the world it’s recommended to use Github Actions for CI/CD to automatically update your live packages on the PowerShell Gallery. At first, this looked somewhat complex to me but it’s relatively easy.

On this page I will show how I’ve uploaded scripts from Github to the PowerShell Gallery with using a Github Action.


Requirements

  • Around 30 minutes of your time
  • Github account
  • Powershell Gallery account
  • A PowerShell script for testing to actually upload to the PowerShell Gallery

In short, the PowerShell Gallery is a public repository which contains PowerShell scripts and modules which all PowerShell users can download and install. All of this using some simple commands:

POWERSHELL
Install-Module ExchangeOnlineManagement

The official “ExchangeOnlineManagement” module is an example of a module dat is uploaded to the gallery which can be download. Before installing, the user needs administrative permissions, the Powershell execution policy applies and we have to accept downloading from the repository.

It has a report-system where malicious scripts and modules can get reported and the deleted, so we can state that it’s pretty secure to use the PowerShell Gallery.


Introduction to Github and Github Actions

Github is a industry-accepted repository hosting service. This allows you to create a repository for a custom solution which you have created, which can be complete applications, source code but in our case a Powershell script. The goal of Github is to publish your source code so others can use and learn from it. You can also create private repositories to share with only specific users.

Github Actions

Inside our Github repository, we have Github Actions which can automate processes for us. As we want to develop using Github, we want our new version automatically pushed to the PowerShell Gallery. Github Actions can do this for us.

The action automatically kicks in every time a file in your repository is changed:

jv-media-5232-13772df5cab2.png


Step 1: Create a repository

Assuming you have a PowerShell script which is ready to upload to the PowerShell Gallery, we must first create a Github repository. Head to Github to do this.

In the top-right corner, click on the “+” button and then on “New repository”.

jv-media-5232-e181fff55a9e.png

Give the repository a name and description, and determine the visibility. Then press “Create repository”.

For this solution to work, the repository can be either Public or Private. As we upload our script to a public reposity, we can also set this to “Public”. This gives users access to the “source code”.

jv-media-5232-b4f331ef3ae4.png

Now the repository is created, and we can upload our PowerShell script to it.

jv-media-5232-1204c515a46e.png

Select the script on your local machine, change the name and upload it to Github.


Because we upload our script to a public repository, we must define some metadata in our script. This includes an Author, tags, description and version number and such.

In Github, change your script and add this part to the top of the .ps1 file

POWERSHELL
<#PSScriptInfo

.VERSION 1.0.0
.GUID fb0384df-0dd8-4a57-b5e5-d3077c30a404
.AUTHOR Justin Verstijnen
.COMPANYNAME JustinVerstijnen
.COPYRIGHT (c) 2025 Justin Verstijnen. All rights reserved.
.TAGS PowerShell, Script, Example
.PROJECTURI https://github.com/JustinVerstijnen/JV-ServerInventoryReport
.RELEASENOTES First publish.
.DESCRIPTION A good description of your script
.LICENSEURI https://opensource.org/licenses/MIT

#>

Change the information, and generate a new GUID with your own Powershell window:

POWERSHELL
New-Guid

Powershell then generates a new GUID for you to use in your script:

jv-media-5232-7fa90749f381.png

My script looks like this now:

jv-media-5232-67090eb82341.png

When you are done pasting and changing the script information, we can save the changes by pressing “Commit changes” twice.

jv-media-5232-3de33c50c6d5.png

Press again to change the file, and we have prepared our script to be uploaded.


For Github to have access to our PowerShell Gallery account, we must create an API key. Head to the PowerShell Gallery.

jv-media-5232-90055b722c3e.png

Go to “API Keys”. Then click on “Create”.

jv-media-5232-9c2fb36dc59b.png

Now we have to fill in some information. In general, it is best-practice to create an API key for every project/repository.

jv-media-5232-a60cc1c10e7c.png

Click “Create” and that gives you the API key. You can only get the key now, so save it in a safe place like your Password manager.

jv-media-5232-de72bb3cf05e.png

We need this API key in the next step.


Step 4: Insert the API key

Now let’s head back to Github to insert our API key.

In your Github repository, go to “Settings”, then “Secrets and variables” and then create a new repository secret.

jv-media-5232-963f1994325e.png

In the “Name” field, paste this:

JSON
PSGALLERY_API_KEY

In the “Secret” field, paste your just saved API key:

jv-media-5232-abf1922b9542.png

Click on “Add secret” to add the secret to your repository.


Step 5: Create your Github Action

Now we have the API key inserted, head back to the repository on Github and let’s create the Github Action that pushes our script automatically to the PowerShell Gallery.

An action is completely based on a single .yml (YAML) file which executes everytime the repository is changed. We will create this file now.

Click on “Add file” and then the option “Create new file”:

jv-media-5232-c3a3ab110b34.png

In the top-left corner, type or paste in:

JSON
.github/workflows/publish.yml

Then paste in this code below, which is a completely prepared action for exactly this use-case:

YAML
name: Publish PowerShell Script to PowerShell Gallery

on:
  push:
    branches:
      - main
    paths:
      - '**/*.ps1'
      - '.github/workflows/publish.yml'

jobs:
  publish:
    runs-on: windows-latest

    env:
      # Variables (change this to your script)
      SCRIPT_NAME: JV-ServersInitialInstall
      SCRIPT_PATH: ./JV-ServersInitialInstall.ps1
      DISPLAY_NAME: JV-ServersInitialInstall
      PSGALLERY_SECRET: ${{ secrets.PSGALLERY_API_KEY }}

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Ensure NuGet and PowerShellGet are available
        shell: pwsh
        run: |
          Set-PSRepository -Name "PSGallery" -InstallationPolicy Trusted
          [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

          if (-not (Get-PackageProvider -Name NuGet -ErrorAction SilentlyContinue)) {
              Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
          }

          Install-Module PackageManagement -Force -AllowClobber -Scope CurrentUser
          Install-Module PowerShellGet -Force -AllowClobber -Scope CurrentUser

      - name: Validate script metadata
        shell: pwsh
        run: |
          Test-ScriptFileInfo -Path "$env:SCRIPT_PATH"

      - name: Publish script to PowerShell Gallery
        shell: pwsh
        run: |
          $ErrorActionPreference = 'Stop'
          Publish-Script -Path "$env:SCRIPT_PATH" -NuGetApiKey "$env:PSGALLERY_SECRET" -Verbose

      - name: Confirm publication
        shell: pwsh
        run: |
          Write-Host "Successfully published $env:DISPLAY_NAME to PowerShell Gallery."

Change the information on lines 17, 18 and 19 to your own information and then save the file by clicking “Commit changes” in the top right corner. Make sure the script name and path exactly match your file name on the repository and do not change anything else.

jv-media-5232-993c6b0d602a.png

For about a minute, this will show on the homepage of your repository:

jv-media-5232-1e134a2a4c42.png

This means the Action is now actually processing the changes and publishing our new script. It will directly upload the script to the PowerShell Gallery for us.


Step 6: Checking the results

Now the the action has ran, and did not give any error. It must now be available on the PowerShell Gallery.

jv-media-5232-3d112869f69d.png

Lets head back to the PowerShell Gallery to check the status. Click on your profile, and then on “Manage Packages”.

Here we see that the packages has been uploaded:

jv-media-5232-b6f42a4641b7.png

If you click on it you get actual instructions to install the script on your computer and we will see the information we have added to the script:

jv-media-5232-359c6885b8d6.png

Pretty cool in my opinion.


Step 7: Installing and testing the script

Now we have our script on the PowerShell Gallery, we can actually download and execute the script using some simple commands.

Open PowerShell on your testing environment and execute this command with your script name to install your newly uploaded script.

POWERSHELL
Install-Script -Name JV-ServersInitialInstall

After executing this command you need to need to answer some questions:

jv-media-5232-b6f2e8d2e105.png

In order to actually run the script, you need to answer all with Yes/All.

After the script is installed, we can run it with your script name:

POWERSHELL
JV-ServersInitialInstall
jv-media-5232-928af176f859.png

The script will run directly which is very nice and useful for mass use.


Conclusion

This setup for uploading scripts to the PowerShell Gallery is really great. We can change our script on one place and it will automatically upload to the live gallery for users to download.

Sources

These sources helped me by writing and research for this post;

  1. https://learn.microsoft.com/en-us/powershell/gallery/getting-started?view=powershellget-3.x
  2. https://docs.github.com/en/actions/get-started/understand-github-actions

Thank you for reading this guide and I hope it was helpful.

Β 

End of the page πŸŽ‰

You have reached the end of the page. You can navigate through other blog posts as well, share this post on X, LinkedIn and Reddit or return to the blog posts collection page. Thank you for visiting this post.

If you think something is wrong with this post or you want to know more, you can send me a message to one of my social profiles at: https://justinverstijnen.nl/about/

Go back to Blog homepage

If you find this page and blog very useful and you want to leave a donation, you can use the button below to buy me a beer. Hosting and maintaining a website takes a lot of time and money. Thank you in advance and cheers :)

Buy me a beer

The terms and conditions apply to this post.

Create AD users with on demand script

Today I have a PowerShell script that creates users by asking the user what to fill in. This works by having a fully prepared “New-ADUser” command with all the properties filled in to have all users using the same attributes.

Today I have a PowerShell script that creates users by asking the user what to fill in. This works by having a fully prepared “New-ADUser” command with all the properties filled in to have all users using the same attributes.

I will explain how this script works on this page.


The create AD users on demand script

For the fast pass, the script can be downloaded from my GitHub page:

Download script from GitHub


The script described

The script is relatively easy and consists of 4 steps:

  1. Importing the modules needed
  2. Asking the user about on what details the user must be created
  3. Making everything ready, creates the user and adds him to the defined security groups
  4. Prints everything in the command window for a summary

Parameters and Attributes

The script contains a set of pre-defined attributes which you can change to your own settings:

jv-media-3685-708348197460.png

You can change all of these settings, but I advice you to not change any $variables because that will break the script.

On line 12 to 14, you have a parameter that specifies the OU to create the user in:

jv-media-3685-b6fda0ca6fba.png

Change this to your own OU when using. You can find this by enabling the “Advanced Features” in the “View” menu and then going to the OU properties and the “Attributes”.

jv-media-3685-8e0911209cc4.png

Search for the “DistinguishedName” attribute and copy that value.


Using the create AD users on demand script

To use my create ad users script, go to my GitHub page and download the script there:

jv-media-3685-b8ebf60bbf7d.png

Click on “Code” and then on “Download ZIP”.

Then place the ZIP file on your Active Directory management server.

Open PowerShell ISE as Administrator:

jv-media-3685-db8174903971.png

Verify your credentials if needed and then use the “Open” function of PowerShell ISE and open the script file:

jv-media-3685-ad901a5a5b5a.png

Review:

  1. The parameters and set the correct OU (line 12 to 14)
  2. The attributes for the user (line 41 to 57)

Correct those if needed.

Before we can run the script, we have to do a one-time bypass for the Powershell Execution Policy by typing the command in the blue window below:

POWERSHELL
Set-ExecutionPolicy Unrestricted -Scope Process

This way the execution policy stays enabled but for this session only it’s been lowered. When you close the window, you have to type this again before be able to run scripts.

Execute the command, and when prompted to lower the policy, click Yes.

Now we can run the script itself by clicking the green “Play” button.

jv-media-3685-8ccaaddd148b.png

Now the script will ask the details for the user:

jv-media-3685-16d98a8d268c.png

After filling this in and hit Enter, the user will be created almost instantly:

jv-media-3685-ab212d3eb337.png

Now let’s take a look in the Active Directory Users and Computers snap-in (dsa.msc):

jv-media-3685-af4be77dd486.png

The user is succesfully created in the desired OU and Group1 has been added to the member of list. Also the extra attributes has been added to the user:

jv-media-3685-ad4376d5a168.png

jv-media-3685-acb968679fbf.png

jv-media-3685-6759df29e1fc.png


Summary

This script can ultimately be used when all users must be created in the same way. Let’s say, the emailaddress field must always be filled in, or the address or department. Those are steps that often will be skipped in real life. Using a pre-determined script will ensure this is always filled in.

Thank you for reading this post and I hope it is helpful.

Sources

These sources helped me by writing and research for this post;

  1. https://learn.microsoft.com/en-us/powershell/module/activedirectory/new-aduser?view=windowsserver2025-ps

Β 

End of the page πŸŽ‰

You have reached the end of the page. You can navigate through other blog posts as well, share this post on X, LinkedIn and Reddit or return to the blog posts collection page. Thank you for visiting this post.

If you think something is wrong with this post or you want to know more, you can send me a message to one of my social profiles at: https://justinverstijnen.nl/about/

Go back to Blog homepage

If you find this page and blog very useful and you want to leave a donation, you can use the button below to buy me a beer. Hosting and maintaining a website takes a lot of time and money. Thank you in advance and cheers :)

Buy me a beer

The terms and conditions apply to this post.

How to Export Active Directory (AD) users fast and easy

Sometimes we need to export all of our AD users. The one time for applying changes, sometimes for monitoring the inventory but often for licensing purposes.

At this page I will show you how to export all your AD users fast and easy.


The Export AD users script:

For the fast pass, I uploaded the script to my Github page:

Download script from GitHub


How to export the AD users by hand

To export the users without using a script, navigate to your Active Directory management server and open up Powershell. We will do all the action the script above does, but then by hand and type in every command separately.

Type in the first command to ensure the correct module is loaded:

POWERSHELL
Import-Module ActiveDirectory

Then we can execute the command to query all AD users:

POWERSHELL
$adusers = Get-ADUser -filter * -Properties UserPrincipalName,Mobile,Givenname,sn,name | select UserPrincipalName,Mobile,Givenname,sn,name

This saves all the users in the $adusers variable. Now let’s print this list:

POWERSHELL
$adusers

This shows all users in the PowerShell window itself, but we are able to export this to a CSV file:

POWERSHELL
$adusers | Export-Csv "C:\Users\$env:USERNAME\Desktop\AD_Export.csv" -NTI -Delimiter ";"

This gives us a nice and “Excel-ready” export of all the AD users. It is also very clean, but you can add or remove extra attributes from Active Directory from the second command.

For a complete list of all the attributes that can be used, visit this Microsoft Learn article.


Summary

This page shows an easy way to export all your AD users in a great and readable way. It also has some possibilities for customization but it shows how to do it in the most simple way possible. I also included a automatic way and a manual/by hand way to learnexactly what happens.

Thank you for reading and I hope it was helpful.

Sources

These sources helped me by writing and research for this post;

  1. https://learn.microsoft.com/en-us/powershell/module/activedirectory/get-aduser?view=windowsserver2025-ps#filter
  2. https://learn.microsoft.com/en-us/powershell/scripting/learn/ps101/03-discovering-objects?view=powershell-7.5#active-directory

Β 

End of the page πŸŽ‰

You have reached the end of the page. You can navigate through other blog posts as well, share this post on X, LinkedIn and Reddit or return to the blog posts collection page. Thank you for visiting this post.

If you think something is wrong with this post or you want to know more, you can send me a message to one of my social profiles at: https://justinverstijnen.nl/about/

Go back to Blog homepage

If you find this page and blog very useful and you want to leave a donation, you can use the button below to buy me a beer. Hosting and maintaining a website takes a lot of time and money. Thank you in advance and cheers :)

Buy me a beer

The terms and conditions apply to this post.

Set correct language and timezone on Azure VM

By default, all Azure VMs are set to English language and UTC/Zulu timezone. This will work for a great portion of the Azure VM users but…

By default, all Azure VMs are set to English language and UTC/Zulu timezone. This will work for a great portion of the Azure VM users but there are users in other parts of the world too. Like in the Netherlands, where I live we are 1 or 2 hours ahead of that timezone depending on the season.

Also, in the case of Azure Virtual Desktop, we want to present our users their native language as system language. For this case, I have made a script to correct those settings.


The script to set the language and timezone on Azure VM

For the fast pass, I have the script here:

Download script from GitHub


The script steps described

The script consists of 7 steps:

  1. Ensuring the script runs as Administrator
  2. Querying current language (as it must remove it later on)
  3. Installing the new language pack
  4. Change the system language and regional settings
  5. Sets new timezone
  6. Sets new language for all current and new users
  7. Removing old language and reboots VM

Using the script

To use my script, download it from Github and place it on your newly created or existing Azure VM.

Click on “Code” and then on “Download ZIP”.

jv-media-3665-20af79b03317.png

Place the ZIP file on your server. Then unzip it so we can navigate to the script itself.

jv-media-3665-890f08d74217.png

Now we can execute this script. The easiest way is to open the PowerShell ISE version as this eliminates navigating to the script by hand.

Open PowerShell ISE as Administrator:

jv-media-3665-db8174903971.png

Verify your credentials if needed and then use the “Open” function of PowerShell ISE and open the script file:

jv-media-3665-67cad5d6694a.png

The script will now be opened and review the parameters on line 12 till 16:

jv-media-3665-4ff50ecb0af7.png

By default, everything is set to “Dutch” but you can change them. I added links to the corresponding artices of Microsoft to quickly lookup what your settings must be. The links are also added to the sources at the bottom of this post.

Before we can run the script, we have to do a one-time bypass for the Powershell Execution Policy by typing the command in the blue window below:

POWERSHELL
Set-ExecutionPolicy Unrestricted -Scope Process

This way the execution policy stays enabled but for this session only it’s been lowered. When you close the window, you have to type this again before be able to run scripts.

Execute the command, and when prompted to lower the policy, click Yes.

jv-media-3665-607bf989f877.png

Now we can run the script itself by clicking the green “Play” button.

jv-media-3665-2ef7c09ce1b4.png

The script can take up to 20 minutes, so have a little patience.

jv-media-3665-ea52d8de8602.png

After every task is completed the server will reboot and you will be presented with the new settings.


Before and after the script

Before the script ran, my machine looked like this:

jv-media-3665-2cb911e8db5a.png

After the script ran, my machine looked like this:

jv-media-3665-be29af29e078.png

Perfectly in Dutch settings and ready to go.


Setting 24 hour-clock

Because of usability of my script, I did not include the use of the 24 hour clock because Windows does this because of the culture settings. If wanting to set this manually, you can execute these commands in PowerShell manually:

POWERSHELL
$24hclock = Get-UICulture

($24hclock.DateTimeFormat).ShortTimePattern = 'HH:mm'

Set-Culture $24hclock

This sets the time indication to 24-hour clock system.


Summary

In the beginning of creating Azure VMs this was something I found to be annoying. This was exactly the reason I wrote the script. This is especially useful when deploying Azure Virtual Desktop machines, as you want to present the users with their native language. We IT guys often like the systems in English so for us, it’s no problem.

I hope the script is useful and thank you for reading.

Sources

These sources helped me by writing and research for this post;

  1. https://learn.microsoft.com/en-us/linkedin/shared/references/reference-tables/language-codes
  2. https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/default-time-zones?view=windows-11#time-zones
  3. https://learn.microsoft.com/en-us/windows/win32/intl/table-of-geographical-locations
  4. https://learn.microsoft.com/en-us/powershell/module/languagepackmanagement/set-systempreferreduilanguage?view=windowsserver2025-ps

Β 

End of the page πŸŽ‰

You have reached the end of the page. You can navigate through other blog posts as well, share this post on X, LinkedIn and Reddit or return to the blog posts collection page. Thank you for visiting this post.

If you think something is wrong with this post or you want to know more, you can send me a message to one of my social profiles at: https://justinverstijnen.nl/about/

Go back to Blog homepage

If you find this page and blog very useful and you want to leave a donation, you can use the button below to buy me a beer. Hosting and maintaining a website takes a lot of time and money. Thank you in advance and cheers :)

Buy me a beer

The terms and conditions apply to this post.

Get Windows Product Key with PowerShell

Sometimes we need to have the original installed Windows Product Key just for documentation purposes. This post explains how to retrieve your activation key from the registry.

We simply can do this with one command in PowerShell:

POWERSHELL
(Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SoftwareProtectionPlatform").BackupProductKeyDefault
jv-media-3681-3a0bbc0e5409.png

Please note that I am not encouraging software abuse or pirating, just sharing a tip to make our IT life a bit easier. It happens that a server or computer gets installed and we forget to document the product key or just to match it with our known information.

Β 

End of the page πŸŽ‰

You have reached the end of the page. You can navigate through other blog posts as well, share this post on X, LinkedIn and Reddit or return to the blog posts collection page. Thank you for visiting this post.

If you think something is wrong with this post or you want to know more, you can send me a message to one of my social profiles at: https://justinverstijnen.nl/about/

Go back to Blog homepage

If you find this page and blog very useful and you want to leave a donation, you can use the button below to buy me a beer. Hosting and maintaining a website takes a lot of time and money. Thank you in advance and cheers :)

Buy me a beer

The terms and conditions apply to this post.

Using PowerShell remote sessions

In this guide I will explain how to use PowerShell remote sessions, what they are and how to configure your systems to use this. PowerShell Remote Sessions can be a great way to administer your virtual machines, cluster-nodes or physical Windows-based devices. With a Powershell remote session you can execute powershell commands on a remote device. It works the best with servers in a specific management subnet. I do not recommend to administer client devices with Powershell because this can be a huge security risk.

Requirements

  • Management computer/Priveleged Access Workstation
  • 15-20 minutes of your time
  • Management server and endpoints are Active Directory joined

Starting out

Before we can use Powershell to administer remote computers, we need to enable two things:

  • 1. WinRM service (Endpoint): This is a service in Windows that enables remote management. Powershell Remote relies greatly on this service so we have to enable this on the endpoint. By default it is disabled due to its security reasons.
  • 2. Trusted Hosts (Management server): This has to be configured on your management server. This is a whitelist to protect against security threats who can abuse this option. Here you configure to what machines (name/IP-address) you can connect to.

1. Configure Windows Remote Management (WinRM)

On the endpoint you have to enable WinRM. This can be done manually with one simple command, or at scale with Group Policy.

Simple and one command:

POWERSHELL
winrm quickconfig

At scale with Group Policy:

Create a new or use an existing Group Policy object and go to:

Computer Configuration > Policies > Administrative Templates > Windows Components > Windows Remote Management (WinRM) > WinRM Service.

Pick the option: “Allow remote server management through WinRM”

jv-media-527-9a922997a7e6.png

Here we can define from what IP-addresses we can use WinRM for a more secure use of WinRM.

After this option we have to allow WinRM access in the Windows Firewall to work. This also has to be done on the endpoint.

In the GPO, go to:

Computer Configuration -> Policies -> Windows Settings -> Windows Defender Firewall with Advanced Security

Create a new Inbound rule based on a Predefined rule:

jv-media-527-2d7249a5ee50.png

Click next till the wizard is done.

Now we have a GPO to enable WinRM on all endpoints. Apply this to the OU with the endpoints and wait for the GPO to apply. In the meantime we can configure TrustedHosts on our management workstation.


2. Configure TrustedHosts

To configure your trustedhosts you can use a simple command on your management server:

POWERSHELL
Set-Item WSMan:\localhost\Client\TrustedHosts #IP-address#

You can use IP-addresses, DNS-names, FQDNs and wildcards. To add a whole subnet (like 10.20.0.0/24) to your trustedhosts list, use the following command:

POWERSHELL
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "10.20.0.*"

Another really unsafe option is to add everything to your TrustedHosts list (not recommended):

POWERSHELL
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "*"

One small note: we use the command Set-Item. This will set the complete TrustedHosts setting to the setting in your command and will overwrite all existing entries. We can also use the following command to add an entry with keeping the current configuration:

POWERSHELL
Add-Item WSMan:\localhost\Client\TrustedHosts -Value "10.20.0.*"

If you have set this up like one of the methods above, we are all set and done.


3. Setting up an PowerShell Remote session

To start using a PowerShell remote session after you have done all the prerequisites, use the command below:

POWERSHELL
Enter-PSSession -ComputerName 10.20.0.1

You get a prompt to logon with your credentials. The account has to be member of the local Administrators group.

Now we are logged in and we can execute commands like being locally on the server.

POWERSHELL
[JV-TEST-SERVER]: PS C:\Users\justinverstijnen\Documents>

4. Managing multiple endpoints remotely

To automate some tasks, we can execute commands on our management server on multiple remote endpoints. Think about a group policy update, starting a service or a script that has to be executed directly without restarting the servers to make it work.

We can do this with the Invoke-Command command. In the brackets we can paste our script or command to execute on the endpoints.

POWERSHELL
Invoke-Command -Computername Server1,Server2,Server3,Server4,Server5 -Scriptblock {gpupdate /force}

5. Multiple sessions and session persistence

With Powershell remoting we can also save sessions in a parameter. We mostly use this to execute a script on multiple servers. This can also be done to use it with the Invoke-Command above This works like:

POWERSHELL
$sessions = New-PSSession -ComputerName Server01, Server02, Server03

Invoke-Command -Session $sessions -ScriptBlock { gpupdate /force }

The way this works is that you save the connections in a variable and you use this as a whole to execute your commands. Makes it simple for executing commands at scale.


Summary

PowerShell remote is a very handy tool to remote connect to a endpoint/server. In practice we want to use simple and GUI-based tools but we have to dig into console commands at some point. For example, if you accidentally stop the Remote Desktop service or during a system outage.

Β 

End of the page πŸŽ‰

You have reached the end of the page. You can navigate through other blog posts as well, share this post on X, LinkedIn and Reddit or return to the blog posts collection page. Thank you for visiting this post.

If you think something is wrong with this post or you want to know more, you can send me a message to one of my social profiles at: https://justinverstijnen.nl/about/

Go back to Blog homepage

If you find this page and blog very useful and you want to leave a donation, you can use the button below to buy me a beer. Hosting and maintaining a website takes a lot of time and money. Thank you in advance and cheers :)

Buy me a beer

The terms and conditions apply to this post.

How to enable Remote Group Policy update

This guide explains how to perform Remote Group Policy updates and how to do the initial configuration needed.

Group Policy update to multiple computers

Sometimes you want to force a group policy update on multiple computers. Often when i am configuring Azure Virtual Desktop Session Hosts i need this option instead of logging into all hosts and executing the command manually.

There is a option in Group Policy management to force a group policy update to all computers in a OU:

jv-media-534-b7954db3f633.png

Actually, this only works after you configured this on the remote computers. The good part is, there is a way to do this with Group Policy!


Errors explained

When you do not configure remote group policy update, you get errors like:

  • 0x8007071a
  • The remote procedure call was cancelled

These state that access to the remote computer cannot be established, which is actually because of security reasons.


Enable remote Group Policy update

To enable remote Group Policy update with a GPO, create a new GPO or use an existing one:

Go to the settings for the Windows Firewall:

Computer Configuration -> Policies -> Windows Settings -> Security Settings -> Windows Defender Firewall with Advanced Security

Create 2 new inbound rules based on a predefined sets:

  • Remote Scheduled Tasks Management
  • Windows Management Instrumentation

Select all rules of both of the predefined rulesets.

After this link the GPO to the right OU and do a last manual GPupdate or wait for the scheduled GPupdate to finish.


Performing remote Group Policy updates

You can use the Group Policy update option in Group Policy Management (gpmc.msc) to perform a group policy update on all computers in a OU.

jv-media-534-fec510b3d91d.png

After that you will get succeeded notifications:

jv-media-534-27861d74e1b9.png


Summary

Remote Group Policy update is an excellent way to manage traditional Active Directory computers and updating them remotely instead of physically walk to the computers to perform the update yourself. Even on Microsoft Azure servers, it is a very handy tool because updating policies can be done through your central management server.

Thank you for reading this guide!

Β 

End of the page πŸŽ‰

You have reached the end of the page. You can navigate through other blog posts as well, share this post on X, LinkedIn and Reddit or return to the blog posts collection page. Thank you for visiting this post.

If you think something is wrong with this post or you want to know more, you can send me a message to one of my social profiles at: https://justinverstijnen.nl/about/

Go back to Blog homepage

If you find this page and blog very useful and you want to leave a donation, you can use the button below to buy me a beer. Hosting and maintaining a website takes a lot of time and money. Thank you in advance and cheers :)

Buy me a beer

The terms and conditions apply to this post.

Bulk create Active Directory users with Powershell

This page will share a PowerShell script to create bulk AD users with Powershell including instructions to use it.

When it comes to creating users for Active Directory, especially in new implementations, you want to minimize the time needed to create the accounts. This is possible by creating the AD users with Powershell.


Requirements

  • Minimal knowledge of Powershell
  • An Active Directory environment

Full script for creating AD users

Here is the full script including CSV that creates the ad users:

Download script from GitHub


Step 1: Prepare CSV

Fill in the CSV file with all required information.

The script I am using and sharing at this page has the following headings:

CSV
firstname,lastname,username,password

This is a very simple and effective manner where the script will base additional information like the emailaddress and proxyaddress attributes on the username.

Step 2: Change parameters

The script has the domain justinverstijnen.nl everywhere in it. This has to be changed at the following lines to your own preference:

  • UserPrincipalName
  • Path (Distinguished Name of OU)
  • EmailAddress
  • OtherAttributes

Step 3: Run PowerShell script to create AD users

Download the script file and copy the script and csv file to the same folder on the destination server. After that run the script and it will create the users.

POWERSHELL
Set-ExecutionPolicy RemoteSigned -Scope Process

This will allow all scripts to be runned in the Powershell window till it is closed. After closing the window, running scripts will be blocked again till running this command again.

After running this command you can navigate to the folder where the CSV file and PS1 file are located and run the script by using:

POWERSHELL
.\bulk_user.ps1

Β 

End of the page πŸŽ‰

You have reached the end of the page. You can navigate through other blog posts as well, share this post on X, LinkedIn and Reddit or return to the blog posts collection page. Thank you for visiting this post.

If you think something is wrong with this post or you want to know more, you can send me a message to one of my social profiles at: https://justinverstijnen.nl/about/

Go back to Blog homepage

If you find this page and blog very useful and you want to leave a donation, you can use the button below to buy me a beer. Hosting and maintaining a website takes a lot of time and money. Thank you in advance and cheers :)

Buy me a beer

The terms and conditions apply to this post.