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>