|
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
>
|