MapInfo Pro Developers User Group

 View Only
Expand all | Collapse all

Wait until Run Program has finished

  • 1.  Wait until Run Program has finished

    Posted 09-09-2025 02:01

    I want to write a mbx that executes a RoboCopy command to copy specific MapInfo tables to the user's C: drive, for fast access.

    I want to use RoboCopy because it will only run if the source files are different to the destination files. This saves unnecessary work.

    Is there a way to make the mbx wait until the RoboCopy command has finished running before proceeding with the next part of the mbx script?

    The Help file for Run Program indicates that the mbx will continue whilst the spawned task (RoboCopy) is still running



    ------------------------------
    Nick Lawrence
    Senior Spatial Science Officer
    Department of Transport and Main Roads (QLD)
    Brisbane QLD
    ------------------------------


  • 2.  RE: Wait until Run Program has finished

    Posted 09-09-2025 02:52
    Hello Nick,
    Below is some stock MapBasic code that I've been using for many years and it still seems to work well.
    There are a few data structures, definitions and Windows functions to prototype, but these are all in support of the local function ExecuteAndWait(). You simply pass in your command line... RoboCopy plus parameters in your case. The function returns zero if successful.
    This version will run the command silently, but if you want to see a Command Prompt window appear so you can see what RoboCopy is doing, simply remove the +CREATE_NO_WINDOW from the call to CreateProcessA. Note, however, if you're doing lots of these, it snatches Window focus each time, which makes using your PC difficult!
    Hope it's helpful.

    Regards,
    Warren Vick
    Europa Technologies Ltd.

    Type STARTUPINFO
          cb As Integer
          lpReserved As String
          lpDesktop As String
          lpTitle As String
          dwX As Integer
          dwY As Integer
          dwXSize As Integer
          dwYSize As Integer
          dwXCountChars As Integer
          dwYCountChars As Integer
          dwFillAttribute As Integer
          dwFlags As Integer
          wShowWindow As Smallint
          cbReserved2 As Smallint
          lpReserved2 As Integer
          hStdInput As Integer
          hStdOutput As Integer
          hStdError As Integer
    End Type
    
    Type PROCESS_INFORMATION
          hProcess As Integer
          hThread As Integer
          dwProcessID As Integer
          dwThreadID As Integer
    End Type
    
    define NORMAL_PRIORITY_CLASS   &H20
    define CREATE_NO_WINDOW        &H8000000   
    define INFINITE                -1
    
    declare function CreateProcessA Lib "kernel32"(ByVal lpApplicationName As Integer, ByVal lpCommandLine As String,
         ByVal lpProcessAttributes As Integer, ByVal lpThreadAttributes As Integer, ByVal bInheritHandles As Integer,
         ByVal dwCreationFlags As Integer, ByVal lpEnvironment As Integer, ByVal lpCurrentDirectory As Integer,
         lpStartupInfo As STARTUPINFO, lpProcessInformation As PROCESS_INFORMATION) As Integer
    declare function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Integer,ByVal dwMilliseconds As Integer) As Integer
    declare function GetExitCodeProcess Lib "kernel32" (byval hProcess As Integer, lpExitCode As Integer) as Integer
    declare function CloseHandle Lib "kernel32" (hObject As Integer) As smallint
    
    declare function ExecuteAndWait(ByVal cmdLine as string) as integer
    
    function ExecuteAndWait(ByVal cmdLine as string) as integer
       dim exitCode as integer
       dim rc as integer
       dim pi as PROCESS_INFORMATION
       dim si as STARTUPINFO
    
       si.cb = 256
       si.dwFlags = 1
       si.wShowWindow = 1
    
       rc = CreateProcessA(0, cmdLine, 0, 0, 0, NORMAL_PRIORITY_CLASS+CREATE_NO_WINDOW, 0, 0, si, pi)
       rc = WaitForSingleObject(pi.hProcess, INFINITE)
       rc = GetExitCodeProcess(pi.hProcess, exitCode)
       rc = CloseHandle(pi.hProcess)
       rc = CloseHandle(pi.hThread)
    
       ExecuteAndWait = exitCode
    end function


    ------------------------------
    Warren Vick
    Europa Technologies Ltd.
    ------------------------------



  • 3.  RE: Wait until Run Program has finished

    Posted 09-09-2025 02:54

    That code didn't format well when coming through as e-mail! Better to copy/paste from https://community.precisely.com.



    ------------------------------
    Warren Vick
    Europa Technologies Ltd.
    ------------------------------



  • 4.  RE: Wait until Run Program has finished

    Posted 09-09-2025 02:55

    Thanks! I will try this out



    ------------------------------
    Nick Lawrence
    Senior Spatial Science Officer
    Department of Transport and Main Roads (QLD)
    Brisbane QLD
    ------------------------------



  • 5.  RE: Wait until Run Program has finished

    Posted 09-16-2025 19:41

    Sorry, it did not compile

    For line 53    rc = CreateProcessA(0, cmdLine, 0, 0, 0, NORMAL_PRIORITY_CLASS+CREATE_NO_WINDOW, 0, 0, si, pi)

    The error is Found [___] while searching for [)].



    ------------------------------
    Nick Lawrence
    Senior Spatial Science Officer
    Department of Transport and Main Roads (QLD)
    Brisbane QLD
    ------------------------------



  • 6.  RE: Wait until Run Program has finished

    Posted 09-17-2025 04:23

    Hello Nick,

    It looks like this platform has added some special characters to the end of the CREATE_NO_WINDOW definition, which appears as underscores when copy/pasted.

    define CREATE_NO_WINDOW        &H8000000___

    Simply take those underscores off and you should be fine. I tested the code snippet and it compiles without error. Good luck!

    Regards,

    Warren Vick



    ------------------------------
    Warren Vick
    Europa Technologies Ltd.
    ------------------------------



  • 7.  RE: Wait until Run Program has finished

    Posted 09-22-2025 20:59

    Compilation Successful

    Thanks!

    Now I have to build the rest of my code around this



    ------------------------------
    Nick Lawrence
    Senior Spatial Science Officer
    Department of Transport and Main Roads (QLD)
    Brisbane QLD
    ------------------------------



  • 8.  RE: Wait until Run Program has finished

    Employee
    Posted 11-20-2025 05:16

    Coming a bit late to the game.

    I have a function for doing this in the SystemLib module from my MapBasic Common Library. The function is called SYSExecuteAndWait:

    Function SYSExecuteAndWait(   ByVal sCmdLine As String
                                , ByVal nShowWindow As Integer
                                ) As Logical
    Nick, I also noticed that you raised an idea to have this built into MapBasic. Is that still relevant?



    ------------------------------
    Peter Horsbøll Møller
    Principal Presales Consultant | Distinguished Engineer
    Precisely | Trust in Data
    ------------------------------



  • 9.  RE: Wait until Run Program has finished

    Posted 12-12-2025 00:44

    Hi Peter,

    Yes, the idea that I raised is still relevant.
    I thought that the functionality was important enough that it was worthy of being included in mapbasic



    ------------------------------
    Nick Lawrence
    Senior Spatial Science Officer
    Department of Transport and Main Roads (QLD)
    Brisbane QLD
    ------------------------------



  • 10.  RE: Wait until Run Program has finished

    Posted 12-14-2025 19:43

    Hi Peter and Warren,

    I am comparing the code that you both supplied (thanks!) and I noticed this difference.

    Warren has;

    rc = CreateProcessA(0, cmdLine, 0, 0, 0, NORMAL_PRIORITY_CLASS+CREATE_NO_WINDOW, 0, 0, si, pi)

    Peter has;

    nRetVal = WAPICreateProcess(0, sCmdLine, 0, 0, 1, NORMAL_PRIORITY_CLASS, 0, 0, StartupInfo, ProcInfo)

    I wonder what is the difference between the 0 and the 1 just before NORMAL_PRIORITY_CLASS ?



    ------------------------------
    Nick Lawrence
    Senior Spatial Science Officer
    Department of Transport and Main Roads (QLD)
    Brisbane QLD
    ------------------------------



  • 11.  RE: Wait until Run Program has finished

    Employee
    Posted 12-16-2025 04:59

    As my Copilot states, that is a great question :-)

    Here's Copilot's take on it:

    **************************************

    When bInheritHandles = FALSE (0)

    • The child process does NOT inherit any handles from the parent.
    • This is the safer default because it prevents accidental sharing of resources like files, pipes, or synchronization objects.
    • Use this when the new process doesn't need access to the parent's handles.

    When bInheritHandles = TRUE (1)

    • The child process inherits all handles marked as inheritable in the parent process.
    • This is useful when you want the child to use existing resources, for example:
      • Pipes for inter-process communication.
      • File handles for logging or shared files.
    • Important: Only handles explicitly created with the bInheritHandle flag set to TRUE (e.g., in CreateFile, CreatePipe) will be inherited.

    Key Considerations

    • If you set TRUE, make sure you control which handles are inheritable; otherwise, you might unintentionally share sensitive resources.
    • Handle inheritance is often combined with STARTUPINFO settings (e.g., hStdInput, hStdOutput, hStdError) to redirect I/O for the child process.
    • On Windows, inheritance only works if the child process is created in the same user session.

    *****************************************

    You can find the documentation for the WIN API function here: CreateProcessA function.

    Looking at this again, I wonder why I set it to 1 instead of 0, which would be the safer alternative?

    I may, in fact, change it to a 0 in my implementation.



    ------------------------------
    Peter Horsbøll Møller
    Principal Presales Consultant | Distinguished Engineer
    Precisely | Trust in Data
    ------------------------------