shadowsh: console WSH script for creating "shadow" scripts

Discussion in 'Scripting' started by Alex K. Angelopoulos [Server MVP], Nov 28, 2003.

  1. below is shadowsh.wsf, a script for automatically generating WSH "shadow"
    scripts.

    I use the term "shadow" script for a .CMD or .BAT file which allows you to
    make your WSH scripts function as "proper" console scripts which can handle
    Stdin without problems. Normally, if you just execute a WSH script directly
    by name, your input pipeline breaks - even if cscript is the default host.
    Although this can be fixed by explicitly specifying cscript as the host for
    the script, the normal search path will not be used to hunt down your
    script. This makes it extremely difficult to use WSH scripts for pipeline
    operations in an intuitive and easy fashion.

    This script creates shadow scripts for each WSH file specified on the
    commandline or read from StdIn; the shadow scripts merely launch the script
    explicitly with all arguments passed on untouched.


    ==========================================================

    <?xml version="1.0" encoding="ISO-8859-1" ?>
    <job>
    <runtime>
    <description><![CDATA[
    DESCRIPTION
    Given one or more paths to WSH scripts as arguments or as standard input
    data, this script will generate a "shadowing" CMD script in the same
    directory to allow direct execution of the script as a pipelineable script
    tool.

    LIMITATIONS
    + This script should always be executed with cscript as the host.
    + If the %PATHEXT% environment variable has been modified so that the CMD
    extension comes after the WSH script type you wish to have shadowed, the
    shadow scripts will not work.
    ]]></description>
    <example><![CDATA[
    USAGE SCENARIO
    To create shadow scripts in the current directory and all directories
    underneath it for all files with the .wsf or .vbs extensions, use this:
    dir /s /b *.wsf *.vbs | cscript shadowsh.wsf
    ]]></example>

    <named name="?" helpstring="returns this help message" type="simple"
    required="false"/>
    <named name="A" helpstring="Always create shadow script, whether or not the
    specified script exists" type="string" required="false"/>
    <named name="Y" helpstring="Causes overwrite of pre-existing shadow script
    files. If not specified, files will not be overwritten." type="simple"
    required="false"/>

    <unnamed name="scriptpath" helpstring="one or more scripts to create shadow
    files for." many="true" required="false"/>

    </runtime>

    <object id="fso" progid="Scripting.FileSystemObject"/>
    <reference object="Scripting.FileSystemObject"/>
    <object id="sh" progid="Wscript.Shell"/>

    <script language="VBScript"><![CDATA[
    Option Explicit
    Dim StdIn, StdOut, StdErr, UARGS()
    dim ALWAYS_CREATE, OVERWRITE_CMD
    Main():WScript.Quit(0)

    ' c:\tmp\scr.na
    ' C:\bin\clean.vbs
    Sub Main()
    Script_Initialize true
    ProcessArguments
    dim arg: for each arg in UARGS
    CreateShadow arg
    next
    If UARGS.Count = 0 then
    ' if we didn't have any scripts specified on the command line, read them
    from
    do while not Stdin.AtEndOfStream
    CreateShadow StdIn.ReadLine
    loop
    end if
    end sub

    Sub CreateShadow(byval scriptname)
    if not(FSO.FileExists(scriptname)) or ALWAYS_CREATE then
    StdErr.WriteLine "script not found: " & scriptname
    exit sub
    end if
    dim ShadowPath: ShadowPath = StemNameFromFileSpec(scriptname) & ".cmd"
    dim ShadowCmd: ShadowCmd = "@cscript ""%~dpn0." _
    & FSO.GetExtensionName(scriptname) & """ %*"
    If FSO.FileExists(ShadowPath) and not(OVERWRITE_CMD) then
    StdErr.WriteLine "shadow file found, not overwritten: " & ShadowPath
    exit sub
    end if
    dim file: set file = FSO.OpenTextFile(ShadowPath, ForWriting, True)
    file.Write ShadowCmd
    file.Close
    StdOut.WriteLine "shadow file created: " & ShadowPath
    end sub


    Function StemNameFromFileSpec(byval filespec)
    ' given a filespec as an argument, turns it into a "stem" -
    ' full path to parent directory + the base name.
    StemNameFromFileSpec = FSO.BuildPath( _
    FSO.GetParentFolderName(filespec), FSO.GetBaseName(filespec) )
    end function

    Sub ProcessArguments()
    ' General argument processor template routine.
    ' Insert other handlers below.
    Dim Named, UnNamed, i
    set Named = WScript.Arguments.Named
    Set UnNamed = WScript.Arguments.UnNamed

    If Named.Exists("A") then ALWAYS_CREATE = true else ALWAYS_CREATE = false
    If Named.Exists("Y") then OVERWRITE_CMD = true else OVERWRITE_CMD = false

    ' get unnamed arguments into an array
    redim UARGS(WScript.Arguments.UnNamed.Length - 1)
    for i = 0 to ubound( UARGS )
    UARGS(i) = WScript.Arguments.UnNamed(i)
    next

    End sub

    Sub Script_Initialize(byval bFailOnGUI)
    ' Set up global StdIn, StdOut, StdErr
    if bFailOnGUI and lcase( right(WScript.FullName, 11) ) <> "cscript.exe"
    then
    WScript.Echo "Must be run with cscript as the script host"
    WScript.Arguments.ShowUsage: WScript.Quit 1
    end if
    Set StdIn = WScript.StdIn
    Set StdOut = WScript.StdOut
    Set StdErr = WScript.StdErr
    End Sub

    ]]></script>
    </job>
     
    Alex K. Angelopoulos [Server MVP], Nov 28, 2003
    #1
    1. Advertisements

  2. Alex K. Angelopoulos [Server MVP]

    name Guest

    I can add that you recent attributions flawlessly render

    within a file saved *.xml






     
    name, Nov 29, 2003
    #2
    1. Advertisements

  3. It's nice to see something that actually DOES work according to a standard.
    :)

    I'd be happier if a WSF or WSC also understood custom entities - that would
    make a lot of things much easier to do... :(
     
    Alex K. Angelopoulos [Server MVP], Nov 29, 2003
    #3
  4. below is an UPDATED version of shadowsh.wsf, a script for automatically
    generating WSH "shadow"
    scripts. (Thanks to Tsakalidis EVangelos for pointing out a bug).

    I use the term "shadow" script for a .CMD or .BAT file which allows you to
    make your WSH scripts function as "proper" console scripts which can handle
    Stdin without problems. Normally, if you just execute a WSH script directly
    by name, your input pipeline breaks - even if cscript is the default host.
    Although this can be fixed by explicitly specifying cscript as the host for
    the script, the normal search path will not be used to hunt down your
    script. This makes it extremely difficult to use WSH scripts for pipeline
    operations in an intuitive and easy fashion.

    This script creates shadow scripts for each WSH file specified on the
    commandline or read from StdIn; the shadow scripts merely launch the script
    explicitly with all arguments passed on untouched.

    =================================================

    <?xml version="1.0" encoding="ISO-8859-1" ?>
    <job>
    <runtime>
    <description><![CDATA[
    DESCRIPTION
    Given one or more paths to WSH scripts as arguments or as standard input
    data, this script will generate a "shadowing" CMD script in the same
    directory to allow direct execution of the script as a pipelineable script
    tool.

    LIMITATIONS
    + This script should always be executed with cscript as the host.
    + If the %PATHEXT% environment variable has been modified so that the CMD
    extension comes after the WSH script type you wish to have shadowed, the
    shadow scripts will not work.
    ]]></description>
    <example><![CDATA[
    USAGE SCENARIO
    To create shadow scripts in the current directory and all directories
    underneath it for all files with the .wsf or .vbs extensions, use this:
    dir /s /b *.wsf *.vbs | cscript shadowsh.wsf
    ]]></example>

    <named name="?" helpstring="returns this help message" type="simple"
    required="false"/>
    <named name="A" helpstring="Always create shadow script, whether or not the
    specified script exists" type="string" required="false"/>
    <named name="Y" helpstring="Causes overwrite of pre-existing shadow script
    files. If not specified, files will not be overwritten." type="simple"
    required="false"/>

    <unnamed name="scriptpath" helpstring="one or more scripts to create shadow
    files for." many="true" required="false"/>

    </runtime>

    <object id="fso" progid="Scripting.FileSystemObject"/>
    <reference object="Scripting.FileSystemObject"/>
    <object id="sh" progid="Wscript.Shell"/>

    <script language="VBScript"><![CDATA[
    Option Explicit
    Dim StdIn, StdOut, StdErr, UARGS()
    dim ALWAYS_CREATE, OVERWRITE_CMD
    Main():WScript.Quit(0)

    Sub Main()
    Script_Initialize true
    ProcessArguments
    dim arg: for each arg in UARGS
    CreateShadow arg
    next
    If UBound(UARGS) = 0 then
    ' if we didn't have any scripts specified on the command line,
    ' read them from StdIn
    do while not Stdin.AtEndOfStream
    CreateShadow StdIn.ReadLine
    loop
    end if
    end sub

    Sub CreateShadow(byval scriptname)
    if not(FSO.FileExists(scriptname)) or ALWAYS_CREATE then
    StdErr.WriteLine "script not found: " & scriptname
    exit sub
    end if
    dim ShadowPath: ShadowPath = StemNameFromFileSpec(scriptname) & ".cmd"
    dim ShadowCmd: ShadowCmd = "@cscript ""%~dpn0." _
    & FSO.GetExtensionName(scriptname) & """ %*"
    If FSO.FileExists(ShadowPath) and not(OVERWRITE_CMD) then
    StdErr.WriteLine "shadow file found, not overwritten: " & ShadowPath
    exit sub
    end if
    dim file: set file = FSO.OpenTextFile(ShadowPath, ForWriting, True)
    file.Write ShadowCmd
    file.Close
    StdOut.WriteLine "shadow file created: " & ShadowPath
    end sub


    Function StemNameFromFileSpec(byval filespec)
    ' given a filespec as an argument, turns it into a "stem" -
    ' full path to parent directory + the base name.
    StemNameFromFileSpec = FSO.BuildPath( _
    FSO.GetParentFolderName(filespec), FSO.GetBaseName(filespec) )
    end function

    Sub ProcessArguments()
    ' General argument processor template routine.
    ' Insert other handlers below.
    Dim Named, UnNamed, i
    set Named = WScript.Arguments.Named
    Set UnNamed = WScript.Arguments.UnNamed

    If Named.Exists("A") then ALWAYS_CREATE = true else ALWAYS_CREATE = false
    If Named.Exists("Y") then OVERWRITE_CMD = true else OVERWRITE_CMD = false

    ' get unnamed arguments into an array
    redim UARGS(WScript.Arguments.UnNamed.Length - 1)
    for i = 0 to ubound( UARGS )
    UARGS(i) = WScript.Arguments.UnNamed(i)
    next

    End sub

    Sub Script_Initialize(byval bFailOnGUI)
    ' Set up global StdIn, StdOut, StdErr
    if bFailOnGUI and lcase( right(WScript.FullName, 11) ) <> "cscript.exe"
    then
    WScript.Echo "Must be run with cscript as the script host"
    WScript.Arguments.ShowUsage: WScript.Quit 1
    end if
    Set StdIn = WScript.StdIn
    Set StdOut = WScript.StdOut
    Set StdErr = WScript.StdErr
    End Sub

    ]]></script>
    </job>
     
    Alex K. Angelopoulos [Server MVP], Nov 30, 2003
    #4
  5. Hi Alex,
    Sory but you have reposted the bug.
    The script Is working to my system only if I put :
    *******************************
    If UBound(UARGS) < 0 then
    *******************************
    Tsakalidis G. Evangelos

     
    Tsakalidis G. Evangelos, Nov 30, 2003
    #5
  6. Sheesh. I also found I'd left at least one line long enough for it to wrap
    by accident in most people's email clients...

    One of those days. Here is take # 3 on it..


    =============================================


    <?xml version="1.0" encoding="ISO-8859-1" ?>
    <job>
    <runtime>
    <description><![CDATA[
    DESCRIPTION
    Given one or more paths to WSH scripts as arguments or as standard input
    data, this script will generate a "shadowing" CMD script in the same
    directory to allow direct execution of the script as a pipelineable script
    tool.

    LIMITATIONS
    + This script should always be executed with cscript as the host.
    + If the %PATHEXT% environment variable has been modified so that the CMD
    extension comes after the WSH script type you wish to have shadowed, the
    shadow scripts will not work.
    ]]></description>
    <example><![CDATA[
    USAGE SCENARIO
    To create shadow scripts in the current directory and all directories
    underneath it for all files with the .wsf or .vbs extensions, use this:
    dir /s /b *.wsf *.vbs | cscript shadowsh.wsf
    ]]></example>

    <named name="?" helpstring="returns this help message" type="simple"
    required="false"/>
    <named name="A" helpstring="Always create shadow script, whether or not the
    specified script exists" type="string" required="false"/>
    <named name="Y" helpstring="Causes overwrite of pre-existing shadow script
    files. If not specified, files will not be overwritten." type="simple"
    required="false"/>

    <unnamed name="scriptpath" helpstring="one or more scripts to create shadow
    files for." many="true" required="false"/>

    </runtime>

    <object id="fso" progid="Scripting.FileSystemObject"/>
    <reference object="Scripting.FileSystemObject"/>
    <object id="sh" progid="Wscript.Shell"/>

    <script language="VBScript"><![CDATA[
    Option Explicit
    Dim StdIn, StdOut, StdErr, UARGS()
    dim ALWAYS_CREATE, OVERWRITE_CMD
    Main():WScript.Quit(0)

    Sub Main()
    Script_Initialize true
    ProcessArguments
    dim arg: for each arg in UARGS
    CreateShadow arg
    next
    If UBound(UARGS) < 0 then
    ' if we didn't have any scripts specified on the command line,
    ' read them from StdIn
    do while not StdIn.AtEndOfStream
    CreateShadow StdIn.ReadLine
    loop
    end if
    end sub

    Sub CreateShadow(byval scriptname)
    if not(FSO.FileExists(scriptname)) or ALWAYS_CREATE then
    StdErr.WriteLine "script not found: " & scriptname
    exit sub
    end if
    dim ShadowPath: ShadowPath = StemNameFromFileSpec(scriptname) & ".cmd"
    dim ShadowCmd: ShadowCmd = "@cscript ""%~dpn0." _
    & FSO.GetExtensionName(scriptname) & """ %*"
    If FSO.FileExists(ShadowPath) and not(OVERWRITE_CMD) then
    StdErr.WriteLine "shadow file found, not overwritten: " & ShadowPath
    exit sub
    end if
    dim file: set file = FSO.OpenTextFile(ShadowPath, ForWriting, True)
    file.Write ShadowCmd
    file.Close
    StdOut.WriteLine "shadow file created: " & ShadowPath
    end sub


    Function StemNameFromFileSpec(byval filespec)
    ' given a filespec as an argument, turns it into a "stem" -
    ' full path to parent directory + the base name.
    StemNameFromFileSpec = FSO.BuildPath( _
    FSO.GetParentFolderName(filespec), FSO.GetBaseName(filespec) )
    end function

    Sub ProcessArguments()
    ' General argument processor template routine.
    ' Insert other handlers below.
    Dim Named, UnNamed, i
    set Named = WScript.Arguments.Named
    Set UnNamed = WScript.Arguments.UnNamed

    If Named.Exists("A") then ALWAYS_CREATE = true else ALWAYS_CREATE = false
    If Named.Exists("Y") then OVERWRITE_CMD = true else OVERWRITE_CMD = false

    ' get unnamed arguments into an array
    redim UARGS(WScript.Arguments.UnNamed.Length - 1)
    for i = 0 to ubound( UARGS )
    UARGS(i) = WScript.Arguments.UnNamed(i)
    next

    End sub

    Sub Script_Initialize(byval bFailOnGUI)
    ' Set up global StdIn, StdOut, StdErr
    if bFailOnGUI _
    and lcase( right(WScript.FullName, 11) ) <> "cscript.exe" then
    WScript.Echo "Must be run with cscript as the script host"
    WScript.Arguments.ShowUsage: WScript.Quit 1
    end if
    Set StdIn = WScript.StdIn
    Set StdOut = WScript.StdOut
    Set StdErr = WScript.StdErr
    End Sub

    ]]></script>
    </job>
     
    Alex K. Angelopoulos [Server MVP], Dec 1, 2003
    #6
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.