LS Agent calling Batch file in Console

Hi:BACKGROUND:

I have a LS agent that calls a batch file.

PROBLEM:

When this batch file is called it calls the agent in the console window rather than an external DOS window.

SOLUTION?

Can you explain this as it is causing problems as I want the agent to wait until the external window looses focus and then continues.

rgds, james

Subject: 2 things

a) depends on how you call the batchfile. Provide code here so people can see what you’re doing.b) any calls to execute external programs are asynchronous, ie. they won’t block or wait, the call will immediately return, regardless how long your batch file will run (it’s run inside a CMD.EXE shell anyway). If you really need to wait until the called program completed, you need to obtain the PID of the called process and then monitor it yourself until it goes away (using the W32 API, you could use WaitForSingleObject(), etc.)

Thomas - IBM

Subject: RE: 2 things

You could also wait on a semaphore file created at the end of the batch script. No need to dive into the murky depths of the Win32 API (and it works cross platform)

Subject: RE: 2 things

Sometimes the obviously easier things completely escape me :slight_smile:

Subject: I know, I’ve seen your code. :wink:

Subject: Be careful when you go back to the office next week…

…as all kinds of bad things “all of a sudden” might happen to you…and I wonder why :slight_smile:

Subject: *LOL. When you least expect it, expect it!

Subject: Example Code

Thks guys for all the useful tips :)I use some code that I got of LDD to wait until the external batch file window looses focus.

This code definately worked but something recently has caused it to start executing in the server console???

If I run the agent manually then it executes successfully by running seperately in its own cmd window?

Now you can have a laugh at my ‘simple’ code…

RunApp:

Sub RunApp (program$)

structure:

start.cb = Len(start)

ret& = CreateProcessA(0&, program$, 0&, 0&, 1&, NORMAL_PRIORITY_CLASS, 0&, 0&, start, proc)

ret& = WaitForSingleObject(proc.hProcess, INFINITE)

ret& = CloseHandle(proc.hProcess)

End Sub

Initilaze:

'Execute java

			Print ( " ")

			Print(" *********** Date greater - running java extractor. ***************** ")

'Set current directory using UNC path so extractor can be run from clients

			Chdrive "c"

			Chdir "c:\utils\doti\extractor\src"

		'	taskId% = Shell("extractor.bat", 1)

			Print " ******* Extractor Opened  *********"

			RunApp("c:\utils\doti\extractor\src\extractor.bat")

			Print " ******* Extractor Closed *********"

			qryediflag.SQL = "DELETE FROM XML_FLAG"                   

			resultediflag.Execute

'Vaildation of xml document is performed from extractor program. Therefore the xml file is not created is not valid.

			Print " ********** XML FILE Successfully Generated ******* "  

		End If                    

Any ideas would be greatly appreciated.

james

Subject: RE: Example Code

*DeclareDeclare Function OpenProcess Lib _

“kernel32” (Byval dwDesiredAccess As Long, _

Byval bInheritHandle As Long, _

Byval dwProcessID As Long) As Long

Declare Function WaitForSingleObject _

Lib “kernel32” (Byval hHandle As Long, _

Byval dwMilliseconds As Long) As Long

Declare Function CloseHandle Lib _

“kernel32” (Byval hObject As Long) As Long

Private Const SYNCHRONIZE = &H100000

Private Const INFINITE = -1&

'Error on call

Private Const WAIT_FAILED = -1&

'Normal completion

Private Const WAIT_OBJECT_0 = 0

'Timeout period elapsed

Private Const WAIT_TIMEOUT = &H102&

*Function

Public Function WaitForProcessClose(Byval PID _

As Long, Byval TimeOut As Long) As Boolean

’ Timeout needs to be passed in milliseconds!

Dim hProc As Long

Dim nRet As Long

Const fdwAccess = SYNCHRONIZE

’ Try opening process; wait on it to close.

hProc = OpenProcess(fdwAccess, False, PID)



If hProc Then

	nRet = WaitForSingleObject(hProc, TimeOut)

	Select Case nRet

	Case WAIT_TIMEOUT

        ' Still open.

		WaitForProcessClose = False

	Case WAIT_OBJECT_0

        ' Process has closed.

		WaitForProcessClose = True

	Case Else

        ' Error on call.

		WaitForProcessClose = False

’ ApiErrorDump Err.LastDllError, _

’ “WaitForSingleObject”

	End Select

	

Else

  ' Nothing we can do, at this point.

  ' Process may be gone already?

’ ApiErrorDump Err.LastDllError, _

’ “OpenProcess”

	WaitForProcessClose = True

End If

’ Clean up.

Call CloseHandle(hProc)

End Function

What I also did was to used with the following section in another routine where I had a list of batchfiles to execute, it looks like this:

				Dim taskId As Variant

				Forall i In BatchFileNameList

					Print		BatchFileNameList(Listtag(i))

					taskid = Shellid(BatchFileNameList(Listtag(i)))

					TaskIdList(Listtag(i)) = taskid

				End Forall

After this i only need to step thru the list I used anoter function to do this:

Function ExternalCommandsFinished(TaskIdList List As String) As Boolean

ExternalCommandsFinished = False	

Forall i In TaskIdList

	If WaitForProcessClose(TaskIdList(Listtag(i)),60000) Then

		Print TaskIdList(Listtag(i)) & " is finished"

	Else

		Print TaskIdList(Listtag(i)) & " is hanging"		

		ExternalCommandsFinished = False	

		Exit Function

	End If												 

End Forall

ExternalCommandsFinished = True

End Function

To call this function I used:

		If ExternalCommandsFinished(TaskIdList) Then

Call whatever

		Else				

Call whatever

		End If