Figure 1   WSH 2.0 Features

Feature
Description
WS file format
An XML-based file format that lets you describe a WSH script in a more general and language-independent way.
Include files
A feature of the WS file format to include external files written in any script language with a WS-compatible engine.
Support for multiple engines
Lets you add blocks of script code in any language. Allows you to make calls to JScript functions from VBScript and vice versa.
Support for multiple jobs
Any WS file can contain more batch jobs, where a job is basically a task accomplished through script code.
Tools support
Since it's XML-based, existing tools like Visual InterDev can work with the file format and provide IntelliSense on the WS file.
Type library access
You can import constants from type libraries, saving yourself from time-consuming declarations of dozens of constants.
Shell drag and drop
The ability to drop files over VBScript or JScript and have them get those file names as arguments.
Keystrokes to applications
The ability to send keystrokes to Windows applications.
Pausing scripts
A new method that lets you stop a script for the specified number of milliseconds.
Standard I/O
A new method to access the stdout, stdin, and stderr I/O standard devices.
Adding printers
A new method to add a new printer to the system.


Figure 2   Script Blocks


 <job>
 
 <script language="VBScript">
 Function ShowMessage(s)
    MsgBox s
 End Function
 </script>
 
 <script language="JScript">
 function EvalCode(s) // This block is never used
 {
    eval(s);
 }
 </script>
 
 <script language="VBScript">
 ShowMessage "Hello, world"  
 </script>
 
 </job>

Figure 3   XML Compliance


 <?XML version="1.0" ?>
 <job>
 
 <script language="VBScript">
 Function ShowMessage(s)
 ' A commented line that originates an error!
 ' MsgBox "The message is " & s
 End Function
 </script>
 
 <script language="JScript">
 function EvalCode(s) 
 {
    eval(s);
 }
 </script>
 
 <script language="VBScript">
 ShowMessage "Hello, world"  
 </script>
 
 </job>

Figure 5   New Command-line Switches

Switch
Description
//B
Runs the script in a batch, noninteractive mode. All message boxes, and anything else that requires the user to intervene, are suppressed.
//E:vbscript or E:jscript
Sets the script engine to be used to run the specified script file.
//D
Turns the debugger on.
//X
Launches the program in the debugger.
//Job:ID
Launches the specified job from the .ws file.


Figure 7   Checking the Shell Version


 ' ShellVer.vbs
 ' Verify whether the PC that run this file has the Active Desktop
 ' Shell Update installed. (This means that the version of shell32.dll
 ' must be 4.71 or higher.)
 ' --------------------------------------------------------------------
 
 Dim prgName
 prgName = "c:\windows\system\shell32.dll"
 
 Dim fso 
 Set fso = CreateObject("Scripting.FileSystemObject")
 
 ' Split the string into its numeric components
 ver = fso.GetFileVersion(prgName)
 aVersion = split(ver, ".")
 
 ' Compares against 4.71
 major = aVersion(0)
 minor = aVersion(1)
 
 Dim net
 set net = CreateObject("WScript.Network")
 pcName = net.ComputerName 
 
 if (major >= 4) and (minor >= 71) then
   MsgBox pcName & " is running the Active Desktop shell update.",,ver
 else
    MsgBox "Sorry, but the Active Desktop isn't installed.",,ver
 end if

Figure 8   New Object Model Features

Method/Property
Object
Description
AddWindowsPrinterConnection
WshNetwork
Installs a new printer in the Printers folder.
AppActivate
WshShell
Activates the application whose main window has the specified title.
LogEvent
WshShell
Writes a message to the Windows NT Event viewer.
SendKeys
WshShell
Sends keystrokes to another application.
BuildVersion
WScript
Returns the build number of WScript.
ConnectObject
WScript
Starts receiving events from a certain instance of a certain object.
StdErr
WScript
Returns a TextStream representing the stderr device.
StdIn
WScript
Returns a TextStream representing the stdin device.
StdOut
WScript
Returns a TextStream representing the stdout device.
Sleep
WScript
Pauses a script for the specified number of milliseconds.
Timeout
WScript
Sets/returns the timeout in seconds for the script.


Figure 9   Importing VBScript Classes


 <job>
 
 <!-- Demonstrates importing a VBScript class --> 
 
 <script language="VBScript" src="TickCounter.vbs" />
 
 <script language="VBScript">
 Dim t
 Set t = new TickCounter
 With t
    .IntervalType = "s"
    .Start
    WScript.Sleep(2000)
    MsgBox .StopIt
 End With
 
 </script>
 </job>

Figure 10   SendKeys

SendKeys.h


/* this ALWAYS GENERATED file contains the definitions for the interfaces */


/* File created by MIDL compiler version 5.01.0164 */
/* at Tue Jun 29 19:53:29 1999
 */
/* Compiler settings for D:\Articles\Microsoft Internet Developer\Windows Script Host 2.0
   \Source\SendKeys\SendKeys.idl:
    Oicf (OptLev=i2), W1, Zp8, env=Win32, ms_ext, c_ext
    error checks: allocation ref bounds_check enum stub_data 
*/
//@@MIDL_FILE_HEADING(  )


/* verify that the <rpcndr.h> version is high enough to compile this file*/
#ifndef __REQUIRED_RPCNDR_H_VERSION__
#define __REQUIRED_RPCNDR_H_VERSION__ 440
#endif

#include "rpc.h"
#include "rpcndr.h"

#ifndef __RPCNDR_H_VERSION__
#error this stub requires an updated version of <rpcndr.h>
#endif // __RPCNDR_H_VERSION__

#ifndef COM_NO_WINDOWS_H
#include "windows.h"
#include "ole2.h"
#endif /*COM_NO_WINDOWS_H*/

#ifndef __SendKeys_h__
#define __SendKeys_h__

#ifdef __cplusplus
extern "C"{
#endif 

/* Forward Declarations */ 

#ifndef __IExtKey_FWD_DEFINED__
#define __IExtKey_FWD_DEFINED__
typedef interface IExtKey IExtKey;
#endif     /* __IExtKey_FWD_DEFINED__ */


#ifndef __ExtKey_FWD_DEFINED__
#define __ExtKey_FWD_DEFINED__

#ifdef __cplusplus
typedef class ExtKey ExtKey;
#else
typedef struct ExtKey ExtKey;
#endif /* __cplusplus */

#endif     /* __ExtKey_FWD_DEFINED__ */


/* header files for imported files */
#include "oaidl.h"
#include "ocidl.h"

void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t);
void __RPC_USER MIDL_user_free( void __RPC_FAR * ); 

#ifndef __IExtKey_INTERFACE_DEFINED__
#define __IExtKey_INTERFACE_DEFINED__

/* interface IExtKey */
/* [unique][helpstring][dual][uuid][object] */ 


EXTERN_C const IID IID_IExtKey;

#if defined(__cplusplus) && !defined(CINTERFACE)
    
    MIDL_INTERFACE("6569AB2D-2E58-11D3-B17C-00C0DFE39736")
    IExtKey : public IDispatch
    {
    public:
        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Send( 
            /* [in] */ long keyCode) = 0;
        
    };
    
#else     /* C style interface */

    typedef struct IExtKeyVtbl
    {
        BEGIN_INTERFACE
        
        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )( 
            IExtKey __RPC_FAR * This,
            /* [in] */ REFIID riid,
            /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject);
        
        ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )( 
            IExtKey __RPC_FAR * This);
        
        ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )( 
            IExtKey __RPC_FAR * This);
        
        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetTypeInfoCount )( 
            IExtKey __RPC_FAR * This,
            /* [out] */ UINT __RPC_FAR *pctinfo);
        
        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetTypeInfo )( 
            IExtKey __RPC_FAR * This,
            /* [in] */ UINT iTInfo,
            /* [in] */ LCID lcid,
            /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo);
        
        HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetIDsOfNames )( 
            IExtKey __RPC_FAR * This,
            /* [in] */ REFIID riid,
            /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
            /* [in] */ UINT cNames,
            /* [in] */ LCID lcid,
            /* [size_is][out] */ DISPID __RPC_FAR *rgDispId);
        
        /* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Invoke )( 
            IExtKey __RPC_FAR * This,
            /* [in] */ DISPID dispIdMember,
            /* [in] */ REFIID riid,
            /* [in] */ LCID lcid,
            /* [in] */ WORD wFlags,
            /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
            /* [out] */ VARIANT __RPC_FAR *pVarResult,
            /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
            /* [out] */ UINT __RPC_FAR *puArgErr);
        
        /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Send )( 
            IExtKey __RPC_FAR * This,
            /* [in] */ long keyCode);
        
        END_INTERFACE
    } IExtKeyVtbl;

    interface IExtKey
    {
        CONST_VTBL struct IExtKeyVtbl __RPC_FAR *lpVtbl;
    };

    
#ifdef COBJMACROS


#define IExtKey_QueryInterface(This,riid,ppvObject)    \
    (This)->lpVtbl -> QueryInterface(This,riid,ppvObject)

#define IExtKey_AddRef(This)    \
    (This)->lpVtbl -> AddRef(This)

#define IExtKey_Release(This)    \
    (This)->lpVtbl -> Release(This)


#define IExtKey_GetTypeInfoCount(This,pctinfo)    \
    (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo)

#define IExtKey_GetTypeInfo(This,iTInfo,lcid,ppTInfo)    \
    (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo)

#define IExtKey_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)    \
    (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId)

#define IExtKey_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,
    pExcepInfo,puArgErr)    \
    (This)->lpVtbl -> 
Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr)


#define IExtKey_Send(This,keyCode)    \
    (This)->lpVtbl -> Send(This,keyCode)

#endif /* COBJMACROS */


#endif     /* C style interface */


/* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IExtKey_Send_Proxy( 
    IExtKey __RPC_FAR * This,
    /* [in] */ long keyCode);


void __RPC_STUB IExtKey_Send_Stub(
    IRpcStubBuffer *This,
    IRpcChannelBuffer *_pRpcChannelBuffer,
    PRPC_MESSAGE _pRpcMessage,
    DWORD *_pdwStubPhase);


#endif     /* __IExtKey_INTERFACE_DEFINED__ */


#ifndef __SENDKEYSLib_LIBRARY_DEFINED__
#define __SENDKEYSLib_LIBRARY_DEFINED__

/* library SENDKEYSLib */
/* [helpstring][version][uuid] */ 

typedef /* [public] */ 
enum __MIDL___MIDL_itf_SendKeys_0209_0001
    {    PRINTSCREEN    = 0x1,
    CTRLESC    = 0x2,
    ALTPRINTSCREEN    = 0x3
    }    SpecialKeys;


EXTERN_C const IID LIBID_SENDKEYSLib;

EXTERN_C const CLSID CLSID_ExtKey;

#ifdef __cplusplus

class DECLSPEC_UUID("6569AB2E-2E58-11D3-B17C-00C0DFE39736")
ExtKey;
#endif
#endif /* __SENDKEYSLib_LIBRARY_DEFINED__ */

/* Additional Prototypes for ALL interfaces */

/* end of Additional Prototypes */

#ifdef __cplusplus
}
#endif

#endif
SendKeys.cpp

// SendKeys.cpp : Implementation of DLL Exports.


// Note: Proxy/Stub Information
//      To build a separate proxy/stub DLL, 
//      run nmake -f SendKeysps.mk in the project directory.

#include "stdafx.h"
#include "resource.h"
#include <initguid.h>
#include "SendKeys.h"

#include "SendKeys_i.c"
#include "ExtKey.h"


CComModule _Module;

BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_ExtKey, CExtKey)
END_OBJECT_MAP()

/////////////////////////////////////////////////////////////////////////////
// DLL Entry Point

extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
{
    if (dwReason == DLL_PROCESS_ATTACH)
    {
        _Module.Init(ObjectMap, hInstance, &LIBID_SENDKEYSLib);
        DisableThreadlibrarycalls(hInstance);
    }
    else if (dwReason == DLL_PROCESS_DETACH)
        _Module.Term();
    return TRUE;    // ok
}

/////////////////////////////////////////////////////////////////////////////
// Used to determine whether the DLL can be unloaded by OLE

STDAPI DllCanUnloadNow(void)
{
    return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
}

/////////////////////////////////////////////////////////////////////////////
// Returns a class factory to create an object of the requested type

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
    return _Module.GetClassObject(rclsid, riid, ppv);
}

/////////////////////////////////////////////////////////////////////////////
// DllRegisterServer - Adds entries to the system registry

STDAPI DllRegisterServer(void)
{
    // registers object, typelib and all interfaces in typelib
    return _Module.RegisterServer(TRUE);
}

/////////////////////////////////////////////////////////////////////////////
// DllUnregisterServer - Removes entries from the system registry

STDAPI DllUnregisterServer(void)
{
    return _Module.UnregisterServer(TRUE);
}

Figure 11   Calling a Custom Type Library


<?xml version="1.0" ?>
<job>


<resource id="TEXT">Enter: PrintScreen, StartMenu</resource>

<reference object="SendKeys.ExtKey" version="1.0" />

<object id="shell" progid="WScript.Shell" />
<object id="sk" progid="SendKeys.ExtKey" />


<script language="JScript">
function ShowInMSPaint() {
   shell.run("mspaint.exe");
   shell.AppActivate("untitled - Paint", true)
   WScript.Sleep(100);
   shell.SendKeys("^v{ENTER}", true);
}
</script>


<script language="VBScript">
strCode = InputBox(getResource("TEXT"))

select case strCode
   case "PrintScreen"
      sk.Send PRINTSCREEN
      ShowInMSPaint
   case "StartMenu"
      sk.Send CTRLESC
end select
</script>


</job>