Replacing Java with PowerShell on MID Server Script Include
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
4 weeks ago - last edited 4 weeks ago
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.
