About Pre-Actions and Post-Actions

You can add actions you want to execute on the assets for the Windows, Linux, and Mac deployment job types. Using the pre-actions and post-actions, you can run scripts or install software on assets before or after the patches are installed. You can add actions to determine the software version, install the software before the latest patch can be applied, install a patch that is not supported out-of-the-box by Qualys Patch Management, remediate a vulnerability that might require a configuration change, and so on. You can run a job to execute only one or more actions without adding any patches.

You can add the following actions:

  • Pre-Action: Action that you want to execute before the job starts.
  • Post-Action: Action you want to execute after the job completes.

For detailed information, refer to the following sections:

Types of Actions

Types of pre-actions:

Pre-action Name

Supported for Windows (Y/N)

Supported for Linux (Y/N)

 

Supported for Mac (Y/N)

 

Run Script

Y

Y

Y

Install Software

Y

N

N

Change Registry Key

Y

N

N

Uninstall Software 

Y

N

N

System Reboot

Y

N

N


Types of post-actions:

Post-action Name

Supported for Windows (Y/N)

Supported for Linux (Y/N)

 

Supported for Mac (Y/N)

Run Script

Y

Y

Y

Install Software

Y

N

N

Change Registry Key

Y

N

N

Uninstall Software 

Y

N

N

 

Run ScriptRun Script

Allows you to use a custom script to execute actions.

Field

Description

Available for (Windows, Linux, or Mac Deployment Job)

Action Name

Enter the action name.

You can choose to enable or disable the Bypass Execution Policy while adding the Run Script pre-action or post-action to a Windows deployment job.
When you click the Click here link, you are navigated to the Configuration > Setup tab and then you can enable or disable the Bypass Execution Policy. For more information, see Bypass Execution Policy.

Windows, Linux, and Mac.

Script Type

Select the required script type. The supported script types are Shell Script and Apple Script.

Mac

Custom Script

You can enter a custom script that you want to execute on the assets.

  • For Windows deployment job, you can only enter a Powershell script. The script returns one of the following codes after execution:
    •  a) Success, the custom script was executed successfully: 0
    •  b) Failure, the custom script failed to execute: Nonzero

You can use the Write-Host command in the Powershell script to provide a custom message that is returned in case the action fails.

  • For Linux deployment job, you can only enter a Shell script.
 

Windows, Linux, and Mac.

 

Example 1:  Run a script to check loop failure. 

Run Script.

The error codes and failure descriptions are reported on the Job Progress screen. If a reboot return code is returned by the script, the agent will reboot based on the reboot policy defined for the job.

Example 2: Mac pre-actions and post-actions

Run Script Pre-Action for Mac.

 Install SoftwareInstall Software

Allows you to create a pre-action or post-action to install a specific software or update software that Qualys Patch Management does not support out-of-the-box.

You must provide the following information:

Field

Description

Action Name

The name of the software that you want to install.

Note: You can choose to enable or disable the Bypass Execution Policy while adding the Install Software pre-action or post-action to a Windows deployment job.

When you click the Click here link, you are navigated to the Configuration > Setup tab and then you can enable or disable the Bypass Execution Policy. For more information, see Bypass Execution Policy.

Protocol 

Select https://, http://, or Network Share from the Protocol list.

Enter the download URL in the URL field from where the software installer will be downloaded.

If you have configured the Qualys Gateway Services, the agent will proxy through QGS.

Note: When you select the Network Share protocol, you can download the installable software file from the Universal Naming Convention (UNC) path you provide in the UNC field. 

File Checksum/Hash

The agent validates the integrity of the downloaded file by comparing it to the hash that you provide. You can use publicly available methods, such as certUtil, to generate SHA256 for a file.

Detection Script (optional)

The detection script is used to determine whether to install the software on a specific asset. The script checks the pre-conditions that must be met for the software to be installed or updated.

The script returns one of the following codes after execution:

- Success, to indicate that the software can be installed on the asset: 0
- Failure, abort the action and not install the software: Nonzero (except 10 and 11)

Install Script

This script performs the installation. The installer file downloaded by our agent is stored at the following location: %ProgramData%\Qualys\QualysAgent\PatchManagement\PatchDownloads\

You can check details in the log to understand why an action failed.

The script returns one of the following codes after execution:

- Success, the software was installed: 0
- Failure, the software failed to install: Nonzero (except 10 and 11)
- Reboot needed
    – Success with reboot: 10
    – Failure with reboot: 11

You can use the Write-Host command in the Powershell script to provide a custom message that is returned in case the action fails.

Note that if the script indicates that a reboot is required, the agent uses the job reboot preferences to enforce a reboot. Only one reboot is enforced for a patch job.

 

For example, install Notepad++.

Install Notepad++.

Change Registry KeyChange Registry Key

Allows you to add or update the registry key for an application before or after installation.

Field

Description

Key PATH ending with Key name

Enter the key path, including the key name.

You can change the following registry keys:

 - HKEY_CURRENT_USER

 - HKEY_USERS

 - HKEY_LOCAL_MACHINE

 - HKEY_CLASSES_ROOT

 - HKEY_CURRENT_CONFIG

Note the following important points:

 - You cannot use a forward slash (/).

 - The path should not end with a backslash (\).

 - The path must contain at least one directory after the root path.

Registry Type

Select the registry key type.

 - REG_BINARY

 - REG_DWORD

 - REG_EXPAND_SZ

 - REG_MULTI_SZ

 - REG_QWORD

 - REG_SZ

Note: Only numerical values are accepted for the REG_BINARY, REG_DWORD, and REG_QWORD registry key type.

Registry Value name

Based on the registry type selected, enter the registry value name.

Registry Value data

Based on the registry type selected, enter the registry value data.

Add New Key

Select one of the following options:

 - True: if you want to add the registry key in case it doesn't exist.

 - False: if you don't want to take any action in case the registry key doesn't exist.

 

For example, change the registry key for Internet Explorer.

Registry Key Example.

Uninstall SoftwareUninstall Software

Allows you to uninstall a specified software. Uninstall software is supported only on Windows with PM-enabled assets, and software with msi exec-based installers.

Field

Description

Action Name

Enter an action name.

Example: Uninstall Notepad++ 8.5

Uninstall Registry Key

Enter the registry key path containing the registry value name.

For example, for putty, HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{1E0D5689-40F1-4E46-ABBB-EAAC68B5CD89}.

Software Display Name

Enter the value data for the value name DisplayName under the registry key path.

The value data is the exact name of the software that you want to uninstall.

Software Display Version

Enter the exact value data for the value name Version under the Registry key path. The value data is the version of the software that you want to uninstall.

Note: If you don't specify a version, then any installed version of the software will be uninstalled.

 

Uninstall Software Version Match

The Uninstall Software Version Match field is shown only when you enter details in the Software Display Version field.

Select Equals operator. With this release, we are supporting the Equals operator only, which is the default operator.

Note: When the Equals operator is selected, the software is uninstalled only if the Software Display Version that you provided matches the value data for the value name Version under the registry key.

 

For example, uninstall Notepad ++ version 8.5.

Uninstall Software.

System RebootSystem Reboot

The System Reboot pre-action ensures a machine reboot. The reboot takes effect after all job activities, if configured, are done and honors all the reboot-related settings if configured.

Field

Description

Action Name

Enter the action name. Example: System reboot pre-action.

Note: Consider the following points while creating and scheduling the job to which you want to add a ‘System Reboot’ pre-action:

-    As a cloud agent can run only one job at a time, ensure that other jobs are completed before this job runs for the ‘System Reboot’ pre-action to get executed successfully. 

-    When you add the 'System Reboot' pre-action, you cannot enable the 'Suppress Reboot' option from the 'Deployment and Reboot Communication Options'.

-    You can create a job with a System Reboot action only and without patches. If you configure a job with patches and a System Reboot pre-action, and if the patches need a reboot after installation, the system will reboot only once at the end of the job execution.


System Reboot Pre-Action.

Examples

The following examples help you understand the pre-actions and post-actions user scenarios.

Windows Pre-Actions and Post-Actions Examples

Linux Pre-Actions and Post-Actions Examples

Mac Pre-Actions and Post-Actions Examples

Windows Pre-Actions and Post-Actions Examples

Example 1: To detect if the Notepad++ version 8.1.2 can be installed

This sample script detects if the software is installed or not. If the code returned is 0, the software can be installed, and if the code returned is 1, installation is not required.

Return Code:

- Success: 0

- Failure: 1

***********************************************************************

# Sample pre-detection script for Qualys Patch Manager       *

#                                                            *

#     This sample script demonstrate detection of installed  *

#     software. It returns 0 if software can be installed    *

#     and returns 1 if installation is not required          *

#                                                            *

#                                                            *

#       Return Code                                          *

#                                                            *

#        0 - success                                         *

#        1 - failure                                         *

#*************************************************************

# required parameter

[string]$SoftwareName = "notepad++*"

[string]$SoftwareVersion = "8.1.2"

# Print OS info for asset information and troubleshooting

Write-Host "Gathering OS Information..."

$osInfo = Get-CimInstance Win32_OperatingSystem | Select-Object Caption, Version, ServicePackMajorVersion, OSArchitecture, CSName

$properties = @{

    Caption                 = $osInfo.Caption

    Version                 = $osInfo.Version

    ServicePackMajorVersion = $osInfo.ServicePackMajorVersion

    OSArchitecture          = $osInfo.OSArchitecture

    HostName                = $osInfo.CSNAme

}

$obj = New-Object -TypeName PSObject -Property $properties

Write-Output $obj

Write-Host "Looking for package installation...`n"

# Check install key in both wow64 and normal path. Application can be either 32-bit or 64-bit.

$32bit = Get-ItemProperty HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*

$64bit = Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*

$programs = $32bit + $64bit

$packageFound = $false

foreach ($program in $programs) {

    $program = Write-Output $program | Where-Object Displayname -like $SoftwareName

    if ($null -ne $program.DisplayName) {

        $LastModified = (Get-Item $program.uninstallstring).lastwritetime

        $properties = @{

            ProgramName     = $program.DisplayName

            Publisher       = $program.Publisher

            Version         = $program.DisplayVersion

            UninstallString = $program.UninstallString

            LastModified    = $LastModified

        }

        $package = New-Object -TypeName PSObject -Property $properties

        Write-Output $package

        $packageFound = $true

        break;

    }

}

if ($packageFound -eq $false) {

    Write-Host "No installed package found"

    # Package needs to be isntalled

    exit 0

}

Write-Host "Checking installed software version..."

[System.Version] $installedVersion = $package.Version

[System.Version] $ExpectedVersion = $SoftwareVersion

if ($installedVersion -lt $ExpectedVersion) {

    Write-Host "Installed software is older than required version. Patch upgrade needed."

    exit 0

}

else {

    Write-Host "Installed software is up to date."

    exit 1

}>

Example 2: To install the Notepad++ version 8.1.2

This sample script demonstrates the installation of software. If the code returned is 0, the software is installed successfully, and if the code returned is 1, the installation fails.

Return Code:

- Success: 0

- Failure: 1

#*************************************************************

# Sample install script for Qualys Patch Manager             *

#     This sample script demonstrate installation of         *

#     software. It returns 0 if software is installed        *

#     successfully and returns 1 if installation fails.      *

#       Return Code                                          *

#        0 - success                                         *

#        1 - failure                                         *

#*************************************************************

[string]$PackageName = "npp.8.1.2.Installer.x64.exe"

[string]$InstallerLocation = $Env:ProgramData + "\Qualys\QualysAgent\PatchManagement\PatchDownloads\"

[string]$Arguments = "/S"

#set this 1 if reboot is required after package installation

[int]$RebootFlag = 1

function Get-QualysScriptReturn {

    param (

        [ValidateRange(0, 1)]

        [Int]

        $Success_Code,

        [ValidateRange(0, 1)]

        [Int]

        $RebootFlag

    )

    return $Success_Code + ($RebootFlag * 10)

}

function Start-Program {

    param (

        [ValidateNotNullOrEmpty()]

        [string]

        $ProgramFullPath,

        [Parameter(Mandatory = $false)]

        [string]

        $Arguments        

    )

    

    try {   

        $pinfo = New-Object System.Diagnostics.ProcessStartInfo

        $pinfo.FileName = $ProgramFullPath

        $pinfo.RedirectStandardError = $true

        $pinfo.RedirectStandardOutput = $true

        $pinfo.UseShellExecute = $false

    

        if ($null -ne $Arguments) {

            $pinfo.Arguments = $Arguments

        }    

    

        $pinfo.WorkingDirectory = Get-Location

        $p = New-Object System.Diagnostics.Process

        $p.StartInfo = $pinfo

        $p.Start() | Out-Null

        $p.WaitForExit()

        $stdout = $p.StandardOutput.ReadToEnd()

        $stderr = $p.StandardError.ReadToEnd()

    

        Write-Host "Process Stdout:`n $stdout"

        Write-Host "Process Stderr:`n $stderr"

        Write-Host "exit code: "$p.ExitCode

        return $p.ExitCode

    }

    catch {

        Write-Host -ForegroundColor DarkRed "Failed to execute program" $_.Exception.Message

        return 1

    }

}

Write-Host "Running install script to install -"$PackageName

Write-Host "Looking package installer..."

$InstallerFullPath = $InstallerLocation + $PackageName

if (Test-Path $InstallerFullPath) {

    Write-Host "Found installer at "$InstallerFullPath

}

else {

    Write-Host "Installer does not exist at "$InstallerFullPath

    exit 1;

}

Write-Host "Launching installer..."

$ReturnCode = Start-Program $InstallerFullPath $Arguments

if ($ReturnCode -eq 0) {

    Write-Host -ForegroundColor Green "Installation successfull..."

    exit Get-QualysScriptReturn 0 $RebootFlag;

}

else {

    Write-Host -ForegroundColor DarkRed "Installation failed. See output for more details."

    exit 1

}

Example 3: Custom script to create an array of text files

This sample script checks whether a specific file (pc.txt) already exists in a particular folder; if not, it generates a list of all AD computers and saves it to a new file named pc.txt. It returns 0 if the file does not exist and the latest AD computer list is saved and returns 1 if the file already exists.

Return Code:

- Success: 0

- Failure: 1

#*************************************************************

#     Sample custom script for Qualys Patch Manager          *

#                                                            *

#     This sample script checks whether a specific file      *

#     (pc.txt) already exists in a particular folder;        *

#   if not, it generates a list of all AD computers and      *

#   saves it to a new file named pc.txt. It returns 0 if      *

#     file does not exists and latest AD computer list is    *

#   saved and returns 1 if file already exists.              *

#                                                            *

#       Return Code                                          *

#        0 - success                                         *

#        1 - failure                                         *

#*************************************************************

  #create array of text files

  $files=Get-ChildItem C:\data\*.txt | select -expand fullname

  #check if file exists inside the array

  $files -match "pc.txt"

  #if matching return “True” key then exit, if “False” then create a report

  if($files -eq 'False'){

    Get-ADComputer -Filter * | Export-Csv -Path C:\data\pc.txt

exit 0

  }

  else{

     exit 1

  }

Example 4: Sample run script to uninstall the software 

The following sample run script that can be used to uninstall the software:

# Define the software name and registry key path

$softwareName = "Notepad++ (64-bit x64)"  

# Replace with the exact name of the software
$registryKeyPath = "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Notepad++" # Replace with the actual registry key path

# Function to uninstall software

function Uninstall-Software {

param ( [string]$softwareName

      )

# Search for the software in the uninstall registry keys

$uninstallKeyPaths = @( "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*", "HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"

$uninstallString = $null

foreach ($path in $uninstallKeyPaths) {

$key = Get-ItemProperty -Path $path | Where-Object { $_.DisplayName -eq $softwareName }

if ($key) {

$uninstallString = $key.UninstallString

break

}

if ($uninstallString) {

# Modify the uninstall string to add silent flags

if ($uninstallString -match "msiexec") {

$uninstallString += " /quiet /norestart" }

elseif ($uninstallString -match "uninstall.exe") {

$uninstallString += " /S" }

elseif ($uninstallString -match "setup.exe") {

$uninstallString += " /quiet" }

else { $uninstallString += " /silent /quiet /norestart" }

# Execute the uninstall command silently

Start-Process -FilePath "cmd.exe" -ArgumentList "/c", $uninstallString -NoNewWindow -Wait

Write-Host "Uninstalled $softwareName successfully."

} else {

Write-Host "$softwareName is not installed."

}

}

# Function to remove registry key

function Remove-RegistryKey {

param (

[string]$registryKeyPath

) if (Test-Path $registryKeyPath) {

Remove-Item -Path $registryKeyPath -Recurse -Force

Write-Host "Removed registry key: $registryKeyPath successfully."

} else {

Write-Host "Registry key: $registryKeyPath does not exist."

}

}

# Uninstall the software Uninstall-Software -softwareName $softwareName

# Remove the registry key Remove-RegistryKey -registryKeyPath $registryKeyPath

Linux Pre-Actions and Post-Actions Examples

Example 1: To copy the contents from one file to the other file.

This sample script detects if the contents from a source file are copied to the other file that is the destined file. If the code returned is 0, the content is successfully copied to the destined file, and if the code returned is 1, the content is not copied to the destined file.

Return Code:

- Success: 0

- Failure: 1

********************************************************************

 #!/bin/bash

 # Specify the paths of the source file (the one you want to replace with) and the destination file (the one you want to replace).


source_file="/root/source.txt"
destination_file="/root/Documents/destination.txt"

 # Check if the source file exists.
if [ -f "$source_file" ]; then
    # Remove the destination file if it exists.
    if [ -f "$destination_file" ]; then
        rm "$destination_file"
    fi

 # Copy the source file to the destination location.
    cp "$source_file" "$destination_file"
    echo "File replaced successfully."
    exit 0
else
    echo "Source file does not exist."
    exit 1
fi

Example 2: To install the RPM package for a specific application

This sample script detects whether or not the RPM package for a specific application is installed. If the code returned is 0, the RPM package is installed successfully; if the code returned is 1, the installation fails.

Return Code:

- Success: 0

- Failure: 1

**********************************************************

 #!/bin/bash

# Check if the script is being run as root
if [[ $EUID -ne 0 ]]; then
   echo "This script must be run as root."
   exit 1
fi

 

# Check if an RPM file is provided as an argument
if [ $# -ne 1 ]; then
    echo "Usage: $0 <path_to_rpm_file>"
    exit 1
fi

 

rpm_file="$1"

# Check if the RPM file exists
if [ ! -f "$rpm_file" ]; then
    echo "RPM file not found: $rpm_file"
    exit 1
fi

 

# Install the RPM package
echo "Installing $rpm_file ..."
rpm -i "$rpm_file"

 

# Check the installation status
if [ $? -eq 0 ]; then
    echo "Installation successful."
    exit 0
else
    echo "Installation failed."
    exit 1
fi

 

 

Mac Pre-Actions and Post-Actions Examples

Mac Zsh script examples

You can execute the following sample scripts on Mac ARM Agent 5.3.0.x:

Script 1: With this script, you can create a backup of the text file. 

Before You Begin, you need to grant the execute permission for the sample shell script file after creating it using the following command:

chmod +x <filename.sh>

 
Filebackup.sh
 #!/bin/bash
 touch original.txt
 echo this is original text > original.txt
 touch backup.txt
 echo this is backup text > backup.txt
 source="original.txt"
 backup="backup.txt"
 cp "$source" "$backup"
 echo "Backup created: $backup"

 

Execute the following script:

bash-3.2$ ./Filebackup.sh

Result: The backup file (backup.txt) is created.

Mac Run Script example 1.

Script 2: With this script, you can check the network connectivity of the website 

./networkconnectivity.sh
#!/bin/bash
website="www.google.com"
if ping -q -c 1 "$website" ; then
    echo "Website $website is reachable."
else
    echo "Website $website is unreachable."
Fi

 

Execute the following script:

./ networkconnectivity.sh

Result: Website www.google.com is unreachable.

Mac Run Script example 2.

Mac Apple Script Examples


Script 1: Apple Script to target an app for user interface scripting

The following sample scripts are executed on Mac ARM Agent 5.3.0.x.

Prerequisite

To run a user interface script in Script Editor, you must enable accessibility for Script Editor. Admin credentials are required to enable user interface scripting.
 

tell application "System Events"
    tell process "Safari"
              name of every menu of menu bar 1
        -- Perform user interface scripting tasks
end tell
end tell

 

Result: Refer to the following screenshot, which displays a list of menu names.

Mac Run Script example 3.

Script 2: Apple Script to display a simple dialog box that shows the current date and time.

Script:
set theDialogText to "The current date and time is " & (current date) & "."
display dialog theDialogText

Result: The following dialog box is displayed.

Mac Run Script example 4.

Consider this

  • You can add pre-actions and post-actions to Windows, Linux, and Mac jobs.
  • You can only add actions on assets with Windows Cloud Agent version 4.6.1.6 or later.
  • You can add a maximum of five pre-actions and post-actions each for a job.
  • If one action fails, the other actions continue to execute.
  • The script size cannot exceed 20 KB, and the script length must not exceed 20480 characters, including spaces. The script beyond 20480 characters will be truncated.
  • Success or failure of action execution does not impact the patches that are part of the job. Installation of all patches in a job is attempted.
  • The run time for each action can be at most 180 minutes. If the action is not completed within 180 minutes, the subsequent action is executed.
  • Only one reboot request is honored for one job. If the pre-actions require a reboot, the reboot will happen only after the patches are installed. Post-actions might be executed after the reboot.
  • If a post-action requires a reboot, the job is considered complete only after a reboot.
  • We strongly recommend not to use a force reboot in the script. Since Patch Management only allows one reboot for one job, this can cause the job to go into a reboot loop.
  • You can view details for each action using the Job Progress option after the job is executed. For more information, see Viewing Action Details.
  • You can include the pre-actions and post-actions results in the job progress report. For more information, refer to Reviewing Job Results.
  • For the Install Software action type, ensure that you provide the SHA256 based checksum of the download file.
  • The scripts you provide are sent in the base64 encoded format.
  • Only PowerShell scripts are supported, and we recommend using signed scripts. The PowerShell scripts are executed based on the execution policy that you define. Patch Management will support all execution policies; however, we recommend using AllSigned or RemoteSigned execution policy for security reasons. For more information, see About Execution Policies.

To ensure scripts are executed on an asset, ensure that PowerShell scripts are not blocked on the device or, in case the execution policy only allows signed scripts to run, ensure that you provide a signed script and paste the script and its signature both in the script text box.

  • You can use publicly available methods, such as certUtil, to generate SHA256 for a file. For example, you can run the following command in your command prompt:   certUtil -hashfile "<<filename>>" SHA256.  

    Utility Example.
  • For the Install Software action type, ensure that the script you add contains the code to deploy the binary.
  • The detection script acts as a pre-check for the Install Software action type. The detection script is not mandatory, and if you don't enter the detection script, the install script action will be executed directly. If the detection script fails, the install software. action will not be executed.

Patch Management performs no validation and executes any script you provide. We recommend that you exercise caution with the scripts that you run.

Related Links

Managing Patch Jobs for Windows Assets

Managing Patch Jobs for Linux Assets

Managing Patch Jobs for Mac Assets