{"id":8067,"date":"2021-01-22T11:50:43","date_gmt":"2021-01-22T16:50:43","guid":{"rendered":"https:\/\/jdhitsolutions.com\/blog\/?p=8067"},"modified":"2021-01-22T11:50:49","modified_gmt":"2021-01-22T16:50:49","slug":"building-an-active-directory-watcher-with-cim-and-powershell","status":"publish","type":"post","link":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8067\/building-an-active-directory-watcher-with-cim-and-powershell\/","title":{"rendered":"Building an Active Directory Watcher with CIM and PowerShell"},"content":{"rendered":"\n<div class=\"wp-block-image is-style-default\"><figure class=\"alignleft size-large is-resized\"><a href=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/2DomainWithOus01.png\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/2DomainWithOus01.png\" alt=\"AD Domain\" class=\"wp-image-8068\" width=\"201\" height=\"178\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/2DomainWithOus01.png 402w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/2DomainWithOus01-300x265.png 300w\" sizes=\"auto, (max-width: 201px) 100vw, 201px\" \/><\/a><\/figure><\/div>\n\n\n\n<p>Last week, <a href=\"https:\/\/twitter.com\/adbertram\" target=\"_blank\" rel=\"noreferrer noopener\">Adam Bertram<\/a> sent out a tweet looking for any PowerShell code to notify the user when a new Active Directory user account had been created. I dug out some very, very old code that used a WMI event subscription to watch Active Directory for such an event. The code I shared was something I put together back in the PowerShell v2 days, but it still worked today. However, it used Register-WMIEvent which in today's PowerShell world I consider deprecated. We should be using the newer CIM equivalent cmdlets. I decided to take a little time and polish up the code and bring it up to (my) current standards.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">WMI\/CIM Event Subscriptions<\/h2>\n\n\n\n<p>In the Windows world, when something happens like a service starting or a process ending, we get an <em>event<\/em>. In Active Directory, creating a new user account also fires an event. In many cases, you can watch for these events using WMI\/CIM. You accomplish this by creating a temporary event subscription. This is like any other subscription. You are saying, \"Send me a new issue when there is something new to report.\" You could get a new \"issue\" every 2 weeks or every 2 minutes. <\/p>\n\n\n\n<p>You will use <a href=\"https:\/\/docs.microsoft.com\/powershell\/module\/cimcmdlets\/register-cimindicationevent?view=powershell-7.1&amp;WT.mc_id=ps-gethelp\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">Register-CimIndicationEvent<\/a> to create the subscription. You can create subscriptions for events on your local computer or remote.  This subscription only lasts for the duration of your PowerShell session.  But a word of caution, I would be careful about building a complete management system around it except for small environments. While it is nice to know when something happens like a service stopping or a user account being modified, in larger environments, you are better off investing in tools and software designed for that type of monitoring. I would use temporary event subscriptions for short-term monitoring or troubleshooting. With this in mind, consider the code in this article as proof-of-concept.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Register-CIMIndicationEvent<\/h2>\n\n\n\n<p>I am trusting you will take the time to read full help and examples for this cmdlet. WMI events is a complicated topic and I'm not going to get too deep. There are several ways to use the cmdlet. I'm going to use an old-fashioned query.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">Register-CimIndicationEvent -Query \"Select * from __InstanceCreationEvent Within 10 where TargetInstance ISA 'DS_USER'\" -Namespace root\\directory\\ldap -SourceIdentifier NewUser<\/code><\/pre>\n\n\n\n<p>I am running this code on a domain member Windows 10 desktop. The query says, \"check for a creation event every 10 seconds where the object type is a user account.\" The <strong>Within <\/strong>portion is referred to as <em>polling<\/em>. You don't want to poll too quickly. If you truly need to know within seconds when an event happens, you need to find a true software solution. I'm using 10 seconds for my demo. <\/p>\n\n\n\n<p>This will create an event subscription.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><a href=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-eventsubscriber.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"268\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-eventsubscriber-1024x268.png\" alt=\"\" class=\"wp-image-8069\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-eventsubscriber-1024x268.png 1024w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-eventsubscriber-300x79.png 300w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-eventsubscriber-768x201.png 768w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-eventsubscriber-850x223.png 850w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-eventsubscriber.png 1477w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>The <em>SourceIdentifier <\/em>is how you can reference the subscriber and subsequent events. If you don't specify one, you'll get a GUID. Personally, I find defining my own identifiers much easier. <\/p>\n\n\n\n<p>The event subscriber is running in my local PowerShell session, checking every 10 seconds for a new user creation event in the domain. I'll create a new domain user. 10 seconds later nothing has happened in my session. We'll change that later. Instead I'll run Get-Event.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><a href=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-event.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"246\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-event-1024x246.png\" alt=\"\" class=\"wp-image-8070\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-event-1024x246.png 1024w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-event-300x72.png 300w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-event-768x184.png 768w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-event-1536x368.png 1536w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-event-850x204.png 850w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-event.png 1710w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>Information about the user is buried in the event.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><a href=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/targetinstance.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"377\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/targetinstance-1024x377.png\" alt=\"\" class=\"wp-image-8071\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/targetinstance-1024x377.png 1024w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/targetinstance-300x111.png 300w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/targetinstance-768x283.png 768w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/targetinstance-1536x566.png 1536w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/targetinstance-850x313.png 850w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/targetinstance.png 1983w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>I'll come back to this object in a bit. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Register-ADWatcher<\/h2>\n\n\n\n<p>With these basics in mind, I wrote a PowerShell function that wraps around Register-CimIndicationEvent. The function allows me to watch for different types of events for different categories of Active Directory objects.<\/p>\n\n\n\n<pre title=\"Register-ADWatcher\" class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">Function\u00a0Register-ADWatcher\u00a0{\n\u00a0\u00a0\u00a0\u00a0[cmdletbinding(<em>SupportsShouldProcess<\/em>)]\n\u00a0\u00a0\u00a0\u00a0Param(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[Parameter(<em>Mandatory<\/em>,\u00a0<em>HelpMessage<\/em>\u00a0=\u00a0\"What\u00a0type\u00a0of\u00a0object\u00a0do\u00a0you\u00a0want\u00a0to\u00a0watch?\")]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[ValidateSet(\"User\",\u00a0\"Group\",\u00a0\"Computer\",\u00a0\"OU\")]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[string]$Category,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[Parameter(<em>Mandatory<\/em>,\u00a0<em>HelpMessage<\/em>\u00a0=\u00a0\"What\u00a0type\u00a0of\u00a0activity\u00a0watch?\")]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[ValidateSet(\"Create\",\u00a0\"Modify\",\u00a0\"Remove\")]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[string]$Activity,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[Parameter(<em>HelpMessage<\/em>\u00a0=\u00a0\"How\u00a0often\u00a0do\u00a0you\u00a0want\u00a0to\u00a0poll?\u00a0Enter\u00a0a\u00a0value\u00a0in\u00a0seconds.\u00a0The\u00a0minimum\u00a0and\u00a0default\u00a0is\u00a010.\")]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[ValidateNotNullOrEmpty()]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[ValidateScript({\u00a0$_\u00a0-ge\u00a010\u00a0})]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[int]$Poll\u00a0=\u00a010,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[Parameter(<em>HelpMessage<\/em>\u00a0=\u00a0\"Specify\u00a0an\u00a0action\u00a0scriptblock\u00a0when\u00a0the\u00a0event\u00a0fires.\")]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[scriptblock]$Action,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[Parameter(<em>HelpMessage<\/em>\u00a0=\u00a0\"Specify\u00a0additional\u00a0data\u00a0to\u00a0associate\u00a0with\u00a0the\u00a0watcher.\")]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[string]$MessageData,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[Parameter(<em>HelpMessage<\/em>\u00a0=\u00a0\"Specify\u00a0a\u00a0name\u00a0for\u00a0the\u00a0watcher\")]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[string]$SourceIdentifier,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[parameter(<em>HelpMessage<\/em>\u00a0=\u00a0\"Specify\u00a0the\u00a0name\u00a0of\u00a0a\u00a0computer\u00a0where\u00a0you\u00a0want\u00a0to\u00a0create\u00a0the\u00a0watcher.\")]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[string]$Computername,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[switch]$Passthru\n\u00a0\u00a0\u00a0\u00a0)\n\n\u00a0\u00a0\u00a0\u00a0Write-Verbose\u00a0\"Starting\u00a0$($myinvocation.mycommand)\"\n\u00a0\u00a0\u00a0\u00a0<em>#remove\u00a0bound\u00a0parameters\u00a0that\u00a0don't\u00a0belong\u00a0to\u00a0Register-CimIndicationEvent<\/em>\n\u00a0\u00a0\u00a0\u00a0$drop\u00a0=\u00a0\"Category\",\u00a0\"Activity\",\u00a0\"Poll\",\u00a0\"WhatIf\",\u00a0\"Confirm\",\"Passthru\"\n\u00a0\u00a0\u00a0\u00a0foreach\u00a0($item\u00a0in\u00a0$drop)\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if\u00a0($PSBoundParameters.ContainsKey($item))\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[void]$PSBoundParameters.Remove($item)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0}\n\n\u00a0\u00a0\u00a0\u00a0Switch\u00a0($Category)\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"User\"\u00a0{\u00a0$DS\u00a0=\u00a0\"DS_USER\"\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"Group\"\u00a0{\u00a0$DS\u00a0=\u00a0\"DS_GROUP\"\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"Computer\"\u00a0{\u00a0$DS\u00a0=\u00a0\"DS_COMPUTER\"\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"OU\"\u00a0{\u00a0$DS\u00a0=\u00a0\"DS_ORGANIZATIONALUNIT\"\u00a0}\n\u00a0\u00a0\u00a0\u00a0}\n\n\u00a0\u00a0\u00a0\u00a0Switch\u00a0($Activity)\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"Create\"\u00a0{\u00a0$DSAction\u00a0=\u00a0\"__InstanceCreationEvent\"\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"Modify\"\u00a0{\u00a0$DSAction\u00a0=\u00a0\"__InstanceModificationEvent\"\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"Remove\"\u00a0{\u00a0$DSAction\u00a0=\u00a0\"__InstanceDeletionEvent\"\u00a0}\n\u00a0\u00a0\u00a0\u00a0}\n\n\u00a0\u00a0\u00a0\u00a0$query\u00a0=\u00a0\"Select\u00a0*\u00a0from\u00a0$DSAction\u00a0Within\u00a0$Poll\u00a0where\u00a0TargetInstance\u00a0ISA\u00a0'$DS'\"\n\u00a0\u00a0\u00a0\u00a0$PSBoundParameters.Add(\"Query\",\u00a0$query)\n\u00a0\u00a0\u00a0\u00a0$PSBoundParameters.Add(\"Namespace\",\u00a0\"root\\directory\\ldap\")\n\n\u00a0\u00a0\u00a0\u00a0Write-Verbose\u00a0\"Creating\u00a0an\u00a0AD\u00a0Watcher\u00a0with\u00a0these\u00a0parameters\"\n\u00a0\u00a0\u00a0\u00a0$PSBoundParameters\u00a0|\u00a0Out-String\u00a0|\u00a0Write-Verbose\n\n\u00a0\u00a0\u00a0\u00a0$target\u00a0=\u00a0\"$Activity\u00a0$Category\u00a0within\u00a0$Poll\u00a0seconds\"\n\u00a0\u00a0\u00a0\u00a0If\u00a0($pscmdlet.ShouldProcess($target.toUpper(),\u00a0\"Register\u00a0AD\u00a0Watcher\"))\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[void](Register-CimIndicationEvent\u00a0@PSBoundParameters)\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if\u00a0($Passthru)\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Start-sleep -Seconds 2\n            Get-EventSubscriber | Sort-Object -property SubscriberID | Select-Object -last 1\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0Write-Verbose\u00a0\"Ending\u00a0$($myinvocation.mycommand)\"\n}<\/code><\/pre>\n\n\n\n<p>I'll use this function to watch for new groups.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">Register-ADWatcher -Category Group -Activity Create -MessageData \"A new group has been created\" -SourceIdentifier \"NewGroup\"<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><a href=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/eventsubscribers.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"447\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/eventsubscribers-1024x447.png\" alt=\"\" class=\"wp-image-8072\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/eventsubscribers-1024x447.png 1024w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/eventsubscribers-300x131.png 300w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/eventsubscribers-768x335.png 768w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/eventsubscribers-850x371.png 850w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/eventsubscribers.png 1482w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>I'm eventually going to replace the new user subscription so I'll delete the current one.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">Get-EventSubscriber newuser | Unregister-Event<\/code><\/pre>\n\n\n\n<p>Now to create a new group and see the event.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><a href=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/newgroup-event.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"234\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/newgroup-event-1024x234.png\" alt=\"\" class=\"wp-image-8073\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/newgroup-event-1024x234.png 1024w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/newgroup-event-300x69.png 300w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/newgroup-event-768x176.png 768w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/newgroup-event-1536x351.png 1536w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/newgroup-event-850x194.png 850w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/newgroup-event.png 1749w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Helper Functions<\/h2>\n\n\n\n<p>I know information about the group is in there, but I'm too lazy to parse the object. Instead I'll write a helper function.<\/p>\n\n\n\n<pre title=\"Get-TargetInstance\" class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">Function\u00a0Get-TargetInstance\u00a0{\n\u00a0\u00a0\u00a0\u00a0[cmdletbinding()]\n\u00a0\u00a0\u00a0\u00a0Param(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[Parameter(<em>Mandatory<\/em>,\u00a0<em>ValueFromPipeline<\/em>)]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[object]$EventResult,\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[Parameter(<em>HelpMessage<\/em>\u00a0=\u00a0\"Only\u00a0show\u00a0defined\u00a0properties\")]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[switch]$ShowDefined\n\u00a0\u00a0\u00a0\u00a0)\n\n\u00a0\u00a0\u00a0\u00a0Process\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if\u00a0($ShowDefined)\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$t\u00a0=\u00a0$EventResult.SourceEventArgs.NewEvent.TargetInstance\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$t.psobject.Properties.where({\u00a0$_.name\u00a0-match\u00a0\"^DS|ADSIPath\"\u00a0-AND\u00a0$_.value\u00a0})\u00a0|\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ForEach-Object\u00a0-Begin\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<em>#create\u00a0a\u00a0temporary\u00a0ordered\u00a0hashtable<\/em>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$h\u00a0=\u00a0[ordered]@{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0TimeGenerated\u00a0=\u00a0$EventResult.timeGenerated\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0EventClass\u00a0\u00a0\u00a0\u00a0=\u00a0$EventResult.SourceEventArgs.NewEvent.CimSystemProperties.Classname\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\u00a0-Process\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<em>#add\u00a0each\u00a0property\u00a0that\u00a0has\u00a0a\u00a0value\u00a0to\u00a0the\u00a0hashtable<\/em>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$h.add($_.name,\u00a0$_.value)\u00a0}\u00a0-End\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<em>#Create\u00a0a\u00a0custom\u00a0object\u00a0from\u00a0the\u00a0hashtable<\/em>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0New-Object\u00a0-TypeName\u00a0PSObject\u00a0-Property\u00a0$h\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0else\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$EventResult.sourceEventArgs.NewEvent.TargetInstance\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0}\n}<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><a href=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-targetinstance.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"464\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-targetinstance-1024x464.png\" alt=\"get target event instance\" class=\"wp-image-8074\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-targetinstance-1024x464.png 1024w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-targetinstance-300x136.png 300w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-targetinstance-768x348.png 768w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-targetinstance-1536x696.png 1536w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-targetinstance-850x385.png 850w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-targetinstance.png 1583w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>Because I know the object will have many undefined or null property values, I added a parameter to only show populated properties.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><a href=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-targetinstance-defined.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"508\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-targetinstance-defined-1024x508.png\" alt=\"get target instance defined\n\" class=\"wp-image-8075\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-targetinstance-defined-1024x508.png 1024w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-targetinstance-defined-300x149.png 300w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-targetinstance-defined-768x381.png 768w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-targetinstance-defined-850x422.png 850w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/get-targetinstance-defined.png 1435w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Actions<\/h2>\n\n\n\n<p>In looking at this, I can see that I fat-fingered the group name. Perfect. Let's create a watcher for changes to group objects. I can also show you how to add an Action. This is a scriptblock that runs when the event fires. I'm going to use the BurntToast module, which you can install from the PowerShell Gallery, to show me a notification.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">Register-ADWatcher -Category Group -Activity Modify -SourceIdentifier \"GroupChange\" -Action { New-BurntToastNotification -Text \"A group has changed\"}<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><a href=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/toast.png\"><img loading=\"lazy\" decoding=\"async\" width=\"580\" height=\"171\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/toast.png\" alt=\"\" class=\"wp-image-8076\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/toast.png 580w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/toast-300x88.png 300w\" sizes=\"auto, (max-width: 580px) 100vw, 580px\" \/><\/a><\/figure>\n\n\n\n<p>But there is a trade-off when using an action.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><a href=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/no-event.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"426\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/no-event-1024x426.png\" alt=\"\" class=\"wp-image-8077\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/no-event-1024x426.png 1024w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/no-event-300x125.png 300w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/no-event-768x319.png 768w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/no-event-1536x638.png 1536w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/no-event-850x353.png 850w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/no-event.png 1713w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>There is no event object. Well, I should say, there's no object written to my console. There is an object I can reference in my Action scriptblock. But first let me show what that is.<\/p>\n\n\n\n<p>Here's a watcher for changed user objects.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">Register-ADWatcher -Category User -Activity Modify -SourceIdentifier UserChange -Passthru<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><a href=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/change-event.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"379\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/change-event-1024x379.png\" alt=\"\" class=\"wp-image-8078\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/change-event-1024x379.png 1024w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/change-event-300x111.png 300w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/change-event-768x284.png 768w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/change-event-1536x568.png 1536w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/change-event-850x314.png 850w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/change-event.png 1571w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>When a change event fires, you get a \"before\" and \"after\" object. Naturally you would like to know what changed. I tried using Compare-Object which would seem like the appropriate tool. But unless I specify a property, it doesn't give me a result. So I wrote my own comparison function.<\/p>\n\n\n\n<pre title=\"Compare-DSObject\" class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">Function\u00a0Compare-DSObject\u00a0{\n\u00a0\u00a0\u00a0\u00a0<em>#get-event\u00a0-sourceIdentifier\u00a0changeduser\u00a0|\u00a0Compare-DSObject<\/em>\n\n\u00a0\u00a0\u00a0\u00a0[cmdletbinding()]\n\u00a0\u00a0\u00a0\u00a0Param(\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[Parameter(<em>Mandatory<\/em>,\u00a0<em>ValueFromPipeline<\/em>)]\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[object]$EventResult\n\u00a0\u00a0\u00a0\u00a0)\n\n\u00a0\u00a0\u00a0\u00a0Process\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<em>#write-host\u00a0\"Processing\u00a0an\u00a0event\"\u00a0-ForegroundColor\u00a0Green<\/em>\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$p\u00a0=\u00a0$EventResult.SourceEventArgs.NewEvent.PreviousInstance\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$t\u00a0=\u00a0$EventResult.SourceEventArgs.NewEvent.TargetInstance\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0$prop\u00a0=\u00a0$p.psobject.Properties.name.where(\u00a0{\u00a0$_\u00a0-match\u00a0\"^DS\"\u00a0})\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Write-Verbose\u00a0\"Processing\u00a0Changes\u00a0to\u00a0$($t.ADSIPath)\"\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0foreach\u00a0($item\u00a0in\u00a0$prop)\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if\u00a0(Compare-Object\u00a0-ReferenceObject\u00a0$p\u00a0-DifferenceObject\u00a0$t\u00a0-Property\u00a0$item)\u00a0{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0[pscustomobject]@{\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0PSTypeName\u00a0\u00a0\u00a0\u00a0=\u00a0\"DSComparison\"\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0ADSIPath\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=\u00a0$t.ADSIPath\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0TimeGenerated\u00a0=\u00a0$eventResult.TimeGenerated\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0Property\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=\u00a0$item\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0PreviousValue\u00a0=\u00a0$p.$item\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0NewValue\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0=\u00a0$t.$item\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0}\n\u00a0\u00a0\u00a0\u00a0}\u00a0<em>#process<\/em>\n}<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><a href=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/compare-dsobject.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"322\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/compare-dsobject-1024x322.png\" alt=\"\" class=\"wp-image-8079\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/compare-dsobject-1024x322.png 1024w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/compare-dsobject-300x94.png 300w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/compare-dsobject-768x241.png 768w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/compare-dsobject-850x267.png 850w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/compare-dsobject.png 1500w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>As you can see, it really depends on what you want to do or see when an event fires. <\/p>\n\n\n\n<p>In the Action scriptblock you can reference the event object with the built-in $event object. Here's a watcher for new user accounts that will use BurntToast and display the distinguished name of the new object.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">$action = { \n $toast = @{\n  Text = \"$($event.MessageData) $($event.SourceEventArgs.NewEvent.TargetInstance.DS_distinguishedName)\" \n  Sound = \"Alarm5\"\n }\n New-BurntToastNotification @toast\n }\n $watch = @{\n  Category = \"User\"\n  Activity = \"Create\"\n  MessageData = \"A domain user account has been created.\" \n  SourceIdentifier = \"NewUser\" \n  Action = $Action\n }\n Register-ADWatcher @watch<\/code><\/pre>\n\n\n\n<p>The value of MessageData will be used in the notification.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><a href=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/new-user-toast.png\"><img loading=\"lazy\" decoding=\"async\" width=\"555\" height=\"267\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/new-user-toast.png\" alt=\"\" class=\"wp-image-8080\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/new-user-toast.png 555w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/new-user-toast-300x144.png 300w\" sizes=\"auto, (max-width: 555px) 100vw, 555px\" \/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Putting It All Together<\/h2>\n\n\n\n<p>Let me wrap up this article by pulling everything together. Let's look at a deletion event. I'd like to keep an audit trail in my small domain. When a user is deleted, I want to save the event information to disk and get my toast notification. In my action scriptblock, I'll export the event to disk using Export-CliXML.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"powershell\" class=\"language-powershell\">$action = {\n     #export event to disk\n     if (-not (Test-Path C:\\ADWatch)) {\n         New-Item -Path C:\\ -Name ADWatch -ItemType Directory\n     }\n     $file = \"{0}_{1}.xml\" -f $event.sourceIdentifier.Replace(\" \",\"\"),($event.TimeGenerated.tostring(\"u\").replace(\" \",\"-\").replace(\":\",\"\"))\n     $export = Join-Path -Path C:\\ADWatch -ChildPath $file\n     $event | Export-Clixml -Path $export\n     $ti = $event.SourceEventArgs.NewEvent.TargetInstance\n     $msg = \"[$($event.TimeGenerated)] $($event.messagedata) $($ti.DS_DistinguishedName) See $export for details.\"\n     $toast = @{\n         Header = New-BTHeader -Title \"AD Watcher\"\n         Text =  $msg\n         SnoozeAndDismiss = $True\n         AppLogo = \"C:\\scripts\\db.png\"\n         Sound = \"alarm10\"\n     }\n     New-BurntToastNotification @toast\n }\n Register-ADWatcher -Category User -Activity Remove -Action $action -SourceIdentifier \"DeleteUser\" -MessageData \"ALERT! A domain user account has been removed.\" -Verbose<\/code><\/pre>\n\n\n\n<p>The target instance of the deleted user will be serialized to an XML file in C:\\ADWatch. I'm creating a UTC time stamp as part of the file name.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><a href=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/delete-alert.png\"><img loading=\"lazy\" decoding=\"async\" width=\"562\" height=\"503\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/delete-alert.png\" alt=\"\" class=\"wp-image-8082\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/delete-alert.png 562w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/delete-alert-300x269.png 300w\" sizes=\"auto, (max-width: 562px) 100vw, 562px\" \/><\/a><\/figure>\n\n\n\n<p>The alert message indicates the file which is easily brought back in to PowerShell.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><a href=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/deleted-instance.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"476\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/deleted-instance-1024x476.png\" alt=\"\" class=\"wp-image-8083\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/deleted-instance-1024x476.png 1024w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/deleted-instance-300x139.png 300w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/deleted-instance-768x357.png 768w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/deleted-instance-1536x713.png 1536w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/deleted-instance-850x395.png 850w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/deleted-instance.png 1839w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>I can use my helper function to view the deleted user information.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><a href=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/bunnyhopp.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"719\" src=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/bunnyhopp-1024x719.png\" alt=\"\" class=\"wp-image-8084\" srcset=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/bunnyhopp-1024x719.png 1024w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/bunnyhopp-300x211.png 300w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/bunnyhopp-768x539.png 768w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/bunnyhopp-850x597.png 850w, https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/bunnyhopp.png 1420w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p>As you have seen, it is possible to get notified when things happen in Active Directory. But just because you <em>can <\/em>do it, doesn't mean <em>should<\/em>. There are plenty of other options that are better choices, especially the closer to real-time notification you require. I'd say it also depends on what you need to do with the information. Do you just need to know or does something have to happen?<\/p>\n\n\n\n<p>And to head off a question I'm sure to get, I have no idea if or how this would work with Azure AD. Someone with an Azure AD environment will have to let me know.<\/p>\n\n\n\n<p>But for local events, whether in Active Directory or elsewhere, using CIM events can be a useful tool in your PowerShell toolbox.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last week, Adam Bertram sent out a tweet looking for any PowerShell code to notify the user when a new Active Directory user account had been created. I dug out some very, very old code that used a WMI event subscription to watch Active Directory for such an event. The code I shared was something&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"New on the blog: Building an Active Directory Watcher with CIM and #PowerShell","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[7,4,8,19],"tags":[647,540],"class_list":["post-8067","post","type-post","status-publish","format-standard","hentry","category-active-directory","category-powershell","category-scripting","category-wmi","tag-register-cimindicationevent","tag-scripting"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Building an Active Directory Watcher with CIM and PowerShell &#8226; The Lonely Administrator<\/title>\n<meta name=\"description\" content=\"Here&#039;s a proof-of-concept on how to be notified when things change in Active Directory such as a new user account, using PowerShell and CIM.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/jdhitsolutions.com\/blog\/powershell\/8067\/building-an-active-directory-watcher-with-cim-and-powershell\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Building an Active Directory Watcher with CIM and PowerShell &#8226; The Lonely Administrator\" \/>\n<meta property=\"og:description\" content=\"Here&#039;s a proof-of-concept on how to be notified when things change in Active Directory such as a new user account, using PowerShell and CIM.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/jdhitsolutions.com\/blog\/powershell\/8067\/building-an-active-directory-watcher-with-cim-and-powershell\/\" \/>\n<meta property=\"og:site_name\" content=\"The Lonely Administrator\" \/>\n<meta property=\"article:published_time\" content=\"2021-01-22T16:50:43+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-01-22T16:50:49+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/2DomainWithOus01.png\" \/>\n<meta name=\"author\" content=\"Jeffery Hicks\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@JeffHicks\" \/>\n<meta name=\"twitter:site\" content=\"@JeffHicks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jeffery Hicks\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8067\\\/building-an-active-directory-watcher-with-cim-and-powershell\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8067\\\/building-an-active-directory-watcher-with-cim-and-powershell\\\/\"},\"author\":{\"name\":\"Jeffery Hicks\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\"},\"headline\":\"Building an Active Directory Watcher with CIM and PowerShell\",\"datePublished\":\"2021-01-22T16:50:43+00:00\",\"dateModified\":\"2021-01-22T16:50:49+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8067\\\/building-an-active-directory-watcher-with-cim-and-powershell\\\/\"},\"wordCount\":1151,\"commentCount\":4,\"publisher\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\"},\"image\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8067\\\/building-an-active-directory-watcher-with-cim-and-powershell\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/wp-content\\\/uploads\\\/2021\\\/01\\\/2DomainWithOus01.png\",\"keywords\":[\"Register-CimIndicationEvent\",\"Scripting\"],\"articleSection\":[\"Active Directory\",\"PowerShell\",\"Scripting\",\"WMI\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8067\\\/building-an-active-directory-watcher-with-cim-and-powershell\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8067\\\/building-an-active-directory-watcher-with-cim-and-powershell\\\/\",\"url\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8067\\\/building-an-active-directory-watcher-with-cim-and-powershell\\\/\",\"name\":\"Building an Active Directory Watcher with CIM and PowerShell &#8226; The Lonely Administrator\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8067\\\/building-an-active-directory-watcher-with-cim-and-powershell\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8067\\\/building-an-active-directory-watcher-with-cim-and-powershell\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/wp-content\\\/uploads\\\/2021\\\/01\\\/2DomainWithOus01.png\",\"datePublished\":\"2021-01-22T16:50:43+00:00\",\"dateModified\":\"2021-01-22T16:50:49+00:00\",\"description\":\"Here's a proof-of-concept on how to be notified when things change in Active Directory such as a new user account, using PowerShell and CIM.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8067\\\/building-an-active-directory-watcher-with-cim-and-powershell\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8067\\\/building-an-active-directory-watcher-with-cim-and-powershell\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8067\\\/building-an-active-directory-watcher-with-cim-and-powershell\\\/#primaryimage\",\"url\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/wp-content\\\/uploads\\\/2021\\\/01\\\/2DomainWithOus01.png\",\"contentUrl\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/wp-content\\\/uploads\\\/2021\\\/01\\\/2DomainWithOus01.png\",\"width\":402,\"height\":355},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/8067\\\/building-an-active-directory-watcher-with-cim-and-powershell\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"PowerShell\",\"item\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/category\\\/powershell\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Building an Active Directory Watcher with CIM and PowerShell\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/\",\"name\":\"The Lonely Administrator\",\"description\":\"Practical Advice for the Automating IT Pro\",\"publisher\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\",\"name\":\"Jeffery Hicks\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\",\"caption\":\"Jeffery Hicks\"},\"logo\":{\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Building an Active Directory Watcher with CIM and PowerShell &#8226; The Lonely Administrator","description":"Here's a proof-of-concept on how to be notified when things change in Active Directory such as a new user account, using PowerShell and CIM.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8067\/building-an-active-directory-watcher-with-cim-and-powershell\/","og_locale":"en_US","og_type":"article","og_title":"Building an Active Directory Watcher with CIM and PowerShell &#8226; The Lonely Administrator","og_description":"Here's a proof-of-concept on how to be notified when things change in Active Directory such as a new user account, using PowerShell and CIM.","og_url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8067\/building-an-active-directory-watcher-with-cim-and-powershell\/","og_site_name":"The Lonely Administrator","article_published_time":"2021-01-22T16:50:43+00:00","article_modified_time":"2021-01-22T16:50:49+00:00","og_image":[{"url":"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/2DomainWithOus01.png","type":"","width":"","height":""}],"author":"Jeffery Hicks","twitter_card":"summary_large_image","twitter_creator":"@JeffHicks","twitter_site":"@JeffHicks","twitter_misc":{"Written by":"Jeffery Hicks","Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8067\/building-an-active-directory-watcher-with-cim-and-powershell\/#article","isPartOf":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8067\/building-an-active-directory-watcher-with-cim-and-powershell\/"},"author":{"name":"Jeffery Hicks","@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9"},"headline":"Building an Active Directory Watcher with CIM and PowerShell","datePublished":"2021-01-22T16:50:43+00:00","dateModified":"2021-01-22T16:50:49+00:00","mainEntityOfPage":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8067\/building-an-active-directory-watcher-with-cim-and-powershell\/"},"wordCount":1151,"commentCount":4,"publisher":{"@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9"},"image":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8067\/building-an-active-directory-watcher-with-cim-and-powershell\/#primaryimage"},"thumbnailUrl":"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/2DomainWithOus01.png","keywords":["Register-CimIndicationEvent","Scripting"],"articleSection":["Active Directory","PowerShell","Scripting","WMI"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/jdhitsolutions.com\/blog\/powershell\/8067\/building-an-active-directory-watcher-with-cim-and-powershell\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8067\/building-an-active-directory-watcher-with-cim-and-powershell\/","url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8067\/building-an-active-directory-watcher-with-cim-and-powershell\/","name":"Building an Active Directory Watcher with CIM and PowerShell &#8226; The Lonely Administrator","isPartOf":{"@id":"https:\/\/jdhitsolutions.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8067\/building-an-active-directory-watcher-with-cim-and-powershell\/#primaryimage"},"image":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8067\/building-an-active-directory-watcher-with-cim-and-powershell\/#primaryimage"},"thumbnailUrl":"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/2DomainWithOus01.png","datePublished":"2021-01-22T16:50:43+00:00","dateModified":"2021-01-22T16:50:49+00:00","description":"Here's a proof-of-concept on how to be notified when things change in Active Directory such as a new user account, using PowerShell and CIM.","breadcrumb":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8067\/building-an-active-directory-watcher-with-cim-and-powershell\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/jdhitsolutions.com\/blog\/powershell\/8067\/building-an-active-directory-watcher-with-cim-and-powershell\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8067\/building-an-active-directory-watcher-with-cim-and-powershell\/#primaryimage","url":"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/2DomainWithOus01.png","contentUrl":"https:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2021\/01\/2DomainWithOus01.png","width":402,"height":355},{"@type":"BreadcrumbList","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/8067\/building-an-active-directory-watcher-with-cim-and-powershell\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"PowerShell","item":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},{"@type":"ListItem","position":2,"name":"Building an Active Directory Watcher with CIM and PowerShell"}]},{"@type":"WebSite","@id":"https:\/\/jdhitsolutions.com\/blog\/#website","url":"https:\/\/jdhitsolutions.com\/blog\/","name":"The Lonely Administrator","description":"Practical Advice for the Automating IT Pro","publisher":{"@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/jdhitsolutions.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9","name":"Jeffery Hicks","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg","url":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg","caption":"Jeffery Hicks"},"logo":{"@id":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg"}}]}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":133,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/133\/techmentor-just-around-the-corner\/","url_meta":{"origin":8067,"position":0},"title":"Techmentor Just Around the Corner","author":"Jeffery Hicks","date":"March 4, 2008","format":false,"excerpt":"The registration deadline for the first Techmentor conference of the year is almost upon us. I'll be doing sessions on using Powershell to manage Active Directory, PowerShell and WMI, Logon Scripts and more. Plus, I'm always happy to hang out and chat. I always have a great time. Hope to\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":130,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/130\/techmentor-san-francisco-2008\/","url_meta":{"origin":8067,"position":1},"title":"Techmentor San Francisco 2008","author":"Jeffery Hicks","date":"February 22, 2008","format":false,"excerpt":"I finished up my slide decks last week for the first Techmentor conference of the year in San Francisco (March 30 -April 3). If you've never been to a Techmentor conference you're missing a great opportunity to hear and see your favorite IT speakers. Plus it's a lot of fun\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":37,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/37\/get-active-directory-user-information-in-powershell\/","url_meta":{"origin":8067,"position":2},"title":"Get Active Directory User Information in PowerShell","author":"Jeffery Hicks","date":"July 5, 2006","format":false,"excerpt":"One feature that PowerShell will likely be missing when it first ships is solid support for ADSI and working with Active Directory. You can use .NET DirectoryEntry objects but it feels more like programming and less like scripting. Another option for working with Active Directory in PowerShell is to use\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":148,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/148\/order-managing-active-directory-with-windows-powershell-tfm-finally\/","url_meta":{"origin":8067,"position":3},"title":"Order Managing Active Directory with Windows PowerShell: TFM &#8211; Finally!","author":"Jeffery Hicks","date":"September 22, 2008","format":false,"excerpt":"Yes, its finally true. You can finally get your hands on Managing Active Directory with Windows PowerShell: TFM. The book is being printed so you can get your copy today. You can order it today at ScriptingOutpost.com in both print and ebook format. Or if you prefer the best of\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2025,"url":"https:\/\/jdhitsolutions.com\/blog\/scripting\/2025\/powershell-in-a-nutshell\/","url_meta":{"origin":8067,"position":4},"title":"PowerShell in a Nutshell","author":"Jeffery Hicks","date":"January 26, 2012","format":false,"excerpt":"This past weekend I did an online presentation for a friend of mine who teaches for ITT in Omaha, Nebraska. He wanted me to do a brief talk about what PowerShell is and show how to use it, especially for managing Active Directory. I probably went much longer than I\u2026","rel":"","context":"In &quot;PowerShell v2.0&quot;","block_context":{"text":"PowerShell v2.0","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell-v2-0\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":112,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/112\/powershell-mini-conference\/","url_meta":{"origin":8067,"position":5},"title":"PowerShell Mini-Conference","author":"Jeffery Hicks","date":"June 11, 2007","format":false,"excerpt":"If you've got some free time in early November and want to get up to speed on PowerShell in the least amount of time, then come to Las Vegas. Don Jones (PoweShell MVP) and I will be running a 2 day PowerShell mini-conference. This will be an intense 2 days\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/8067","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/comments?post=8067"}],"version-history":[{"count":0,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/8067\/revisions"}],"wp:attachment":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/media?parent=8067"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/categories?post=8067"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/tags?post=8067"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}