Escaping parameters passed to perl script within Windows Shell - asp.net

I have a perl script that was provided by a vendor, and that takes a series of parameters. I would like to call this via a Windows Shell object in ASP classic.
If I type the following in the cmd line on the web server, it works just fine:
path_to_perl\perl.exe path_to_pl\myfile.pl --arg1 "something" --arg2 "somethingelse"
If I do the following in ASP classic, it doesn't work:
strCMD = "path_to_perl\perl.exe path_to_pl\myfile.pl --arg1 ""something"" --arg2 ""somethingelse"""
Set objWShell = CreateObject("WScript.Shell")
Set objCmd = objWShell.Exec("cmd.exe /c " & strCMD)
The issue is that the argument have all sorts of special characters, so I need to quote them. I have read conflicting information as to how I should escape them - via a caret or a back-slash. Any help would be greatly appreciated!

Shoulf call Perl directly, like this:
system_call_test( 'c:/complete/path_to_pl/myfile.pl --arg1 "something" ... ' )
See the discussion here: How to call perl programs from ASP page
and aspecially the answers of Charles K. Clarkson here.
It will simplify the problem, as you will not have to deal with escaping characters
for ASP, CMD and Perl - all at the same time.
(in that discussion the problem was a syntax-error at the Perl-script, eventually,
but it still shows how to code it in ASP).

Related

Error in system(command, intern = TRUE) : '“C:\Program' not found selectWeka function

I'm trying to run the code below from BioSeqClass package, however I get an error message:
Error in system(command, intern = TRUE) : '“C:\Program' not found
selectWeka(data, evaluator="CfsSubsetEval", search="BestFirst", n)
This is a problem with how BioSeqClass is calling java: it is leaving the file names unprotected/unquoted, and R's system and system2 commands are horrible by not forcing quoting. (If you ever think of using these commands directly yourself, I strongly recommend something like processx.)
One should create an issue or bug-report, but I don't know how to do that with Bioconductor, and their mirror on github (https://github.com/Bioconductor-mirror) is defunct, so I'm at a loss there. Hopefully somebody with more info can weigh in on this.
Workarounds
It is not obvious if the problem is due to where weka.jar is located or perhaps one of the other arguments. You can find out where the problem is by debugging the selectWeka function and inspecting the value of command before the system call. Look for the Program Files component of a path.
If the problem is with weka.jar, then this suggests that you are installing packages somewhere under C:\Program Files\, which is in my experience bad practice on two counts:
For many problems I cannot recall (but this one re-ignites the discussion), I never install R in the default location under C:\Program Files\...; instead, I install it under a new directory, C:\R\R-3.5.3 (version-based) and go from there. You may not have control over this if on a university/company system.
Since this is not in a base-R package, this suggests that either you are not using a personal library location (collection of packages), or have placed your personal library for some reason under C:\Program Files. If the former, I strongly suggest you never install new packages inside the base-R installation directory, instead using your own. See ?.libPaths and many other tutorials/discussions on the topic online. Using packrat or checkpoint might also mitigate this problem.
If the problem is with trainFile (if I'm reading the source correctly), then your "permanent" fix is to change where Windows puts temporary files, as this trainFile is a temporary file created specifically for this function-run. If this is your problem, I'll leave it up to you to fix.
Regardless, you may not have time or need to make a more permanent solution, you just want to run this once or twice and then move on. For that fix:
Again, debug(selectWeka), and once command is defined (the next command to be executed is tmp <- system(command,intern = TRUE)), run this code to fix the value of command:
if(search=="Ranker"){
command = paste("java -cp ", shQuote(file.path(.path.package("BioSeqClass"), "scripts", "weka.jar")),
" weka.attributeSelection.", evaluator, " -i ", shQuote(trainFile),
" -s \"weka.attributeSelection.", search, " -N ", n, "\"", sep="" )
}else{
command = paste("java -cp ", shQuote(file.path(.path.package("BioSeqClass"), "scripts", "weka.jar")),
" weka.attributeSelection.", evaluator, " -i ", shQuote(trainFile),
" -s weka.attributeSelection.", search, sep="" )
}
(For the record, all I changed was adding shQuote twice to each paste.) Confirm that command now has quotes around things, something like
Browse[2]> command
[1] "java -cp \"C:\\Program Files\\...\\weka.jar" weka.attributeSel... -i \"c:\\path\\to\\some\\tempfile\" ...
Then you can continue-out of the debugger and let it run its course.
(I hope you don't have hundreds of calls to selectWeka.)
Caveat: I am not a use of BioSeqClass, so I'm saying all of this from speculation and inference. I might have mis-located the source of the error. And since I don't know what I'm doing with it, I have not tested the modified command assignment within selectWeka. I believe shQuote(...) is the right way to go, but you might need to use sQuote or dQuote instead, I'm not sure how your system is setup.

keep Shell / cmd open when launching R script from VBA

I have an R script that is being run from an Excel workbook via a button that is linked to a VBA script.
The problem is every time the R script encounters an error - say it does not find one of the files it was supposed to read - the Shell / cmd window the R script is running in closes down instantly. The problem with that is you cannot see any clues as to why it failed. I then have to debug it manually by modifying the code and running in RStudio to find the errors - usually I have to do this for other people that do not know R.
The VBA code I use was copied and modified from one of the SO posts I found here. I am not very proficient in VBA and do not understand a lot of the code so I'm looking for a simple solution to this. My VBA code is this:
Option Explicit
Public Sub RunRscript()
ActiveWorkbook.Save
Dim shell As Object
Set shell = VBA.CreateObject("WScript.Shell")
Dim waitTillComplete As Boolean: waitTillComplete = True
Dim style As Integer: style = 1
Dim scriptPath As String
scriptPath = Range("F5").Value
Dim argument As String
argument = Range("F3").Value
Dim path As String
path = """C:\Program Files\R\R-3.4.2\bin\Rscript.exe"" """ & scriptPath & """ """
& argument & """"
ActiveWorkbook.Save
Dim errorcode As Integer
errorcode = shell.Run(path, style, waitTillComplete)
ActiveWorkbook.Save
End Sub
scriptPath points to the path of the R script and argument is an argument I pass to the R script.
I have tried passing the usual arguments to keep the cmd window open but I didn't manage to figure it out. This is also complicated by the fact that as mentioned I do not understand VBA syntax very well and the 'path' variable being very convoluted because of those endless double quotes.
You might use
errorcode = shell.Run("cmd /k " & path, style, waitTillComplete)
instead of
errorcode = shell.Run(path, style, waitTillComplete)
We open a new instance of the command-line tool, thus can use its parameters. The parameter /k keeps the cmd-window open (use /c to close). After the cmd-parameter we add the script to be executed.
But there is one problem: if you close the cmd-window, VBA throws an overflow error. I use a flag in my Excel sheet to switch between debug mode and normal mode:
debugging = Range("N5").Value 'True/False
If debugging Then
errorCode = shell.Run("cmd /k " & path, style, waitTillComplete)
Else
errorCode = shell.Run(path, style, waitTillComplete)
End If
If the script fails I rerun it setting debug mode to True in a cell of the Excel sheet.
Based on this comment:
#FreeMan, the output of the R script is actually a series of Excel workbooks that it opens, prints data in and then saves. it reads a list with the paths of all the files it needs to read as an input to generate the output data required to print in excel. Sometimes, one of the paths in that list is wrong, so the program stops halfway and there is no clue as to why for the user. (the reason could be something else as well). It would be good if I could pass the text that is generated in shell / cmd automatically to a notepad / textpad file at least, so the user could then open and check
It sounds like the best bet may be to have your R script validate the paths/files prior to attempting to do its processing. I'm barely familiar with R, but what I know of it there should be a library somewhere that will allow you to test for the existence of a path and/or a file on that path. If it doesn't exist, the script would simply put an error message in the file it was supposed to create/update indicating that it couldn't find the requested path/file, or it could write that message to an error log that could be opened by your VBA code at the completion of its processing.

How to execute a command with multiple parameters from a file in gradle?

I have below command in a .txt-file:
java -jar /path/to/something.jar --classpath="/path/to/something/other.jar" --url="something:#127.0.0.1:1234:TEST12" --driver=some.driver update
As can be seen multiple parameters with different syntax (with -, --, and/or with and without "") are used.
I tried the following code:
task test(type: Exec) {
workingDir '/path/to/working/dir'
String commandFromFile = new File('/path/to/file/with/command' + 'filewithcommand.txt').getText('UTF-8')
commandLine commandFromFile
}
On windows platforms this code is working but on unix it doesn't.
As you can see in the documentation of the Exec task, you should split up your command into its parts. So doing commandLine commandFromFile.split(' ') should work if you do not have spaces in your arguments. If you have, you need a more sophisticated way to split the command that takes quotes into account.
Or you change the format of your command file so that it has one argument per line and you use .readLines('UTF-8') instead of .getText('UTF-8').
I'm not 100% sure about the following, but it could be that you also have to remove the quoting around arguments even if they contain spaces, as you give the arguments as single entities to the commandLine call and thus need no quoting for escaping spaces here. Depending on OS and tool you call it could even break the command if there are quotes that it cannot handle.
Alternatively, but that is the worse method imho, you can also do something like
if (windows) {
commandLine 'cmd', '/c', commandFromFile
} else {
commandLine 'sh', '-c', commandFromFile
}
where then the command processor does the splitting and so on. There you need the quotes and stuff of course. The windows variable in this example of course needs to be determined, e. g. from system properties.

Running a Windows executable file from within R with command line options

I am trying to call a Windows program called AMDIS from within R using the call
system("C:/NIST08/AMDIS32/AMDIS_32.exe /S C:/Users/Ento/Documents/GCMS/test_cataglyphis_iberica/queens/CI23_Q_120828_01.CDF")
in order to carry out an analysis (specified using the /S switch) on a file called CI23_Q_120828_01.CDF, but it seems that no matter what I try the file is not loaded in correctly, presumably because the options are not passed along. Does anyone have a clue what I might be doing wrong?
Right now this command either
doesn't do anything,
makes AMDIS pop up, but it doesn't load the file I specify
gives me the error
Warning message:
running command 'C:/NIST08/AMDIS32/AMDIS_32.exe /S
C:/Users/Ento/Documents/GCMS/test_cataglyphis_iberica/queens/CI23_Q_120828_01.CDF'
had status 65535
(I have no idea what results in these different outcomes of the same command)
(the AMDIS command line options are described here at the page 8)
Cheers,
Tom
EDIT:
Found it had to do with forward vs backslashes - running
system("C:\\NIST08\\AMDIS32\\AMDIS_32.EXE C:\\Users\\Ento\\Documents\\GCMS\\test_cataglyphis_iberica\\queens\\CI23_Q_120828_01.CDF /S /E")
seems to work - thank you all for the suggestions!
You've heard of bquote , noquote , sQuote, dQuote , quote enquote and Quotes, well now meet shQuote!!! :-)
This little function call works to format a string to be passed to an operating system shell. Personally I find that I can get embroiled in backslash escaping hell, and shQuote saves me. Simply type the character string as you would on the command line of your choice ('sh' for Unix alikes like bash , csh for the C-shell and 'cmd' for the Windows shell ) wihtin shQuote and it will format it for a call from R using system:
shQuote("C:/NIST08/AMDIS32/AMDIS_32.exe /S C:/Users/Ento/Documents/GCMS/test_cataglyphis_iberica/queens/CI23_Q_120828_01.CDF" , type = "cmd" )
#[1] "\"C:/NIST08/AMDIS32/AMDIS_32.exe /S C:/Users/Ento/Documents/GCMS/test_cataglyphis_iberica/queens/CI23_Q_120828_01.CDF\""
More generally, you can use shQuote like this:
system( shQuote( "mystring" , type = c("cmd","sh") ) , ... )

Write binary data using javascript on the server

I'm trying to output a PDF using server side javascript (ASP). The current method I'm using is:
xfile=Server.MapPath(lib.fso.GetTempName())
xf=lib.fopen(xfile,"wb");
lib.fwrite(xf,this.buffer);
lib.fclose(xf);
outB = Server.CreateObject("ADODB.Stream")
outB.Type = 1
outB.Open()
outB.LoadFromFile (xfile)
Response.BinaryWrite(outB.Read())
outB.Close()
lib.fso.DeleteFile(xfile);
This works, but requires write access on the server. Is there a way to do the same thing without writing to a file?
I havn't been able to figure out how to convert the string this.buffer into a array of byte that I can then write using Response.BinaryWrite without writing to a file first.
Why not simply use:-
Response.Write(this.buffer)
Assuming the codepage of the response is set correctly (I.e., its the same as in the Locale that the VBScript is running in) then Response.Write should do the same conversion that your StringToMultiByte is doing.
I suspect you've tried this and is hasn't worked. If so I really think you need to look into why that is rather attempt this strange usage of BinaryWrite. Currently your solution is going to kill your server.
My solution was to use VBScript.
replace the above code with:
Response.BinaryWrite(StringToMultiByte(this.buffer));
and add this to the end of the file:
<script language="vbscript" runat="server">
function StringToMultiByte(S)
Dim i, MultiByte
For i=1 To Len(S)
MultiByte = MultiByte & ChrB(Asc(Mid(S,i,1)))
Next
StringToMultiByte = MultiByte
End function
</script>

Resources