Event Log Entry: Checking for software and Event Log reporting

This particular requirement was to use a management server to run a script on all the Windows devices at a timed interval in this case that was every 24 hours, and the job of the software is check for Java JDK and JRE - it also needs to report on any versions that are marked as non-compliant - which will be unique to your particular situation.

If this was found which can be queried by the registry key for this particular example in the location "HKLM:\SOFTWARE\JavaSoft\Java Development Kit"

We also need to register a new event source before we can write the Event ID to the Event Log, which means we need this to run from an evaluated command prompt for the first time to registered successfully, once registered it no longer requires the elevation.

We also need an Event ID that we can then monitor for with our alerting solution to give us an alert if the JDK is found, so we need to add this as the requirement below:

Event Log = Application
Source = JDK Check
Event ID if JDK is found : 6666
Event ID if JDK is no found : 6665

Right, now we need to summon the Powershell genie to get this script done, so I need a keyboard and a plan (which is above) now lets rub the lamp a couple of times and we get the script below.

CheckJavato Event Log Script

# CheckJava.ps1

# Function to check Java in the registry
function Check-RegistryForJava {
    param (
    try {
        $key = Get-Item -Path $path -ErrorAction Stop
        return $key
    } catch {
        return $null

# Function to create event source if it doesn't exist
function Ensure-EventSource {
    param (

    if (-not [System.Diagnostics.EventLog]::SourceExists($source)) {
        [System.Diagnostics.EventLog]::CreateEventSource($source, $logName)

# Define registry paths to check for JDK and JRE
$jdkPath = "HKLM:\SOFTWARE\JavaSoft\Java Development Kit"
$jrePath = "HKLM:\SOFTWARE\JavaSoft\Java Runtime Environment"

# Ensure the event source exists
$eventSource = "Java Check"
$eventLog = "Application"
Ensure-EventSource -source $eventSource -logName $eventLog

# Define non-compliant Java versions

$nonCompliantVersions = @(
    "1.7.0_80",  # Java 7 Update 80
    "11",        # Java 11
    "9", "10", "12", "13", "14", "15", "16" # Java 9,10,12-16

function Is-NonCompliantVersion {
    param (
    Write-Output "Checking version $version for compliance..."

    # Check for exact matches in the non-compliant list
    foreach ($nonCompliant in $nonCompliantVersions) {
        if ($version -like "$nonCompliant*") {
            Write-Output "Version $version matches non-compliant version $nonCompliant"
            return $true

    # Check for Java 8 Update 211 or greater
    if ($version -match "^1\.8\.0_(\d+)$") {
        $updateVersion = [int]$matches[1]
        Write-Output "Java 8 detected with update version $updateVersion"
        if ($updateVersion -ge 211) {
            Write-Output "Java 8 Update $updateVersion is non-compliant"
            return $true

    Write-Output "Version $version is compliant"
    return $false

# Check for JDK
$jdkRegistryKey = Check-RegistryForJava -path $jdkPath
$jdkInstalled = $jdkRegistryKey -ne $null
$jdkVersion = if ($jdkInstalled) { $jdkRegistryKey.GetValue("CurrentVersion") } else { "Not installed" }

# Check for JRE
$jreRegistryKey = Check-RegistryForJava -path $jrePath
$jreInstalled = $jreRegistryKey -ne $null
$jreVersion = if ($jreInstalled) { $jreRegistryKey.GetValue("CurrentVersion") } else { "Not installed" }

# Output results and log events
if ($jdkInstalled) {
    Write-Output "JDK is installed, version $jdkVersion"
    [System.Diagnostics.EventLog]::WriteEntry($eventSource, "Java Development Kit (JDK) is installed. Version: $jdkVersion", [System.Diagnostics.EventLogEntryType]::Warning, 6666)
} else {
    Write-Output "JDK is not installed"
    [System.Diagnostics.EventLog]::WriteEntry($eventSource, "Java Development Kit (JDK) is not installed.", [System.Diagnostics.EventLogEntryType]::Information, 6665)

if ($jreInstalled) {
    Write-Output "JRE is installed, version $jreVersion"
    [System.Diagnostics.EventLog]::WriteEntry($eventSource, "Java Runtime Environment (JRE) is installed. Version: $jreVersion", [System.Diagnostics.EventLogEntryType]::Warning, 6664)

    if (Is-NonCompliantVersion -version $jreVersion) {
        Write-Output "JRE version $jreVersion is non-compliant"
        [System.Diagnostics.EventLog]::WriteEntry($eventSource, "Java Runtime Environment (JRE) version $jreVersion is non-compliant.", [System.Diagnostics.EventLogEntryType]::Error, 6667)
        exit 4
} else {
    Write-Output "JRE is not installed"
    [System.Diagnostics.EventLog]::WriteEntry($eventSource, "Java Runtime Environment (JRE) is not installed.", [System.Diagnostics.EventLogEntryType]::Information, 6663)

# Exit codes: 0 = JDK and JRE not installed, 1 = JDK installed, 2 = JRE installed, 3 = Both installed, 4 = Non-compliant JRE version
if ($jdkInstalled -and $jreInstalled) {
    exit 3
} elseif ($jdkInstalled) {
    exit 1
} elseif ($jreInstalled) {
    exit 2
} else {
    exit 0

Run this script now and if you run it interactively you will get this retuned:

That is not where the magic happens though, if you open the eventlog and look under the Application event log you will now see you have an entry like this:

Then the main information details will be like this, which is same text from the script.

However if you get a non-compliant version it will look like this:

Now we have this we can setup an alert to monitor for that Event ID and Source, so using for weapon of choice and in this instance is System Centre Operations Manager, and from here will need a new monitor that will be triggered from the Event Log, you will need to add this to a management pack as well....

Next we need to give it a Name then a Monitor target which for this is "Windows Operating System" as we need to target all Windows installs, then add it to the configuration and ensure its NOT enabled at this point, we will enable it later with overrides for testing.

Next we need when the script will run, in this case every 24 hours:

Then we need the name of the script and the actual script as below (this was from above)

Then we need the "unhealthy" expression, which will need to contain:

Parameter Name: Property[@Name='StdOut']
Operator : Equals
Value : 1

Then we need the "healthy" expression, which will need to contain:

Parameter Name: Property[@Name='StdOut']
Operator : Equals
Value : 0

Then we need to map out the health states, this is how they will appear in the console:

This is where you can configure an alert for the script state and that will work, but that would mean the Event ID would be pointless, but to drive that Event ID you need this script to run to start with, so you can either choose to alert here or you can do another rule to monitor for that alert as another monitor.

If you want an alert on the Event ID then you can create another monitor this time as a simple manual reset event detection:

Then as before give it the required details like a name, descriptions a monitor target then ensure it is not enabled at this stage.

Then we require the Application event log:

Then you need to give it the trigger criteria from earlier:

Then ensure the health is "Warning"

Now we wish to enable the alerting on this object as below:

Previous Post Next Post

Ω†Ω…ΩˆΨ°Ψ¬ Ψ§Ω„Ψ§ΨͺΨ΅Ψ§Ω„