PowerShell / Community-Blog

Submissions for posts to the PowerShell Community Blog -https://devblogs.microsoft.com/powershell-community
MIT License
107 stars 47 forks source link

Post idea - How Can I Be Notified Any Time a Service Goes Down? #52

Open doctordns opened 3 years ago

doctordns commented 3 years ago

In #51, we look at permanent WMI eventing. In this old Scripting Guy post, the author looks at temporary eventing.

The scenario is you want to know when services change state.

farismalaeb commented 3 years ago

Is this post still available? I will write it if allowed.

doctordns commented 3 years ago

Feel free to take a stab!

Let me know how we can help!

farismalaeb commented 3 years ago

Here we are, let me know your comments, and surely you will have to help with my low-quality grammar 😄 Also, I don't know if allow referring to an article outside Microsoft.com site, In this post, I refer to one article on https://adamtheautomator.com/ website. Looking forward to hearing from you.

How Can I Be Notified Any Time a Service Goes Down?

How Can I Be Notified Any Time a Service Goes Down?

Q: How Can I Be Notified Any Time a Service Goes Down?

A: The short quick answer to utilizing WMI and PowerShell 7.

Using Powershell to create temporary event monitoring in the WMI database, which keeps on monitoring any services changes and generates an alert once it detects a change.

Basic Requirement

To achieve this, you need PowerShell 5.1 and above. This post uses the latest version of PowerShell 7. So if you are don't yet have PowerShell 7, get it for free from Microsoft.com.

Also, make sure that PowerShell is running as administrator.

Finding the Required Class

Before going into details, you need to find the required class to monitor. To get a list of all available classes, use the following code.

Get-CimClass -Namespace root\cimv2

The returned result represents all the available classes in the namespace. To monitor Windows services, the WMI class name is Win32_Service.

To Enumerate the Win32_Services WMI class and get all the available services using PowerShell run the following code.

Get-CimInstance -Namespace root\CIMV2 -ClassName win32_service

The result looks like the following.

PS C:\> Get-CimInstance -Namespace root\CIMV2 -ClassName win32_service
ProcessId Name                                     StartMode State   Status  ExitCode
--------- ----                                     --------- -----   ------  --------
3784      AdobeARMservice                          Auto      Running OK      0
3792      AdobeUpdateService                       Auto      Running OK      0
3800      AGMService                               Auto      Running OK      0
3824      AGSService                               Auto      Running OK      0
0         AJRouter                                 Manual    Stopped OK      1077
0         ALG                                      Manual    Stopped OK      1077
0         AppIDSvc                                 Manual    Stopped OK      1077
6708      Appinfo                                  Manual    Running OK      0
21444     AppMgmt                                  Manual    Running OK      0
0         AppReadiness                             Manual    Stopped OK      1077
0         AppVClient                               Disabled  Stopped OK      1077
0         AppXSvc                                  Manual    Stopped OK      0
0         AssignedAccessManagerSvc                 Manual    Stopped OK      1077

For now, you can use PowerShell to find the required class, and enumerate it to get the available services. Let's go deeper now and start creating the WMI Event Subscription.

There are three steps you need to follow to create a WMI Event Subscription:

Creating WMI Query

WMI database has several system WMI Classes. For instance, the CIM_InstModification monitors the targeted class for any changes. So, in this case, Win32_Service.

The query syntax looks like

Select * from <**WMI System Class**> within <**Number of Seconds**> where TargetInstance ISA <**WMI Class name**>

Let apply the same to Win32_Serivce. Start by Creating a PowerShell variable name it $Query and type the following query

$query = "Select * from CIM_InstModification within 10 where TargetInstance ISA 'Win32_Service'"

A full explanation for the WQL query is available in Your Goto Guide for Working with Windows WMI Events and PowerShell

Registering The Query

We have the WQL query, let move to the next step and register the query to the WMI events by using the Register-CimIndicationEvent

Register-CimIndicationEvent -Namespace 'ROOT\CIMv2' -Query $query -SourceIdentifier 'WindowsServices' -MessageData 'Service Status Change'

To confirm the successful registration, type the following cmdlet Get-EventSubscriber, the output looks like the following

Get-EventSubscriber
SubscriptionId   : 1
SourceObject     : Microsoft.Management.Infrastructure.CimCmdlets.CimIndicationWatcher
EventName        : CimIndicationArrived
SourceIdentifier : **WindowsServices**
Action           :
HandlerDelegate  :
SupportEvent     : False
ForwardEvent     : False

And that's all that we need, simple as that.

Reading the events

Now the event is registered and active. Next, create an event, and by that, I mean stopping or starting a service.

Try Windows Update service (wuauserv), run the following cmdlet to see the status of the bits service.

Get-Service wuauserv
Status   Name               DisplayName
------   ----               -----------
Running  wuauserv           Windows Update

So the service is running, let stop it by typing the following

Stop-Service wuauserv

To see the newly created events, type

$EventVariable=Get-Event
$EventVariable

Look at the MessageData, it's the same message used in the Register-CimIndicationEvent

ComputerName     :
RunspaceId       : 91c6b6fb-cda9-4b15-983f-d7af1f639358
EventIdentifier  : 1
Sender           : Microsoft.Management.Infrastructure.CimCmdlets.CimIndicationWatcher
SourceEventArgs  : Microsoft.Management.Infrastructure.CimCmdlets.CimIndicationEventExceptionEventArgs
SourceArgs       : {Microsoft.Management.Infrastructure.CimCmdlets.CimIndicationWatcher,
                   Microsoft.Management.Infrastructure.CimCmdlets.CimIndicationEventExceptionEventArgs}
SourceIdentifier : WindowsServices
TimeGenerated    : 30-Jul-21 12:08:06 AM
MessageData      : Service Status Change

To find the current state of this event

$EventVariable.SourceEventArgs.NewEvent.SourceInstance

And the output looks like

ProcessId Name     StartMode State   Status ExitCode
--------- ----     --------- -----   ------ --------
0         wuauserv Manual    Stopped OK     0

To see the previous event state

$EventVariable.SourceEventArgs.NewEvent.PreviousInstance
ProcessId Name     StartMode State   Status ExitCode
--------- ----     --------- -----   ------ --------
16508     wuauserv Manual    Running OK     0

This monitoring remains active as long as PowerShell console is active. It will create such a temporary job which runs in the background to monitor the services class. You can also end this process by rebooting the computer. Hope you learn something new today.

doctordns commented 3 years ago

Hi

Thanks for this good start, We need to turn it into Markdown asnd get it into github.

Some general commewnts:

  1. Remove the word ‘will’ and contractions (eg we’ll) – future tense is problematic especially as some readers local language doesn’t really do future tense.
  2. With console output, the porompt should be PS> - helps since Linux doesn thave a C: drive.
  3. You need to style the URL correctly using MD – the format is: [stuff to be in the doc](url to the doc). The backetys and parenthesis are importgnt foir URLs
  4. Under each of the three steps – you need to shpw some actual code and preferable output.

So get the document into github, and create a pull request and I can give you the line by line review.

Thanks!!

Thoma

From: Faris Malaeb @.> Sent: 29 July 2021 22:42 To: PowerShell/Community-Blog @.> Cc: Thomas Lee @.>; Author @.> Subject: Re: [PowerShell/Community-Blog] Post idea - How Can I Be Notified Any Time a Service Goes Down? (#52)

Here we are, let me know your comments, and surely you will have to help with my low-quality grammar 😄 Also, I don't know if allow referring to an article outside Microsoft.com site, In this post, I refer to one article on https://adamtheautomator.com/ website. Looking forward to hearing from you.

How Can I Be Notified Any Time a Service Goes Down?

How Can I Be Notified Any Time a Service Goes Down?

Q: How Can I Be Notified Any Time a Service Goes Down?

A: The short quick answer to utilizing WMI and PowerShell 7.

Using Powershell to create temporary event monitoring in the WMI database, which keeps on monitoring any services changes and generates an alert once it detects a change.

Basic Requirement

To achieve this, you need PowerShell 5.1 and above. This post uses the latest version of PowerShell 7. So if you are don't yet have PowerShell 7, get it for free from Microsoft.comhttp://microsoft.com/.

Also, make sure that PowerShell is running as administrator.

Finding the Required Class

Before going into details, you need to find the required class to monitor. To get a list of all available classes, use the following code.

Get-CimClass -Namespace root\cimv2

The returned result represents all the available classes in the namespace. To monitor Windows services, the WMI class name is Win32_Service.

To Enumerate the Win32_Services WMI class and get all the available services using PowerShell run the following code.

Get-CimInstance -Namespace root\CIMV2 -ClassName win32_service

The result looks like the following.

PS C:> Get-CimInstance -Namespace root\CIMV2 -ClassName win32_service

ProcessId Name StartMode State Status ExitCode


3784 AdobeARMservice Auto Running OK 0

3792 AdobeUpdateService Auto Running OK 0

3800 AGMService Auto Running OK 0

3824 AGSService Auto Running OK 0

0 AJRouter Manual Stopped OK 1077

0 ALG Manual Stopped OK 1077

0 AppIDSvc Manual Stopped OK 1077

6708 Appinfo Manual Running OK 0

21444 AppMgmt Manual Running OK 0

0 AppReadiness Manual Stopped OK 1077

0 AppVClient Disabled Stopped OK 1077

0 AppXSvc Manual Stopped OK 0

0 AssignedAccessManagerSvc Manual Stopped OK 1077

For now, you can use PowerShell to find the required class, and enumerate it to get the available services. Let's go deeper now and start creating the WMI Event Subscription.

There are three steps you need to follow to create a WMI Event Subscription:

Creating WMI Query

WMI database has several system WMI Classes. For instance, the CIM_InstModification monitors the targeted class for any changes. So, in this case, Win32_Service.

The query syntax looks like

Select * from <WMI System Class> within <Number of Seconds> where TargetInstance ISA <WMI Class name>

Let apply the same to Win32_Serivce. Start by Creating a PowerShell variable name it $Query and type the following query

$query = "Select * from CIM_InstModification within 10 where TargetInstance ISA 'Win32_Service'"

A full explanation for the WQL query is available in Your Goto Guide for Working with Windows WMI Events and PowerShellhttps://adamtheautomator.com/your-goto-guide-for-working-with-windows-wmi-events-and-powershell/

Registering The Query

We have the WQL query, let move to the next step and register the query to the WMI events by using the Register-CimIndicationEvent

Register-CimIndicationEvent -Namespace 'ROOT\CIMv2' -Query $query -SourceIdentifier 'WindowsServices' -MessageData 'Service Status Change'

To confirm the successful registration, type the following cmdlet Get-EventSubscriber, the output looks like the following

Get-EventSubscriber

SubscriptionId : 1

SourceObject : Microsoft.Management.Infrastructure.CimCmdlets.CimIndicationWatcher

EventName : CimIndicationArrived

SourceIdentifier : WindowsServices

Action :

HandlerDelegate :

SupportEvent : False

ForwardEvent : False

And that's all that we need, simple as that.

Reading the events

Now the event is registered and active. Next, create an event, and by that, I mean stopping or starting a service.

Try Windows Update service (wuauserv), run the following cmdlet to see the status of the bits service.

Get-Service wuauserv

Status Name DisplayName


Running wuauserv Windows Update

So the service is running, let stop it by typing the following

Stop-Service wuauserv

To see the newly created events, type

$EventVariable=Get-Event

$EventVariable

Look at the MessageData, it's the same message used in the Register-CimIndicationEvent

ComputerName :

RunspaceId : 91c6b6fb-cda9-4b15-983f-d7af1f639358

EventIdentifier : 1

Sender : Microsoft.Management.Infrastructure.CimCmdlets.CimIndicationWatcher

SourceEventArgs : Microsoft.Management.Infrastructure.CimCmdlets.CimIndicationEventExceptionEventArgs

SourceArgs : {Microsoft.Management.Infrastructure.CimCmdlets.CimIndicationWatcher,

               Microsoft.Management.Infrastructure.CimCmdlets.CimIndicationEventExceptionEventArgs}

SourceIdentifier : WindowsServices

TimeGenerated : 30-Jul-21 12:08:06 AM

MessageData : Service Status Change

To find the current state of this event

$EventVariable.SourceEventArgs.NewEvent.SourceInstance

And the output looks like

ProcessId Name StartMode State Status ExitCode


0 wuauserv Manual Stopped OK 0

To see the previous event state

$EventVariable.SourceEventArgs.NewEvent.PreviousInstance

ProcessId Name StartMode State Status ExitCode


16508 wuauserv Manual Running OK 0

This monitoring remains active as long as PowerShell console is active. It will create such a temporary job which runs in the background to monitor the services class. You can also end this process by rebooting the computer. Hope you learn something new today.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://github.com/PowerShell/Community-Blog/issues/52#issuecomment-889479943, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AA3WJ6JPK5EXC4RG7SM6BQLT2HDK5ANCNFSM43XXBS5Q.

farismalaeb commented 3 years ago

Hi, I am doing a pull request but get rejected.

sdwheeler commented 2 years ago

@farismalaeb Are you still getting an error when you try to submit a PR? If so, can you provide steps to reproduce the problem?

farismalaeb commented 2 years ago

Hi I used to get the error when i fork and want to merge But it has been a while since I fork and merge (contribute to others) github

Thanks

On Sat, 21 May 2022, 1:14 AM Sean Wheeler @.***> wrote:

@farismalaeb https://github.com/farismalaeb Are you still getting an error when you try to submit a PR? If so, can you provide steps to reproduce the problem?

— Reply to this email directly, view it on GitHub https://github.com/PowerShell/Community-Blog/issues/52#issuecomment-1133383269, or unsubscribe https://github.com/notifications/unsubscribe-auth/AOMFJFTCLKK3Z6CANQNVDW3VK76DDANCNFSM43XXBS5Q . You are receiving this because you were mentioned.Message ID: @.***>