Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scope problems in batch file with nested loops

Tags:

batch-file

I have an SSIS job running in a batch file that executes asynchronously.

I need to know when the SSIS job is done outputting a bunch of PDF and XLS files.

The files appear in two directories, PDFs first XLS following.

I chose to write a second batch file that will wait a bit after the SSIS job exits, then check to see that the last file written in the directory has been there for 3 minutes, which, after observation, is an ample interval for the job to write a file.

The problem is: the outer loop is never run if the inner loop iterates more than once, which seems to indicate that the second time MYPATH is declared, the value of n is foobarred, but this cannot be true because the script is returning 1, rather than crapping out when Arr[badval] is checked.

@ECHO OFF

REM SSIS process is asyncronous, and executes in background. Problematic for
REM DAG, which relies on exit code to understand process.
REM Check for "last file written" in output directories every N seconds.
REM It's a good bet we are done when they match.

@setlocal enabledelayedexpansion

REM "sleep" wait for non-existent command to complete
waitfor ragnarok /t 180>NUL 2>&1

set Arr[0]=E:\pdf_output
set Arr[1]=E:\xls_output

for /l %%n in (0,1,2) do (

    if defined Arr[%%n] (
        REM set value for path within loop or scope will bite you
        set MYPATH=!Arr[%%n]!
        echo Checking file ages in !MYPATH!.
    ) else (
        echo Done
        EXIT /B 0
    )

    :while1
        REM don't put a blank line here, it throws a syntax error
        FOR /F "delims=|" %%I IN ('DIR !MYPATH! /B /O:D') DO SET FILE1=%%I

        REM "sleep" use ping for delay, since waitfor will break loop
        arp -s 192.168.1.254 >nul
        ipconfig /flushdns >nul
        ping localhost -n 180 >nul

        FOR /F "delims=|" %%I IN ('DIR !MYPATH! /B /O:D') DO SET FILE2=%%I

        if NOT "!FILE1!" == "!FILE2!" (
            goto :while1
        )
)
endlocal
REM Something is wrong, return 1 to stop DAG and invite inspection.
exit /B 1
like image 514
Foo Barberger Avatar asked May 28 '26 14:05

Foo Barberger


1 Answers

Breaking the while loop into a subroutine as @aschipfl suggested seems to have done the trick:

@ECHO OFF

REM SSIS process is asyncronous, and executes in background. Problematic for
REM DAG, which relies on exit code to understand process.
REM Check for "last file written" in output directories every N seconds.
REM It's a good bet we are done when they match.

@setlocal enabledelayedexpansion

REM "sleep" wait for non-existent command to complete
waitfor ragnarok /t 120>NUL 2>&1

set Arr[0]=E:\pdf_output
set Arr[1]=E:\xls_output

for /l %%n in (0,1,2) do (

    if defined Arr[%%n] (
        REM set value for path within loop or scope will bite you
        set MYPATH=!Arr[%%n]!
        echo Checking file ages in !MYPATH!.
        CALL :checkfiles
    ) else (
        echo Done
        goto :NormalExit
    )
)

:checkfiles
    :while1
        REM don't put a blank line here, it throws a syntax error
        FOR /F "delims=|" %%I IN ('DIR !MYPATH! /B /O:D') DO SET FILE1=%%I

        REM "sleep" use ping for delay, since waitfor will break loop
        arp -s 192.168.1.254 >nul
        ipconfig /flushdns >nul
        ping localhost -n 120 >nul

        FOR /F "delims=|" %%I IN ('DIR !MYPATH! /B /O:D') DO SET FILE2=%%I

        if NOT "!FILE1!" == "!FILE2!" (
            goto :while1
        )
endlocal

:NormalExit
    exit /B 0

REM Something is wrong, return 1 to stop DAG and invite inspection.
exit /B 1
like image 63
Foo Barberger Avatar answered May 31 '26 15:05

Foo Barberger



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!