PowerShell running on server core

Aaron Parker saw my presentation on Windows Server 2008 server core earlier this week and it got him thinking…

I said that Microsoft don’t see server core as an application platform but there’s no real reason why not as long as the applications you want to run don’t have dependencies on components that don’t exist in server core. I even suggested that, with a reduced surface attack area and less patching required, server core is a great platform for those applications that don’t rely on the shell, Internet Explorer, the .NET Framework or anything else that has been removed.

I also mentioned that PowerShell doesn’t run on server core because it relies on the .NET Framework.

So Aaron used SoftGrid to repackage the Microsoft .NET Framework and Windows PowerShell for server core – and it worked! He says there are a few errors, but as a proof of concept it’s a great idea – and a good demonstration of how flexible application virtualisation can be.

Controlling Virtual Server 2005 R2 using Windows PowerShell

One of my jobs involves looking after a number of demonstration and line of business servers running (mostly) on Virtual Server 2005 R2. Because I’m physically located around 90 miles away from the servers and I have no time allocated to managing the infrastructure, I need to automate as much as possible – which means scripting. The problem is that my scripting abilities are best described as basic. I can write batch files and I can hack around with other people’s scripts – that’s about it – but I did attend a Windows PowerShell Fundamentals course a few weeks back and really enjoyed it, so I decided to write some PowerShell scripts to help out.

Virtual Server 2005 R2 has a Component Object Model (COM) API for programmatic control and monitoring of the environment (this is what the Virtual Server Administration web interface is built upon). For a quick introduction to this API, Microsoft has an on-demand webcast (recorded in December 2004), where Robert Larson explained using the Virtual Server COM API to create scripts to automate tasks like virtual machine (VM) creation, configuration, enumeration, and provisioning VMs.

The Virtual Server COM API has 42 interfaces and hundreds of calls; however the two key interfaces are for virtual machines (IVMVirtualMachine) and the Virtual Server service (IVMVirtualServer). Further details can be found in the Programmers Guide (which is supplied with Virtual Server) and there is a script repository for Virtual Server available on the Microsoft TechNet website.

Because the scripting model is based on COM, developers are not tied to a specific scripting language. This means that, theoretically, Windows PowerShell can be used to access the COM API (although in practice, my PowerShell scripts for Virtual Server are very similar to their VBScript equivalents).

Every script using the Virtual Server COM API needs to initiate the VirtualServer.Application object. For Visual Basic, this would mean calling:

Set objVS=CreateObject("VirtualServer.Application)

Because I want to use PowerShell, I have to do something similar; however there is a complication – as Ben Armstrong explains in his post on controlling Virtual Server through PowerShell, PowerShell is a Microsoft.NET application and as such does not have sufficient priviledges to communicate with the Virtual Server COM interfaces. There is a workaround though:

  1. Compile the C# code that Ben supplies on his blog to produce a dynamic link library (.DLL) that can be used to impersonate the COM security on the required object (I initially had some trouble with this but everything was fine once I located the compiler). I placed the resulting VSWrapperForPSH.dll file in %userprofile%\Documents\WindowsPowerShell\
  2. Load the DLL into PowerShell using [System.Reflection.Assembly]::loadfrom("%userprofile%\Documents\WindowsPowerShell\VSWrapperForPSH.dll") > $null (I do this in my %userprofile%\Documents\WindowsPowerShell\profile.ps1 file as Ben suggests in his follow-up post on PowerShell tweaks for controlling Virtual Server).
  3. After creating each object using the Virtual Server COM API (e.g. $vs=New-Object –com VirtualServer.Application –Strict), set the security on the object with [Microsoft.VirtualServer.Interop.PowerShell]::SetSecurity($vs). Again, following Ben Armstrong’s advice, I do this with a PowerShell script called Set-Security.ps1 which contains the following code:


    Then, each time I create a new object I call set-security($objectname)

Having got the basics in place, it’s fairly straightforward to manipulate the COM objects in PowerShell and I followed Ben’s examples for listing registered VMs on a given host, querying guest operating system information and examining .VHD files. I then spent quite a lot of time writing a script which will output all the information on a given virtual machine but although it was an interesting exercise, I’m not convinced it has much value. What I did learn was that:

  • Piping objects through Get-Member is can be useful for understanding the available methods and properties.
  • Where a collection is returned (e.g. the NetworkAdapters property on a virtual machine object), individual items within the collection can be accessed with .item($item) and a count of the number of items within a collection can be obtained with .count, for example:


    $vs=New-Object -com VirtualServer.Application -strict


    Write-Host $vm.Name "has" $dvdromdrives.count "CD/DVD-ROM drives"

Of course, System Center Virtual Machine Manager (SCVMM) includes it’s own PowerShell extensions and therefore makes all of this work totally unnecessary but at least it’s an option for those who are unwilling or unable to spend extra money on SCVMM.

How Windows PowerShell exposes passwords in clear text

I’m attending a two-day Windows PowerShell course, delivered by my colleague Dave – who I know reads this blog and should really think about starting his own…

I’ve written before about Windows PowerShell (twice) and I think it’s a great product, but it is a version 1.0 product and as such it has some faults. One (which I was horrified to discover today) is that this product, which is intended to be secure by default (for a number of good reasons) has the ability to store user credentials in clear text!

All it takes is two lines of PowerShell script:

$cred=get-credential username

(the user wil then be prompted for their password using a standard Windows authentication dialog)


(the username, password and domain will be displayed in clear text)

Some people ask what’s wrong with this? After all there are legitimate reasons for needing to use credentials in this manner. That may be so but one of the fundamental principles of Windows security is that passwords are never stored in clear-text – only as a hashed value – clearly this breaks that model. Those who think there is nothing wrong with this argue that the credentials are then only used by the user that entered them in the first place. Even so, I’m sure this method could easily be used as part of a phishing attempt using a fake (or altered) script (digitally signing scripts may be the default configuration but many organisations will disable this, just as they do with signed device drivers and many othe security features).

After searching Microsoft Connect and being surprised that I couldn’t find any previous feedback on this I’ve raised the issue as a bug but expect to see it closed as “Resolved – by design” within a few days. If it really is by design, then I don’t feel that it’s a particularly smart design decision – especially as security is tauted as one of the key reasons to move from VBscript to PowerShell.

Windows PowerShell for IT administrators

“Go away or I will replace you with a very small shell script”

[T-shirt slogan from an attendee at tonight’s Windows PowerShell for IT administrators event.]

I’m back in my hotel room having spent the evening at one of Microsoft UK’s TechNet events and this time the topic was Windows PowerShell for IT administrators. I’ve written previously about PowerShell (back when it was still a beta, codenamed Monad) but tonight’s event was presented by Richard Siddaway from Perot Systems, who is not only an experienced infrastructure architect but also leads the PowerShell UK user group and thinks that PowerShell is one of the best pieces of technology ever (maybe a touch OTT but it is pretty powerful).

The event was demo-heavy and I didn’t grab all of the example commands (Richard plans to publish them on the user group website this week) so this post concentrates on what PowerShell can (and can’t) do and I’ll link to some more examples later.

What is PowerShell?
According to Microsoft, PowerShell is the next generation shell for Windows that is:

  • As interactive and composable as BASH/KSH.
  • As programmable as Perl/Ruby.
  • As production-oriented as AS400 CL/VMS DCL.

In addition to the attributes described above, PowerShell is extensible with snapins, providers and scripts. The provider model allows easy access to data stores (e.g. registry, Active Directory, certificate store), just as if they were a file system.

Scripting is accomodated in various forms, including text (Microsoft’s interpretation of the traditional Unix scripting model), COM (WSH/VBScript-style scripting), Microsoft.NET or commands (PowerShell cmdlets, emitting Microsoft .NET-based objects). As for the types of data that PowerShell can manipulate – it’s extensive, including flat files (CSV, etc.), .NET objects, XML (cmdlets and .NET), WMI, ADSI, ADO/ADO.NET and SQL.

So, PowerShell is a scripting interface with a heavy interface on Microsoft.NET – are programming skills required?
Not really. As Richard described, just because you can use native .NET code doesn’t mean that you should; however the more that you know, the more you can do with PowerShell.

Basically, simple scripts will need some .NET functions such as [STRING] and [MATH] and advanced scripts can use any .NET object but cmdlets provide an excellent administrative and scripting experience and are easier to work with – writing .NET code can be thought of as a safety net for when something isn’t possible using another method, rather than as a first port of call.

Where can I get PowerShell?
Although it a core element of the Windows Server System, providing automation and integration capabilities across the various technology platforms, PowerShell is a separate download for Windows XP (SP2)/Server 2003 (SP1 or later, including R2)/Vista and will be included within Windows Server 2008. Note that PowerShell is not supported on Windows 2000.

How can I learn to use PowerShell?
PowerShell’s documentation includes a getting started guide, a user guide, a quick reference guide and help text. Microsoft Switzerland has also produced a short Windows PowerShell book that’s available for download free of charge, there are plenty of other books on the subject and a “young but keen” community of administrators exists who are discovering how PowerShell can be put to use; however it’s probably best to just get stuck in – practice some ad-hoc development:

  • Try things out in an interactive shell.
  • Stitch things together with utilities and put the results in a script file (then realise that the tools are unsuitable and restart the process).
  • Once happy with the basic concepts, generalise the code (e.g. parameterise it) and clean it up (make it production-quality).
  • Once tested, integrate the PowerShell scripts with the infrastructure to be managed and then share scripts with the community.

One more thing – remember that it’s better to have many small scripts that each do one thing well than to have a behomoth of a script that’s very inflexible.

Is there anything else I should know before getting started?
There are a few concepts that it’s worth getting to grips with before launching into PowerShell:

  • Cmdlets are a great way to get started with PowerShell. Based on a verb-noun naming, they each provide specific functionality (e.g. get-help and make the resulting code self-describing (hence suprisingly easy to read).
  • The pipeline (think Unix or MS-DOS) – allows the output of one instruction to be fed into the next using the | symbol; however, unlike Unix/MS-DOS, .NET objects are passed between instructions, not text.
  • There is a text-based help system (cf. man pages on Unix-derived operating systems).
  • PowerShell is not case-sensitive (although tab completion will sometimes capitalise cmdlets and parameters); however it’s worth understanding that whilst double quotes (" ") and single quotes (' ') can be used interchangably, variables enclosed in double-quotes are resolved to their value, whereas the single-quote variant is treated as a variable.

There are also some issues to be aware of:

  • The default installation will not run scripts (not even the user’s profile) and scripts need to be enabled with set-executionpolicy.
  • There is no file association with PowerShell (for security reasons), so scripts cannot be run automatically or via a simple double-click. Scripts do normally use the .ps1 extension and although PowerShell will recognise a command as a script without this, using the extension helps PowerShell to work out what type of instruction is being issued (i.e. a script).
  • There is no capacity for remoting (executing code on a remote system) but workarounds are possible using .NET and WMI.
  • The current working directroy is not on the path (as with Unix-derived operating systems), so scripts are launched with .\scriptname.ps1. Dot sourced scripts (e.g. . . \scriptname.ps1) run in the context of the shell (rather than in their own context).
  • Although PowerShell supports use of the entire Microsoft.NET framework, not all .NET assemblies are loaded – some may need to be specified within a script.

Are there any other tools that work with PowerShell?
Various ISVs are extending PowerShell. Many of the tools are currently available as trial versions although some are (or may become) commercial products. Examples include:

Where can I find out more?
The following links provide more information about PowerShell:

Microsoft’s next generation command shell

Back in June 2004, I got in a panic because I heard that VBScript was about to be phased out. Don Jones commented that VBScript will still be there in Windows, it just won’t be developed any further, then later I heard about the new Microsoft scripting host (MSH) shell (codenamed Monad).

At yesterday’s IT Forum ’05 highlights (part 2) event, Thomas Lee gave a preview of Monad. Although I am enrolled on the Microsoft command shell beta program, pressures of work and family life have left very little time to do anything with it up to now, but having seen Thomas’ demo, I’ve installed MSH beta 3 on my day-to-day notebook computer and will try to use it instead of cmd.exe, regedit.exe and some of my other everyday tools.

Those of us who have worked with Windows since… well since MS-DOS… will remember the command prompt, as will those who use other operating systems. Graphical user interfaces (GUIs) are all very well (and a well designed GUI can be remarkably intuitive), but a command line interface (CLI) is my preference. Despite a whole load of new and powerful commands in recent Windows releases (like netsh.exe), Windows still lags behind Unix in many ways when it comes to command line operations and MSH is an attempt to catch up with, and then exceed, the tools provided by other operating systems.

MSH is a next-generation shell that is intended to:

  • Be as interactive and scriptable as BASH or KSH.
  • Be as programmatic as Perl or Ruby.
  • Be as production-oriented as AS/400 CL or VMS DCL.
  • Allow access to data stores as easily as accessing file systems.

It sounds like a tall order but amazingly, Microsoft seem to have cracked it. MSH is also pretty easy to use and, it’s secure by default, avoiding many of the issues associated with VBScript. So secure, in fact, that before running MSH you may wish to execute the following registry change:

Windows Registry Editor Version 5.00

"Path"="C:\\Program Files\\Microsoft Command Shell\\v1.0\\msh.exe"

(There’s more on MSH security below).

MSH is instantly recognisable. If I was to type cmd, I would be greeted with something similar to the following:

Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.


If I type msh instead, everything is very familiar:

Microsoft Command Shell
Copyright (C) 2005 Microsoft Corporation. All rights reserved.

MSH C:\>

Type dir and guess what happens? For that matter, type ls! If you want to see the contents of a file then either type filename or cat filename will work too. get-history returns a list of commands, to re-run, save, or edit.

Whereas Unix (and Unix-like) systems tend to store configuration in text files, Windows configurations are incredibly complex with multiple data stores (the registry, text files, DNS, Active Directory, etc.). These data stores normally fall into one of two categories: hierarchical, highly recursive data structures (file system directories, registry keys, Active Directory organizational units, etc.) or fairly flat structures (e.g. DNS zones and records). MSH makes them all easy to navigate using a system of data providers.

For example, I can type cd hklm: followed by dir to see all the HKEY_LOCAL_MACHINE keys, navigating the registry as though it were a file system. This simplicity is both elegant and incredibly powerful. There are no AD or DNS providers yet, but the next version of Exchange (codenamed Exchange 12) will include MSH support, treating Exchange databases as just another data store (get-mailbox, etc.). Exchange 12 support is not implemented as a data provider, but as a commandlet (cmdlet), because its data structure is not really hierarchical (at least down to the mailbox level) – the full list of Exchange commands can be found using get-excommand.

For example, if I want to see the details of my system, I can use get-wmiobject command. That’s a bit long to type, so I can actually use get-w and then complete the command with the tab key (as can in cmd.exe these days). get-wmiobject win32_computersystem returns the details of my system as an object with attributes, that I can assign to a variable (e.g. $mysystem=get-wmiobject win32_computersystem). After that, $mysystem.name returns the name of my computer, $mysystem.manufacturer returns Fujitsu Siemens and $mysystem.model returns Lifebook S7010. That would have been so much harder to obtain in VBscript. Take it to the next level and you can see how the data can be queried and actions taken according to the results (e.g. if ($mysystem.model -eq "Lifebook S7010") {"Do something"}).

MSH has built in help (e.g. get-wmiobject -?) and more is no longer an external command so get-wmiobject -? | more works too.

Some commands will return an array of objects, for example get-wmiobject -list. That’s a pretty long and unmanageable list but if I use $wmilist=get-wmiobject -list, I can use $wmilist.length to see how many objects were returned, $wmilist[objectnumber] to view a single object and of course I can also use $wmilist[objectnumber].attributename to refer to a single item.

On a typical Unix system, pipes are used to pass text between commands. Scripts can be used to split strings and extract data (also known as prayer-based parsing, because if the command output is changed, the scripts break). MSH pipes are .NET objects with metadata. That means that a hierarchy of objects can be passed between commands. So, I can also show my WMI array as a table by piping it through format table (ft), i.e. $wmilist | ft (fl is format list).

Having looked at how simple to use, yet powerful, MSH is, let’s look at some of the product specifications:

  • MSH is intended to support a number of different administrative levels:
  • Operators – command line only.
  • Simple scripters – simple sequences, untyped variables and functions with unnamed parameters.
  • Advanced scripters – typed variables and functions with named parameters.
  • Sophisticated scripters – scoped variables, functions with initialised parameters, function cmdlets and scriptblocks.
  • The four administrative levels are supported with different script types:
    • Text – .NET interpretations of the traditional Unix scripting model.
    • COMWindows script host (WSH)/VBScript-style scripting.
    • .NET – for manipulating any native .NET object.
    • Commands – MSH cmdlets emitting objects.
  • These script types are supported with a variety of data types, including .NET, XML, WMI/ADSI and ADO.
  • MSH is intended to be tremendously customisable and it will eventually allow dispense with the style separation between GUI, CLI and systems programming skills so that even an infrastructure bod like me will be able to issue a GUI command (or use a Win32 program) and see what the MSH equivalent command is, so that I can build my own scripts and run a task repeatedly! Unfortunately this GUI-CLI functionality has been dropped from the first release, but hopefully we’ll see it in a service pack later.

    From a security perspective, MSH is extremely secure, with four operational modes:

    • Restricted mode allows interactive operations only, with no script execution.
    • AllSigned mode requires that scripts must be signed by a trusted source.
    • RemoteSigned mode requires that scripts from the Internet must be signed by a trusted source.
    • Unrestricted mode will allow any script to run, but will always warn before remote scripts are executed.

    Other security measures include:

    • No file association for .msh files.
    • The current folder (.) is not on the path by default.

    So when can we get MSH? Beta 3 is available for download now and the final release is expected with Exchange 12. Although MSH will not included with Windows Vista, I’m told that it does work on a Vista/Longhorn platform.

    Finally, for one more example of how easy Monad can be to use, try this:

    "Monad Rocks " * 200

    Thomas Lee’s Monad information centre
    Monad on Channel 9
    Monad product team blog
    MSH on Wikipedia
    microsoft.public.windows.server.scripting newsgroup

    Windows management technologies

    At the Best of the Microsoft Management Summit 2005 event a few weeks back, Vlad Joanavic gave an overview of some of the “free” Windows Management technologies that are available (in addition to the “paid” products under the System Center brand).

    These basically break down into:

    • Windows Software Update Services (WSUS).
    • Windows Management Instrumentation (WMI) and WS-Management.
    • Group Policy Management Console (GPMC).
    • Microsoft Management Console (MMC) v3.0.
    • Windows Installer v3.1
    • Microsoft Scripting Host (codenamed Monad).

    The rest of this post discusses each of these in turn.


    WSUS is Microsoft’s update management offering for corporate customers, effectively allowing customers to host a local copy of Microsoft Update and to manage update approval accordingly. Free to licensed users of Windows 2000 Server and Windows Server 2003 (with appropriate Windows Server/core client access licenses) it is a core component of Microsoft’s patch and update management roadmap.

    Unlike its predecessor, Software Update Services (SUS), WSUS supports more than just Windows updates, and allows selective targeting of computers based on group membership and automatic approval of updates (if required). It also uses a database rather than flat file storage for its configuration data (storage of the actual updates is still file-based) and offers a much richer user experience. At the time of writing, WSUS supports 8 types of update for a number of products (with more to be added over time). WSUS is also localised to provide for international support and has multi-language user interface (MUI) support.

    WSUS does not require a new client component to be installed as the automatic updates client within Windows XP is self-updating. Most client functionality is implemented via a Win32 service with an extensible architecture for MSI, update.exe and driver handling and automatic updates can also be controlled via group policy.

    WSUS servers uses the background intelligent transfer service (BITS) to ensure that the network is utilised effectively during the transfer of updates. Microsoft recognises a number of WSUS deployment options:

    • Single server – for small organisations or simple networks.
    • Multiple servers – for a large organisations or a complex network, allowing a hierarchy of WSUS servers to be created.
    • Disconnected network (e.g. on a ship), whereby updates are downloaded to one WSUS server and then exported for transfer via removable media (e.g. DVD) to a disconnected WSUS server which validates the Microsoft certificates on the content and services clients on the remote network.

    WMI and WS-Management

    WMI is the Microsoft implementation of web based enterprise management (WBEM)/common interface model (CIM), allowing access to over 600 WMI classes and 3000 properties. Provided as a standard Windows component since Windows 2000 (and downloadable for Windows NT 4.0), the number of WMI providers has grown from 15 in Windows NT to 29 in Windows 2000 and 80 in Windows Server 2003. WMI supports a variety of clients including the Windows Script Host (WSH), native C++ and managed code using any language supported by the Microsoft.NET Framework. It also supports command line operations (WMIC) and DCOM-based remoting.

    The goal of WMI is to provide a single API for access to large volumes of system data. WMI providers expose data from content sources; this information is placed into a repository, and WMI consumers (e.g. applications and scripts) consume this data.

    I previously blogged about web services (WS-*) and WS-Management is a joint effort to provide a WS-* protocol for interoperable management. Implemented as a web service, WS-Management is XML/SOAP-based and runs over HTTPS to access most existing WMI objects. WS-Management also allows for out of band access (i.e. when there is no operating system installed, or the operating system has crashed) to service processors (e.g. remote management hardware). In-band access provides a richer set of capabilities, specifically for software management.

    The first version of WS-Management will ship as part of Windows Server 2003 R2, with access to hardware instrumentation, HTTPS access to Windows instrumentation and a command line functionality (WSMAN).


    I’ve blogged previously about the GPMC but even though it has been available for a couple of years now, it seems that many administrators still do not use it. I’m not sure why (I guess it’s because it is a separate download), but GPMC represents a huge step forward in the management of group policies and I find the ability to create XML/HTML-based group policy object (GPO) reports a significant advantage in documenting group policy (much better than trying to capture it in a set of Excel spreadsheets).

    Many of the GPMC tasks are scriptable, including:

    • Creating/deleting/renaming GPOs.
    • Linking GPOs and WMI filters.
    • Delegation of:
      • Security on WMI filters.
      • GPO-related security on sites, domains and organizational units (OUs).
      • Creation rights for GPOs and WMI filters.
    • Generating reports of GPO settings and resultant set of policy (RSOP) data.
    • GPO backup/restoration/import/export/copy/paste/search.

    MMC v3.0

    MMC v3.0 (previously known as MMC v2.1) is intended to offer a number of benefits:

    • More reliable (recognising the issues related to loading third party code such as MMC snap-ins into a core process) through improved detection and reporting of snap-in problems and an ability to isolate hung snap-ins from the console (new snap-ins only).
    • Improved usability with an asynchronous UI model, simpler console customisation and discoverability of actions (including sub-panes providing actions for a selected tree node and item, along with a helpful description).
    • Richer snap-ins with simplified customisation, template-base snap-in design, and functionally rich views.

    Windows Installer v3.1

    Windows Installer (.MSI) v3.0 shipped with Windows XP service pack 2 (and v3.1 is the latest version, as described in Microsoft knowledge base article 893803). Whilst it does not support Windows 95, 98, ME or NT, Windows Installer offers:

    • Improved logging.
    • Scripting objects.
    • Sourcelist API enhancements.
    • Enhanced inventory API.
    • Command line switches.
    • Enhanced patching.
    • New software development kit (SDK) tools and documentation updates.

    Microsoft Scripting Host/Monad

    Monad is a new command shell for Windows, designed to address some of the problems associated with the existing Windows shell, i.e. a weak “language” and sporadic command line coverage, combined with a GUI that is difficult to automate. Monad provides command-oriented scripting capabilities for administrators and systems integrators, including an integrated shell, “commandlets”, new utilities and a scripting language. Wikipedia has a good description the MSH shell including links to additional resources.

    Batch file command reference

    Even though modern versions of Windows have rich scripting capabilities I regularly find myself writing batch (.bat) or command (.cmd) files for automating system tasks, sometimes during migrations from older versions of MS-DOS or Windows which do not have the same command set. I generally consider my batch file writing skills to be pretty good, but I have found the Computer Hope Batch File Help website to be a useful resource for checking syntax between different operating system versions.

    Creating files of a predetermined size

    In order to test FTP file transfers across a newly installed network connection, I needed to create some files of a predetermined size (e.g. 512Kb). The easiest method I found was to run a command that writes out six characters each time it loops (plus two more bytes – a carriage return and a line feed):

    @FOR /L %x IN (1,8,524288) DO @echo xxxxxx>>512kb.txt

    This increments a counter by 8 each time it loops starting at 1 and ending at 524288, appending to a file called 512kb.txt. To change the file size, change 524288 to another number (divisible by 8) and the output filename to something more suitable.

    Avoiding using hard-coded pathnames in scripts

    Another gem gained from my anonymous colleague is the use of the %0 environment variable (which returns the current command name in the same way as %1, %2, etc. return any arguments passed to the command) to avoid using hard coded paths in scripts. For example, %0\..\ refers to the directory in which the file is located, and can be used where a pathname is required, but the drive letter may vary, e.g. %0\..\scripts\ (where the scripts folder could be on any available drive, but always the same drive as the calling command).

    Scripting the deletion of registry keys and values

    One of my colleagues (who wishes to remain anonymous) gave me a great tip this morning – how to delete registry keys and values using a .REG file.

    To delete a value, set its contents to – in the .REG file, e.g.


    Or to delete a key, add a – sign after the leading [ in the .REG file, e.g. [-HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\MyKey]

    Apparently this works on all version of Windows from Windows 2000 onwards, although I’ve only tried it with Windows XP Professional.