Powershell: Create Event with parameters

This function will let you stamp events to the Windows EventLog, and feed the event with filterable parameterdata (which in the cases you use SCOM to sniff events, is pretty awesome).

I use this all the time in cases where a script should dump some kind of result to the eventlog, and using SCOM to fetch the event and trigger on special texts or values in the parameterdata returned.

function createParamEvent ()
  Function for creating events, just like create-event or eventcreate.exe - but with the added functionality to add up to 5 filterable parameters.
  The function stamps Windows Events to the Windows Eventlog by your choice, but can also be fed up to 5 different parameters, where param1 contains the basic Event Description, and param2 to param5 contains data of your choosing.
  For Information events, use eventID 220:
  CreateParamEvent -source "TestSource" -evtID 220 -param1 "The server $hostname shut down at $timestamp" -param2 $hostname -param3 $timestamp -param4 "Some generic text"
  For Warning events:
  CreateParamEvent -source "TestSource" -evtID 221 -param1 "The server $hostname shut down at $timestamp" -param2 $hostname -param3 $timestamp -param4 "some generic text"
  For Error events, with the manditory param1 set. All parameters from param2 to param5 are not manditory:
  CreateParamEvent -source "TestSource" -evtID 222 -param1 "The server $hostname shut down at $timestamp"
  Alle andre eventID'er vil logges som information events.
  Mandatory: The logic in this function is based on the principle where the sample eventIDs (222, 221, 220) will throw an error corresponding to the Event Type (error, warning, information). Other EventIDs can be used, but will then be logged as an Information Event.
  .PARAMETER param1
  Mandatory: The full description in the event.
  .PARAMETER param2-5
  Use theese parameters to add additional useful information to the mix, for example additional information that can be pulled from the Event in SCOM.
  - Param1 = Full description in the event
  - Source is mandetory
  - EventID is mandetory
  - Eventid 222 = Error event
  - Eventid 221 = Warning event
  - Eventid 220 = Information event
  - Param2 to 5 are optional.
    #Define the event log
    $evtlog = "Application"

    #Load the event source to the log if not already loaded.  This will fail if the event source is already assigned to a different log.
    if ([System.Diagnostics.EventLog]::SourceExists($source) -eq $false) {
        [System.Diagnostics.EventLog]::CreateEventSource($source, $evtlog)

    if ($evtID -eq 222){
    $id = New-Object System.Diagnostics.EventInstance($evtID,1,1); #ERROR EVENT
    elseif ($evtID -eq 221){
    $id = New-Object System.Diagnostics.EventInstance($evtID,1,2); #WARNING EVENT
    $id = New-Object System.Diagnostics.EventInstance($evtID,1); #INFORMATION EVENT
    $evtObject = New-Object System.Diagnostics.EventLog;
    $evtObject.Log = $evtlog;
    $evtObject.Source = $source;
    $evtObject.WriteEvent($id, @($param1,$param2,$param3,$param4,$param5))


SCCM Lab: Part 2 – DHCP and DNS Server roles on our AD controller

This part in the SCCM Lab series will cover installing and configuring the DHCP and DNS Server roles on our headless Windows 2019 server we configured in Part 1. Here we go.

The DNS server was created when AD DS role installed the root forest. We can see that the DNS role is installed using the Get-WindowsFeature command:

Get-WindowsFeature -name "DNS*

As you can see, the DNS Server feature is installed – BUT If your DNS server is not installed, you can install it with this command:

Install-WindowsFeature DNS -IncludeManagementTools

The DNS primary zone is created when the forest is generated. Next, the network ID and file entry is made:

Add-DnsServerPrimaryZone -NetworkID -ZoneFile “”

Next, the forwarder is added:

Add-DnsServerForwarder -IPAddress -PassThru

You should now be able to test your dns server:

Test-DnsServer -IPAddress -ZoneName "sccmlab.net"

That’s it for configuring DNS – now let’s look at the DHCP Server Feature

To do this, you have to set a static IP address on your server. This we covered in Part 1, but if you totally forgot, don’t worry. Set a static IP address like this:

New-NetIPAddress -InterfaceIndex 2 -IPAddress -PrefixLength 24 -DefaultGateway

Next, install the DHCP Server Feature.

Install-WindowsFeature DHCP -IncludeManagementTools

After this, a security group is created using the netsh command. The service is then restarted. When the following command is run, the DHCP Administrators and DHCP Users security groups are created in Local Users and Groups on the DHCP server.

netsh dhcp add securitygroups
restart-service dhcpserver

Now that the DHCP role and security groups are installed, we need to configure the subnets, scope and exclusions. Configure the DHCP scope for the domain. This will be the addresses that are handed out the to network by DHCP.

AddDhcpServerV4Scope -name "Lab Servers Scope" -StartRange -EndRange -subnetmask -State Active
Next, authorize the DHCP server to operate in the domain:
Set-DHCPServerv4OptionValue -ScopeID -DnsDomain sccmlab.net -DnsServer -Router

Finally, the DHCP Server is added to the DC:

Add-DhcpServerInDC -DnsName sccm-ad1.sccmlab.net -IpAddress

We can verify the DHCP Scope setting using this command:


We can verify the existence of this DHCP server in this DC with the following command:


Restart the DHCP service:

Restart-service dhcpserver


SCCM Lab: Part 1 – AD Controller

I am currently setting up a new SCCM testenvironment in my home-lab – this will be one of (possibly) many quick-n-dirty how-to’s for setting up a functioning SCCM lab.

First things first – the lab wil consist of Server 2019 and Windows 10 servers and clients.
The SCCM version used is SCCM current-branch 1902.

All servers will be headless.

I have already installed a box-fresh Windows 2019 Standard server, without GUI. Continuing on from that, we will do the following:

  • Configure network settings
  • Configure Local date/time
  • Configure the firewall to allow pingreplies

Using sconfig – name your server something. In this case, I am calling it sccm-ad1.
Next up, edit your network card settings – configure your adapter with a static IP address, and set DNS server to

Return to the main menu, and configure your local Date and Time settings to your correct timezone.

Restart your server – and jump in to a powershell session.

I like my labcomputers replying to pingrequests, so to allow this – type in the following command (applies to IPV4):

New-NetFirewallRule -Displayname "Allow inbound ICMPv4" -direction Inbound -Protocol ICMPv4 -IcmpType 8 -remoteaddress <your subnet> -action allow

Restart your server.

Next up, we will install the AD Controller role.
Jump in to a Powershell session, and enter the following:

Get-WindowsFeature AD-Domain-Services | Install-WindowsFeature

let the installation finish, then enter the following:

Import-Module ADDSDeployment

Then, to install the new AD controller in our new forest, enter the following:


Continue by entering your domainname of choice, and a SafeMode password. After installation is finished, the server will restart and finish configuration.

Next I’ll create a new AD user in this domain, for administrating the environment. Do this by entering a Powershell session, and enter:

New-ADUser -name "Awesome" -Givenname "Awesome" -Surname "Sauce" -SamAccountName "Awesome" -UserPrincipalName "awesome@your.domain"

Test that you have successfully created the user by entering:

Get-AdUser Awesome

You will find the user is not active yet. Before enabling the user, set the password for that user.

Command to set password:

Set-ADAccountPassword 'CN=Awesome,CN=users,DC=sccmlab,DC=net' -Reset -NewPassword (ConvertTo-SecureString -AsPlainText “YourPassword” -Force)

Add the user to Domain Admins group

Add-AdGroupMember ‘Domain Admins’ Awesome

And there you have it – your very own Headless Windows Server 2019 AD Controller.


Powershell: Get file- and foldersize for given path

Quick and dirty little thing I use to get the file- and foldersize for any given path.

# Get-pathsize.ps1
# Use: C:scriptsget-pathsize.ps1 -path <your-path>

param (

try {
 Get-ChildItem $path -Hidden -ErrorAction Stop

catch {

$colItems = (Get-ChildItem $path -recurse | Measure-Object -property length -sum) 
[int]$size = [math]::round($colItems.sum /1MB, 2) 
write-host "Files and foldersize in $path is: $size MB"


SCOM: Get Subscriber in Subscription

This little thing will search through, and get all subscribers containing your searchword in any subscription you may have set up in SCOM.


$sub = Get-SCOMNotificationSubscription | select displayname,torecipients

write-host "Searchword: ""$searchword"" exists in the following subscriptions:"
foreach ($s in $sub){
    $recipient = $s.torecipients.name
    if ($recipient -like "$searchword"){
    write-host ""$s.displayname""

– F

SCOM: Command Channel Script

This little script is what I use in cooperation with the SCOM Command Channel to parse and send SCOM alerts to a logfile.
The script will take the SCOM alert parameters and put them neatly in a .log file, one file for each alert I want. This, of course, is customizable – I just like to see the amount of files being generated.

The Channel:


The above channel parameters:

Path: C:\windows\system32\WindowsPowershell\v1.0\powershell.exe
Cmd: -file “C\:Script\AlertExport.ps1” “$Data[Default=’Not Present’]/Context/DataItem/AlertId$##$Data[Default=’Not Present’]/Context/DataItem/AlertName$##$Data[Default=’Not Present’]/Context/DataItem/AlertDescription$##$Data[Default=’Not Present’]/Context/DataItem/EntityPath$##$Data[Default=’Not Present’]/Context/DataItem/EntityDisplayName$”
Startdir: c:\

This will get you the following (of MANY) Alert details: AlertID, Alert Name, Alert Description, Path and Displayname.

The Script:

# Alert Params
$params = $parameters.split('##') | ? {$_ -ne ''}

# Build params (added commented blocks of Alert parameter data for your convenience)
$AlertID = $params[0] # $Data/Context/DataItem/AlertID$
$AlertName = $params[1] # $Data/Context/DataItem/AlertName$
$AlertDesc = $params[2]# $Data/Context/DataItem/AlertDescription$
$Path = $params[3] # $Data/Context/DataItem/ManagedEntityPath$
$DisplayName = $params[4] # $Data/Context/DataItem/ManagedEntityDisplayName$

# Sharestuff
$date = get-date
$Alertfile = "SCOM Alert - $(get-date -Format "dd.MM.yyyy HH.mm.ss").log"

# Format AlertMessage
$AlertMessage = @()

$AlertMessage += "ID: $AlertID"
$AlertMessage += "Date: $date"
$AlertMessage += "DisplayName: $DisplayName"
$AlertMessage += "AlertName: $AlertName"
$alertMessage += "Path: $Path"
$AlertMessage += "Description: $AlertDesc"

# Output alert to textfile
$AlertMessage >> $share$alertfile

Put the script on all your Management Servers, in this case in the C:\script folder, and suddenly, if all goes well, your selected Alerts will start pumping out to this share.


– F

Request Template Certificates using CertReq and Powershell

Installing SCOM agents on non-domain servers can be a real time-consuming affair, especially the Create template-request-export-import-certificates procedure.
I decided to use my basic certificate and CertReq knowlegde to create this little script that helps me automate the whole thing.

NOTE: This is meant for inspiration only. If will for the most part not work in your environment unless you heavily modify it.

Basically it requests a new certificate from your CA server, based on a predefined Template.
It then works some magic, and you are left with the *.pfx certificate file with private key, necessary for the SCOM agent on the non-domain server to communicate with the rest of the SCOM environment.

In the end, the certificate can be copied to the non-domain server, and import it using MOMCertImport found in the SCOM Agent Support Tools folder.

#$password = Read-Host -Prompt "Enter Password" -AsSecureString
$server = read-host -Prompt "Enter FQDN for DMZ Server"

$CERTPATH = "Location you want to save Certificate to"
$CAFQDN = "CAserver.domain.net"
$CASERVER = "CAserver.domaint.netIssuing CA1 example"

write-host "Variables set. Continue to create .inf"  -foregroundcolor green

write-host "Generating Certificate INF File..."
$certinf = @"
ProviderName="Your Provider"
CertificateTemplate=CA Template Name

$certinf >> "$CERTPATH$server.inf"

write-host ".inf created. Continue to create .req file"  -foregroundcolor green

CertReq.exe -new "$CERTPATH$server.inf" "$CERTPATH$server.req"

write-host ".req created. Checking to see of files exist"  -foregroundcolor green

$testinf = Test-Path "$CERTPATH$server.inf"
$testreq = Test-Path "$CERTPATH$server.req"

if ($testinf -eq $true){
write-host "$CERTPATH$server.inf successfully generated." -foregroundcolor green
else {
write-host "$CERTPATH$server.inf could not be found. Check for errors." -ForegroundColor Red
if ($testreq -eq $true){
write-host "$CERTPATH$server.req successfully generated." -foregroundcolor green
else {
write-host "$CERTPATH$server.req could not be found. Check for errors." -ForegroundColor Red

write-host "Submitting new Certificate for $server"

CertReq -Submit -config "CAserver.domaint.netIssuing CA1 example" "$CERTPATH$server.req" "$CERTPATH$server.cer"

write-host "Importing .cer"

certreq -accept "$CERTPATH$server.cer"
write-host "All OK. Continue"  -foregroundcolor green

#Exporting certificate with Private Key
write-host "exporting shit with private key"
certutil -exportpfx -p "YOUR CERTIFICATE PASSWORD" my "$server" "$certpath$server.pfx" "nochain" 

Move-Item -Path "$CERTPATH*cer","$CERTPATH*inf","$CERTPATH*req" -Destination "$CERTPATHold"

And there you have it. The task that normally was done in 10-20 minutes is now done in 10-20 seconds.
I also have a script that copies SCOM agent files to the non-domain server, installs the SCOM agent based on bit-architechture, imports the certificate using MOMCertImport.exe and restarts the Microsoft Monitoring Agent, but this was not written by me, and I don’t remember where I found it (or who to credit) – so if you want it, hit me up in the comment section, and I’ll send it to you.

– F