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.

Move file to mapped network drive with MID Server Script Include

greg54
Tera Expert

Hello,

We have a MID Server Script Include running that generates a text file. I am trying to move the generated file (via code) to a network drive that is mapped from the Windows machine the MID Server is running on after it is created. I was able to move the file to a different directory locally using the Java File object, but when I put a UNC path in as the destination directory, I am receiving a "java.io.IOException: Access is denied" error.

I am able to create/update a file in the mapped drive manually, so I know it isn't really a permission issue, but something about doing it via code, it doesn't like.

Does anybody have any advice to point me in the right direction?

Much appreciated!

8 REPLIES 8

Hi Marc,

I did manage to create such functionality, but its a bit tricky...
First of all, I'm exporting the attachment to a folder on the Mid server, because directly exporting it to the wanted network drive took to long and crashed the action most of the times.
Second, if a file is larger then 3-5Mb the copy action also doesn't work.
But most files (when nicely compressed) aren't that large so its fine (and I created an error message for the user when it fails to copy).

So here is the script include code:

createFiles: function () {
var result = this.newItem('result');
var Id = this.getParameter('sysparm_id');
var fileName = '';
var serverPath = '\\\\servername\\sharename$\\folder1\\folder2\\folder3';

//fileName = some value from table, make sure to filter out below characters
fileName = fileName.toString().replace(/[(?!/|\\|:|\*|\?|"|<|>|\|)]+/g, "");
fileName = fileName.toString().replace(/\]+/g,')').replace(/\[+/g,'(');

var gr = new GlideRecord('sys_attachment');
		gr.addQuery('table_sys_id', Id);
		gr.addQuery('table_name','source_table');
		gr.query();
		if (gr.next()) {
			var fileparts = gr.file_name.split('.');
			var ext = fileparts[fileparts.length-1];
			//var ext = gr.file_name.split('.')[1];
			fileName += '.' + ext;
			var sa = new GlideSysAttachment();
			var binData = sa.getBytes(gr); //Get attachment
			var encData = GlideStringUtil.base64Encode(binData); //encode attachment 

			var ftpFilePath = "D:\\Output\\Files\\";   // file path on mid server where file will be copied to.
			
			var server_probe = "";
			
			var gr_sta = new GlideRecord('sys_status');
			gr_sta.addQuery('name', 'glide.db.name');
			gr_sta.query();
			if (gr_sta.next()) {
				if (gr_sta.value.indexOf('test') > -1 ) {
					server_probe = "MID server TEST";	
				}
				else if (gr_sta.value.indexOf('dev') > -1) {
					server_probe = "MID server DEV";
				}
				else {
					server_probe = "MID server PROD";
				}
			}
			try {
				var jspr = new JavascriptProbe(server_probe);   // Creates a dynamic probe for the mid server specified in quotes.
				//gs.log('Begin create file probe');
				jspr.setName('FileToMidServer');   //This is a arbitrary name for the dynamic probe
				jspr.setJavascript("var ddr = new AttachmentSender(); res= ddr.execute();"); //this is the script the probe must run. In this case it calls a mid server script include.
				jspr.addParameter("targetFileName",fileName);
				jspr.addParameter("encodedData",encData);
				jspr.addParameter("targetPath",ftpFilePath);
				jspr.create();
			}
			catch(e) {
				gs.log('Exception downloading attachment: ' + e);
				}
			
			try {
				var wf = new Workflow();
				var workflowId = '6c75df3fdb9913041eb9fbd5ae961982'; // Move File
				var vars = {};
				vars.u_input_target_path = serverPath;
				vars.u_input_file_name = fileName;
				vars.u_input_temp_path = ftpFilePath;
				wf.startFlow(workflowId, emqugr, 'insert', vars);
			}	
			catch(e) {
				gs.log('Exception in workflow Move File: ' + e);
			}
result.setAttribute('answer', fileName);
}

There you see I'm starting a workflow to actually move the file:
find_real_file.png

The run script with the cursor on it does this:

var input_file_name = workflow.inputs.u_input_file_name;
var input_temp_path = workflow.inputs.u_input_temp_path;
//Check mainpath exists
workflow.scratchpad.test_script = 'if(!(Test-Path -Path "' + workflow.scratchpad.target_path + '")) { ' +
	//Create mainpath
	'New-Item -Path "' + workflow.scratchpad.target_path + '" -ItemType directory -Force > $null } ';
//Check if file already exists
workflow.scratchpad.exists_script = 'if ((Test-Path -Path "' + workflow.scratchpad.target_path + '\\' + input_file_name + '")) { ' +
	//Check if Archive folder already exists
	'if (!(Test-Path -Path "' + workflow.scratchpad.target_path + '\\Archive'+ '")) { ' +
		//Create Archive folder
		'New-Item -Path "' + workflow.scratchpad.target_path + '\\Archive' + '" -ItemType directory -Force > $null } ' +
	//Move existing file to Archive
	'Move-Item -Path "' +  workflow.scratchpad.target_path + '\\' + input_file_name + '" -Destination "' + workflow.scratchpad.target_path + '\\Archive' + '" -force }';
//Move new file to mainpath	
workflow.scratchpad.move_script = 'Move-Item -Path "' + input_temp_path + input_file_name + '" -Destination "' + workflow.scratchpad.target_path + '" -Force';
workflow.scratchpad.reloop = 0;

Followed by the Run Powershell (command field):

try { 
#[IO.File]::OpenWrite("&'${workflow.inputs.u_input_temp_path}${workflow.inputs.u_input_file_name}'").close();
${workflow.scratchpad.test_script};
${workflow.scratchpad.exists_script};
${workflow.scratchpad.move_script};
$output = "True"
#Write-Output "%output%" 
Write-Output "$($output)"
#Write-Outpit "%%"

 }
catch { 
$output = "False"
#Write-Output "%%output%%" 
Write-Output "$($output)"
#Write-Output "%%"
 } 

And the following line in the Sensor script of the Run Powershell:

workflow.scratchpad.movesuccess = trim(activity.output);

 

Like I said, not that easy, but it works for me!

Ow this is not exactly a Mid server script include like the title of the topic says...
Ah never mind, perhaps this can still help you 😉

Community Alums
Not applicable

I ended up cheating, we gave the mid server account write access to the directories, made a batch file that copies the files, the batch file is executed by a scheduled task set to run as the mid server user account.

It's not cheating if you don't get caught 😄

j/k nice workaround!