| 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 : 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>