|
From: Ted H. <thu...@ro...> - 2004-07-15 17:59:46
|
We have been using the Java Service Wrapper successfully for the past year with JBoss 3.2.1. It has worked flawlessly. However we just added a new application feature using the Java Runtime class to spawn a VB script in the operating system environment (Windows Script Host environment or 'cscript'). The VB script starts an instance of Excel, inserts some values, does some processing, then emails the spreadsheet. Excel is instructed to exit at the final line of the VB script. The VB script works fine in standalone mode. It also works correctly when JBoss is run without the Java Service Wrapper. However, when JBoss is wrapped, Excel never exits. Repeated executions cause multiple, zombie versions of Excel to hang around, consuming memory & resources. It is not always possible to kill these zombies Excel's from the Windows Task Manager. A reboot is often required. (This is Windows 2000 Server). It seems that the Java Service Wrapper interferes with one or more of the following: 1) the java Runtime class 2) the Windows Script Host Environment (cscript) or 3) Excel Recommendations or suggested gladly welcome! Thank you. My JSP code looks like this: StringBuffer cmd; cmd.append( "cscript C:\\src\\excel.vbs fo...@ba..." ); Runtime.getRuntime( exec( cmd.toString() ) ); My VB script (excel.vbs) looks like this: Set objExcel = CreateObject( "Excel.Application" ) objExcel.DisplayAlerts = False objExcel.Visible = False Set wb = objExcel.Workbooks.Open( "C:\src\template.xls" ) . Set address = WScript.Arguments(0) wb.SendMail address, "title", False wb.Close False objExcel.Quit WScript.Quit I am using wrapper_win32_3.0.5 -- Ted Hudacko thu...@ro... |
|
From: Leif M. <le...@ta...> - 2004-07-16 07:40:18
|
Ted,
I wish you had posted this a couple weeks ago. I had to figure out how
to do this for a
client. Got it all figured out last week.
I was having the same problem when running as a service. The problem is
actually not
related to the Wrapper. If Excel runs into any problems while it is
running, it will pop up an
error dialog and not continue until a user has accepted it. The problem
of course is that
when running as a service, there is no way to see the dialog.
I solved this by including the root function in an On Error block which
stores the error
message into the registry and then returns. The cscript then waits for
Excel to quit and
checks for an error message in the registry. If there is an error then I
can proceed to log
it. Not sure if that is the best way to do it. In fact, I thought it was
rather sloppy... But
it gets the job done.
My Java code also included some timeout code to kill the cscript process
if it takes too
long to complete. But the problem is that Excel is a child process of
the cscript process,
so killing the script process does not get rid of Excel.
To figure out what the error is, I would try running in console mode
until you have gotten
things working. All paths etc should then be the same when running as a
service. My first
guess would be that you are having a path problem. The working directory
might not be
getting set to what you are expecting.
You may be able to display Excel as it runs if you remove the flags that
hide it from your
cscript. Have not tested it, but you may be able to get it to be visible
when running as a
service by setting the wrapper.ntservice.interactive property.
Here are some fragments from the code that I implemented. It has been
many a year since
I last touched VBA so you may have some suggestions on how I could do
things better as
well :-)
First, my cscript, it takes the name of a csv formatted txt file and
then uses Excel to generate a
set of HTML reports which are then zipped up and placed into a
directory. The only way I
could figure out how to pass info back and forth between Excel was to
use the registry. :-P
---
On Error Resume Next
if WScript.arguments.count = 3 then
set shell = CreateObject ("WScript.Shell")
' Get the full base file.
fullFile = WScript.arguments(0)
WScript.echo "arg[0] Full File: " & fullFile
excelFile = WScript.arguments(1)
WScript.echo "arg[1] Excel File: " & excelFile
report = WScript.arguments(2)
WScript.echo "arg[1] Report: " & report
' Strip off the path and extension
set fsObj = WScript.CreateObject ("Scripting.FileSystemObject")
set fileObj = fsObj.GetFile (fullFile)
fileBase = fileObj.Name
If Right (fileBase, 4) = ".txt" then
fileBase = Left(fileBase, Len(fileBase) - 4)
End If
WScript.echo "File Base: " & fileBase
' Store the location of the file into the Registry
Shell.RegWrite "HKCU\Software\VB and VBA Program Settings\File
Passing\LINE NEWS\" &report, fileBase & ".txt", "REG_SZ"
' Store the location of the application root into the Registry
set fsObj = WScript.CreateObject ("Scripting.FileSystemObject")
set fileObj = fsObj.GetFile (excelFile)
set parentObj = fileObj.ParentFolder.ParentFolder
Shell.RegWrite "HKCU\Software\VB and VBA Program Settings\File
Passing\LINE NEWS\ROOT", parentObj.Path, "REG_SZ"
Shell.RegWrite "HKCU\Software\VB and VBA Program Settings\File
Passing\LINE NEWS\" &report& "_ERR", "", "REG_SZ"
' Load Excel to run its vba script.
WScript.echo "Launching Excel..."
set xlObj = CreateObject ("Excel.Application")
'xlObj.visible = false
xlObj.SetWarnings = false
xlObj.Workbooks.Open fileObj.Path
xlObj.run "auto_open"
xlObj.quit
set xlObj=Nothing
WScript.echo "Excel Completed."
excelErr = Shell.RegRead("HKCU\Software\VB and VBA Program Settings\File
Passing\LINE NEWS\" &report& "_ERR")
If excelErr <> "" then
WScript.echo "Excel had errors: " & excelErr
WScript.quit 1
End If
' Store the generated HTML report along with its files into a ZIP via a
temporary file.
zipFile = "..\..\shinbun-data\import\" & fileBase & ".zip"
tempFile = "..\..\shinbun-data\import\" & fileBase & ".tmp"
WScript.echo "tempFile: " & tempFile
WScript.echo "Generating Report Archive: " & zipFile
'WScript.echo "tempFile: " & tempFile
shell.Run "jar cvf " & tempFile & " -C ..\work\generate " & fileBase &
".files", 0, true
shell.Run "jar uvf " & tempFile & " -C ..\work\generate " & fileBase &
".htm", 0, true
'Rename the temp file to its final name
'set objFSO = CreateObject( "Scripting.FileSystemObject" )
'objFSO.DeleteFile zipFile
fsObj.MoveFile tempFile, zipFile
'Delete zip source files
'fsObj.DeleteFile "..\work\generate\" & fileBase & ".files\*.*"
fsObj.DeleteFile "..\work\generate\" & fileBase & ".htm"
'WScript.echo "------" & "..\work\generate\" & fileBase & ".files"
set folderObj = fsObj.GetFolder ("..\work\generate\" & fileBase & ".files")
folderObj.Delete
WScript.echo "Done."
WScript.quit 0
else
WScript.echo "Usage: cscript generate_report.vbs <data file> <excel
file> <report>"
WScript.quit 1
end if
---
The Excel code was not all written by me. I just added the error
trapping and registry
code. The original script had been run manually to generate the HTML files.
---
Sub Auto_Open()
Dim Msg As String, Style As Integer, Response As Integer
Dim File_CheckFLG As String, FileName As String, RootPath As String,
workDir As String
On Error GoTo DeathHandler
RootPath = GetSetting("File Passing", "LINE NEWS", "ROOT", "NONE")
workDir = "\work\"
DIR_WK = RootPath & workDir & "generate\"
DIR_DAT1 = RootPath & "\..\shinbun-data\import\"
DIR_DAT2 = RootPath & "\shell\"
DIR_DAT3 = RootPath & workDir & "generate\"
Application.WindowState = xlMaximized
ActiveWindow.Visible = False
ChDrive Left(DIR_WK, 1)
ChDir Left(DIR_WK, (Len(DIR_WK) - 1))
Msg = "Lead Time"
Style = vbOKCancel
Response = vbOK
If Response = vbOK Then
Dbpart_Flag = 0
DIR_WK2 = DIR_DAT1
FILE_TXT = GetSetting("File Passing", "LINE NEWS", "LT", "NONE")
If Right(FILE_TXT, 3) = "txt" Then
FileName = Left(FILE_TXT, Len(FILE_TXT) - 4)
Else
FileName = FILE_TXT
End If
If Len(DIR_WK2 & FILE_TXT) = 0 Then
File_CheckFLG = ""
Else
On Error Resume Next
File_CheckFLG = Dir(DIR_WK2 & FILE_TXT)
On Error GoTo DeathHandler
End If
If Len(File_CheckFLG) <> 0 Then
'
' Snip guts that generate the data
'
Windows(FILE_WK0).Activate
ActiveWindow.Visible = True
ActiveWindow.Close saveChanges:=False
' Save the HTML
Application.ActiveWorkbook.Worksheets("LTGraph").SaveAs
FileName:=DIR_DAT3 & FileName, FileFormat:=xlHtml
Else
Msg = "Bad input file." & Chr(13) & Chr(10)
Style = vbOKOnly
Response = MsgBox(Msg, Style)
End If
End If
Msg = "Lead Time complete." & Chr(13) & Chr(10)
Style = vbOKCancel
ActiveWindow.Visible = True
ActiveWindow.Close saveChanges:=False
Exit Sub
DeathHandler:
Msg = "Error #" & Err.Number & " in " & Err.Source & " : " & Err.Description
SaveSetting "File Passing", "LINE NEWS", "LT_ERR", Msg
Err.Clear
Exit Sub
End Sub
---
Hope that makes sense to you.
Cheers,
Leif
Ted Hudacko wrote:
> We have been using the Java Service Wrapper successfully for the past
> year with JBoss 3.2.1. It has worked flawlessly. However we just added
> a new application feature using the Java Runtime class to spawn a VB
> script in the operating system environment (Windows Script Host
> environment or ‘cscript’). The VB script starts an instance of Excel,
> inserts some values, does some processing, then emails the
> spreadsheet. Excel is instructed to exit at the final line of the VB
> script. The VB script works fine in standalone mode. It also works
> correctly when JBoss is run without the Java Service Wrapper.
>
> However, when JBoss is wrapped, Excel never exits. Repeated executions
> cause multiple, zombie versions of Excel to hang around, consuming
> memory & resources. It is not always possible to kill these zombies
> Excel’s from the Windows Task Manager. A reboot is often required.
> (This is Windows 2000 Server).
>
> It seems that the Java Service Wrapper interferes with one or more of
> the following:
>
> 1) the java Runtime class
>
> 2) the Windows Script Host Environment (cscript) or
>
> 3) Excel
>
> Recommendations or suggested gladly welcome! Thank you.
>
> My JSP code looks like this:
>
> StringBuffer cmd;
>
> cmd.append( “cscript C:\\src\\excel.vbs fo...@ba...
> <mailto:fo...@ba...>” );
>
> Runtime.getRuntime( exec( cmd.toString() ) );
>
> My VB script (excel.vbs) looks like this:
>
> Set objExcel = CreateObject( “Excel.Application” )
>
> objExcel.DisplayAlerts = False
>
> objExcel.Visible = False
>
> Set wb = objExcel.Workbooks.Open( “C:\src\template.xls” )
>
> …
>
> Set address = WScript.Arguments(0)
>
> wb.SendMail address, “title”, False
>
> wb.Close False
>
> objExcel.Quit
>
> WScript.Quit
>
> I am using wrapper_win32_3.0.5
>
|
|
From: Sal I. <sal...@vo...> - 2004-07-16 08:08:10
|
i understand that you want to reuse your script, but you can avoid the problem alltogether if you rewrite your script in java. you can use this library to read/write your excel doc: http://jakarta.apache.org/poi/index.html and you can use java mail to send email or you can use the ant wrapper for it which is very clean: http://ant.apache.org/ -----Original Message----- From: wra...@li... [mailto:wra...@li...]On Behalf Of Leif Mortenson Sent: Friday, July 16, 2004 12:39 AM To: wra...@li... Subject: Re: [Wrapper-user] Wrapper causes zombie procecesses started from Runtime.getRuntime( exec ( cmd ) ); Ted, I wish you had posted this a couple weeks ago. I had to figure out how to do this for a client. Got it all figured out last week. I was having the same problem when running as a service. The problem is actually not related to the Wrapper. If Excel runs into any problems while it is running, it will pop up an error dialog and not continue until a user has accepted it. The problem of course is that when running as a service, there is no way to see the dialog. I solved this by including the root function in an On Error block which stores the error message into the registry and then returns. The cscript then waits for Excel to quit and checks for an error message in the registry. If there is an error then I can proceed to log it. Not sure if that is the best way to do it. In fact, I thought it was rather sloppy... But it gets the job done. My Java code also included some timeout code to kill the cscript process if it takes too long to complete. But the problem is that Excel is a child process of the cscript process, so killing the script process does not get rid of Excel. To figure out what the error is, I would try running in console mode until you have gotten things working. All paths etc should then be the same when running as a service. My first guess would be that you are having a path problem. The working directory might not be getting set to what you are expecting. You may be able to display Excel as it runs if you remove the flags that hide it from your cscript. Have not tested it, but you may be able to get it to be visible when running as a service by setting the wrapper.ntservice.interactive property. Here are some fragments from the code that I implemented. It has been many a year since I last touched VBA so you may have some suggestions on how I could do things better as well :-) First, my cscript, it takes the name of a csv formatted txt file and then uses Excel to generate a set of HTML reports which are then zipped up and placed into a directory. The only way I could figure out how to pass info back and forth between Excel was to use the registry. :-P --- On Error Resume Next if WScript.arguments.count = 3 then set shell = CreateObject ("WScript.Shell") ' Get the full base file. fullFile = WScript.arguments(0) WScript.echo "arg[0] Full File: " & fullFile excelFile = WScript.arguments(1) WScript.echo "arg[1] Excel File: " & excelFile report = WScript.arguments(2) WScript.echo "arg[1] Report: " & report ' Strip off the path and extension set fsObj = WScript.CreateObject ("Scripting.FileSystemObject") set fileObj = fsObj.GetFile (fullFile) fileBase = fileObj.Name If Right (fileBase, 4) = ".txt" then fileBase = Left(fileBase, Len(fileBase) - 4) End If WScript.echo "File Base: " & fileBase ' Store the location of the file into the Registry Shell.RegWrite "HKCU\Software\VB and VBA Program Settings\File Passing\LINE NEWS\" &report, fileBase & ".txt", "REG_SZ" ' Store the location of the application root into the Registry set fsObj = WScript.CreateObject ("Scripting.FileSystemObject") set fileObj = fsObj.GetFile (excelFile) set parentObj = fileObj.ParentFolder.ParentFolder Shell.RegWrite "HKCU\Software\VB and VBA Program Settings\File Passing\LINE NEWS\ROOT", parentObj.Path, "REG_SZ" Shell.RegWrite "HKCU\Software\VB and VBA Program Settings\File Passing\LINE NEWS\" &report& "_ERR", "", "REG_SZ" ' Load Excel to run its vba script. WScript.echo "Launching Excel..." set xlObj = CreateObject ("Excel.Application") 'xlObj.visible = false xlObj.SetWarnings = false xlObj.Workbooks.Open fileObj.Path xlObj.run "auto_open" xlObj.quit set xlObj=Nothing WScript.echo "Excel Completed." excelErr = Shell.RegRead("HKCU\Software\VB and VBA Program Settings\File Passing\LINE NEWS\" &report& "_ERR") If excelErr <> "" then WScript.echo "Excel had errors: " & excelErr WScript.quit 1 End If ' Store the generated HTML report along with its files into a ZIP via a temporary file. zipFile = "..\..\shinbun-data\import\" & fileBase & ".zip" tempFile = "..\..\shinbun-data\import\" & fileBase & ".tmp" WScript.echo "tempFile: " & tempFile WScript.echo "Generating Report Archive: " & zipFile 'WScript.echo "tempFile: " & tempFile shell.Run "jar cvf " & tempFile & " -C ..\work\generate " & fileBase & ".files", 0, true shell.Run "jar uvf " & tempFile & " -C ..\work\generate " & fileBase & ".htm", 0, true 'Rename the temp file to its final name 'set objFSO = CreateObject( "Scripting.FileSystemObject" ) 'objFSO.DeleteFile zipFile fsObj.MoveFile tempFile, zipFile 'Delete zip source files 'fsObj.DeleteFile "..\work\generate\" & fileBase & ".files\*.*" fsObj.DeleteFile "..\work\generate\" & fileBase & ".htm" 'WScript.echo "------" & "..\work\generate\" & fileBase & ".files" set folderObj = fsObj.GetFolder ("..\work\generate\" & fileBase & ".files") folderObj.Delete WScript.echo "Done." WScript.quit 0 else WScript.echo "Usage: cscript generate_report.vbs <data file> <excel file> <report>" WScript.quit 1 end if --- The Excel code was not all written by me. I just added the error trapping and registry code. The original script had been run manually to generate the HTML files. --- Sub Auto_Open() Dim Msg As String, Style As Integer, Response As Integer Dim File_CheckFLG As String, FileName As String, RootPath As String, workDir As String On Error GoTo DeathHandler RootPath = GetSetting("File Passing", "LINE NEWS", "ROOT", "NONE") workDir = "\work\" DIR_WK = RootPath & workDir & "generate\" DIR_DAT1 = RootPath & "\..\shinbun-data\import\" DIR_DAT2 = RootPath & "\shell\" DIR_DAT3 = RootPath & workDir & "generate\" Application.WindowState = xlMaximized ActiveWindow.Visible = False ChDrive Left(DIR_WK, 1) ChDir Left(DIR_WK, (Len(DIR_WK) - 1)) Msg = "Lead Time" Style = vbOKCancel Response = vbOK If Response = vbOK Then Dbpart_Flag = 0 DIR_WK2 = DIR_DAT1 FILE_TXT = GetSetting("File Passing", "LINE NEWS", "LT", "NONE") If Right(FILE_TXT, 3) = "txt" Then FileName = Left(FILE_TXT, Len(FILE_TXT) - 4) Else FileName = FILE_TXT End If If Len(DIR_WK2 & FILE_TXT) = 0 Then File_CheckFLG = "" Else On Error Resume Next File_CheckFLG = Dir(DIR_WK2 & FILE_TXT) On Error GoTo DeathHandler End If If Len(File_CheckFLG) <> 0 Then ' ' Snip guts that generate the data ' Windows(FILE_WK0).Activate ActiveWindow.Visible = True ActiveWindow.Close saveChanges:=False ' Save the HTML Application.ActiveWorkbook.Worksheets("LTGraph").SaveAs FileName:=DIR_DAT3 & FileName, FileFormat:=xlHtml Else Msg = "Bad input file." & Chr(13) & Chr(10) Style = vbOKOnly Response = MsgBox(Msg, Style) End If End If Msg = "Lead Time complete." & Chr(13) & Chr(10) Style = vbOKCancel ActiveWindow.Visible = True ActiveWindow.Close saveChanges:=False Exit Sub DeathHandler: Msg = "Error #" & Err.Number & " in " & Err.Source & " : " & Err.Description SaveSetting "File Passing", "LINE NEWS", "LT_ERR", Msg Err.Clear Exit Sub End Sub --- Hope that makes sense to you. Cheers, Leif Ted Hudacko wrote: > We have been using the Java Service Wrapper successfully for the past > year with JBoss 3.2.1. It has worked flawlessly. However we just added > a new application feature using the Java Runtime class to spawn a VB > script in the operating system environment (Windows Script Host > environment or ‘cscript’). The VB script starts an instance of Excel, > inserts some values, does some processing, then emails the > spreadsheet. Excel is instructed to exit at the final line of the VB > script. The VB script works fine in standalone mode. It also works > correctly when JBoss is run without the Java Service Wrapper. > > However, when JBoss is wrapped, Excel never exits. Repeated executions > cause multiple, zombie versions of Excel to hang around, consuming > memory & resources. It is not always possible to kill these zombies > Excel’s from the Windows Task Manager. A reboot is often required. > (This is Windows 2000 Server). > > It seems that the Java Service Wrapper interferes with one or more of > the following: > > 1) the java Runtime class > > 2) the Windows Script Host Environment (cscript) or > > 3) Excel > > Recommendations or suggested gladly welcome! Thank you. > > My JSP code looks like this: > > StringBuffer cmd; > > cmd.append( “cscript C:\\src\\excel.vbs fo...@ba... > <mailto:fo...@ba...>” ); > > Runtime.getRuntime( exec( cmd.toString() ) ); > > My VB script (excel.vbs) looks like this: > > Set objExcel = CreateObject( “Excel.Application” ) > > objExcel.DisplayAlerts = False > > objExcel.Visible = False > > Set wb = objExcel.Workbooks.Open( “C:\src\template.xls” ) > > … > > Set address = WScript.Arguments(0) > > wb.SendMail address, “title”, False > > wb.Close False > > objExcel.Quit > > WScript.Quit > > I am using wrapper_win32_3.0.5 > ------------------------------------------------------- This SF.Net email is sponsored by BEA Weblogic Workshop FREE Java Enterprise J2EE developer tools! Get your free copy of BEA WebLogic Workshop 8.1 today. http://ads.osdn.com/?ad_id=4721&alloc_id=10040&op=click _______________________________________________ Wrapper-user mailing list Wra...@li... https://lists.sourceforge.net/lists/listinfo/wrapper-user |
|
From: Leif M. <le...@ta...> - 2004-07-16 08:55:10
|
Thanks. In this particular case, I got a rather complicated VBA app inside of an Excel file which reads in a csv text file. Does lots and lots of processing and then dumps out a set of HTML pages which contain a dozen or so graphs as images. No desire to rewrite all of that. They had a poor secretary who had to manually load and generate several of these a day. I just had to automate the process so she can do more interesting things. :-) They have asked about generating simple Excel files in the past. I have always "pushed" them on to using other technologies. This would make some of that possible. So thanks for pointing it out. Cheers, Leif Sal Ingrilli wrote: >i understand that you want to reuse your script, but you can avoid >the problem alltogether if you rewrite your script in java. > >you can use this library to read/write your excel doc: >http://jakarta.apache.org/poi/index.html > >and you can use java mail to send email or you can use the ant wrapper >for it which is very clean: >http://ant.apache.org/ > > |
|
From: Ted H. <thu...@ro...> - 2004-07-16 14:48:42
|
Leif and Sal, Leif, Sal, Thank you very much for detailed your responses. You have given me a multiple areas to investigate, but I may have already been down some of these paths. 1) Possible unacknowledged error dialogs: I was reasonably certain that the line in my VB script: objExcel.DisplayAlerts = False would suppress error dialogs to the user. And I did thoroughly test the VB script standalone (from the console) and from JBoss unwrapped. But I will revisit this as a possibility. I see that your script has the following line which I shall add: xlObj.SetWarnings = false 2) Path or working directory problems: I didn't think this would be an issue, as I pass all arguments on the command line, and refer to the template Excel spreadsheet with an absolute, not relative, filesystem path. My additional investigation yesterday led me to believe that my problem might be in how I construct the cmd string in this line: Runtime.getRuntime( exec( cmd.toString() ) ); These two links indicated this might be the problem: http://java.sun.com/j2se/1.4.2/docs/api/ (See Process and Runtime classes) http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html The first article specifically warns of issues in the Windows environment. Per the second article's suggestion, I switched to a different version of the overloaded exec() method. Now using String[] cmdArray as argument instead of a long cmd String. Also, I added StreamGobbler class and the constructs of the GoodWinExec.java example. After making these changes, I had the same result as before: It works in an unwrapped JBoss, but not the wrapped JBoss. 3) Making Excel visible. Yes, I do reset this flag during debugging. objExcel.Visible = True Very fun to watch! 4) We tried changing the value of the wrapper.ntservice.interactive flag but it did not have any apparent effect. 5) VB On Error block. I also am not a VB expert nor have I done any registry hacking but I will definitely investigate this. Re: Sal's suggestions: 1) I was unaware of Poi http://jakarta.apache.org/poi/index.html Reading & writing Excel format files is useful but to leverage the Excel object model and to use Excel's computation engine, Excel has to be running. 2) Java Mail API. I use this elsewhere in the application for some separate functionality that generates PDF documents then emails them. Works great! We considered reusing that functionality here but decided against PDF format in favor of Excel because of certain computation and tabular formatting where Excel is better suited. The PDF generation runs in process and synchronously, blocking email until the PDF doc is written to the file system. We also wanted the Excel process to run asynchronously and not have to block the email waiting on the file. Since the Excel object model allows emailing natively, this seemed cleaner than writing a file and having another process reopen it to send it. The Excel email capability works fine when exec()'ed from an unwrapped JBoss. Regards, Ted -----Original Message----- From: wra...@li... [mailto:wra...@li...] On Behalf Of Leif Mortenson Sent: Friday, July 16, 2004 12:39 AM To: wra...@li... Subject: Re: [Wrapper-user] Wrapper causes zombie procecesses started from Runtime.getRuntime( exec ( cmd ) ); Ted, I wish you had posted this a couple weeks ago. I had to figure out how to do this for a client. Got it all figured out last week. I was having the same problem when running as a service. The problem is actually not related to the Wrapper. If Excel runs into any problems while it is running, it will pop up an error dialog and not continue until a user has accepted it. The problem of course is that when running as a service, there is no way to see the dialog. I solved this by including the root function in an On Error block which stores the error message into the registry and then returns. The cscript then waits for Excel to quit and checks for an error message in the registry. If there is an error then I can proceed to log it. Not sure if that is the best way to do it. In fact, I thought it was rather sloppy... But it gets the job done. My Java code also included some timeout code to kill the cscript process if it takes too long to complete. But the problem is that Excel is a child process of the cscript process, so killing the script process does not get rid of Excel. To figure out what the error is, I would try running in console mode until you have gotten things working. All paths etc should then be the same when running as a service. My first guess would be that you are having a path problem. The working directory might not be getting set to what you are expecting. You may be able to display Excel as it runs if you remove the flags that hide it from your cscript. Have not tested it, but you may be able to get it to be visible when running as a service by setting the wrapper.ntservice.interactive property. Here are some fragments from the code that I implemented. It has been many a year since I last touched VBA so you may have some suggestions on how I could do things better as well :-) First, my cscript, it takes the name of a csv formatted txt file and then uses Excel to generate a set of HTML reports which are then zipped up and placed into a directory. The only way I could figure out how to pass info back and forth between Excel was to use the registry. :-P --- On Error Resume Next if WScript.arguments.count = 3 then set shell = CreateObject ("WScript.Shell") ' Get the full base file. fullFile = WScript.arguments(0) WScript.echo "arg[0] Full File: " & fullFile excelFile = WScript.arguments(1) WScript.echo "arg[1] Excel File: " & excelFile report = WScript.arguments(2) WScript.echo "arg[1] Report: " & report ' Strip off the path and extension set fsObj = WScript.CreateObject ("Scripting.FileSystemObject") set fileObj = fsObj.GetFile (fullFile) fileBase = fileObj.Name If Right (fileBase, 4) = ".txt" then fileBase = Left(fileBase, Len(fileBase) - 4) End If WScript.echo "File Base: " & fileBase ' Store the location of the file into the Registry Shell.RegWrite "HKCU\Software\VB and VBA Program Settings\File Passing\LINE NEWS\" &report, fileBase & ".txt", "REG_SZ" ' Store the location of the application root into the Registry set fsObj = WScript.CreateObject ("Scripting.FileSystemObject") set fileObj = fsObj.GetFile (excelFile) set parentObj = fileObj.ParentFolder.ParentFolder Shell.RegWrite "HKCU\Software\VB and VBA Program Settings\File Passing\LINE NEWS\ROOT", parentObj.Path, "REG_SZ" Shell.RegWrite "HKCU\Software\VB and VBA Program Settings\File Passing\LINE NEWS\" &report& "_ERR", "", "REG_SZ" ' Load Excel to run its vba script. WScript.echo "Launching Excel..." set xlObj = CreateObject ("Excel.Application") 'xlObj.visible = false xlObj.SetWarnings = false xlObj.Workbooks.Open fileObj.Path xlObj.run "auto_open" xlObj.quit set xlObj=Nothing WScript.echo "Excel Completed." excelErr = Shell.RegRead("HKCU\Software\VB and VBA Program Settings\File Passing\LINE NEWS\" &report& "_ERR") If excelErr <> "" then WScript.echo "Excel had errors: " & excelErr WScript.quit 1 End If ' Store the generated HTML report along with its files into a ZIP via a temporary file. zipFile = "..\..\shinbun-data\import\" & fileBase & ".zip" tempFile = "..\..\shinbun-data\import\" & fileBase & ".tmp" WScript.echo "tempFile: " & tempFile WScript.echo "Generating Report Archive: " & zipFile 'WScript.echo "tempFile: " & tempFile shell.Run "jar cvf " & tempFile & " -C ..\work\generate " & fileBase & ".files", 0, true shell.Run "jar uvf " & tempFile & " -C ..\work\generate " & fileBase & ".htm", 0, true 'Rename the temp file to its final name 'set objFSO = CreateObject( "Scripting.FileSystemObject" ) 'objFSO.DeleteFile zipFile fsObj.MoveFile tempFile, zipFile 'Delete zip source files 'fsObj.DeleteFile "..\work\generate\" & fileBase & ".files\*.*" fsObj.DeleteFile "..\work\generate\" & fileBase & ".htm" 'WScript.echo "------" & "..\work\generate\" & fileBase & ".files" set folderObj = fsObj.GetFolder ("..\work\generate\" & fileBase & ".files") folderObj.Delete WScript.echo "Done." WScript.quit 0 else WScript.echo "Usage: cscript generate_report.vbs <data file> <excel file> <report>" WScript.quit 1 end if --- The Excel code was not all written by me. I just added the error trapping and registry code. The original script had been run manually to generate the HTML files. --- Sub Auto_Open() Dim Msg As String, Style As Integer, Response As Integer Dim File_CheckFLG As String, FileName As String, RootPath As String, workDir As String On Error GoTo DeathHandler RootPath = GetSetting("File Passing", "LINE NEWS", "ROOT", "NONE") workDir = "\work\" DIR_WK = RootPath & workDir & "generate\" DIR_DAT1 = RootPath & "\..\shinbun-data\import\" DIR_DAT2 = RootPath & "\shell\" DIR_DAT3 = RootPath & workDir & "generate\" Application.WindowState = xlMaximized ActiveWindow.Visible = False ChDrive Left(DIR_WK, 1) ChDir Left(DIR_WK, (Len(DIR_WK) - 1)) Msg = "Lead Time" Style = vbOKCancel Response = vbOK If Response = vbOK Then Dbpart_Flag = 0 DIR_WK2 = DIR_DAT1 FILE_TXT = GetSetting("File Passing", "LINE NEWS", "LT", "NONE") If Right(FILE_TXT, 3) = "txt" Then FileName = Left(FILE_TXT, Len(FILE_TXT) - 4) Else FileName = FILE_TXT End If If Len(DIR_WK2 & FILE_TXT) = 0 Then File_CheckFLG = "" Else On Error Resume Next File_CheckFLG = Dir(DIR_WK2 & FILE_TXT) On Error GoTo DeathHandler End If If Len(File_CheckFLG) <> 0 Then ' ' Snip guts that generate the data ' Windows(FILE_WK0).Activate ActiveWindow.Visible = True ActiveWindow.Close saveChanges:=False ' Save the HTML Application.ActiveWorkbook.Worksheets("LTGraph").SaveAs FileName:=DIR_DAT3 & FileName, FileFormat:=xlHtml Else Msg = "Bad input file." & Chr(13) & Chr(10) Style = vbOKOnly Response = MsgBox(Msg, Style) End If End If Msg = "Lead Time complete." & Chr(13) & Chr(10) Style = vbOKCancel ActiveWindow.Visible = True ActiveWindow.Close saveChanges:=False Exit Sub DeathHandler: Msg = "Error #" & Err.Number & " in " & Err.Source & " : " & Err.Description SaveSetting "File Passing", "LINE NEWS", "LT_ERR", Msg Err.Clear Exit Sub End Sub --- Hope that makes sense to you. Cheers, Leif Ted Hudacko wrote: > We have been using the Java Service Wrapper successfully for the past > year with JBoss 3.2.1. It has worked flawlessly. However we just added > a new application feature using the Java Runtime class to spawn a VB > script in the operating system environment (Windows Script Host > environment or 'cscript'). The VB script starts an instance of Excel, > inserts some values, does some processing, then emails the > spreadsheet. Excel is instructed to exit at the final line of the VB > script. The VB script works fine in standalone mode. It also works > correctly when JBoss is run without the Java Service Wrapper. > > However, when JBoss is wrapped, Excel never exits. Repeated executions > cause multiple, zombie versions of Excel to hang around, consuming > memory & resources. It is not always possible to kill these zombies > Excel's from the Windows Task Manager. A reboot is often required. > (This is Windows 2000 Server). > > It seems that the Java Service Wrapper interferes with one or more of > the following: > > 1) the java Runtime class > > 2) the Windows Script Host Environment (cscript) or > > 3) Excel > > Recommendations or suggested gladly welcome! Thank you. > > My JSP code looks like this: > > StringBuffer cmd; > > cmd.append( "cscript C:\\src\\excel.vbs fo...@ba... > <mailto:fo...@ba...>" ); > > Runtime.getRuntime( exec( cmd.toString() ) ); > > My VB script (excel.vbs) looks like this: > > Set objExcel = CreateObject( "Excel.Application" ) > > objExcel.DisplayAlerts = False > > objExcel.Visible = False > > Set wb = objExcel.Workbooks.Open( "C:\src\template.xls" ) > > . > > Set address = WScript.Arguments(0) > > wb.SendMail address, "title", False > > wb.Close False > > objExcel.Quit > > WScript.Quit > > I am using wrapper_win32_3.0.5 > ------------------------------------------------------- This SF.Net email is sponsored by BEA Weblogic Workshop FREE Java Enterprise J2EE developer tools! Get your free copy of BEA WebLogic Workshop 8.1 today. http://ads.osdn.com/?ad_id=4721&alloc_id=10040&op=click _______________________________________________ Wrapper-user mailing list Wra...@li... https://lists.sourceforge.net/lists/listinfo/wrapper-user |
|
From: Eoin C. <eo...@pe...> - 2004-07-16 15:17:42
|
Ted, Some other things you could check to try and narrow it down: Does the problem occur with any script, or only if the script uses excel? Does it occur with any sheet or only this one? You say you call the script asynchronously - in your tests are there more than one vbsript process executing simultaneously? Now that you have StreamGobbler, you could stick in some Console.writeln's and see if the process get's stuck at a certain point in the script, or after the script exits? eoin. Ted Hudacko wrote: >Leif and Sal, >Leif, Sal, > >Thank you very much for detailed your responses. You have given me a >multiple areas to investigate, but I may have already been down some of >these paths. > >1) Possible unacknowledged error dialogs: >I was reasonably certain that the line in my VB script: > objExcel.DisplayAlerts = False > >would suppress error dialogs to the user. And I did thoroughly test the VB >script standalone (from the console) and from JBoss unwrapped. But I will >revisit this as a possibility. I see that your script has the following >line which I shall add: > xlObj.SetWarnings = false > >2) Path or working directory problems: >I didn't think this would be an issue, as I pass all arguments on the >command line, and refer to the template Excel spreadsheet with an absolute, >not relative, filesystem path. > >My additional investigation yesterday led me to believe that my problem >might be in how I construct the cmd string in this line: > Runtime.getRuntime( exec( cmd.toString() ) ); > >These two links indicated this might be the problem: > http://java.sun.com/j2se/1.4.2/docs/api/ (See Process and Runtime >classes) > http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html > > >The first article specifically warns of issues in the Windows environment. > >Per the second article's suggestion, I switched to a different version of >the overloaded exec() method. Now using String[] cmdArray as argument >instead of a long cmd String. Also, I added StreamGobbler class and the >constructs of the GoodWinExec.java example. > >After making these changes, I had the same result as before: It works in an >unwrapped JBoss, but not the wrapped JBoss. > >3) Making Excel visible. Yes, I do reset this flag during debugging. > objExcel.Visible = True >Very fun to watch! > >4) We tried changing the value of the wrapper.ntservice.interactive flag >but it did not have any apparent effect. > >5) VB On Error block. >I also am not a VB expert nor have I done any registry hacking but I will >definitely investigate this. > >Re: Sal's suggestions: >1) I was unaware of Poi http://jakarta.apache.org/poi/index.html >Reading & writing Excel format files is useful but to leverage the Excel >object model and to use Excel's computation engine, Excel has to be running. > >2) Java Mail API. I use this elsewhere in the application for some separate >functionality that generates PDF documents then emails them. Works great! >We considered reusing that functionality here but decided against PDF format >in favor of Excel because of certain computation and tabular formatting >where Excel is better suited. The PDF generation runs in process and >synchronously, blocking email until the PDF doc is written to the file >system. >We also wanted the Excel process to run asynchronously and not have to block >the email waiting on the file. Since the Excel object model allows emailing >natively, this seemed cleaner than writing a file and having another process >reopen it to send it. > >The Excel email capability works fine when exec()'ed from an unwrapped >JBoss. > > |
|
From: Ted H. <thu...@ro...> - 2004-07-16 22:56:01
|
Eoin, The problem occurs with pretty much any script, not just a script using excel. I tried a simple example with Word, instead of Excel. Same result: works fine when JBoss is unwrapped, doesn't do anything if wrapped. There is only one VB script running at a time. As to your suggestion about Console.writeln's, I assume you mean I should insert print statements into the VB script, not in the Java application context? Yes, I have done this in the following form: WScript.echo "example" These are visible when running in wscript (not cscript) but again, only when JBoss is unwrapped. The only relevant factor appears to be using the Java Service Wrapper or not. Ted -----Original Message----- From: wra...@li... [mailto:wra...@li...] On Behalf Of Eoin Curran Sent: Friday, July 16, 2004 8:18 AM To: wra...@li... Subject: Re: [Wrapper-user] Wrapper causes zombie procecesses started from Runtime.getRuntime( exec ( cmd ) ); Ted, Some other things you could check to try and narrow it down: Does the problem occur with any script, or only if the script uses excel? Does it occur with any sheet or only this one? You say you call the script asynchronously - in your tests are there more than one vbsript process executing simultaneously? Now that you have StreamGobbler, you could stick in some Console.writeln's and see if the process get's stuck at a certain point in the script, or after the script exits? eoin. |
|
From: Ted H. <thu...@ro...> - 2004-07-17 19:14:31
|
Here is a self-contained and complete example of a JSP that execs a VB script. The VB script opens Excel, sleeps 4 seconds, quits Excel, then exits the script environment. On my Win2k server(s), this only works when JBoss is running standalone without the Java Service Wrapper. Could someone please try to reproduce my results? Thank you in advance. To install/run: 1) Copy VB script to C:\exectest.vbs 2) Install exectest.jsp to JBoss in your normal manner. --CUT HERE, FILE 1: exectest.vbs BEGIN--- Set objExcel = CreateObject( "Excel.Application" ) objExcel.DisplayAlerts = False objExcel.Visible = True WScript.Sleep 4000 objExcel.Quit WScript.Quit -- CUT HERE, FILE 2: exectest.jsp BEGIN-- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <%@ page import="java.io.*,java.net.*,java.util.* " %> <html> <head> <title>Runtime.getRuntime().exec() Test</title> <%! public class StreamGobbler extends Thread { InputStream is; String type; OutputStream os; public StreamGobbler( InputStream is, String type ) { this( is, type, null ); } public StreamGobbler( InputStream is, String type, OutputStream redirect ) { this.is = is; this.type = type; this.os = redirect; } public void run() { try { PrintWriter pw = null; if( os != null ) pw = new PrintWriter(os); InputStreamReader isr = new InputStreamReader(is); BufferedReader br = new BufferedReader(isr); String line = null; while( (line = br.readLine()) != null ) { if( pw != null ) pw.println( line ); System.out.println( type + ")" + line ); } if( pw != null ) pw.flush(); } catch( IOException ioe ) { ioe.printStackTrace(); } } } %> <% String[] cmdArray = new String[2]; cmdArray[0] = "cscript"; cmdArray[1] = "C:\\exectest.vbs"; try { Process proc = Runtime.getRuntime().exec( cmdArray ) ; StreamGobbler errorGobbler = new StreamGobbler( proc.getErrorStream(), "ERR" ); StreamGobbler outputGobbler = new StreamGobbler( proc.getErrorStream(), "OUT" ); errorGobbler.start(); outputGobbler.start(); int exitVal = proc.waitFor(); out.println("Exit Value =" + exitVal ); } catch( Exception e ) { e.printStackTrace(); } %> </html> |
|
From: Ted H. <thu...@ro...> - 2004-07-18 18:57:03
|
I'm still trying to work through this problem. I >I was having the same problem when running as a service. The problem is >actually not >related to the Wrapper. If Excel runs into any problems while it is >running, it will pop up an >error dialog and not continue until a user has accepted it. The problem >of course is that >when running as a service, there is no way to see the dialog. The simple example in my previous post (exectest.vbs and exectest.jsp) simply opens Excel, sleeps then quits. There are no operations to cause error dialogs. >To figure out what the error is, I would try running in console mode >until you have gotten >things working. All paths etc should then be the same when running as a >service. My first >guess would be that you are having a path problem. The working directory >might not be getting set to what you are expecting. Would you believe that it works in console mode, but not as a service? This is getting more mysterious. Ted |
|
From: Leif M. <le...@ta...> - 2004-07-18 23:56:20
|
Ted Hudacko wrote: >Would you believe that it works in console mode, but not as a service? This >is getting more mysterious. > > Ahhh, I think I might know what the problem is then. Some versions of Office have a little auto registration wizard that pops up the very first time any specific user runs office.. What may be happening is that when the Wrapper is running as the SYSTEM user, Excel is popping up that wizard and waiting for the user to complete it?? What happens if you run the Wrapper as the user you are normally logged in as? You can do this using the wrapper.ntservice.account / wrapper.ntservice.password properties. Let me know whether or not it works when running as you. If so then we can proceed with trying to figure out how to get it running as the SYSTEM user. Cheers, Leif |
|
From: Ted H. <thu...@ro...> - 2004-07-19 05:29:05
|
>Ahhh, I think I might know what the problem is then. Some versions of >Office have a little auto registration wizard that pops up the very first time any specific >user runs office.. What >may be happening is that when the Wrapper is running as the SYSTEM user, >Excel is popping >up that wizard and waiting for the user to complete it?? That is an excellent hypothesis. I experimented with an even simpler version of the VB script that, rather than opening Excel, simply created a new text file in the root directory. E.g.: Set objFS = CreateObject( "Scripting.FileSystem" ) objFS.CreateTextFile "C:\foobar.txt" This works fine in both console and service modes, and with the service running either as LocalSystem or Administrator (the account I normally log in as). Unfortunately, when I substitute the commands to open Excel back into the VB script, Excel does not open. Same result happens if the script is changed to simply display a message box: MsgBox foo So it does indeed appear that the issue is interactivity with the desktop by the service wrapper under certain user identities. >What happens if you run the Wrapper as the user you are normally logged >in as? You can >do this using the wrapper.ntservice.account / wrapper.ntservice.password >properties. Let >me know whether or not it works when running as you. If so then we can >proceed with >trying to figure out how to get it running as the SYSTEM user. I uninstalled, then reinstalled the JBoss service, making sure that I had the following properties set in the wrapper.conf: wrapper.ntservice.adviser=true wrapper.ntservice.account=.\Administrator wrapper.ntservice.password=mypassword wrapper.ntservice.interactive=true However, the following warning appears: wrapper | Ignoring the wrapper.ntservice.interactive property because it can not be set when wrapper.ntservice.account is also set. Checking your source code, this string appears in wrapperBuildNTServiceInfo() Wrapper_3.1.0_src\src\c\wrapper.c Here, you force the interactive property to FALSE when both flags are set in wrapper.conf. Not being familiar with your code, it's unclear in what context this is called. Is this called every time the wrapper runs, or just when you install the wrapper as a service? The Windows Services GUI does not permit you to set "Allow service to interact with desktop" for accounts other than Local System account. This article suggests a hack to the Registry entry for that service: http://www.dotnet247.com/247reference/msgs/33/166835.aspx I tried setting this bit for the JBoss service after installing with InstallJBoss-NT.bat But this still didn't work as desired. Ted |
|
From: Leif M. <le...@ta...> - 2004-07-19 10:58:22
|
Ted, Ted Hudacko wrote: >That is an excellent hypothesis. I experimented with an even simpler >version of the VB script that, rather than opening Excel, simply created a >new text file in the root directory. E.g.: > > Set objFS = CreateObject( "Scripting.FileSystem" ) > objFS.CreateTextFile "C:\foobar.txt" > >This works fine in both console and service modes, and with the service >running either as LocalSystem or Administrator (the account I normally log >in as). > >Unfortunately, when I substitute the commands to open Excel back into the VB >script, Excel does not open. Same result happens if the script is changed >to simply display a message box: > > MsgBox foo > >So it does indeed appear that the issue is interactivity with the desktop by >the service wrapper under certain user identities. > > Ok, so is sounding more like that might what your problem is. When you run as the default SYSTEM user, with wrapper.ntservice.interactive set, you are not seeing anything come up? I would have thought that would have made any dialogs visible. I have noticed that when using remote terminal to connect to a system, it does not seem possible to use interactive services. ie, they never show up on these remote connections. Not sure the details behind this, but I have noticed at a customer site. Also note the issue with pre 1.4.0 JVMs described here: http://wrapper.tanukisoftware.org/doc/english/prop-ntservice-interactive.html I am not sure if this also pertains to their child processes. >>What happens if you run the Wrapper as the user you are normally logged >>in as? You can >>do this using the wrapper.ntservice.account / wrapper.ntservice.password >>properties. Let >>me know whether or not it works when running as you. If so then we can >>proceed with >>trying to figure out how to get it running as the SYSTEM user. >> >> > >I uninstalled, then reinstalled the JBoss service, making sure that I had >the following properties set in the wrapper.conf: > wrapper.ntservice.adviser=true > wrapper.ntservice.account=.\Administrator > wrapper.ntservice.password=mypassword > wrapper.ntservice.interactive=true > >However, the following warning appears: > wrapper | Ignoring the wrapper.ntservice.interactive property because it >can not be set when wrapper.ntservice.account is also set. > >Checking your source code, this string appears in >wrapperBuildNTServiceInfo() > Wrapper_3.1.0_src\src\c\wrapper.c > >Here, you force the interactive property to FALSE when both flags are set in >wrapper.conf. Not being familiar with your code, it's unclear in what >context this is called. Is this called every time the wrapper runs, or just >when you install the wrapper as a service? > > This is an issue with the underlying Windows API. The service manager only allows you to set a service as being interactive if and only if you are using the SYSTEM user. Other users are not allowed to interact with the desktop. I added code to the Wrapper to detect this case and display an error message rather than simply having it not work when the service was run. >The Windows Services GUI does not permit you to set "Allow service to >interact with desktop" for accounts other than Local System account. This >article suggests a hack to the Registry entry for that service: > http://www.dotnet247.com/247reference/msgs/33/166835.aspx > > Reading this, I am not sure that it would correct the problem and make non-system users able to interact with the desktop. Even for Windows, I would be surprised if it was that easy considering they have gone out of their way to disallow you the ability to set it in the service control panel. The only time the Wrapper makes use of the wrapper.ntservice.interactive property is when the service is being installed. Once a service has been installed, it does not have the ability to control this in its own process. >I tried setting this bit for the JBoss service after installing with >InstallJBoss-NT.bat But this still didn't work as desired. > > When using the Administrator account, do you still need to be able to interact with the desktop? If you can get the Wrapper and your application working in console mode when logged in as the Administrator, then I would expect it to work exactly the same when running as a service. Cheers, Leif |