Search code examples
powershellcobol

Compile Micro Focus Net Express 5.1 Cobol in Powershell


I am hoping someone might be able to help me with writing a COBOL MF Net Express 5.1 compile command in Powershell. I have the command as it was used in the original batch script. I am currently working on reworking this in Powershell as a build script.

COBOL.EXE "%%inFile%%" OUTDD NOERRQ NOFLAGQ NOQUERY noALTER noanim nobound checkdiv COMP errlist list() FASTLINK omf"gnt" perform-type"osvs" SCHEDULER TARGET"PENTIUM" noTRUNC vsc2(1) listpath"","%%OUTPUT%%";,;,;

My attempt at converting this to Powershell has been like this:

$cobolExe = ".\COBOL.EXE"
$expression = "& $cobolExe `"$($inputfile)`" OUTDD NOERRQ NOFLAGQ NOQUERY noALTER noanim nobound checkdiv COMP errlist list() FASTLINK omf`"gnt`" perform-type`"osvs`" SCHEDULER TARGET`"PENTIUM`" noTRUNC vsc2(1) listpath`"`", `"$binPath\`";,;,;"
Invoke-Expression $expression

Invoke-Expression: 
Line |
   1 |  Invoke-Expression $expression
     |  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | At line:1 char:97 + … GQ NOQUERY noALTER noanim nobound checkdiv COMP errlist list() FASTLI … +                                                                ~
An expression was expected after '('.  At line:1
     | char:221 + … NTIUM" noTRUNC vsc2(1) listpath"", "C:\dev\dimensions\test\bin\";,;,; +                                                                     ~
Missing expression after unary operator ','.  At line:1
     | char:223 + … NTIUM" noTRUNC vsc2(1) listpath"", "C:\dev\dimensions\test\bin\";,;,; +                                                                       ~
Missing expression after unary operator ','.

I successfully have this working with CBLLINK.EXE, but it does not require as many parameters.

$cobolFile = "$Path\cobol.dir"
$cbllinkExe = ".\CBLLINK.EXE"

$expression = "$cbllinkExe -s -o$($outputFile) `"$($inputFile)`" adis adisinit adiskey -u`"$cobolFile`""
Invoke-Expression $expression

Anyone who might have any insight and could provide some assistance, I would very much appreciate it. Please let me know if I can provide anything else?


Solution

  • Calling external exe's/cmd's via PowerShell requires specific attention. It is a well-documented thing.

    See these details from Microsoft and others: ---

    PowerShell: Running Executables

    1. The Call Operator &
    # Example:
    & 'C:\Program Files\Windows Media Player\wmplayer.exe' "c:\videos\my home video.avi" /fullscreen
    

    Things can get tricky when an external command has a lot of parameters or there are spaces in the arguments or paths!

    With spaces you have to nest Quotation marks and the result it is not always clear!

    In this case it is better to separate everything like so:

    $CMD = 'SuperApp.exe'
    $arg1 = 'filename1'
    $arg2 = '-someswitch'
    $arg3 = 'C:\documents and settings\user\desktop\some other file.txt'
    $arg4 = '-yetanotherswitch'
    
    & $CMD $arg1 $arg2 $arg3 $arg4
    
    # or same like that:
    $AllArgs = @('filename1', '-someswitch', 'C:\documents and settings\user\desktop\some other file.txt', '-yetanotherswitch')
    & 'SuperApp.exe' $AllArgs
    
    1. cmd /c - Using the old cmd shell ** This method should no longer be used with V3

    Why: Bypasses PowerShell and runs the command from a cmd shell. Often times used with a DIR which runs faster in the cmd shell than in PowerShell (NOTE: This was an issue with PowerShell v2 and its use of .Net 2.0, this is not an issue with V3).

    Details: Opens a CMD prompt from within powershell and then executes the command and returns the text of that command. The /c tells CMD that it should terminate after the command has completed. There is little to no reason to use this with V3.

    # Example:
    #runs DIR from a cmd shell, DIR in PowerShell is an alias to GCI. This will return the directory listing as a string but returns much faster than a GCI
    cmd /c dir c:\windows
    

    Using Windows PowerShell to run old command line tools (and their weirdest parameters)

    Solution 2A: Use CMD /C

    As with the first problem, you can run CMD.EXE itself and pass your command and its parameters in quotes. Efficiency aside, this will work fine, since PowerShell will not try to parse the string in quotes.

    CMD.EXE /C "ICACLS.EXE C:TEST /GRANT USERS:(F)"
    
    <#
    # Results
    
    processed file: C:TEST
    Successfully processed 1 files; Failed processing 0 files
    #>
    

    ..there are more like these.