Java ProcessBuilder and VBS script issue - java

Am going round in circles here trying to execute a bit of VBScript from java using processbuilder. I'm running my java code as part of a tomcat servlet. If I run the same command from a command line - its running fine. Have tried opening permissions right up (everyone=full perms)
Java Code (excerpt):
ProcessBuilder pb = new ProcessBuilder("cscript", "C:\\Users\\Public\\Documents\\office2pdf.vbs", "C:\\Users\\Public\\Documents\\temp\\22.doc");
Process pr = pb.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(pr.getErrorStream()));
String line = null;
StringBuilder sb = new StringBuilder("");
while ( (line = reader.readLine()) != null) {
sb.append(line);
}
int i = pr.waitFor() ;
getServletContext().log("pb response="+i+", er="+sb.toString());
VBScript (excerpt):
Sub SaveWordAsPDF(p_strFilePath)
'Save Word file as a PDF
'Initialise
Dim objWord, objDocument
Set objWord = CreateObject("Word.Application")
Wscript.Echo p_strFilePath
'Open the file
Set objDocument = objWord.Documents.Open(p_strFilePath)
'Save the PDF
objDocument.SaveAs PathOfPDF(p_strFilePath), WORD_PDF
'Close the file and exit the application
objDocument.Close FALSE
objWord.Quit
End Sub
I've traced it as far to see that the vbscript is infact loading; the line 'Wscript.Echo p_strFilePath' does in fact actually print the correct path to the word doc. According to the error stream returned from java the offending line from vbscript is: 'Set objDocument = objWord.Documents.Open(p_strFilePath)' for which its saying:
Microsoft VBScript runtime error: Object required: 'objWord.Documents.Open(...)'
not sure if this is only triggered from incomplete path; looked at lots of posts - haven't been able to find any that exactly match my situation. Any advice is greatly appreciated!

Related

How can I get all errors when executing a command?

I'm developing a java program, at a certain point in the program I need to execute some commands and show all the errors returned by that command. But I can only show the first one.
This is my code:
String[] comando = {mql,"-c",cmd};
File errorsFile = new File("C:\\Users\\Administrator2\\Desktop\\errors.txt");
ProcessBuilder pb = new ProcessBuilder(comando);
pb.redirectError(errorsFile);
Process p = pb.start();
p.waitFor();
String r = errorsFile.getAbsolutePath();
Path ruta = Paths.get(r);
Charset charset = Charset.forName("ISO-8859-1");
List<String> fileContents = Files.readAllLines(ruta,charset);
if (fileContents.size()>0){
int cont = 1;
for(String str : fileContents){
System.out.println("Error"+cont);
System.out.println("\t"+str);
cont++;
}
}
else{
//other code
}
In this case I know that there are more than one errors, so I expect more than one output but as you can see in the photo I get only one.
I think the key here might be that ProcessBuilder's redirectError(File file) is actually redirectError (Redirect.to(file)) .
From Oracle's documentation of ProcessBuilder class:
This is a convenience method. An invocation of the form redirectError(file) behaves in exactly the same way as the invocation redirectError (Redirect.to(file)).
Most example's I have seen use Redirect.appendTo(File file) rather than Redirect.to(file). The documentation may explain why.
From Oracle's documentation of ProcessBuilder.Redirect :
public static ProcessBuilder.Redirect to(File file)
Returns a redirect to write to the specified file. If the specified file exists when the subprocess is started, its previous contents will be discarded.
public static ProcessBuilder.Redirect appendTo(File file)
Returns a redirect to append to the specified file. Each write operation first advances the position to the end of the file and then writes the requested data.
I would try replacing
pb.redirectError(errorsFile)
with
pb.redirectError(Redirect.appendTo(errorsFile))
and see if you get more lines that way.
Have you debugged and checked the contents of fileContents?
EDIT: Sorry, it should be a comment, but can't do it yet :(

Error in starting openday light netconf testtool simulator

While starting open daylight netconf test tool simulator I am getting the following error:
"java -jar netconf-testtool-1.5.0-SNAPSHOT-executable.jar --device-count 2 --schemas-dir yangs/"
Exception in thread "main" java.lang.NullPointerException
at java.util.regex.Matcher.getTextLength(Matcher.java:1283)
at java.util.regex.Matcher.reset(Matcher.java:309)
at java.util.regex.Matcher.<init>(Matcher.java:229)
at java.util.regex.Pattern.matcher(Pattern.java:1093)
at org.opendaylight.netconf.test.tool.TesttoolParameters.validate(TesttoolParameters.java:316)
at org.opendaylight.netconf.test.tool.Main.main(Main.java:58)
I can able to start it with some other yang files, but not with this specific yang files. What may be the issue causing this?
Take a look at the source code:
final Matcher matcher = YANG_FILENAME_PATTERN.matcher(file.getName());
if (!matcher.matches()) {
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line = reader.readLine();
while (!DATE_PATTERN.matcher(line).find()) { <--- Line 316
line = reader.readLine();
}
...
}
}
It's trying to ensure the yang file has a revision date. If it's not in the yang file name, then it opens the file and searches for a revision date. It blows up b/c it reaches the EOF without finding it. That's my take from reading the source - assuming I'm correct then either rename the offending file with a valid revision or add a revision statement to the yang.

Execute command from Java code deployed on Apache Tomcat

I was trying to convert a DOCX file to PDF file, found this vb script code which perfectly converts DOCX to PDF file, it uses .bat file for file generation. The code can be executed through java.
I am facing a strange problem, when I execute the code on my local machine, the file is generated, but when I deployed the app on Server , the code executes with no errors but the file is not generated.
Do we need any permission to execute commands through java?
Following is the details:
Server Operating system : Windows Server 2012 R2 Standard
Application server :Apache Tomcat 7.0.75
Code:
1)Java
public static void generatePDF() {
try {
File file = new File("C:\\Docx_To_Pdf_Converter\\errorLog.txt");
PrintStream printStreamToFile = new PrintStream(file);
System.setOut(printStreamToFile);
String docToPdf = "C:\\Docx_To_Pdf_Converter\\doc2pdf.bat";
File docPath = new File("C:\\Docx_To_Pdf_Converter\\Letter1.docx");
File pdfPath = new File("C:\\Docx_To_Pdf_Converter\\LetterPDF.pdf");
String command = String.format("%s %s %s", docToPdf, docPath, pdfPath);
Process process = Runtime.getRuntime().exec(command);
// The next line is optional and will force the current Java
//thread to block until the script has finished its execution.
process.waitFor();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
and the .bat file code:
#Echo off
pushd %~dp0
cscript C:\Docx_To_Pdf_Converter\doc2pdf.vbs %1 %2
vbscript code which actually converts the docx to pdf
Const wdFormatPDF = 17 ' PDF format.
Const wdFormatXPS = 18 ' XPS format.
Const WdDoNotSaveChanges = 0
Dim arguments
Set arguments = WScript.Arguments
Function CheckUserArguments()
If arguments.Unnamed.Count < 1 Or arguments.Unnamed.Count > 2 Then
WScript.Echo "Use:"
WScript.Echo "<script> input.doc"
WScript.Echo "<script> input.doc output.pdf"
WScript.Quit 1
End If
End Function
// Transforms a doc to a pdf
Function DocToPdf( docInputFile, pdfOutputFile )
Dim fileSystemObject
Dim wordApplication
Dim wordDocument
Dim wordDocuments
Dim baseFolder
Set fileSystemObject = CreateObject("Scripting.FileSystemObject")
Set wordApplication = CreateObject("Word.Application")
Set wordDocuments = wordApplication.Documents
docInputFile = fileSystemObject.GetAbsolutePathName(docInputFile)
baseFolder = fileSystemObject.GetParentFolderName(docInputFile)
If Len(pdfOutputFile) = 0 Then
pdfOutputFile = fileSystemObject.GetBaseName(docInputFile) + ".pdf"
End If
If Len(fileSystemObject.GetParentFolderName(pdfOutputFile)) = 0 Then
pdfOutputFile = baseFolder + "\" + pdfOutputFile
End If
//' Disable any potential macros of the word document.
wordApplication.WordBasic.DisableAutoMacros
// 'from below line the code does not executes
Set wordDocument = wordDocuments.Open(docInputFile)
wordDocument.SaveAs pdfOutputFile, wdFormatPDF
wordDocument.Close WdDoNotSaveChanges
wordApplication.Quit WdDoNotSaveChanges
Set wordApplication = Nothing
Set fileSystemObject = Nothing
End Function
// ' Execute script
Call CheckUserArguments()
If arguments.Unnamed.Count = 2 Then
Call DocToPdf( arguments.Unnamed.Item(0), arguments.Unnamed.Item(1) )
Else
Call DocToPdf( arguments.Unnamed.Item(0), "" )
End If
Set arguments = Nothing
It is not possible to give you a 100% guaranteed answer as we don't have access to your deployment server, but here's what I think is happening there.
If the .bat file were missing or not executable for some reason, then you would get an IOException in your Java code. Since you didn't get an exception, clearly the .bat file was found and executed.
However, whatever is within the .bat file is not being executed as you expect. Either cscript.exe is missing, or the .vbs file is missing. The way your code is written, you would not be aware of this. All you would see is a non-zero status return from the waitfor() method, and you don't bother to check that. Therefore you have no knowledge of what actually happened.
At the very minimum you should change the waitfor() method invocation to:
int rc = process.waitFor();
System.out.printf("Process returned %d\n", rc);
This will tell you the return status from the attempt to execute the .bat file. If it's not zero, then you have a problem, and I'm 99.999% sure you will find this to be non-zero. To troubleshoot this you will need to capture the output from the command. The following is a highly simplified (as in no error handling; that's up to you) example:
Process proc = Runtime.getRuntime().exec(command);
BufferedReader procOutput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
String line;
while((line = procOutput.readLine()) != null)
{
System.out.println(line);
// Or whatever you need to do to in your environment, such
// as log the output or examine it to ensure the script did
// what you want
}
int rc = proc.waitFor();
System.out.printf("Process returned %d\n", rc);
NOTE The above is not production-level code, it is only an example of how to use the API. This works ONLY if the external command requires no redirected input; if it does require input then you need to handle input and output in separate threads to prevent deadlocks.
Also, you should consider using ProcessBuilder as it is much more flexible. For example, it allows you to redirect the process' output to append to a log file, which you should probably implement.

Call java command line program from .net and return output of STDOUT to variable

I have a java command line program I need execute from within a .net program(VB)
The java command line program spits out a number when it's done executing that I need to know.
Can I take the STDOUT from the java program and read it into the .net program?
EDIT: I've got the program executing, but how do I read the inputstream?
Here is the code for executing the java program
Dim processinfo As New ProcessStartInfo()
processinfo.WorkingDirectory = "C:\path\to\working\directory"
processinfo.FileName = "java.exe"
processinfo.Arguments = "-jar myprogram.jar argumentA argumentB"
Process.Start(processinfo)
This nets me a command box and I get to watch the program execute..
EDIT: full code sample that works
Dim processinfo As New ProcessStartInfo()
processinfo.WorkingDirectory = "C:\"
processinfo.FileName = "java.exe"
processinfo.Arguments = "-jar my.jar list of params"
Dim myProcess As New Process()
processinfo.UseShellExecute = False
processinfo.RedirectStandardOutput = True
myProcess.StartInfo = processinfo
myProcess.Start()
Dim myStreamReader As StreamReader = myProcess.StandardOutput
' Read the standard output of the spawned process.
Dim myString As String
Do
myString = myStreamReader.ReadLine()
TextBox1.Text += myString
Loop Until (myStreamReader.EndOfStream)
myProcess.WaitForExit()
myProcess.Close()
Yes, use Process.StandardOutput (e.g., StreamReader.ReadToEnd among other possibilities). Be sure to set ProcessStartInfo.UseShellExecute to false, and ProcessStartInfo.RedirectStandardOutput to true.

Why do I loose new line character when I load text from a java servlet to JTextPane?

I try to load content of a text file that contains some text in multiple lines using java servlet.
When I test servlet in browser it works fine. Text is loaded with new line chars.
But when I load it to a string in my swing application and then use textpane.setText(text); new lines are gone. I tried many solutions I found int the net, but still can't get it right.
Servlet Code:
Reading text from file (simplified):
File file = new File(path);
StringBuilder data = new StringBuilder();
BufferedReader in = new BufferedReader(new FileReader(file));
String line;
while ((line = in.readLine()) != null) {
data.append(line);
data.append("\n");
}
in.close();
Sending text:
PrintWriter out = response.getWriter();
out.write(text));
Is it some platform issue? Servlet was writen and compiled on Linux, but I run it on Windows (on JBoss). Textfiles are also stored on my machine.
Instead of data.append("\n") use
data.append(System.getProperty("line.separator"));

Categories