Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

Replacing Java with PowerShell on MID Server Script Include

Frank Silveira
Tera Contributor

Hello Experts,

 

I'm currently trying to convert a MID Server Script include from using Java packages to use PowerShell. The problem is, I don't really know what I'm doing 😅.

 

The MID Server Script include sends a javascript probe, and withing that probe there is a log info that should also be included.

 

Below you can se the original script (working well, as we want it to) and my version with PowerShell (that works everything but the logging part).

 

Working Version:

var ProcessPaymentReport = Class.create();

ProcessPaymentReport.prototype = {

    String: Packages.java.lang.String,
    File: Packages.java.io.File,
    Files: Packages.java.nio.file.Files,
    PostMethod: Packages.org.apache.commons.httpclient.methods.PostMethod,

    FileRequestEntity: Packages.org.apache.commons.httpclient.methods.FileRequestEntity,
    HTTPClient: Packages.com.glide.communications.HTTPClient,
    FilePart: Packages.org.apache.commons.httpclient.methods.multipart.FilePart,
    StringPart: Packages.org.apache.commons.httpclient.methods.multipart.StringPart,
    AuthScope: Packages.org.apache.commons.httpclient.auth.AuthScope,
    UsernamePasswordCredentials: Packages.org.apache.commons.httpclient.UsernamePasswordCredentials,


    initialize: function() {
        this.resLog = "";

        this.postMethodType = 'POST';
        this.headers = [];
        this.responseObj;

        this.logPrefix = probe.getParameter("log_prefix");
        this.endPoint = probe.getParameter("end_point");
        this.filePathProcessed = probe.getParameter("file_path_processed");
        this.filePath = probe.getParameter("file_path");

        //Execute the probe
        this.response = this.execute();

    },

    execute: function() {
        try {
            this._log("Running ProcessPaymentReport execute", "INFO");

            var importFolder = new this.File(this.filePath);
            var filesArr = importFolder.listFiles();

            // Create "Processed file" folder
            var processedDir = new this.File(this.filePathProcessed);
            if (!processedDir.exists()) {
                processedDir.mkdir();
            }

			if (filesArr.length == 1 && !filesArr[0].isFile()) {
                this._log("No files to process", "INFO");
            } else {

				this._log("REST Call to:" + this.endPoint, "INFO");
				var fileIndex = 0;
				
                for (var i = 0; i < filesArr.length; i++) {
                    if (filesArr[i].isFile()) {
                        this._log("Posting the file: " + filesArr[i].getPath(), "INFO");
                        
						
						var result = this.postFileString(this.endPoint, filesArr[i], fileIndex);
						
						fileIndex++;
						
                        this._log("Result of file posting: " + result, "INFO");
                        if (result) {
                            this._log("Moving the file to: " + this.filePathProcessed + filesArr[i].getName(), "INFO");
                            if (filesArr[i].renameTo(new this.File(this.filePathProcessed + filesArr[i].getName()))) {
                                this._log("File moved succesfully", "INFO");
                            } else {
                                this._log("Failed to move the file", "INFO");
                            }
                        }
                    }
                }
				this._log('FILECOUNTSTART'+fileIndex+'FILECOUNTEND');
            }


        } catch (e) {
            this._log("Function execute error " + e.toString(), "ERROR");
        }
        return JSON.stringify(this.result);
    },

	postFileString: function (url, file, index) {
		this._log("Posting back to: ECC QUEUE", "INFO");
        this._log("File:" + file, "INFO");

        try {
			var fileReader = this.Files;
			var xmlString = fileReader.readString(file.toPath());
			
			this._log('CONTENTPAINFILE'+index+'START' + xmlString + 'CONTENTPAINFILE'+index+'END', 'CONTENT');
			
			return true; // no validation
			
        } catch (e) {
            this._log("POST File call error: " + e.toString(), "ERROR");
        }
	},


    getLog: function() {
        return this.resLog;
    },

    //Logger function
    _log: function(str, level) {
        var logStr = this.logPrefix +
            " - " + level +
            " - " + str;
        this.log(logStr);
        this.resLog += logStr + "\n";
    },

    _getConfigParameter: function(parm) {
        var m = Packages.com.service_now.mid.MIDServer.get();
        var config = m.getConfig();
        var res = config.getParameter(parm);
        var res2 = config.getProperty(parm);
        if (res) {
            return res;
        } else if (res2) {
            return res2;
        } else {
            config = Packages.com.service_now.mid.services.Config.get();
            return config.getProperty(parm);
        }

    },

    type: 'ProcessPaymentReport'
};

 

Version with problem:

var ProcessPaymentReport_V2 = Class.create();

ProcessPaymentReport_V2.prototype = {

    PSCommand: sn_ws.PSCommand,

    initialize: function() {
        this.resLog = "";

        this.postMethodType = 'POST';
        this.headers = [];
        this.responseObj;

        this.logPrefix = probe.getParameter("log_prefix");
        this.endPoint = probe.getParameter("end_point");
        this.filePathProcessed = probe.getParameter("file_path_processed");
        this.filePath = probe.getParameter("file_path");

        //Execute the probe
        this.response = this.execute();
    },

    execute: function() {
        try {
            this._log("Running ProcessPaymentReport_V2 execute", "INFO");

            // List files in folder
            var ps = new this.PSCommand();
            ps.setCommand("Get-ChildItem -Path '" + this.filePath + "' -File | Select-Object -ExpandProperty FullName");
            var filesArr = ps.execute().getOutput().split('\n');

            // Ensure processed folder exists
            var psDir = new this.PSCommand();
            psDir.setCommand("if (-not (Test-Path '" + this.filePathProcessed + "')) { New-Item -ItemType Directory -Path '" + this.filePathProcessed + "' | Out-Null }");
            psDir.execute();

            if (filesArr.length == 0 || (filesArr.length == 1 && filesArr[0] == "")) {
                this._log("No files to process", "INFO");
            } else {
                this._log("REST Call to:" + this.endPoint, "INFO");
                var fileIndex = 0;

                for (var i = 0; i < filesArr.length; i++) {
                    var file = filesArr[i].trim();
                    if (file) {
                        this._log("Posting the file: " + file, "INFO");

						var result = this.postFile(this.endPoint, filesArr[i]);
                        fileIndex++;

                        this._log("Result of file posting: " + result, "INFO");
                        if (result) {
                            var dest = this.filePathProcessed + "\\" + file.split('\\').pop();
                            this._log("Moving the file to: " + dest, "INFO");

                            var psMove = new this.PSCommand();
                            psMove.setCommand("Move-Item -Path '" + file + "' -Destination '" + dest + "' -Force");
                            var moveResult = psMove.execute();

                            if (moveResult.getError()) {
                                this._log("Failed to move the file: " + moveResult.getError(), "ERROR");
                            } else {
                                this._log("File moved successfully", "INFO");
                            }
                        }
                    }
                }
                this._log('FILECOUNTSTART' + fileIndex + 'FILECOUNTEND');
            }

        } catch (e) {
            this._log("Function execute error " + e.toString(), "ERROR");
        }
        return JSON.stringify(this.result);
    },

    postFile: function(url, file) {
        this._log("Posting to:" + url, "INFO");
        this._log("File:" + file, "INFO");

        try {
            var midUser = this._getConfigParameter("mid.instance.username");
            var midPassword = this._getConfigParameter("mid.instance.password");

            var ps = new this.PSCommand();
            ps.setCommand(
                "$body = Get-Content -Path '" + file + "' -Raw; " +
                "$cred = New-Object System.Management.Automation.PSCredential('" + midUser + "', (ConvertTo-SecureString '" + midPassword + "' -AsPlainText -Force)); " +
                "$resp = Invoke-RestMethod -Uri '" + url + "' -Method Post -Body $body -ContentType 'application/xml' -Credential $cred -ErrorAction Stop; " +
                "if ($resp.StatusCode) { $resp.StatusCode } else { 200 }"
            );
            var result = ps.execute();

            var status = result.getOutput().trim();
            if (status != '200' && status != '201' && status != '202') {
                this._log("Call result " + status, "ERROR");
                return false;
            } else {
                return true;
            }

        } catch (e) {
            this._log("POST File call error: " + e.toString(), "ERROR");
        }
    },

    getLog: function() {
        return this.resLog;
    },

    //Logger function
    _log: function(str, level) {
        var logStr = this.logPrefix + " - " + level + " - " + str;
        this.log(logStr);
        this.resLog += logStr + "\n";
    },

    _getConfigParameter: function(parm) {
        // Replace Java config fetch with PowerShell registry/env lookup
        var ps = new this.PSCommand();
        ps.setCommand(
            "$val = (Get-ItemProperty -Path 'HLM:\\SOFTWARE\\ServiceNow\\MID Server' -ErrorAction SilentlyContinue)." + parm + "; " +
            "if (-not $val) { $val = [Environment]::GetEnvironmentVariable('" + parm + "') }; " +
            "Write-Output $val"
        );
        var result = ps.execute();
        return result.getOutput().trim();
    },

    type: 'ProcessPaymentReport_V2'
};

 

This is how both scripts are being called (Scheduled job):

getReportFileFromMID();

function getReportFileFromMID() {
    var jspr = new global.JavascriptProbe(gs.getProperty('mid_server_name'));
	jspr.setName('ProcessPaymentReport_V2');
    jspr.addParameter("log_prefix", 'Process Payment Report File');
    jspr.addParameter("end_point", gs.getProperty('glide.servlet.uri') + 'api/imp_status_report');
    jspr.addParameter("file_path", gs.getProperty('import_folder'));
    jspr.addParameter("file_path_processed", gs.getProperty('import_folder_processed'));
    jspr.setJavascript('var req = new ProcessPaymentReport_V2(); req.getLog();');
    jspr.setSource(gs.generateGUID());
    jspr.addParameter('skip_sensor', true);
    jspr.create();
}

 

 

This was done mainly with AI help, as I didn't know how to tackle this issue.

 

In the PowerShell version, everything works except for the log part (the log info should be shown in the ECC Queue input record).

 

Any help to identify/correct the issue would really be appreciated.

 

Thank you in advance. 

0 REPLIES 0