Our Blog

PowerShell Modules I worked on in 2019

  • Standard
  • 0
  • Przemyslaw Klys

It's year 2020 and 365 days passed since my last year blog post about PowerShell modules I worked on in 2018. I thought it would be a good occasion to review what happened and how things changed during that time. When I wrote the last blog post in the first days of 2019, my PowerShell modules were downloaded just a bit over 15000 times. Fast Forward today, and the counter is at 280000 times spread over 40 modules. Of course, not all those modules are equal. In 2019 I created multiple new PowerShell modules, but some modules were archived, while others were migrated back to their „parents”. Just to see how my community road was going in the last years I decided to check some statistics.

Created 21 PowerShell Modules in 2018

Created 20 PowerShell Modules in 2019

While that doesn't tell you much, I've decided that I need some statistics for my own needs. Below you can find a table that shows all modules from PowerShellGallery and their respective GitHub projects. By the way that table below is automatically generated with PSWriteHTML – and I spent less than 5 minutes preparing it.

Name Type GitHub Stars GitHub Forks GitHub Open Issues GitHub Archived GitHub Created GitHub Updated Download CountTotal Download CountLast Releases Total Releases CurrentYear (2020) Releases LastYear (2019) Releases PreviousYear (2018) Last Updated PS Gallery Url Description
ADEssentials Module 9 3 0 False 22.07.2019 14:00:29 30.12.2019 22:53:37 3977 0 26 1 25 0 04.01.2020 12:46:35 +01:00 https://www.powershellgallery.com/packages/ADEssentials Helper module for Active Directory
Connectimo Module 6 1 0 False 13.06.2019 23:00:35 28.11.2019 14:27:54 31796 4338 3 0 3 0 28.11.2019 13:26:41 +01:00 https://www.powershellgallery.com/packages/Connectimo Simple connectivity project
Dashimo Module 81 8 0 True 17.03.2019 17:08:43 27.12.2019 18:30:35 4276 908 18 0 18 0 28.09.2019 20:58:32 +02:00 https://www.powershellgallery.com/packages/Dashimo Simple module to help building HTML Dashboard. This module has now been integrated into PSWriteHTML and it's not nessecary to download it separtly anymore.
Documentimo Module 10 2 0 False 25.03.2019 19:37:21 20.11.2019 13:39:01 674 71 7 0 7 0 17.11.2019 08:34:22 +01:00 https://www.powershellgallery.com/packages/Documentimo Simple project generating documentation to Microsoft Word.
Emailimo Module 47 6 0 True 12.04.2019 09:25:53 11.11.2019 22:05:51 3034 339 10 0 10 0 11.11.2019 21:03:23 +01:00 https://www.powershellgallery.com/packages/Emailimo Easy way to send emails in PowerShell
Excelimo Module 6 2 0 False 25.03.2019 19:37:36 17.11.2019 14:52:31 301 34 3 0 3 0 17.11.2019 13:53:30 +01:00 https://www.powershellgallery.com/packages/Excelimo Simple project generating Excel Workbooks/Worksheets
Graphimo Module 1 0 0 False 27.12.2019 08:28:37 27.12.2019 14:54:13 4 4 1 0 1 0 27.12.2019 07:33:25 +01:00 https://www.powershellgallery.com/packages/Graphimo Module that helps managing some tasks on Office 365/Azure with Microsoft Graph
LittleInfrastructureManager Module 4 2 0 False 05.08.2018 21:24:56 19.08.2019 13:07:58 108 104 2 0 0 2 05.08.2018 19:41:25 +02:00 https://www.powershellgallery.com/packages/LittleInfrastructureManager Simple project
PesterInfrastructureTests Module 36 6 1 True 25.07.2018 13:32:51 15.10.2019 12:25:59 1280 815 3 0 1 2 05.09.2019 05:23:43 +02:00 https://www.powershellgallery.com/packages/PesterInfrastructureTests Small module that helps with quickly testing Active Directory infrastructure for potential issues.
PSAutomator Module 40 7 6 False 14.10.2018 21:13:29 13.09.2019 03:38:05 213 199 3 0 0 3 25.10.2018 17:19:31 +02:00 https://www.powershellgallery.com/packages/PSAutomator PowerShell Module is new approach to onboarding, offboarding and business as usual processes running in companies infrastructure. Usually each company has different rules, different approaches on how processes should look like and this module takes an easy approach that's similar to what you can find in services like IFTTT or Microsoft Flow
PSBlackListChecker Module 38 6 0 False 27.04.2018 11:04:52 17.12.2019 12:32:01 9612 5027 13 0 7 6 01.11.2019 07:43:43 +01:00 https://www.powershellgallery.com/packages/PSBlackListChecker This module allows you to easily check if your defined list of IPs are on any of defined blacklists.
It additionally allows you to easily setup Task Scheduled monitoring and send you reports daily / hourly or weekly if needed.
In new version you now have ability to send notificatins to Microsoft Teams, Slack and Discord.
PSDiscord Module 8 3 0 False 30.12.2018 17:32:02 19.12.2019 17:49:38 9835 9474 7 0 6 1 12.04.2019 20:40:26 +02:00 https://www.powershellgallery.com/packages/PSDiscord Simple module to send messages to Discord
PSEventViewer Module 33 8 3 False 20.04.2018 15:40:36 02.01.2020 13:27:22 10917 58 34 1 15 18 01.01.2020 14:46:13 +01:00 https://www.powershellgallery.com/packages/PSEventViewer Simple module allowing parsing of event logs. Has its own quirks...
PSFreshService Module 1 1 0 False 15.10.2018 10:39:13 30.06.2019 11:56:41 104 104 1 0 0 1 15.10.2018 09:16:48 +02:00 https://www.powershellgallery.com/packages/PSFreshService Simple project
PSLansweeper Module 14 1 0 False 13.07.2019 18:48:53 12.12.2019 07:16:45 192 184 3 0 3 0 14.07.2019 10:37:49 +02:00 https://www.powershellgallery.com/packages/PSLansweeper Module that queries Lansweeper for data.
PSManageService Module 1 3 0 True 31.05.2018 18:14:28 15.10.2019 12:26:34 266 232 5 0 0 5 20.06.2018 20:35:26 +02:00 https://www.powershellgallery.com/packages/PSManageService Simple project
PSMyPassword Module 1 4 0 False 24.10.2018 08:38:38 12.08.2019 18:27:11 151 121 3 0 2 1 20.01.2019 12:02:28 +01:00 https://www.powershellgallery.com/packages/PSMyPassword Module helping out with some password security
PSParseHTML Module 11 6 0 False 10.08.2019 21:45:07 09.12.2019 22:43:54 392 181 12 0 12 0 08.12.2019 15:09:10 +01:00 https://www.powershellgallery.com/packages/PSParseHTML Module that allows to manipulate, parse, format and optimize HTML, JavaScript and CSS
PSPasswordExpiryNotifications Module 22 9 2 False 06.05.2018 21:29:00 20.12.2019 21:02:52 530 38 9 0 6 3 02.12.2019 19:17:15 +01:00 https://www.powershellgallery.com/packages/PSPasswordExpiryNotifications This module allows creation of password expiry emails for users, managers and administrators according to defined template.
PSPublishModule Module 1 3 0 False 08.06.2018 21:03:11 17.11.2019 14:57:01 213 17 20 0 17 3 17.11.2019 13:57:30 +01:00 https://www.powershellgallery.com/packages/PSPublishModule Simple project allowing preparing, managing and publishing modules to PowerShellGallery
PSPulsewayManager Module 4 2 0 False 08.06.2018 11:27:43 13.09.2019 03:25:15 152 117 6 0 0 6 20.06.2018 20:36:11 +02:00 https://www.powershellgallery.com/packages/PSPulsewayManager This powershell module allows easy management and configuration of Pulseway Manager.
PSSharedGoods Module 49 12 1 False 04.09.2018 14:45:07 03.01.2020 17:04:09 49569 392 104 0 62 42 26.12.2019 19:56:32 +01:00 https://www.powershellgallery.com/packages/PSSharedGoods Module covering functions that are shared within multiple projects
PSTeams Module 96 10 0 False 11.07.2018 15:43:34 01.01.2020 10:41:52 24815 266 16 0 11 5 22.12.2019 20:20:34 +01:00 https://www.powershellgallery.com/packages/PSTeams Simple project to send messages to Microsoft Teams Channel.
PSUnifi Module 1 2 0 False 11.03.2019 20:18:25 30.06.2019 11:56:23 166 159 2 0 2 0 11.03.2019 17:58:24 +01:00 https://www.powershellgallery.com/packages/PSUnifi Simple module to help with managing Unifi
PSWebToolbox Module 5 3 0 False 10.11.2018 23:48:43 13.09.2019 03:43:42 174 73 3 0 2 1 24.07.2019 09:37:27 +02:00 https://www.powershellgallery.com/packages/PSWebToolbox PowerShell Module providing a simple way to gather cleaned RSS feeds from websites. It's easy to use.
PSWinDocumentation Module 160 21 5 False 29.06.2018 09:20:17 01.01.2020 10:42:09 4039 271 30 0 12 18 18.11.2019 07:51:18 +01:00 https://www.powershellgallery.com/packages/PSWinDocumentation Simple project generating Active Directory, AWS, Exchange, Office 365 (Exchange, Azure AD) documentation to Microsoft Word, Microsoft Excel and Microsoft SQL. More things to follow...
PSWinDocumentation.AD Module 60 5 4 False 25.03.2019 19:36:46 24.12.2019 01:13:21 4934 595 24 0 24 0 18.11.2019 07:35:07 +01:00 https://www.powershellgallery.com/packages/PSWinDocumentation.AD Useful module that covers extractiong of Active Directory data into a single object that can be later on utilized for reporting or other means.
PSWinDocumentation.AWS Module 3 3 0 False 25.03.2019 19:37:06 05.12.2019 10:40:17 1871 281 4 0 4 0 18.11.2019 07:18:53 +01:00 https://www.powershellgallery.com/packages/PSWinDocumentation.AWS Dataset convering Amazon AWS
PSWinDocumentation.AzureHealthService Module 2 0 0 False 07.12.2019 22:22:53 09.12.2019 22:43:41 52 49 2 0 2 0 08.12.2019 15:11:24 +01:00 https://www.powershellgallery.com/packages/PSWinDocumentation.AzureHealthService Module that helps providing Azure Health as PowerShell data.
PSWinDocumentation.DNS Module 2 1 0 False 15.05.2019 16:08:15 13.09.2019 04:00:06 1702 1579 7 0 7 0 29.08.2019 19:52:40 +02:00 https://www.powershellgallery.com/packages/PSWinDocumentation.DNS Dataset covering DNS
PSWinDocumentation.O365 Module 1 3 0 False 25.03.2019 19:39:29 18.11.2019 08:21:00 1990 294 4 0 4 0 18.11.2019 07:21:24 +01:00 https://www.powershellgallery.com/packages/PSWinDocumentation.O365 Dataset covering Office 365
PSWinDocumentation.O365HealthService Module 11 6 0 False 30.03.2019 21:40:32 14.12.2019 21:05:06 878 73 10 0 10 0 13.12.2019 18:42:09 +01:00 https://www.powershellgallery.com/packages/PSWinDocumentation.O365HealthService Dataset covering Office 365 Health Service
PSWinReporting Module 470 46 14 False 12.05.2018 23:59:16 27.12.2019 11:47:36 2724 805 25 0 9 16 26.05.2019 19:11:51 +02:00 https://www.powershellgallery.com/packages/PSWinReporting This PowerShell Module, which started as an event library (Get-EventsLibrary.ps1), has now grown up and became full fledged PowerShell Module. This module has multiple functionalities but one of the signature features of this module is ability to parse Security (mostly) logs on Domain Controllers.
PSWinReportingV2 Module 470 46 14 False 12.05.2018 23:59:16 27.12.2019 11:47:36 4912 1065 15 0 15 0 11.09.2019 05:56:11 +02:00 https://www.powershellgallery.com/packages/PSWinReportingV2 PSWinReportingV2 is fast and efficient Event Viewing, Event Reporting and Event Collecting tool. It's version 2 of known PSWinReporting PowerShell module and can work next to it.
PSWriteColor Module 41 10 1 False 20.04.2018 13:03:21 20.11.2019 17:03:05 55821 31191 15 0 3 12 22.07.2019 21:09:02 +02:00 https://www.powershellgallery.com/packages/PSWriteColor Write-Color is a wrapper around Write-Host allowing you to create nice looking scripts, with colorized output. It provides easy manipulation of colors, logging output to file (log) and nice formatting options out of the box.
PSWriteExcel Module 33 6 2 False 15.08.2018 09:13:20 30.12.2019 13:23:43 12206 1035 26 0 6 20 17.11.2019 13:51:31 +01:00 https://www.powershellgallery.com/packages/PSWriteExcel Little project to create Excel files without Microsoft Excel being installed.
PSWriteHTML Module 178 27 30 False 15.12.2018 19:39:43 04.01.2020 18:39:03 22713 1083 60 0 55 5 26.12.2019 18:00:38 +01:00 https://www.powershellgallery.com/packages/PSWriteHTML Module that allows creating HTML content/reports in a easy way.
PSWritePDF Module 12 0 0 False 02.11.2019 10:47:30 04.01.2020 02:59:17 146 72 5 0 5 0 28.12.2019 22:25:26 +01:00 https://www.powershellgallery.com/packages/PSWritePDF Little project to create, read, modify, split, merge PDF files on Windows, Linux and Mac.
PSWriteWord Module 128 15 8 False 16.06.2018 20:07:33 01.01.2020 10:42:21 8049 611 42 0 13 29 18.11.2019 07:49:19 +01:00 https://www.powershellgallery.com/packages/PSWriteWord Simple project to create Microsoft Word in PowerShell without having Office installed.
Statusimo Module 39 5 1 False 04.03.2019 19:35:24 29.12.2019 11:05:51 1640 1181 5 0 5 0 04.08.2019 17:16:27 +02:00 https://www.powershellgallery.com/packages/Statusimo Simple project to create easy to use Status Pages.
Testimo Module 107 6 44 False 19.03.2019 18:00:44 30.12.2019 22:31:58 1752 44 26 0 26 0 29.12.2019 22:54:44 +01:00 https://www.powershellgallery.com/packages/Testimo Testimo is Powershell module that tests Active Directory against specific set of tests.
Name Type GitHub Stars GitHub Forks GitHub Open Issues GitHub Archived GitHub Created GitHub Updated Download CountTotal Download CountLast Releases Total Releases CurrentYear (2020) Releases LastYear (2019) Releases PreviousYear (2018) Last Updated PS Gallery Url Description

Ok, it wasn't just 5 minutes. Sure HTML part is using PSWriteHTML, so creating tables with the ability to export to Excel, CSV, or some advanced dashboards is straightforward, but I still had to go and prepare the data to fill in that for you. It was generated with the help of my PSDevSummary PowerShell Module that I've created just for this purpose (I'm so lazy that I don't even want to try and prepare data manually also if it takes less time). Here's the code to generate a table as above for any other Author on PowerShellGallery. Of course, it makes some assumptions, so your results may vary, but feel free to log any issues on the GitHub repository.

Import-Module PSDevSummary -Force

# This is required so you don't get prompts all the time from PowerShellForGitHub module
Set-GitHubConfiguration -SuppressTelemetryReminder
Set-GitHubConfiguration -DisableTelemetry
Set-GitHubConfiguration -AssemblyPath "$($Env:UserProfile)\.githubassembly"

# This is the commands from this module
$Modules = Get-DevSummary -Author 'Przemyslaw Klys' -UseHTMLLinks -UseCache

# Use PSWriteHTML/Dashimo to create dashboard
Dashboard -FilePath "$PSScriptRoot\Output\EmbeddingModules.HTML" {
    Table -DataTable $Modules -DisablePaging {
        TableConditionalFormatting -Name 'GitHub Stars' -ComparisonType number -Operator le -Value 20 -BackgroundColor Orange -Color Black
        TableConditionalFormatting -Name 'GitHub Stars' -ComparisonType number -Operator lt -Value 10 -BackgroundColor Red -Color Black
        TableConditionalFormatting -Name 'GitHub Stars' -ComparisonType number -Operator gt -Value 20 -BackgroundColor Yellow -Color Black
        TableConditionalFormatting -Name 'GitHub Stars' -ComparisonType number -Operator gt -Value 100 -BackgroundColor Green -Color Black
    } -Filtering -InvokeHTMLTags
} -Show -UseCssLinks -UseJavaScriptLinks

# Use PSParseHTML to Optimize/Minify HTML
Optimize-HTML -File "$PSScriptRoot\Output\EmbeddingModules.HTML" -OutputFile $PSScriptRoot\Output\EmbeddingModules1.HTML -Verbose

Since that list above isn't self-explanatory, what is what let me try to do a bit of summary for you for the most important projects (according to me). If you're interested in exploring a particular topic, visit the GitHub project, or use the search on my blog to find related articles. I'm not great at documenting stuff, but I do try providing Examples on GitHub so you can see the usage, but I also spend a lot of time writing blogs that cover some or most of the functionality.

Speaking about blog posts – over the years I've create a total of 214 blog posts.

Wrote 10 blog posts in 2017

Wrote 61 blog posts in 2018

Wrote 65 blog posts in 2019

Improvement year to year is visible, and I'm happy that I was able to keep up with my work in 2019. It's not as many as some people do, but still good enough. I read about a guy who did 360 blog posts in a year. That's a crazy high number. Oh well. My 65 blogs mean I wasn't that lazy, after all. I do hope the content, the style has also improved, and it's easier to read. I know I make mistakes, but I try my best to make sure to provide a good read. Since I'm lazy with just about everything, even stats from above are autogenerated using PowerShell. I've used my PowerShell module PSWebToolbox for that.

# Install-Module PSWebToolbox

$Blogs = Get-RSSFeed -Url 'https://evotec.xyz/rss' -All

$DateFrom = Get-Date -Year 2017 -Month 01 -Day 01
$DateTo = Get-Date -Year 2018 -Month 01 -Day 01

$Year2017 = $Blogs | Where-Object { $_.PublishDate -ge $DateFrom -and $_.PublishDate -le $DateTo }

$DateFrom = Get-Date -Year 2018 -Month 01 -Day 01
$DateTo = Get-Date -Year 2019 -Month 01 -Day 01

$Year2018 = $Blogs | Where-Object { $_.PublishDate -ge $DateFrom -and $_.PublishDate -le $DateTo }

$DateFrom = Get-Date -Year 2019 -Month 01 -Day 01
$DateTo = Get-Date -Year 2020 -Month 01 -Day 01

$Year2019 = $Blogs | Where-Object { $_.PublishDate -ge $DateFrom -and $_.PublishDate -le $DateTo }

While that code above gives you a bit of summary it can also give you full output of RSS from any website. Of course the variables hold full PowerShell Objects with Title, Link, Date and so on, that with just a bit of PSWriteHTML magic I can easily push this into HTML on my blog

Before we can do that, I want the links to be clickable, so I need to quickly convert the list of blogs I have and make sure we add HTML tags into it. After that, it's just a matter of using Out-HtmlView, which can make any PowerShell table into the exportable HTML file.

$PrettiefiedHTML = foreach ($Blog in $Year2019) {
    [PSCustomObject] @{
        Title       = New-HTMLTag -Tag 'a' -Attributes @{ href = $Blog.Link } { $Blog.Title }
        Date        = $Blog.PublishDate
        Tags        = $Blog.Categories
        Description = $Blog.Description
$PrettiefiedHTML | Out-HtmlView -FilePath $PSScriptRoot\Output\EmbeddingBlog.html -InvokeHTMLTags -DateTimeSortingFormat 'DD.MM.YYYY HH:mm:ss' -Filtering -PagingOptions 5,10,15,20

# PSParseHTML Minify HTML
Optimize-HTML -File "$PSScriptRoot\Output\EmbeddingBlog.HTML" -OutputFile $PSScriptRoot\Output\EmbeddingBlog1.HTML -Verbose
Title Date Tags Description
Merging, splitting and creating PDF files with PowerShell 29.12.2019 17:20:33 merge-pdf,pdf,PowerShell,pswritepdf,split-pdf We're in the last days of 2019, and this will be my last blog post this year. What better way to end a good year than with the release of the new PowerShell module. If the title of today's blog post isn't giving it up yet, I wanted to share a PowerShell module called PSWritePDF that can help you create and modify (split/merge) PDF documents. It joins my other PowerShell modules to create different types of documents such as PSWriteWord, PSWriteExcel, PSWriteHTML. I know that PSWriteExcel is relatively basic, but both PSWriteHTML and PSWriteWord deliver robust build capabilities.
Sending Messages to Microsoft Teams from PowerShell just got easier and better 22.12.2019 21:21:26 microsoft teams,Office 365,PowerShell Christmas time is upon us, and I've decided that my PSTeams module needs some love. I wrote it in late 2018 and updated it a few times at the beginning of 2019. This release hopefully is worth of having 1.0 version number. I don't do that often and usually go for build numbers changes only, but Microsoft Teams message cards have their limits on functionality. Therefore, there are not many things that can be added unless Microsoft opens up and gives us all the cool features of Adaptive Cards. PSTeams module uses Webconnector to send messages to Teams. That method only supports Message Cards, which even Microsoft calls Legacy. But legacy doesn't mean fully functional with some cool features of their own. If you're new to PSTeams you may want to read those 2 posts below to get information how to set it up.
Invoke-RestMethod : The underlying connection was closed: An unexpected error occurred on a send while connecting Graph API 14.12.2019 11:01:16 invoke-restmethod,Office 365,PowerShell,tls 1.0,tls 1.1,tls 1.2 In the last few days, I've got two reports that my PowerShell module for Office 365 Health suddenly started giving errors. This was a bit weird because it worked perfectly fine on my end. But while I could understand one person having an issue of their own, with their network or firewalls, if the second person comes along with the same report, that means something else is going on.
Getting Azure Health by parsing HTML using PSParseHTML 08.12.2019 16:38:22 Azure,azure health,PowerShell,psparsehtml Some time ago I've wrote PowerShell way to get all information about Office 365 Service Health, and if you were thinking that I would try the same concept for Azure Services you were right. However, I failed. This is because Office 365 Health can be gathered using Microsoft Graph API, and Azure Health information, as far as I know, is not available in the form I wanted it. Azure Status is available as part of Azure Status website. Contrary to Office 365 health you don't have to login to your Office 365 tenant to read it.
Microsoft Graph – InvalidAuthenticationToken – Access token validation failure. Invalid audience 05.12.2019 21:25:24 microsoft graph,Office 365,PowerShell The post Microsoft Graph - InvalidAuthenticationToken - Access token validation failure. Invalid audience appeared first on Evotec.
Set-PSRepository Installation Policy Trusted – Invalid Class Error 21.11.2019 16:11:48 errors,import-module,install-module,PowerShell,powershellget I have to admit - executing the same command three times and expecting different results is dumb, but I still do it anyway. Fortunately, after trying three times I usually resort to other methods and try to solve the problem I have. Today while trying to trust PowerShellGallery I was greeted with an error.
Removing user from local administrator group based on data stored in Active Directory 17.11.2019 21:09:21 active directory,adsi,PowerShell,powershell 2.0,windows 7 We need to deal with a group names through SID's rather than names because each group name is different in different languages. The second problem is to distinguish whether a user is a local or domain user. Finally, I need to connect to Active Directory to verify if the user I am about to remove has ExtensionAttribute10 (or any other field in AD) filled in or not.
Emailimo merged into PSWriteHTML, IE support and no dependencies 12.11.2019 15:41:10 emailimo,ie,internet explorer,PowerShell,pswritehtml If you don't know this yet, I use PSWriteHTML a lot. That means I get to test it under a lot of different conditions. I use it in reports, emails for small, medium, and large companies. Today's blog post summarizes the work I did in the last few weeks over different areas of PSWriteHTML.
Create a local user or administrator account in Windows using PowerShell 30.10.2019 13:44:27 administrator,gpo,PowerShell,Windows The post Create a local user or administrator account in Windows using PowerShell appeared first on Evotec.
Nested Tabs, Diagram Updates, Diagram Events, Calendar Object and more in PSWriteHTML 13.10.2019 16:52:40 dashimo,html,PowerShell,pswritehtml One of the new features I've worked on was connecting Diagrams with Tables. Someone suggested, and I thought it would be cool to be able to click on the Diagram node and find more details about it in a table next to it. But then I thought it would be even cooler if you could have multiple tables linked to one Diagram. For example, below, I've created two tables with Users and Computers and populated Diagram with that data.
Easy way to create diagrams using PowerShell and PSWriteHTML 29.09.2019 17:48:32 architecture,css,dashimo,diagram,html,js,network,PowerShell,pswritehtml,reports A few months ago, when I was working on PSWriteWord and PSWriteHTML, I thought to myself that in 2020 if I'll get time, I'll try to create PSWriteVisio. While I wasn't sure I would be able to make it past some concept, it was in my plans for 2020. It's still 2019 though, and while working on Testimo for Active Directory Healthchecks, I thought it would be nice to have a visual representation of network, forest schema or replication. I couldn't get this idea out of my head. I thought on using PSGraph from Kevin Marquette to generate image and import that to PSWriteHTML but it was a bit tricky and PSGraph requires external software to work - and has some additional steps for Windows, Mac or Linux.
What do we say to health checking Active Directory? 08.09.2019 17:48:39 Active Directory,ad,dhcp,dns,health checks,PowerShell,security checks,testimo,Windows Setting up a new Active Directory is an easy task. You download and install Windows Server, install required roles and in 4 hours or less have a basic Active Directory setup. In an ideal world that would be all and your only task would be to manage users, computers, and groups occasionally creating some Group Policies. Unfortunately, things with Active Directory aren't as easy as I've pictured it. Active Directory is a whole ecosystem and works well ranging from small companies with ten users to 500k users or more (haven't seen one myself - but so they say!). When you scale Active Directory adding more servers, more domains things tend to get complicated, and while things on top may look like they work correctly, in practice, they may not. That's why, as an Administrator, you need to manage Active Directory in terms of its Health and Security. Seems easy right? Not quite. While you may think you have done everything, checked everything, there's always something missing. Unless you have instructions for everything and can guarantee that things stay the same way as you left them forever, it's a bit more complicated. That's why Microsoft delivers you tools to the troubleshoot your Active Directory, such as dcdiag, repadmin and some others. They also sell monitoring solutions such as Microsoft SCOM which can help and detect when some things happen in your AD while you were gone. Surely there are some 3rd party companies give you some tools that can help with a lot of that as well. Finally, there is lo of folks within the community creating PowerShell scripts or functions that help with some Health Checks of your Active Directory.
Making PowerShellGallery modules Portable 08.09.2019 09:12:08 module,portable,PowerShell I'm a big fan of PowerShellGallery. It's easy to use, Microsoft owned, a place to host your PowerShell modules. Every time I release a new PowerShell module, it's readily available for me or anyone with a single command Install-Module. No need to host it yourself, no need to prepare anything - plug & play. Additionally, if your PowerShell module has any dependencies, it will download and install them, so it directly works out of the box. But what if you can't use PowerShellGallery? What if you don't want to use Install-Module on 100 computers, but you prefer to do it in a more controlled way? What if your servers do not have internet connectivity?
Comparing two or more objects visually in PowerShell (cross-platform) 25.08.2019 15:01:32 compare,dashimo,html,out-htmlview,PowerShell,pswritehtml,statusimo For the last few weeks I'm working on a small project, that should be released within next few weeks (it is open source so don't worry - you'll get to play with it). This project requires me to compare two or more objects and tell if those are equal and if those aren't to what degree. Of course, PowerShell offers built-in functionality via Compare-Object command. It's mighty but it leaves comparing differences, different properties to you. While there are probably other solutions that help users compare objects, I haven't found anything that would meet my requirements. After I've written Compare-MultipleObjects function, I thought it could be interesting to implement visual comparison - you know human-readable - and I had the perfect place to apply it.
Formatting and minifying resources (HTML, CSS, JavaScript) with PowerShell 11.08.2019 18:42:54 css,html,javascript,PowerShell,psparsehtml,pswritehtml When you work with HTML, CSS, and JavaScript, you often meet three versions on how those are stored in files - minified, formatted, somewhere in the middle (usually a total mess). I have all three versions in my PSWriteHTML module. Some are minified 3rd party resources, some are generated by my PowerShell commands (and are a total mess when it comes to formatting), and finally, some are formatted resources by using built-in VSCode features. In whatever form they are, they generally have no impact on how browsers display them. Browsers will read them in any kind and not care for how they look.
Getting Active Directory Last Backup Time using PowerShell 05.08.2019 14:40:18 Active Directory,PowerShell I shouldn't be telling you that, but Active Directory Backup is an essential part of your Active Directory setup. When a backup of Active Directory happens, AD is aware of it. Following PowerShell solution allows you to get Active Directory Last Backup Time for the whole forest or by domain.
Working with HTML in PowerShell just got better 04.08.2019 20:04:55 css,dashimo,emailimo,html,js,PowerShell,pswritehtml Last few weeks, I've been working on making creating HTML based Dashboards, Reports, and Emails better. PSWriteHTML already allows fancy looking reports or emails without much effort, but this release makes it even more helpful. I will be mixing three PowerShell modules in this blost post - PSWriteHTML (responsible for creating HTML/CSS/JS code), Emailimo (simplifies creating emails based on PSWriteHTML) and Dashimo (simple dashboard building). If you've never heard of those modules before I encourage you to start from earlier blogs about them to understand the concepts before you dive into this one.  Hopefully, those will give you some ideas that will match what you will learn today.
Testing LDAP and LDAPS connectivity with PowerShell 04.08.2019 16:55:32 Active Directory,ldap,PowerShell One of the common ways to connect to Active Directory is thru LDAP protocol. There are a lot of applications that talk to AD via LDAP. By default Active Directory has LDAP enabled but that's a bit insecure in today's world. That's where LDAPS comes in. It's not easy to set up, but when you get it done, it works. The problem I had recently is that while setting up LDAPS on DC's I only did this on some of the DC's, and not all of them as I should.
Instant Replication between Active Directory sites with PowerShell 21.07.2019 15:31:06 Active Directory,ad,instant replication,PowerShell,replication In Active Directory when you change something, it's replicated to other Domain Controllers regularly. It's a standard procedure that happens automatically in the background for you. It's a handy feature because you can have multiple DC's all over the world and have your users data in sync. You can change almost anything on DC nearest to you and be sure it will be the same value all over the place. But is it always the same? Well, it should be unless it isn't. Today I was given a new migration from  Exchange to Office 365. I started with ADConnect installation and wanted to make sure that UserPrincipalNames have all UPNSuffixes in place.
Executing hidden or private functions from PowerShell Modules 14.07.2019 18:15:59 hidden,PowerShell,powershell module When you write PowerShell modules, there's a high chance you will have conflicts with either existing system commands (you should avoid that) or with someone else's modules. There are also times when someone wants to use a private function from a module that only exports essential functions. Here's a couple of ways how to deal with those scenarios.
Using Lansweeper with PowerShell to your advantage 14.07.2019 16:23:17 dbatools,lansweeper,PowerShell,reporting,sql,user reports I'm on a tight deadline for one of the chapters for PowerShell Conference Book vol. 2. That means my brain wants me to do a lot of different things but writing that chapter. I've decided to write this simple PowerShell command that allows me to use Lansweeper in PowerShell. If you never heard of Lansweeper, it's a great inventory tool that can scan Windows, Linux, Network, Printers, and other types of assets gathering it all in SQL Database. Usually, you would use their friendly, fast interface to access data it stores because it offers a lot of flexibility, export options, and many many features.
Getting Bitlocker and LAPS summary report with PowerShell 11.07.2019 19:07:22 Active Directory,ad,bitlocker,laps,PowerShell Having Bitlocker and LAPS in modern Active Directory is a must. But just because you enable GPO and have a process that should say Bitlocker and LAPS are enabled doesn't mean much. Now and then you should verify things yourself. One of the Facebook users on PowerShell group just had this idea of exporting Bitlocker keys and then giving that list to his colleagues for manual verification. He wanted to do it half PowerShell and half manually. While the idea was great, why not take full advantage of PowerShell and have a helpful report with all the necessary information?
Sending HTML emails with PowerShell and zero HTML knowledge required 11.07.2019 09:24:21 Altaro,dashimo,email,emailimo,html,PowerShell,pswritehtml I saw this article by Altaro tweeted Building PowerShell Tools for MSPs: HTML Tables for Reporting, and it describes how you can create HTML emails with just a few lines of code. Luke created that article in 2018 (tweets from the archive I guess), but I just saw it now so thought I would make a slight comparison. In 2018 I would probably go the same way as shown by Luke Orellana, who takes a simple example of querying WMI to get disk drive sizes and send them over, formatted via Email.
All your HTML Tables are belong to us 28.06.2019 18:35:13 dashimo,html,javascript,PowerShell,pswritehtml Last few days, I've fulfilled my little dream related to building HTML tables. You know I've been using HTML based scripts for a long while for Microsoft Exchange from multiple people like Steve Goodman or Paul Cunningham (and others) and when I was going thru their PowerShell building code on how they create an HTML table with multi-row titles I thought Those guys are crazy. The effort to build an HTML table for a report for a person who has no clue how to do it is not something one can easily digest and understand. Sure I've learned how to build HTML tables at some point, but there was one final piece that I was missing - multi-row headers. If you don't know what I mean, and how they look like the below image from Steve's Goodman script should give you a hint.
Fixing Active Directory PasswordNotRequired with PowerShell 25.06.2019 12:29:44 Active Directory,ad,PasswordNotRequired,PowerShell There was I, deploying PSPasswordExpiryNotifications for one of my Clients when I started getting complaints that some users are not getting their Password Expiry Notifications. Well, that's a new one. I've tested this script multiple times, and it worked just fine. So I dive into the details of my script to see what I did in there (I don't even remember anymore - it just works) to find out this little line:
Export-CliXML and Import-CliXML serialization woes 23.06.2019 12:12:27 Active Directory,export-clixml,import-clixml,PowerShell I've been working today trying to deliver to one of my Clients Active Directory documentation. To my surprise, something that worked fine for a very long time has started to provide weird results. So, after spending about 8 hours taking apart a few of my PowerShell modules trying to find out what is wrong finally, I've found it: Export-CliXML / Import-CliXML. Those two commands are great. I've used them multiple times with great success (or so I thought).
Dashimo (PSWriteHTML) – Charting, Icons and few other changes 17.06.2019 12:46:20 css,dashimo,html,javascript,js,PowerShell,pswritehtml A few months ago when I first released Dashimo, I've promised that Charts will come. Unfortunately, time passed by, and there were no Charts in sight. It's not that I didn't want to deliver, I just wasn't sure on the way I want to allow charts building. Today after playing with the idea for a while I've decided to release essential support for diagrams, with a couple of other fixes. Some of that stuff is already there for longer while I just never announced it. There are probably a lot of other hidden gems you may find if you explore PSWriteHTML or Dashimo.
Getting Windows 10 build version from Active Directory 14.06.2019 17:03:06 Active Directory,build,PowerShell,windows 10 Today I saw an article on how to get Windows Version Report from Active Directory and thought that this is a cool idea. Something handy for migration scenarios or information on how up to date is your infrastructure. Since there are many ways to do the same thing I decided to tackle this myself and further include it into PSWinDocumentation.AD project. By default Active Directory stores Operating System and Operating System Version but it doesn't really show versions one may expect.
Install-module : The ‘install-module’ command was found in the module ‘PowerShellGet’, but the module could not be loaded. 30.05.2019 10:24:14 import-module,install-module,PowerShell,powershellget I've been working last few hours trying to set up my laptop for PowerShell Conference, and one of the tasks is to get my modules up and running. To my surprise on Windows 10 1903 Install-Module thrown a weird error
How I didn’t know how powerful and fast hashtables are 19.05.2019 11:49:26 Active Directory,hashtable,learn,PowerShell,speed I've been using PowerShell for a long while now using Hashtables, OrderedDictionary, and other types of data types in PowerShell, but I never paid attention to how powerful those are. And I don't mean your general knowledge about hashtables that is already covered by Kevin Marquette in his article Everything you wanted to know about Hashtables or my article PowerShell – Few tricks about HashTables and Arrays I wish I knew when I started. Let's find out, how Powerful they are, shall we?
What do we say to writing Active Directory documentation? 12.05.2019 14:46:24 Active Directory,dashimo,documentation,documentimo,excel,excelimo,PowerShell,pswindocumentation,Windows,word It's no secret that nobody likes creating documentation. I don't like it, and you don't like it, even documentation lovers don't like it. But while you can live without documentation, you really shouldn't. And I am not talking here only about documentation that is only useful in the onboarding process of new employees or documentation concerning introducing someone to some concepts to get them easily start. I'm talking about documentation for your live environment where you know what you have, how you have set it up, but is still the same after one week, one month, or one year? Usually, not so much. And one of the worst mistakes admin can do is assume that his environment doesn't change, things are as they were when they were set up.
The only PowerShell Command you will ever need to find out who did what in Active Directory 28.04.2019 17:52:32 Active Directory,ad,events,events viewer,PowerShell,pswinreporting,pswinreportingv2,Windows While the title of this blog may be a bit exaggeration, the command I'm trying to show here does it's best to deliver on the promise. What you're about to witness here is something I've worked on for a while now, and it meets my basic needs. If you don't have SIEM product or products that monitor who does what in Active Directory this command makes it very easy, even for people who don't have much experience in reading Event Logs. If you'd like to learn about working with Windows Event Logs here's a great article I wrote recently - PowerShell - Everything you wanted to know about Event Logs and then some.
Does having Format-Table or Format-List in the middle of the pipeline makes sense? 24.04.2019 22:03:02 Format-List,Format-Table,PowerShell Recently there was this discussion on PowerShell Group on Facebook about issue posted by one user. While the subject doesn't matter for this post, few people commented on the idea that he was using Format-Table in the middle of the pipeline to do something. They all said Format-Table should be used as last in the pipeline. Otherwise, you would get the wrong output. But should it? Well, it depends!
The curious case of $null should be on the left side of equality comparisons PSScriptAnalyzer 24.04.2019 15:29:42 $null,PowerShell,PSScriptAnalyzer If you're using VSCode with Powershell extension, you probably got used to PSScriptAnalyzer giving you all kind of tips on optimizing things. It makes your code better. Chris Bergmeister does a great job working on it. One of the tips PSScriptAnalyzer gives you when you use $null on the right side of the comparison.
Preparing Azure App Registrations permissions for Office 365 Service Health 22.04.2019 18:25:02 Azure,health,office 365,PowerShell As you may have seen in my other post, there's a simple, PowerShell way to get Office 365 Health Service data for you to use any way you like it. But before you can use that, you need to register granular permissions on your Office  365 tenant so that that data is provided to you. Here's a step by step way to do it.
PowerShell way to get all information about Office 365 Service Health 22.04.2019 18:24:43 Azure,health,Office 365,PowerShell,pswindocumentation Office 365 is an excellent cloud service. But like any service, there's some infrastructure behind it that has to be cared for. Since this is Cloud, Microsoft does this for you. But any problems Microsoft has to have some impact on your end users. And you may want to have that visibility for your users. Microsoft provides this to Admins when they login to the portal, but while useful you may want to use that data in other ways than those planned by Microsoft.
Meet Emailimo – New way to send pretty emails with PowerShell 12.04.2019 10:13:43 css,emailimo,html,javascript,js,Linux,Mac OS X,mailing,outlook,PowerShell,pswritehtml,send-email,send-mail,Windows When reading this blog post, you may be thinking that there's nothing new one can add to emailing with PowerShell as there were tons of articles in recent years covering this subject pretty good. It's all known, and people have used it since the early days of PowerShell. You can even send an email with just one line using Send-MailMessage. Now, this post is not about that. This post is about sending HTML based emails. You see when you want to send an email that is just text based that's pretty trivial. Things get complicated when you want your emails to have some colors, some tables, some links or some lists. This is where you have to involve HTML and CSS. Since I've been working with PowerShell for a while now, I've seen my share of scripts/modules or blog posts that cover this but one thing that usually hit me - it was sometimes tough to understand what is happening, what the author is doing, and what happens if I change this or that. While I've seen people dismissing programmers doing HTML / CSS or JavaScript for not being real programmers, I disagree entirely. You have to know what you're doing if you want your stuff to look good. I've spent days or even weeks playing with HTML/CSS/JS, and I must admit half of what I do I don't even understand until I see the output. So before you go and tell people that HTML/CSS is easy, think again.
Out-HtmlView – HTML alternative to Out-GridView 06.04.2019 20:47:55 cross-platform,Mac OS X,PowerShell,powershell 6,powershell 7,powershell core,Ubuntu,Windows One of the most comfortable output's in PowerShell to work and analyze data is Out-GridView. It's handy as you can search, sort and have things done quicker than trying to do things in the console. However it's currently not available in PowerShell Core (PowerShell 6+), and when it is available in PowerShell 7, it will NOT be cross-platform.  Since I had released Dashimo a few days ago, I thought it was trivial to make a simple command out of it that could solve this problem.
Dashimo – Easy Table Conditional Formatting and more 04.04.2019 22:17:24 dashimo,PowerShell,pswritehtml,reporthtml Dashimo ultimate goal is to be as easy to use as possible. With the introduction of it a few days ago I made a promise to myself that I want to keep it as simple to use as possible. If you don't know what Dashimo is, have a read here - Meet Dashimo. When I posted it on Reddit few people had some ideas and feature request that would make it a bit nicer, and when I heard about I agreed. So today, after a couple of days I have a few updates. I also noticed that my examples might have been too hard to use and understand for beginners and people not having a lot of touch with Active Directory. This time all code you can find below will use Get-Process as a way to show you that you can use any output that comes as a Table.
Meet Dashimo – PowerShell Generated Dashboard 01.04.2019 21:45:38 css,dashboard,dashimo,html,javascript,PowerShell,statusimo Today I wanted to introduce a little product that I've created in the last few weeks called Dashimo. It doesn't cover everything I wanted from it (feature wise), but it already can be used in production. Therefore, I thought it would be a good idea to get some feedback on whether I should spend some more time on it or throw it in the dumpster. Dashimo joins it's older brother Statusimo of PowerShell modules allowing an easy way to build HTML output. If it will feel familiar, it's because it was inspired with Bradley Wyatt PowerShell script he did. It gave me the idea of how I would like to build something similar but in a bit different way then he did, with much more flexibility. Still, if it wasn't for him, the idea wouldn't be there, therefore you should send him your thanks.
Backing up Bitlocker Keys and LAPS passwords from Active Directory 31.03.2019 22:01:43 Active Directory,bitlocker,laps,PowerShell Having a modern, secure infrastructure in 2019 is a requirement. You should implement BitLocker to make sure that in the event of stolen laptop data is not readily extractable and implementing LAPS is a must in a fast changing IT world. But I'm not here to convince you to those two security features. I'm here to show you an easy way to backup LAPS and BitLocker. While having everything stored in Active Directory is excellent, things can get complicated when you don't have access to your Active Directory, or you restore an older version of it. You see, LAPS, for example, keeps only last Administrator password. This is great and all but what happens if you restore the machine from backup from 6 months back? Your password has already changed multiple times. During our testing of DR scenarios, we wanted to access the computer via their local Administrator credentials and we just couldn't because that password was already gone.
Creating Visual Indicators for spoofed / external emails with PowerShell 30.03.2019 22:28:27 Exchange,exchange 2013,exchange 2016,exchange online,Office 365,PowerShell I've been managing mail service for users for a lot of years now. I don't do it daily but I've spent my fair share of time analyzing spam emails. Mail vendors are doing what they can fighting spam, but it's not easy. Each month, each year spam is getting more sophisticated. Spam emails either look like a legit email, or worse someone is targeting your company trying to get them to transfer money into a wrong account. While most of those end up in spam, there are those that come thru. It's even worse if the company you work with has not implemented SPF or their SPF is configured to soft fail which can't be treated as spam.
Accessing AzureVM with NLA and broken domain trust relationship 28.03.2019 09:22:42 Active Directory,ad trust,Azure,azure vm,nla,PowerShell Hosting your VM's in Azure Cloud is excellent. You have all those features, professionally managed and virtually limitless. I don't want to take your time to sell you Azure Services but to share a solution to one of the things I had to solve in Azure and sooner or later you may end up with on. During the test restore for Active Directory and multiple other machines which were much older (or newer) then Active Directory Domain Controller that was restored it turned out one can't log in to most of the devices. First of all your domain password is already changed, but that can quickly be addressed. Your second and more significant problem is Network Level Authentication (NLA), and your 3rd problem is broken trust relationship.
Active Directory – The directory service was unable to allocate a relative identifier 27.03.2019 20:39:25 Active Directory,ad,error,PowerShell I've been testing Disaster Recovery scenario restoring Active Directory. One of the servers was restored, and it worked for a moment after restore. If you can regain your Primary DC, it's best to do so. If you can't, a standard thing to do during DR is to move all FSMO roles to the restored server so that it can become a master server. You can find out your FSMO holders by using those commands below:
Changing Exchange folder permissions in multilanguage Office 365 tenants 22.03.2019 18:58:49 Exchange,exchange online,Office 365,PowerShell,room mailbox One of the tasks I often get when setting up new Office 365 tenant or installing Exchange Servers is to change the visibility of Room Mailboxes or in some cases even standard users. There's nothing hard about it, and there are plenty of articles about it. It's just three simple steps.
Using PowerShell to fix Ubiquiti Unifi requirement for MongoDB 3.6 on Ubuntu 18 11.03.2019 21:31:14 linux,mongodb,PowerShell,Ubuntu,ubuntu 18.04,UniFi I've been using Ubiquiti Unifi for some years now, for both home and work usage. It's great hardware at a great price, and the best thing for a software maniac like me is that it's continuously updated. Some time ago I upgraded Ubuntu to 18.04, and things went a bit sideways. You see Unifi started to add to their DEB packages that Mongo 3.6 is not supported and therefore blocking any installation. The idea is, it works perfectly fine on MongoDB 3.6 but migration between 3.4 to 3.6 is just not straightforward. Long story short when I upgraded Ubuntu I was suddenly greeted with not working Unifi.  I've fixed that, and blogged about it how you can do so using manual steps - Ubuntu 18.04 – Fixing Unifi .deb package to run with 3.6 MongoDB. The thing is with each new version out I have to do multiple steps to fix every single package from Unifi (you see where I'm going right?). While a few years ago I would be stuck to use bash or some other workaround which would be a pain for me, this is 2019, and PowerShell Core works excellent on Linux systems! I know that installing PowerShell Core for hardcore Linux fans may not be as fun as it is for me, but you do get a lot of benefits from it.
PSWinReporting 1.8 – Split of branches (Legacy vs. New Hope) 10.03.2019 20:39:43 Active Directory,event,event monitoring,events,PowerShell,pswinreporting,Windows A new branch of PSWinReporting is slowly coming, and I thought it would be the best time to have a final article about it with all configuration options available for those that will want to stay using PSWinReporting from Legacy branch. The idea is that you may have it working in your systems and it's good enough for you. You may not want to change it, and with New Hope, the changes are so big it's a rewrite.
PowerShell – Returning one object from a function as an Array 08.03.2019 10:11:31 array,foreach,foreach-object,goot-to-know,PowerShell Few weeks had passed since I've initially written PowerShell – Few tricks about HashTables and Arrays I wish I knew when I started. I was happily using my tips and tricks myself till today when I noticed a strange problem. Do you know how I showed you that you could use a comma to return Array with just one member (that otherwise would be unwrapped and end up a string)?
Meet Statusimo – PowerShell generated Status Page 06.03.2019 17:45:52 css,html,javascript,PowerShell,status page,statusimo A few weeks ago, Mateusz Czerniawski, mentioned that he wants to build a Status Page for his company services. While I haven't needed for myself, it seems like an excellent idea to try and create one in PowerShell. Since I've been working on PSWriteHTML for a while, it wasn't that far fetched idea. While PSWriteHTML has a long way to go, to be in a state I want it to be, after a few days I had a prototype that didn't require much work to generate. If you're wondering what Status Page is it's a little summary page for your users to check what is the status of services they use. It has been popular in the last few years and is offered by many services (Twitter, GitHub, Office 365 - they all have it). Companies are selling it as a service as well where you can host your status page for your users. This one is free.
Hyper-V – Can’t start Virtual Machine because it’s backing up 25.02.2019 21:29:14 backup,error,Hyper-V,PowerShell Working as a small business often brings you little tasks here and there. Today I've decided to shut down the Hyper-V machine to expand its disks. Unfortunately for me, while extending of HDD went great, I couldn't start Virtual Machine any longer.
PowerShell – Everything you wanted to know about Event Logs and then some 20.02.2019 13:22:19 Active Directory,event logs,events,get-eventlog,get-winevent,microsoft window,PowerShell,Windows,windows server If you feel this title is very familiar to you it's because I actually have stolen the title from Kevin Marquette. I'm in awe of his posts that take you thru topic from beginning till the end. No splitting, no hiding anything, everything on a plate, in a single post. That's why I've decided to write a post that will take you on a trip on how to work with Event Logs, something that is an internal part of Windows Administration. If you've never worked with Events and you're in IT you most likely should make an effort to find out what it is and how you can eat it.
PowerShell – Few tricks about HashTables and Arrays I wish I knew when I started 18.02.2019 15:52:59 array,arraylist,genericlist,hashtable,PowerShell,tricks I've been working with PowerShell for a while now and like with most things I do I've learned it by doing and not by reading. I had a job to do, and since I don't like doing things over and over, I thought it's time to learn and do it in PowerShell. Problem with that approach is that you take bits and pieces from PowerShell scripts online that sometimes do the job but not necessarily pay attention to details. And it's fine. I've learned a lot from reading someone else's work, and I learn something new every day. Hopefully, it will be useful to you to some extent.
Bittitan MigrationWiz – The selected Mailboxes cannot be subscribed 14.02.2019 21:10:28 bittitan,Exchange,exchange online,Office 365 Recently I'm doing yet another migration between Office 365 tenants using Bittitan Migration Wizard. It's a great tool and takes away a lot of headaches when dealing with the migration of mailboxes or OneDrive data. Unfortunately, like with many blogs on my website I had to hit yet another error. This time error occurred when I tried to assign User Migration Bundle license to users on the Migration Wizard.
How to find different server types in Active Directory with PowerShell 06.02.2019 18:25:30 Active Directory,ad,adconnect,Azure AD,exchange,Hyper-V,PowerShell,sql,Windows Working as a freelancer is a great thing if you can handle it. Each day, each week something new happens and a new problem shows up on my doorstep. It also means it's almost never boring at your job and you get to play with new stuff. But there's one drawback to this. You're often thrown at the problem, told to fix it but often that's about as much information as you get. It wasn't very different today. I was told to switch Office 365 from ADFS to Password Synchronization. While reasons for this are not really important, the important question here is what is the name of AD Connect server that's responsible for this configuration?
A short story on PowerShell HashTables that beat me hard 03.02.2019 20:29:09 PowerShell,powershell hashtable,pscustomobject Today's story happened a few days back to me, and I think many people may not even know about some object behaviors in PowerShell (just like me). I know some of you may think this is basic PowerShell knowledge but even thou I've written a lot of different PowerShell modules I kind of skipped basics. That means I often find myself struggling with something that's obvious if you've done your due diligence before starting to work with the code. But that's typical me, playing with complicated stuff, failing at simple things.
Office 365 – Report containing User Information and Mailbox Usage 29.01.2019 15:30:04 Exchange,exchange online,msol,Office 365,PowerShell Working with Office 365 is my bread and butter in the last few months. I'm a System Architect and I am dropped in multiple projects, both new and old, to fix certain aspect and get out before anyone sees me. One of the common tasks I get is to provide some data about users stored in Office 365.
Active Directory – How to track down why and where the user account was locked out 24.01.2019 15:25:31 Active Directory,event viewer,get-events,get-winevent,PowerShell,pseventviewer,pswinreporting,Windows,windows server I've been working with Windows Events for a while now. One of the things I did to help me diagnose problems and reporting on Windows Events was to write PSEventViewer to help to parse the logs and write PSWinReporting to help monitor (with use of PSEventViewer) Domain Controllers for events that happen across the domain. It's handy and I, get those excellent daily reports of what happened while I was gone.
How to change your own expired password when you can’t login to RDP 23.01.2019 10:41:40 expired password,PowerShell,rdc,rdp,remote desktop connection,remote desktop protocol,Windows I must admit that it was a bit embarrassing to see my Administrator password expired when I tried to log in as Domain Admin to Domain Controller. I got this little message saying This user account's password has expired. The password must change in order to logon. Please update the password or contact your system administrator or technical support.
Windows Server 2019 – Desktop path for all users redirected to System32 \ SystemProfile \ Desktop 22.01.2019 14:31:49 ransomware,Windows,windows 2019,windows server The post Windows Server 2019 - Desktop path for all users redirected to System32 \ SystemProfile \ Desktop appeared first on Evotec.
Windows 2019 – Windows License Expired 19.01.2019 19:31:08 expired license,license,Windows,windows 2019,windows server,windows server 2019 Windows Server 2019 is out now for a couple of months now, and some of you may be interested in playing with it. When you first install it, you can test it for 180 days (so-called Grace Period) after which you need to activate it with a proper production license.
PowerShell modules I worked on in 2018 06.01.2019 17:39:32 module,PowerShell,powershellgallery,windows We're a few days in 2019, and from a time perspective, I can say I had a busy 2018. I must say I've never expected that but in 2018 I've created or worked on 24 PowerShell modules. Some were simpler ones, some were a bit more advanced, and some will be retired in 2019 because their features will be moved to other modules. In PowerShellGallery alone those were downloaded over 15000 times (I must admit that some of those are surely automated tests - "Hello Pester" that I've learned in 2018. It's a nice number thou, and something I'm kind of proud of myself. After all, before 2018 I've not created a single PowerShell module before. Sure, I've created a bunch of scripts, hardcoded, that did the task that I had to solve. But I've never before built something, that could be installed by one little command Install-Module (something I've learned in 2018 as well) and executed by anyone, anywhere. I know the title says Sixteen PowerShell Modules but some modules are just too simple to give them anything else than a small mention.
Active Directory – Move-AD Directory Server Operation Master Role: Access is denied 06.01.2019 09:10:18 Active Directory,fsmo,PowerShell When working with Active Directory one of the common tasks is to move FSMO roles between servers. Well, maybe not that common but it happens from time to time where you have to move all or just some of the FSMO roles. For that purposes, there is single PowerShell command Move-ADDirectoryServerOperationalMasterRole. Sure you can do this via GUI but if there's one command available to fix it all why bother? To make the move one has to be a Domain Admin, Enterprise Admin and Schema Admin. Everything was going smoothly for some roles but wasn't working for others.
A command with name is already available on this system. This module may override the existing commands. 02.01.2019 19:37:18 module,PowerShell Another day, another issue one may say. Today I wanted to install one of my modules to a new server and was greeted with a well-known message (it may seem on first look): A command with name '' is already available on this system. This module 'PSEventViewer' may override the existing commands. If you still want to install this module 'PSEventViewer', use -AllowClobber parameter.
Windows 2019 – How to add language pack? 02.01.2019 13:38:16 Windows,windows server,windows server 2019 Today I've been setting up a new server on Windows 2019. By default, I install Windows with English version even if Client works in their language such as German, Polish or Swedish. While some people install Windows in a language they desire to work with, years of experience taught me that installing English and then adding Language Pack is the best way to go. All errors, windows events, and general troubleshooting is much easier if those are in the native English language. Each version of Windows made it easier to install the language pack and have that up and running in no time. In Windows 2019 it's even more comfortable... or is it?
Title Date Tags Description
PSWinReporting - Poor Man's SIEM (Security Information and Event Management)

Let's start with the PowerShell module that at the time of this writing has over 450 stars on GitHub called PSWinReporting. In 2018 it was at version 1, and in 2019 I released PSWinReportingV2. This module is a Poor Man's SIEM tool. One of my favorite features about that module is the availability of the Find-Events command. This is The only PowerShell Command you will ever need to find out who did what in Active Directory With that little command, you can find out where user accounts are locking out, who created new user, who deleted that user or when a user was added to Domain Admin groups. It's straightforward to use and can simplify your life as an admin. Before Find-Events, it was pretty hard to get everything in one place. That command so far covers the following event types, which can be scanned in Parallel on one or more servers (Domain Controllers). That command has defined 20+ report types which are as follows:

  • ADComputerChangesDetailed
  • ADComputerCreatedChanged
  • ADComputerDeleted
  • ADGroupChanges
  • ADGroupChangesDetailed
  • ADGroupCreateDelete
  • ADGroupEnumeration
  • ADGroupMembershipChanges
  • ADGroupPolicyChanges
  • ADLogsClearedOther
  • ADLogsClearedSecurity
  • ADUserChanges
  • ADUserChangesDetailed
  • ADUserLockouts
  • ADUserLogon
  • ADUserLogonKerberos
  • ADUserStatus
  • ADUserUnlocked
  • ADOrganizationalUnitChangesDetailed
  • OSStartupShutdownCrash
  • OSCrash
  • NetworkAccessAuthenticationPolicy –  covers authorizations approved/denied for WIFI and ETHERNET

The usage is very simple

Find-Events -Report ADUserChanges -DatesRange Last3days -Servers AD1,AD2 -Quiet

But that command is just a small addon. This PowerShell module can be set up, so it sends daily, weekly, monthly emails with a summary of what has happened in a Domain for a given period. It can send data directly to Microsoft TeamsSlack, and Discord as the events happen. My goal for 2020 is to simplify the setup of that monitoring. In PSWinReporting, things were simpler. PSWinReportingV2 is more powerful, but at the same time, there are lots of possible options that can potentially look like a complicated tool. And to be honest, most of my clients are still on PSWinReporting, and PSWinReportingV2 is installed mainly for Find-Events.

PSEventViewer - Replacement for Get-WinEvent / Get-EventLog and Write-EventLog

PSWinReporting would be nothing without PSEventViewer. While it's not so shiny and feature packed it's enough to get your attention to it. You surely know Get-WinEvent, Get-EventLog and Write-EventLog. Those are built-in commands that provide event parsing and event writting capabilities. However except for basic usage they start to get complicated if you want to do some heavy event lifting. PSEventViewer with it's sets of commands is able to overcome some issues they have and provide you with some cool features that PSWinReporting and it's Find-Events funciton utilizes. Those are:

  • Easily list different types of Windows Events
  • Advanced Event Parsing in simple way
  • Runspaces allowing you to run code in parallel (scanning 1-20+ servers at the same time)
  • Automatic splitting of number of events in 22 chunks (Get-WinEvent simply ignores request if there are more events than 22)
  • Automatic conversion of hidden data into variables
  • Keywords and Levels in their prettified form

PSEventViewer (Get-Events)

Articles worth reading

All those articles have one thing in common PSEventViewer. While PSWinReporting is the SIEM tool that's mostly for Active Directory (although you can configure it to scan other types of servers), PSEventViewer is a replacement for Get-WinEvent which allows you to do whatever is necessary. It also contains some cool addon commands such as Get-EventsFilter, which will enable you to build custom XML queries.

Get-EventsFilter -NamedDataFilter @{ TargetUserName = 'Test'; SubjectUserName = 'Test' } `
    -ProviderName 'Microsoft-Windows-Security-Auditing' `
    -LogName 'Security' `
    -ID 1,2,3,4,5,6,7,8,9,10
<# XML
    <Query Id="0" Path="Security">
        <Select Path="Security">
                ((*[System[(((((((((EventID=1) or (EventID=2)) or (EventID=3)) or (EventID=4)) or (EventID=5)) or (EventID=6)) or (EventID=7)) or (EventID=8)) or (EventID=9)) or (EventID=10)]]) and (*[System[Provider[@Name='Microsoft-Windows-Security-Auditing']]])) and (*[EventData[(Data[@Name='SubjectUserName'] = 'Test') or (Data[@Name='TargetUserName'] = 'Test')]])
Get-EventsFilter -NamedDataFilter @{ TargetUserName = 'Test'; SubjectUserName = 'Test' } `
    -ProviderName 'Microsoft-Windows-Security-Auditing' `
    -LogName 'Security' `
    -ID 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 `
    -StartTime ((Get-Date).AddDays(-1)) `
    -EndTime (Get-Date)
<# XML
    <Query Id="0" Path="Security">
        <Select Path="Security">
                ((((*[System[(((((((((EventID=1) or (EventID=2)) or (EventID=3)) or (EventID=4)) or (EventID=5)) or (EventID=6)) or (EventID=7)) or (EventID=8)) or (EventID=9)) or (EventID=10)]]) and (*[System[TimeCreated[timediff(@SystemTime) <= 86400001]]])) and (*[System[TimeCreated[timediff(@SystemTime) >= 1]]])) and (*[System[Provider[@Name='Microsoft-Windows-Security-Auditing']]])) and (*[EventData[(Data[@Name='SubjectUserName'] = 'Test') or (Data[@Name='TargetUserName'] = 'Test')]])

Get-Events also has that built-in. Combined with parallel processing, it's a beast when you need to scan multiple servers and events over 22. Why would you want so many events? Well, it's much faster to ask Event Log about 30 events than three times for 10.

Get-Events (PSEventViewer)

Testimo - Health Check / Configuration Check for Active Directory

Testimo is a fairly new kid on the block with just over 100 GitHub stars. It was created a few months back as a way to help me automate Active Directory Configuration and Health Checks. Testimo introduced one command (similar to Find-Events) called Invoke-Testimo. This command is very powerful because it can execute configuration and health checks for your entire Forest, each Domain separately, finally going thru all or just some of your Domain Controllers. DFS problems? Replication issues? Misconfigured services? Different group policies on different servers? Testimo can detect that and more. It's read-only by design. It doesn't try to fix issues for you but instead gives you a summary of your problems, and that starts your journey to explore how to fix it. It's slowly in development, and since it, the original release amount of tests has expanded. I'll continue adding more tests and invite you to try and ones yourself (it's quite easy). Additionally, I plan to rewrite some portions of it to provide scoring rather than Pass / Fail approach.

  • DCDiagnostics
  • DCDiskSpace
  • DCDnsNameServes
  • DCDnsResolveExternal
  • DCDnsResolveInternal
  • DCEventLogs
  • DCFileSystem
  • DCGroupPolicySYSVOL
  • DCInformation
  • DCLanManagerSettings
  • DCLanManServer
  • DCMSSLegacy
  • DCNetSessionEnumaration
  • DCNetworkCardSettings
  • DCNTDSParameters
  • DCOperatingSystem
  • DCPingable
  • DCPorts
  • DCRDPPorts
  • DCRDPSecurity
  • DCServices
  • DCServiceWINRM
  • DCSMBProtocols
  • DCSMBShares
  • DCTimeSettings
  • DCTimeSynchronizationExternal
  • DCTimeSynchronizationInternal
  • DCWindowsRemoteManagement
  • DCWindowsRolesAndFeatures
  • DCWindowsUpdates
  • DomainComputersUnsupported
  • DomainComputersUnsupportedMainstream
  • DomainDHCPAuthorized
  • DomainDNSForwaders
  • DomainDNSScavengingForPrimaryDNSServer
  • DomainDnsZonesAging
  • DomainDNSZonesDomain0ADEL
  • DomainDNSZonesForest0ADEL
  • DomainEmptyOrganizationalUnits
  • DomainGroupPolicyADM
  • DomainGroupPolicyMissingPermissions
  • DomainKerberosAccountAge
  • DomainOrphanedForeignSecurityPrincipals
  • DomainPasswordComplexity
  • DomainRoles
  • DomainSecurityGroupsAccountOperators
  • DomainSecurityGroupsSchemaAdmins
  • DomainSecurityUsersAcccountAdministrator
  • DomainSysVolDFSR
  • DomainTrusts
  • DomainWellKnownFolders
  • ForestBackup
  • ForestObjectsWithConflict
  • ForestOptionalFeatures
  • ForestOrphanedAdmins
  • ForestReplication
  • ForestReplicationStatus
  • ForestRoles
  • ForestSiteLinks
  • ForestSiteLinksConnections
  • ForestSites
  • ForestTombstoneLifetime

Each of those Sources (name like any other) has 1 or more tests associated to data it gathers (ranging from 1 to 20 for now) so for fairly small domains one run can take from 5 to 30 minutes, but if you have lots of DC's this is going to take a while. I do have to improve error handling in this module because currently if the tests target DC that is down each test will have to be executed and fail after timeout. And timeout is so long that it usually takes much longer to finish one dead DC than 5 good ones. You can enable/disable particular sources, so it's possible to use only what makes sense in your environment. One of the features that needs improvement is exclusion process. Right now the exclusion process covers Domains and Domain Controllers but it only applies to excluding those from testing (as in tests don't target exclusions) however if within a test there is a function that scans all domain controllers, well that isn't excluded so if you have 400 Domain Controllers that's gonna take a while – even if you decided to exclude them overall.

Testimo by default outputs to console, but that output is pretty limited. It usually shows the time it took for a test, true/false approach, and so fixing issues from that may be a bit hard. This is why Testimo provides ShowReport functionality which, with the help of PSWriteHTML, generates Dashboards that help you asses why the test was a fail. With a simple command like this one:

Invoke-Testimo -ShowReport

You get full overview about your Active Directory.

As you can see above, the whole test of my broken, tiny AD took 1 hour and 7 minutes. This is because of many of DC's being down or not responding, and as I said in the beginning. Currently, the tests continue one by one even thou DC is dead. Of course, as mentioned in the beginning, it still has a long way to go. I've started it after PowerShell Conference in August or so, and it requires a lot more work to cover Active Directory needs. If you can help with some development of new tests, optimizations to support exclusions, it would be beneficial. Otherwise, you will have to wait until I get enough time & motivation to fix it all myself. Below is what the summary report looks like. You get an overview of all tests, and then next to each test, you get PowerShell Code that was used to test it. If you take that PowerShell code and run it, you can get more insights into the problem as well.

I will say this here, so in 2021 review post I can check how it went – Year 2020 will be the year of Testimo :-)

PSWinDocumentation - Documenting Infrastructure with PowerShell

PSWinDocumentation with it's over 150 GitHub stars is module I've written in 2018 and expanded in 2019. It's original goal was to create Active Directory, Office 365 and AWS documentation with just one command and configured via Hashtable. That approach changed in the begining of 2019. The reason for this change was that documentation generated by PSWinDocumentation and one command was pretty limited in what you could configure. Different companies, different consultants, different needs. I've also decided to split visualization part from gathering part. This meant I had to split module into multiple smaller modules. So while the original module is still there, it uses data gathering from other modules. At the same time you can use those smaller modules for your own needs.

PSWinDocumentation – main module, that can generate Word/Excel documentation for AD and Office 365. Active Directory part is fairly complete. Office 365 part needs heavy improvements to be useful.

PSWinDocumentation.AD – covers data gathering from Active Directory. It's read-only, and with one command can get you full forest information. It provides lots of information that can be used not only for PSWinDocumentation but also for your own needs any way you like it. I usually combine it with PSWriteHTML, Documentimo, or PSWriteExcel.

PSWinDocumentation.O365 – covers that gathering for Office 365. It's not prime time ready. It works, it delivers some information but far from what I imagine it should have. Feel free to explore. Will 2020 be the year of this module? We will see.

PSWinDocumentation.AWS – covers data gathering from AWS. I didn't write this module, but my colleague Mateusz Niemczyk. It wasn't updated for a while, so not sure how useful it is to anyone into AWS. It would be great if Mateusz decided to improve it since I have about zero knowledge from AWS, and it's pretty hard for me to provide good content here. Does anyone want to improve? Be my guest!

PSWinDocumentation.DNS – covers data gathering from DNS. I started working on it but never actually finished. It's not that I didn't want, but Testimo just needed all the attention. I'm using parts of this module in Testimo, so not all is lost, and I do hope to improve data gathering from DNS in 2020 to be of similar quality that PSWinDocumentation.AD.

PSWinDocumentation.DHCP – covers data gathering for DHCP. Nothing to see here. Move on. It's not really functional. Something to fix in 2020.

PSWinDocumentation.O365HealthService – this module covers Office 365 Health. Since it uses the graph to gather Office 365 Health Data, it's separated from the main Office 365 module. You know how when you log in to Office 365, and you can see all those Health issues for your tenant. Well, this module delivers Office 365 Health just in a PowerShell form. Mix it up with PSWriteHTML, and you can have your dashboard without the need to log in. If you want to set it up for your tenant, read PowerShell way to get all information about Office 365 Service Health.

PSWinDocumentation.AzureHealthService – this module is covering Azure Health Check. However, it doesn't show you your Azure, but it focuses on Azure as a whole. Unfortunately, since there is no API, exposed, it works on the HTML level parsing webpage using the PSParseHTML module, and if you want to find out how to set it up – Getting Azure Health by parsing HTML using PSParseHTML.

Azure Health

PSWriteHTML - Reporting / Emailing with zero HTML/CSS/JS knowledge

PSWriteHTML is my most favorite PowerShell module. It's my favorite because it pushes me to learn PowerShell, HTML, CSS and JavaScript at the same time. And it's not easy, at least not for me! PSWriteHTML was introduced in my last year summary blog as PowerShell module you will hear about in 2019. We're in 2020 and I have to say I believe we managed to just do that! This is what I had to say about it January 2019

This module is a fork of ReportHTML at least partially. And it's something I plan to work on in 2019. It's not prime time ready, but I can assure you that in 2019 I've big plans for it. Unfortunately besides deciding on how I would like my module to look like I've to also learn and play with HTMLJavaScript, and CSS. Something that is a bit out of my comfort zone, but I made some progress on it.

During 2019 I've managed to create separate modules called Dashimo and Emailimo with it's own features and syntax that were using PSWriteHTML behind the scenes. Those modules are now part of PSWriteHTML to minimize amount of modules required to create great HTML content. Ok, so I've been blabbing about how great PSWriteHTML is but I've not shown anything right?


PSWriteHTML supports multiple options. It allows you to build complicated tables, diagrams, calendars and many other things without knowing any HTML at all. It allows you to link Diagram with Table in a way where you click on node and it shows you corresponding element in table that provides additional information about it.


$Processes = Get-Process | Select-Object -First 10
$TableID = 'RandomID'

New-HTML -TitleText 'My Title' -UseCssLinks -UseJavaScriptLinks -FilePath $PSScriptRoot\Example30-LinkedProcesses.html -ShowHTML {
    New-HTMLSection -Invisible {
        New-HTMLPanel {
            New-HTMLTable -DataTable $Processes -DataTableID $TableID
        New-HTMLPanel {
            New-HTMLDiagram -Height '1000px' {
                New-DiagramEvent -ID $TableID -ColumnID 1
                New-DiagramNode -Label 'Processes' -IconBrands delicious
                foreach ($_ in $Processes) {
                    New-DiagramNode -Label $_.ProcessName -Id $_.Id -To 'Processes'

Similarly to what you can do in reporting using PSWriteHTML/Dashimo, you can achieve similar results in Email.


if ($null -eq $Table) {
    $Table = (Get-Process | Select-Object -First 5 -Property Name, BasePriority, Company, CompanyName)
if ($null -eq $Table1) {
    $Table1 = (Get-ChildItem | Select-Object -First 5)

Email -AttachSelf -AttachSelfName 'My report' {
    EmailHeader {
        EmailFrom -Address 'reminder@domain.pl'
        EmailTo -Addresses "przemyslaw.klys@domain.pl"
        EmailCC -Addresses "przemyslaw.klys@domain.pl"
        EmailBCC -Addresses "kontakt@domain.pl"
        EmailServer -Server 'mail.domain.pl' -UserName 'UserName' -Password 'C:\Support\Important\Password-Evotec-Reminder.txt' -PasswordAsSecure -PasswordFromFile
        EmailOptions -Priority Low
        EmailSubject -Subject 'This is a test email'
    EmailBody {

        EmailTextBox -FontFamily 'Calibri' -Size 17 -TextDecoration underline -Color DarkSalmon -Alignment center {
        EmailText -LineBreak
        EmailTextBox -FontFamily 'Calibri' -Size 15 {
            "This is some text that's preformatted with Emoji 🤷 ‍️"
            "Adding more text, notice ths should be on next line"
            "Empty line above will cause a blank space. If you want to continue writting like you would do in normal email please use here strings as seen below."
                This is tricky but it works like one ❤
                big line... even thou we've split this over few lines
                already this will be one continues line. Get it right? 😎
        EmailTable -Table $Table
        EmailTextBox -FontSize 15 -Color DarkCyan -FontStyle italic {
                This is tricky 😁 but it works like one
                big line... even thou we've split this over few lines
                already this will be one continues line. Get it right?
                Notice how I gave it color and made it font size 15.
        EmailList -FontSize 15 {
            EmailListItem -Text 'First item' -Color Red
            EmailListItem -Text '2nd item' -Color Green
            EmailList {
                EmailListItem -Text '3rd item' -FontStyle italic
                EmailListItem -Text '4th item' -TextDecoration line-through

        EmailTable -Table $Table1
        EmailText -LineBreak
        EmailText -FontSize 15 -Text 'This is my', 'text' -Color Red, Green -TextDecoration underline -FontFamily 'Calibri'
        EmailText -LineBreak
        EmailText -FontSize 15 -Text 'This is my', 'text', ' but ', ' with different formatting.' -Color Blue, Red, Green -TextDecoration underline, none, 'line-through' -FontFamily 'Calibri'

        EmailText -LineBreak

But that's not all the features PSWriteHTML can do. One of the commands it has is Out-HtmlView. This is command, a bit like Export-CSV or similar. It allows you to output any table to HTML, which than has export to excel, pdf and csv built-in. One of the cool features of that command is ability to compare two or more objects in a visually attractive way, giving you ability to see quickly what are the differences between them.

Get-ADComputer -SearchBase 'OU=Domain Controllers,DC=ad,DC=evotec,DC=xyz' -Filter * -Properties * | Select-Object -First 5 | Out-HtmlView -Compare -HighlightDifferences {
    New-HTMLTableReplace -Replacements 'AD2', 'AD1'
    New-HTMLTableReplace -Replacements 'AD3', 'AD1'

Out-HtmlView -Compare

I could spend all day showing you different examples of cool things that can be done with PSWriteHTML but it's just better to link to articles that talk about it.

All examples are also included in the Examples folder on the PSWriteHTML GitHub page.

Statusimo - PowerShell Generated Status Page

Statusimo is PowerShell Module that is based on PSWriteHTML. Most of the big companies have their own Status Page that shows status of different services they run. This module allows you to do something similar just with PowerShell.

All that content above is a single .html file that you can host on IIS/Apache or anywhere you want. You can generate it with a single command

New-StatusimoPage -FilePath $PSScriptRoot\StatusPage.html -IncidentsPath $PSScriptRoot\Incidents -MaintenancePath $PSScriptRoot\Maintenance

All other changes are done with JSON or with supporting commands adding Incidents or maintenance windows. It's simple in it's features, but at the same time quite useful. Any updates to Status Page are done with PowerShell just by generating a new HTML page. It's easy, fast, and can be automated. If you would like to find out more, read some old blog posts about it:

PSTeams - Sending messages to Microsoft Teams with advanced customization

PSTeams module was written in 2018, but in the last days of 2019, I've improved the way you can use it. Using code as below, you can send messages to the Microsoft Teams channel without much effort on your side.

Send-TeamsMessage -Verbose {
    New-TeamsSection {
        ActivityTitle -Title "**Elon Musk**"
        ActivitySubtitle -Subtitle "@elonmusk - 9/12/2016 at 5:33pm"
        ActivityImageLink -Link "https://pbs.twimg.com/profile_images/782474226020200448/zDo-gAo0.jpg"
        ActivityText -Text "Climate change explained in comic book form by xkcd xkcd.com/1732"
    New-TeamsSection {
        ActivityTitle -Title "**Mark Knopfler**"
        ActivitySubtitle -Subtitle "@MarkKnopfler - 9/12/2016 at 1:12pm"
        ActivityImageLink -Link "https://pbs.twimg.com/profile_images/1042367841117384704/YvrqQiBK_400x400.jpg"
        ActivityText -Text "Mark Knopfler features on B.B King's all-star album of Blues greats, released on this day in 2005..."
    New-TeamsSection {
        ActivityTitle -Title "**Elon Musk**"
        ActivitySubtitle -Subtitle "@elonmusk - 9/12/2016 at 5:33pm"
        ActivityImageLink -Link "https://pbs.twimg.com/profile_images/782474226020200448/zDo-gAo0.jpg"
        ActivityText -Text "Climate change explained in comic book form by xkcd xkcd.com/1732"
} -Uri $TeamsID -Color DarkSeaGreen -MessageSummary 'Tweet'


If you've been writing JSON in your scripts to send messages to Microsoft Teams, you can stop and use all cool features from the PSTeams module.


ADEssentials - Bunch of useful AD functions

ADEssentials is a small Active Directory module that has a handful of useful commands for AD needs. Testimo uses it to provide some insights into AD, but it also has some helpful set commands. I do intend to add more Active Directory commands into this module in 2020.

  • Get-WinADBitlockerLapsSummary
  • Get-WinADDFSHealth
  • Get-WinADForestObjectsConflict
  • Get-WinADForestReplication
  • Get-WinADForestRoles
  • Get-WinADGPOMissingPermissions
  • Get-WinADGPOSysvolFolders
  • Get-WinADLastBackup
  • Get-WinADLMSettings
  • Get-WinADPriviligedObjects
  • Get-WinADProxyAddresses
  • Get-WinADSiteConnections
  • Get-WinADSiteLinks
  • Get-WinADTombstoneLifetime
  • Get-WinADUsersForeignSecurityPrincipalList
  • Repair-WinADEmailAddress
  • Set-WinADReplication
  • Set-WinADReplicationConnections
  • Set-WinADTombstoneLifetime
  • Sync-DomainController
  • Test-ADDomainController
  • Test-ADRolesAvailability
  • Test-ADSiteLinks
  • Test-DNSNameServers
  • Test-FSMORolesAvailability
  • Test-LDAP
PSWritePDF - Module that allows you to create, split, merge PDF documents on Windows / Linux and macOs

I've released PSWritePDF at the end of 2019. It has couple of nice features such as ability to splitting and merging PDF documents. It's not as complete as PSWriteWord but it does bring couple of useful features and good starting point for future improvements.


Merging PDF?

$FilePath1 = "$PSScriptRoot\Input\OutputDocument0.pdf"
$FilePath2 = "$PSScriptRoot\Input\OutputDocument1.pdf"
$OutputFile = "$PSScriptRoot\Output\OutputDocument.pdf" # Shouldn't exist / will be overwritten
Merge-PDF -InputFile $FilePath1, $FilePath2 -OutputFile $OutputFile

Splitting PDF?

Split-PDF -FilePath "$PSScriptRoot\SampleToSplit.pdf" -OutputFolder "$PSScriptRoot\Output"

That's it. It works on Windows, Linux and macOs. It works on PowerShell 5.1, PowerShell 6 and PowerShell 7. If you would like to find out about all the features it has here's my article about it Merging, splitting and creating PDF files with PowerShell.

PSWriteWord - Creating / Reading Microsoft Word documents with PowerShell without Word being installed

PSWriteWord was on my module list last year already. I do continue adding new features and improving its experience. For now, it only works on Windows, but maybe in 2020, it will be able to work on all systems. Unfortunately, it's not entirely my choice as it's based on the Xceed DocX library. They also changed a license for the newest 1.5 release, which complicates things a bit. Currently, PSWriteWord stays at 1.4, which is freer than the new one. But with the release of 1.6 and hopefully support for .NET Standard, I will have no other choice than to adopt that version. In 2020 I've created Documentimo, which is based on PSWriteWord. It takes an approach that I'm using in PSWriteHTML/Dashimo/Excelimo and PSWritePDF. It simplifies creating new Word documents making it as easy as this:

Import-Module Documentimo -Force
$Table = Get-Process | Select-Object -First 5
$TableForCharts = @(
    [PSCustomObject] @{ Name = 'Test 1'; SomeValue = 1 }
    [PSCustomObject] @{ Name = 'Test 2'; SomeValue = 5 }
    [PSCustomObject] @{ Name = 'Test 3'; SomeValue = 6 }
Documentimo -FilePath $PSScriptRoot\Test.docx {
    DocTOC -Title 'Table of content'
    DocPageBreak -Verbose
    DocNumbering -Text 'My document' -Level 0 -Type Numbered -Heading Heading1 {
        DocText -Text 'Test', ' Test2' -Color Yellow
        DocTable -DataTable $Table -Design ColorfulGrid
    DocNumbering -Text 'Chart' {
        DocChart -Title 'Processes' -DataTable $Table  -Key 'ProcessName' -Value 'Handles'
    DocNumbering -Text 'AnotherChart' {
        DocChart -Title 'Priviliged Group Members' -DataTable $TableForCharts  -Key 'Name' -Value 'SomeValue'
    $Table1 = Get-Process | Select-Object -First 5
    DocTable -DataTable $Table -Design ColorfulGrid
    DocList {
        DocListItem -Text 'Test' -Level 0
        DocListItem -Text 'Test1' -Level 2
    DocList -Type Numbered {
        DocListItem -Text 'Test' -Level 0
        DocListItem -Text 'Test1' -Level 2
    DocTable -DataTable $Table1 -Design ColorfulGrid
} -Open


Right now, Documentimo is a separate module that has PSWriteWord as a required module. However, in 2020, I'd like to migrate it back to PSWriteWord and limit the number of modules that I've to support and potentially improve it.

PSWriteWord - Creating / Reading Microsoft Word documents with PowerShell without Word being installed

Another new module in 2019 was PSLansweeper. Lansweeper is excellent, free, or almost free inventory system that provides lots of details over your infrastructure. PSLansweeper uses the SQL database of Lansweeper to provide data that is visible, available in it as PowerShell objects. This allows you to create new automation on inventory data Lansweeper has gathered over months or years.


If you would like to find out more about it, all information is included in my blog post Using Lansweeper with PowerShell to your advantage.

PSParseHTML - HTML reading, formatting and minifying

PSParseHTML is to reading HTML like PSWriteHTML is to writing it. For now, it has only nine commands, but those commands are useful enough. Trust me on that.

  • Convert-HTMLToText
  • ConvertFrom-HtmlTable
  • ConvertFrom-HTMLTag
  • Format-CSS
  • Format-HTML
  • Format-JavaScript
  • Optimize-CSS
  • Optimize-HTML
  • Optimize-JavaScript

You can minify or format your HTML, JavaScript, or CSS to either make sure it's as small as possible or as readable as possible. It also has parsing capabilities of the website with the ability to extract whole tables from the site as a PowerShell object.

$Test = ConvertFrom-HtmlTable -Url 'https://www.goal.com/en-us/premier-league/table/2kwbbcootiqqgmrzs6o5inle5'
$Test | Format-Table -AutoSize *
$Test = ConvertFrom-HtmlTable -Url 'https://www.goal.com/en-us/premier-league/table/2kwbbcootiqqgmrzs6o5inle5' -Engine AngleSharp
$Test | Format-Table -AutoSize *


This gives you unlimited possibilities in PowerShell extracting League Tables, Wikipedia articles, and so on.

Summary of 2019

There are many, many more modules I've touched during 2019, and hopefully, in 2020, I'll make some improvements to them. Feel free to explore my GitHub as everything I create usually ends up there, free to use, open-source. I have no financial gain from making them. I have no ads on my website, which would cover development and I don't intend to have any. I do it mostly in my free time, providing it for free. Not sure how accurate WakaTime stats are, because I don't remember when I enabled a VSCode extension, but it would seem I've spent over 300 hours on PSWriteHTML alone.

Programming Stats for 2019

My stats from blog also improved year to year.

Google Analytics Evotec

As I mentioned on begining of this post download count for all my modules also improved year to year.


All in all I must say 2019 was a good year for me with lot's of learning. A lot of people helped along the way. Thank you!

Tags: , , ,

This is a unique website which will require a more modern browser to work! Please upgrade today!