Skip to main content
Skip table of contents

Writing scripts for remote actions on Windows

The payload of remote actions on Windows are PowerShell scripts that run on employee devices. PowerShell is a scripting language from Microsoft that is suited for task automation and configuration management and is built on top of the .NET Framework in Windows devices. PowerShell is therefore ideal for getting on-demand data from devices, performing self-healing tasks or modifying the configuration of a device, which are typical use cases for remote actions.

This article assumes that the reader is familiar with PowerShell scripting.

Find more information about writing scripts for remote actions on Community:

Encoding

To write your own PowerShell scripts for remote actions, encode the files that contain the text of your scripts in UTF-8 with byte order mark (BOM). BOM is a Unicode character that must be present at the beginning of the file and whose representation in UTF-8 documents is the following sequence of three bytes, in hexadecimal: EF BB BF.

End each line in the code with the usual character sequence in Windows systems: CR+LF.

Failing to provide the right encoding to your script files results in the inability of remote actions to run on employee devices.

Signing your own scripts

For security reasons, Nexthink strongly recommends that you sign all scripts that you write. Unsigned scripts are only suitable for testing in pre-production environments.

To sign your PowerShell scripts, use the Set-Authenticode command as follows:

  1. Get your code-signing certificate from:

    • The PowerShell certificate provider:
      $cert = Get-ChildItem -Path Cert:\CurrentUser\My -CodeSigningCert

    • A PFX file:
      $cert = Get-PfxCertificate -FilePath C:\Test\Mysign.pfx

  2. Sign your script for a remote action, for example remoteaction.ps1, with the code-signing certificate, adding a timestamp to keep it working after certificate expiration. The example below uses the DigiCert timestamp server: Set-AuthenticodeSignature -FilePath .\remoteaction.ps1 -Certificate $cert -IncludeChain All -TimestampServer "http://timestamp.digicert.com"

  3. Optional: Verify the signature in the script. Get-AuthenticodeSignature .\remoteaction.ps1 -Verbose | fl

Deploying the code-signing certificate

The default policy lets the official remote actions from Nexthink Library execute on the device without requiring any additional configuration. If you choose to create and sign your own scripts for remote actions, add the signing certificate to the Local Computer > Trusted Publishers certificate store in Microsoft Windows.

If you do not add the code-signing certificate to the Local Computer > Trusted Publishers store in Microsoft Windows then the system generates the following error: The remote action could not be executed: the script signature is invalid or the certificate is not trusted.

Additionally, if your certificate to sign scripts was generated by a private CA, a CA whose root certificate is not already present in the Local Computer’s Trusted Root Certification Authorities certificate store of Windows, add the root certificate of the CA to the Local Computer’s Trusted Root Certification Authorities certificate store. Similarly, if you used an intermediate certificate to sign your scripts, include the full chain of intermediate certificates in the Local Computer’s Intermediate Certification Authorities certificate store:

  1. Log in to Microsoft Windows as an administrator.

  2. Press Win+R keys to open the Run dialog:

    1. Type in certlm.msc.

    2. Click OK.

  3. Click Yes to allow the program to make changes to your device.

  4. Right-click the name of the desired certification store, for example, Trusted Publishers on the left-hand side list.

    1. Select All-tasks > Import... from the context menu to start the Certificate Import Wizard.

  5. Click Next to start the wizard.

  6. Click Browse and select your certificate file.

  7. Click Next.

  8. Click Next to accept the suggested certificate store in the Place all certificates in the following store dialog window.

  9. Verify the certificate you are importing and click Finish.

Certificates

Nexthink recommends not to import the certificates individually on every device but to use an administration tool to deploy the certificates on all devices at the same time. Use Group Policy Objects (GPOs) of Active Directory, for example, to achieve this.

Writing generic scripts

You can write scripts in a generic way to adapt them to particular use cases. To make your script generic, declare formal parameters at the beginning of the PowerShell script. Provide actual values to the parameters in the Nexthink web interface when editing the remote action that contains the script.

Keeping the script generic is especially useful in the case of digitally signed scripts that require some customization. When a script is signed, any modification to its text content breaks the signature. By making a signed script generic, you allow its customization via parameters. With parameters, the script text remains unchanged, and thus the digital signature remains valid. The values for the parameters that a remote action passes to the script determine its actual behavior.

For example, to make a script that reads from a generic registry key, declare a parameter in the script that contains the path to the key in the registry. In this way, several remote actions may use the same script to read from different registry keys by supplying a different path to the parameter in the script.

Declare parameters at the beginning of a script in the usual way for PowerShell scripts: 

CODE
param(
    [string]$filePath,
    [string]$regPath
)

When uploading the script during the remote action configuration, the system recognizes the parameters of any imported PowerShell script and lists them in the Parameters section. Provide actual values to the parameters in the text input boxes displayed to the right of each parameter name. Note that the actual values are always passed to the script as text: if the script declares parameters with a type other than string, ensure that you provide values that the script can convert to their expected type.

Output variables

The execution of a script may generate output that you want to store as on-demand in the data layer. To that end, Nexthink provides a .NET assembly (nxtremoteactions.dll) that is installed on an employee device at the same time as Collector. The assembly includes a class called Nxt that provides the methods to write results to the data layer.

To use the Nxt class, add the following line at the beginning of a PowerShell script for remote actions:

Add-Type -Path $env:NEXTHINK\RemoteActions\nxtremoteactions.dll

Use the Nxt class methods to write the desired outputs. All write methods accept two arguments: the name of the output and the value to write. For instance, to write the size of a file to the data layer:

[Nxt]::WriteOutputSize("FileSize", $fileSize)

When uploading the script during the remote action configurations, the system recognizes the calls to write outputs in the script and lists the output variables under the Outputs section below the script text. Set the label of the output to indicate how to refer to it in investigations and metrics.

The ending of each written method indicates the type of output. Find the list of available methods and the corresponding PowerShell type of the value to be written in the table below:

Nxt write method

PowerShell type

Constraints

WriteOutputString

[string]

0 - 1024 characters (output truncated if bigger)

WriteOutputBool

[bool]

true / false

WriteOutputUInt32

[uint32]

  • Min: 0

  • Max: 4 294 967 295

WriteOutputFloat

[float]

  • Min: -3.4E+38

  • Max: 3.4E+38

WriteOutputSize

[float]

  • Min: 0

  • Max: 3.4E+38

WriteOutputRatio

[float]

WriteOutputBitRate

[float]

WriteOutputDateTime

[DateTime]

DD.MM.YYYY@HH:MM

WriteOutputDuration

[TimeSpan]

  • Min: 0 ms

  • Max: 49 days

  • Precision in milliseconds

WriteOutputStringList

[string[]]

Same as string

Interacting with employees in self-help scenarios

To help employees solve issues by themselves, combine remote actions with campaigns. In combination with remote actions, campaigns let you inform employees about the detection of an issue and guide them through its resolution.

To display a campaign on the desktop of an employee who is interacting with a device:

  • The campaign must have a Remote action trigger and be published.

  • The script of the remote action can be executed either:

    • In the context of the employee, if the action does not need any special privileges.

    • In the context of the local system account, if the action needs administrative privileges.

Obtaining a campaign identifier

The methods to run a campaign from a remote action require a campaign identifier to be passed as an argument. You can use both the campaign NQL ID (recommended) and the campaign UID (classic option).

Support for the NQL ID as an identifier requires Collector version 23.5 or later.

To pass the campaign identifier to a remote action, declare a parameter in the script of the remote action for each required campaign. Use the NQL ID (or UID) as the actual value for the parameter when editing the remote action.

Refer to the Triggering a campaign documentation for more information on how to get the NQL ID or the UID of a campaign in the Nexthink web interface.

Running a campaign from the script of a remote action

To interact with campaigns, the remote action script must load a .NET assembly (nxtcampaignaction.dll) that is installed on an employee device along with Collector. The assembly includes the class Nxt.CampaignAction that provides the methods of controlling the execution of a campaign and getting the responses from an employee.

To load the assembly, add the following line at the beginning of the script:

Add-Type -Path $env:NEXTHINK\RemoteActions\nxtcampaignaction.dll

The methods of Nxt.CampaignAction to control campaigns are the following:

NxTrayResp RunCampaign(string campaignUid)

Run the campaign identified by the campaignUid and wait until the employee finishes answering the campaign. The campaignUid argument can contain either the UID or the NQL ID (recommended). Return the response in an object of type NxTrayResp.

NxTrayResp RunCampaign(string campaignUid, int timeout)

Run the campaign identified by the campaignUid and wait until the employee finishes answering the campaign or after the specified amount of time defined by timeout (in seconds) elapses. The campaignUid argument can contain either the UID or the NQL ID (recommended). Return the response in an object of type NxTrayResp.

RunStandAloneCampaign(string campaignUid)

Run the campaign identified by the campaignUid. The campaignUid argument can contain either the NQL ID (recommended) or the UID.

string GetResponseStatus(NxTrayResp response)

Given a response object of type NxTrayResp, the method returns a string that reflects the status of the campaign. Possible values for the status:

  • fully: the employee has fully answered the campaign questions.

  • declined: the employee has declined to participate in the campaign.

  • postponed: the employee has agreed to participate in the campaign.

  • timeout: the system timed out the campaign before the employee finished answering it.

  • connectionfailed: the script was unable to connect to the Collector component that controls campaign notifications due to a technical error in communication between Collector components.

  • notificationfailed: the script was unable to display the campaign successfully, due to one of the following:

    • The campaign definition could not be retrieved from the platform because of a non-existing campaign or non-published campaign.

    • Another campaign is already being displayed to employees.

    • A non-urgent campaign cannot be shown due to the focus protection or do-not-disturb rules of Collector. Refer to Limiting the reception rate of campaigns documentation for more information.

string[] GetResponseAnswer(NxTrayResp response, string questionLabel)

Given a response object of type NxTrayResp and the label that identifies a question in the campaign, the method returns the response given by the employee.

  • In the case of a single-answer question, the returned string array only has one element.

  • In the case of a multiple-answer question, the returned string array has as many elements as answers selected by the employee. Optional free text is ignored.

  • If the employee has not fully answered the campaign, for example, status is not fully, the returned string array is empty. Optional free text is ignored.

For security reasons, remote actions for self-help scenarios ignore the optional free text answers of multiple answer or opinion scale questions. Therefore, it is useless to include optional free text answers in campaigns to be used exclusively in self-help scenarios.

Code example

In this example, we assume that you have created a single-answer campaign where one of the possible answers is yes:

CODE
Add-Type -Path "$env:NEXTHINK\RemoteActions\nxtcampaignaction.dll"

$CampaignUid  = "<NQL ID of a single-answer campaign>"
$maxWaitTimeinSeconds = 60

$result = [Nxt.CampaignAction]::RunCampaign($CampaignUid, $maxWaitTimeinSeconds)
$status = [Nxt.CampaignAction]::GetResponseStatus($result)

if ($status -eq "fully") {
    $questionName = "question1"
    $choiceName =[Nxt.CampaignAction]::GetResponseAnswer($result, $questionName)
    if ($choiceName -eq "yes") {
        # user has confirmed - let's do some actions:
        Start-Process notepad.exe
    }
}

Error handling

Nexthink detects whether the execution of a remote action was successful or not based on the return value of the PowerShell process that ran the script:

  • An exit code value of 0 indicates a successful execution.

  • A non-zero value indicates an error.

However, unhandled exceptions in PowerShell may cause the termination of a script without returning an appropriate exit code. To handle unexpected errors, Nexthink recommends you begin the body of all your scripts with the following code snippet:

CODE
 trap {
     $host.ui.WriteErrorLine($_.ToString())
     exit 1
 }


Place this default error handler underneath the inclusion of the necessary DLL dependencies, which follow the optional declaration of formal parameters.

Performance measurement

To measure the performance and resource consumption of your scripts, turn on the logs for Collector in debug mode with the help of the Collector configuration tool:

nxtcfg.exe /s logmode=2

The output is stored in the nxtcod.log file.

The operations described in this article should only be performed by a Nexthink Engineer or a Nexthink Certified Partner.

If you need help or assistance, please contact your Nexthink Certified Partner.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.