DOS command hangs processing etc

Smud

Member
Had the problem where the DOS command causes Openedge to wait till process has finished etc and could not see a decent resolution in any of the forums, so the difference between;

DOS SILENT notepad c:\temp\text.

and

OS-COMMAND SILENT ("start /B notepad.exe c:\temp\text.txt").

is the first one waits till you close notepad before continuing the other does not. Hope this helps anybody with a similar issue. There is probably a few variations that work but the key is to use "start /B" rather than just running your DOS / Windows command. At least till Micro$oft does an upgrade!
 

Cecil

19+ years progress programming and still learning.
Had the problem where the DOS command causes Openedge to wait till process has finished etc and could not see a decent resolution in any of the forums, so the difference between;

DOS SILENT notepad c:\temp\text.

and

OS-COMMAND SILENT ("start /B notepad.exe c:\temp\text.txt").

is the first one waits till you close notepad before continuing the other does not. Hope this helps anybody with a similar issue. There is probably a few variations that work but the key is to use "start /B" rather than just running your DOS / Windows command. At least till Micro$oft does an upgrade!

I can across this very problem a few months ago too and I had to use the DOS command start /B to overcome the problem. I was using CURL.exe to which was connecting to a socket on the same process which executed the curl command. I ended up in a "Process embrace lock".
 

Osborne

Active Member
Out of interest, do you have to use "start /B" if you use NO-WAIT or same problem with NO-WAIT?:
Code:
OS-COMMAND NO-WAIT ("notepad.exe c:\temp\text.txt").
or
OS-COMMAND NO-WAIT VALUE(QUOTER("notepad.exe c:\temp\text.txt")).
 

Smud

Member
I had the same problem with "no-wait", and "no-console".
 

TomBascom

Curmudgeon
I have mostly given up on DOS and OS-COMMAND on Windows. I use DLL calls to CreateProcessA() instead.
 

Osborne

Active Member
I had the same problem with "no-wait", and "no-console".
Thanks for the information.
 

Cecil

19+ years progress programming and still learning.
I have mostly given up on DOS and OS-COMMAND on Windows. I use DLL calls to CreateProcessA() instead.
Some examples could be handy.
 

TomBascom

Curmudgeon
From the ProTop source:

Code:
if opsys begins "win" then
  do:

    if process-architecture = 64 then
      run lib/windows64.p persistent.
     else
      run lib/windows32.p persistent.

  end.
Code:
/* lib/windows32.p
*
* windows kernel calls
*
* use this when _progres is a 32 bit executable
*
*/
    
session:add-super-procedure( this-procedure ).
   
return.
    
     
PROCEDURE CreateProcessA EXTERNAL "kernel32.dll":
  DEFINE INPUT  PARAMETER lpApplicationName    AS LONG.
  DEFINE INPUT  PARAMETER lpCommandline        AS CHAR.
  DEFINE INPUT  PARAMETER lpProcessAttributes  AS LONG.
  DEFINE INPUT  PARAMETER lpThreadAttributes   AS LONG.
  DEFINE INPUT  PARAMETER bInheritHandles      AS LONG.
  DEFINE INPUT  PARAMETER dCreationFlags       AS LONG.
  DEFINE INPUT  PARAMETER lpEnvironment        AS LONG. 
  DEFINE INPUT  PARAMETER lpCurrentDirectory   AS LONG. 
  DEFINE INPUT  PARAMETER lpStartupInfo        AS LONG. 
  DEFINE INPUT  PARAMETER lpProcessInformation AS LONG. 
  DEFINE RETURN PARAMETER bResult              AS LONG. 
end procedure.
   
procedure OpenProcess external "kernel32.dll" :
  define input  parameter desiredAccess as long.
  define input  parameter inheritFlag   as long.
  define input  parameter pid           as long.
  define return parameter procHdl       as long.
end procedure.
     
procedure TerminateProcess external "kernel32.dll" :
  define input  parameter hProcess  as long.
  define input  parameter uExitCode as long.
  define return parameter retval    as long.
end procedure.
     
procedure CloseHandle external "kernel32.dll":
  define input  parameter procHdl  as long.
  define return parameter statcode as long.
end.

procedure spawn:
 
  DEFINE INPUT  PARAMETER CommandLine as character NO-UNDO.
  DEFINE INPUT  PARAMETER WorkingDir  as character NO-UNDO.
  DEFINE OUTPUT PARAMETER PID         AS INTEGER   NO-UNDO.
     
  define variable wShowWindow   AS INTEGER NO-UNDO INITIAL 0.
  define variable bResult       AS INTEGER NO-UNDO.
  define variable ReturnValue   AS INTEGER NO-UNDO.
  define variable lpStartupInfo AS MEMPTR  NO-UNDO.
   
  SET-SIZE ( lpStartupInfo )     = 68.
   
  PUT-LONG ( lpStartupInfo, 1 )  = 68.
  PUT-LONG ( lpStartupInfo, 45 ) = 1. /* = STARTF_USESHOWWINDOW */
 
  PUT-SHORT( lpStartupInfo, 49 ) = wShowWindow.
 
  define variable lpProcessInformation AS MEMPTR.
  SET-SIZE( lpProcessInformation )   = 16.
     
  define variable lpWorkingDirectory AS MEMPTR.
  IF WorkingDir NE "" THEN DO:
    SET-SIZE( lpWorkingDirectory )     = 256.
    PUT-STRING( lpWorkingDirectory, 1 ) = WorkingDir.
  END.

RUN CreateProcessA(
    0,
    CommandLine,
    0,
    0,
    0,
    0,
    0,
    ( IF WorkingDir = "" THEN 0 ELSE GET-POINTER-VALUE( lpWorkingDirectory )),
    GET-POINTER-VALUE( lpStartupInfo ),
    GET-POINTER-VALUE( lpProcessInformation ),
    OUTPUT bResult
  ).
      
  IF bResult <> 0 THEN     /* release kernel-objects hProcess and hThread: */
    do:
   
      PID = GET-LONG( lpProcessInformation, 9 ).
      RUN CloseHandle ( input GET-LONG( lpProcessInformation, 1 ), OUTPUT ReturnValue ).
      RUN CloseHandle ( input GET-LONG( lpProcessInformation, 5 ), OUTPUT ReturnValue ).
   
    end.

  SET-SIZE( lpStartupInfo )        = 0.
  SET-SIZE( lpProcessInformation ) = 0.
  SET-SIZE( lpWorkingDirectory )   = 0.
     
END PROCEDURE. 
     
     
procedure kill:
     
  define input parameter PID as integer no-undo.
  define variable processHandle as integer no-undo.
  define variable returnValue   as integer no-undo.
   
  run OpenProcess ( 1, 0, PID, OUTPUT ProcessHandle ).
   
  if processHandle NE 0 then
    do:
      run TerminateProcess ( processHandle, 0, output returnValue ).
      run CloseHandle ( processHandle, output returnValue ).
    end.
     
end.
 

TomBascom

Curmudgeon
part 2 - lib/windows64.p

(... and in case you're wondering about all of the pre-processor nonsense: Progress KB - Windows API call fails with error 13712 in 11.7 64-bit)

Code:
/* lib/windows64.p
*
* windows kernel calls
* 
* use this when _progres is a 64 bit executable or when running source
*
*/
     
session:add-super-procedure( this-procedure ).
     
return.

PROCEDURE CreateProcessA EXTERNAL "kernel32.dll":
  &IF DECIMAL(SUBSTRING(PROVERSION,1,INDEX(PROVERSION,".") + 1)) < 11.3 &THEN
    DEFINE INPUT  PARAMETER lpApplicationName    AS LONG. 
    DEFINE INPUT  PARAMETER lpCommandline        AS CHAR. 
    DEFINE INPUT  PARAMETER lpProcessAttributes  AS LONG. 
    DEFINE INPUT  PARAMETER lpThreadAttributes   AS LONG. 
    DEFINE INPUT  PARAMETER bInheritHandles      AS LONG. 
    DEFINE INPUT  PARAMETER dCreationFlags       AS LONG. 
    DEFINE INPUT  PARAMETER lpEnvironment        AS LONG. 
    DEFINE INPUT  PARAMETER lpCurrentDirectory   AS LONG.  
    DEFINE INPUT  PARAMETER lpStartupInfo        AS LONG. 
    DEFINE INPUT  PARAMETER lpProcessInformation AS LONG. 
    DEFINE RETURN PARAMETER bResult              AS LONG. 
  &ELSE  
    &IF {&PROCESS-ARCHITECTURE} = 64 &THEN
      DEFINE INPUT  PARAMETER lpApplicationName    AS INT64.
      DEFINE INPUT  PARAMETER lpCommandline        AS CHAR.
      DEFINE INPUT  PARAMETER lpProcessAttributes  AS INT64.
      DEFINE INPUT  PARAMETER lpThreadAttributes   AS INT64.
      DEFINE INPUT  PARAMETER bInheritHandles      AS INT64.
      DEFINE INPUT  PARAMETER dCreationFlags       AS INT64.
      DEFINE INPUT  PARAMETER lpEnvironment        AS INT64.
      DEFINE INPUT  PARAMETER lpCurrentDirectory   AS INT64.
      DEFINE INPUT  PARAMETER lpStartupInfo        AS INT64.
      DEFINE INPUT  PARAMETER lpProcessInformation AS INT64.
      DEFINE RETURN PARAMETER bResult              AS INT64.
    &ELSE
      DEFINE INPUT  PARAMETER lpApplicationName    AS LONG.
      DEFINE INPUT  PARAMETER lpCommandline        AS CHAR.
      DEFINE INPUT  PARAMETER lpProcessAttributes  AS LONG.
      DEFINE INPUT  PARAMETER lpThreadAttributes   AS LONG.
      DEFINE INPUT  PARAMETER bInheritHandles      AS LONG.
      DEFINE INPUT  PARAMETER dCreationFlags       AS LONG.
      DEFINE INPUT  PARAMETER lpEnvironment        AS LONG.
      DEFINE INPUT  PARAMETER lpCurrentDirectory   AS LONG.
      DEFINE INPUT  PARAMETER lpStartupInfo        AS LONG.
      DEFINE INPUT  PARAMETER lpProcessInformation AS LONG.
      DEFINE RETURN PARAMETER bResult              AS LONG.
    &ENDIF
  &ENDIF
end procedure.
     
procedure OpenProcess external "kernel32.dll" :
  &IF DECIMAL(SUBSTRING(PROVERSION,1,INDEX(PROVERSION,".") + 1)) < 11.3 &THEN
    define input  parameter desiredAccess as long.
    define input  parameter inheritFlag   as long.
    define input  parameter pid           as long.
    define return parameter procHdl       as long.
  &ELSE
    &IF {&PROCESS-ARCHITECTURE} = 64 &THEN
      define input  parameter desiredAccess as int64.
      define input  parameter inheritFlag   as int64.
      define input  parameter pid           as int64.
      define return parameter procHdl       as int64.
    &ELSE
      define input  parameter desiredAccess as long.
      define input  parameter inheritFlag   as long.
      define input  parameter pid           as long.
      define return parameter procHdl       as long.
    &ENDIF
  &ENDIF
end procedure.

procedure TerminateProcess external "kernel32.dll" :
  &IF DECIMAL(SUBSTRING(PROVERSION,1,INDEX(PROVERSION,".") + 1)) < 11.3 &THEN
    define input  parameter hProcess  as long.
    define input  parameter uExitCode as long.
    define return parameter retval    as long.
  &ELSE
    &IF {&PROCESS-ARCHITECTURE} = 64 &THEN
      define input  parameter hProcess  as int64.
      define input  parameter uExitCode as int64.
      define return parameter retval    as int64.
    &ELSE
      define input  parameter hProcess  as long.
      define input  parameter uExitCode as long.
      define return parameter retval    as long.
    &ENDIF
  &ENDIF
   
end procedure.

procedure CloseHandle external "kernel32.dll":
  &IF DECIMAL(SUBSTRING(PROVERSION,1,INDEX(PROVERSION,".") + 1)) < 11.3 &THEN
    define input  parameter procHdl  as long.
    define return parameter statcode as long.
  &ELSE
    &IF {&PROCESS-ARCHITECTURE} = 64 &THEN
      define input  parameter procHdl  as int64.
      define return parameter statcode as int64.
    &ELSE
      define input  parameter procHdl  as long.
      define return parameter statcode as long.
    &ENDIF
  &ENDIF
end.

procedure spawn:
     
  DEFINE INPUT  PARAMETER CommandLine as character NO-UNDO.
  DEFINE INPUT  PARAMETER WorkingDir  as character NO-UNDO.
  DEFINE OUTPUT PARAMETER PID         AS INTEGER   NO-UNDO.
 
  define variable wShowWindow   AS INTEGER NO-UNDO INITIAL 0.
  define variable bResult       AS INTEGER NO-UNDO.
  define variable ReturnValue   AS INTEGER NO-UNDO.
  define variable lpStartupInfo AS MEMPTR  NO-UNDO.
 
  SET-SIZE ( lpStartupInfo )     = 68.
   
  &IF DECIMAL(SUBSTRING(PROVERSION,1,INDEX(PROVERSION,".") + 1)) < 11.3 &THEN
    PUT-LONG ( lpStartupInfo, 1 )  = 68. 
    PUT-LONG ( lpStartupInfo, 45 ) = 1. /* = STARTF_USESHOWWINDOW */
  &ELSE
    &IF {&PROCESS-ARCHITECTURE} = 64 &THEN
      PUT-INT64 ( lpStartupInfo, 1 )  = 68.
      PUT-INT64 ( lpStartupInfo, 45 ) = 1. /* = STARTF_USESHOWWINDOW */
    &ELSE
      PUT-LONG ( lpStartupInfo, 1 )  = 68.
      PUT-LONG ( lpStartupInfo, 45 ) = 1. /* = STARTF_USESHOWWINDOW */
    &ENDIF
  &ENDIF

  PUT-SHORT( lpStartupInfo, 49 ) = wShowWindow.
 
  define variable lpProcessInformation AS MEMPTR.
  SET-SIZE( lpProcessInformation )   = 16.
 
  define variable lpWorkingDirectory AS MEMPTR.
  IF WorkingDir NE "" THEN DO:
    SET-SIZE( lpWorkingDirectory )     = 256.
    PUT-STRING( lpWorkingDirectory, 1 ) = WorkingDir.
  END.

RUN CreateProcessA(
    0,
    CommandLine,
    0,
    0,
    0,
    0,
    0,
    ( IF WorkingDir = "" THEN 0 ELSE GET-POINTER-VALUE( lpWorkingDirectory )),
    GET-POINTER-VALUE( lpStartupInfo ),  
    GET-POINTER-VALUE( lpProcessInformation ),
    OUTPUT bResult
  ).

  IF bResult <> 0 THEN     /* release kernel-objects hProcess and hThread: */
    do:
 
      &IF DECIMAL(SUBSTRING(PROVERSION,1,INDEX(PROVERSION,".") + 1)) < 11.3 &THEN
        PID = GET-LONG( lpProcessInformation, 9 ).
        RUN CloseHandle ( input GET-LONG( lpProcessInformation, 1 ), OUTPUT ReturnValue ).
        RUN CloseHandle ( input GET-LONG( lpProcessInformation, 5 ), OUTPUT ReturnValue ).
      &ELSE
        &IF {&PROCESS-ARCHITECTURE} = 64 &THEN
          PID = GET-INT64( lpProcessInformation, 9 ).
          RUN CloseHandle ( input GET-INT64( lpProcessInformation, 1 ), OUTPUT ReturnValue ).
          RUN CloseHandle ( input GET-INT64( lpProcessInformation, 5 ), OUTPUT ReturnValue ).
        &ELSE
          PID = GET-LONG( lpProcessInformation, 9 ).
          RUN CloseHandle ( input GET-LONG( lpProcessInformation, 1 ), OUTPUT ReturnValue ).
          RUN CloseHandle ( input GET-LONG( lpProcessInformation, 5 ), OUTPUT ReturnValue ).
        &ENDIF
      &ENDIF
     
    end.
   
  SET-SIZE( lpStartupInfo )        = 0.
  SET-SIZE( lpProcessInformation ) = 0.
  SET-SIZE( lpWorkingDirectory )   = 0.

END PROCEDURE.
      
procedure kill:
     
  &IF DECIMAL(SUBSTRING(PROVERSION,1,INDEX(PROVERSION,".") + 1)) < 11.3 &THEN
    define input parameter PID as integer no-undo.
    define variable processHandle as integer no-undo.
    define variable returnValue   as integer no-undo.
  &ELSE
    &IF {&PROCESS-ARCHITECTURE} = 64 &THEN
      define input parameter PID as int64 no-undo.
      define variable processHandle as int64 no-undo.
      define variable returnValue   as int64 no-undo.
    &ELSE
      define input parameter PID as integer no-undo.
      define variable processHandle as integer no-undo.
      define variable returnValue   as integer no-undo.
    &ENDIF 
  &ENDIF
   
  run OpenProcess ( 1, 0, PID, OUTPUT ProcessHandle ).
 
  if processHandle NE 0 then
    do:
      run TerminateProcess ( processHandle, 0, output returnValue ).
      run CloseHandle ( processHandle, output returnValue ).
    end.

end.
 

TomBascom

Curmudgeon
For the record -- I preserved the casing, hungarian notation and abbreviations from the original source that I copied. Some day I expect I will fix all of that. Although I keep hoping Windows support will be dropped and I will be spared the trouble.
 
Top