At Tech Ed in Orlando last week John Waters picked up "Windows PowerShell Unleashed by Tyson Kopczynski" and as John has a eye for cool technology I did likewise and got hooked on PowerShell. I'm not usually a live-on-the-command-line-love-batch-files kind of guy but PowerShell covers enough ground in a powerful and consistent way that I'm considering adding this to my technology toolbox. Although PowerShell is intended for system administrator use, there may be a place for PowerShell in development to do limited testing against .NET objects, task automatation and general exploration. In any case it's a great toy and a hoot to play with.
PowerShell has several important differences from cmd.exe.
- PowerShell lets you use NET FCL objects, COM objects and even your own .NET classes.
- PowerShell scripts can be code signed (see Windows PowerShell Unleashed by Tyson Kopczynski for detailed steps). Previous scripting environments like Windows Scripting Host (WSH) opened large security holes. This feature allows scripts from trusted sources to be run.
- PowerShell is object based, not text based. This eliminates parsing and reformatting to use the output from a command.
- PowerShell provides a consistent interface.
- You can navigate through files, the certificate store, environmental variables and the registry, all using commands you already know.
- Commands confirm to the pattern verb-name, i.e. "get-service" to cut down on memorization. There are aliases for historic DOS and UNIX commands so you can list a directory with the PowerShell native "get-childitem", UNIX style "ls" or DOS "dir".
- PowerShell lets you locate and interrogate available commands and objects.
- PowerShell is extensible. You can create your own commands in a .NET assembly and register them for use in PowerShell. There are several other points of extensibility including providers for navigation, types and formatting.
Here's a sample session of PowerShell to give you a very brief notion of how it works. Be aware that this is only scratching the surface of the possibilities for PowerShell. Let's say we want to work with Windows services, so we need to know what commands are available:
PS C:\Clients\Falafel\Projects\FalafelCmdletLibrary\bin\Debug> get-command *service
CommandType Name Definition
----------- ---- ----------
Cmdlet Get-Service Get-Service [[-Name] <String[]>] [-Include <Stri...
Cmdlet New-Service New-Service [-Name] <String> [-BinaryPathName] <...
Cmdlet Restart-Service Restart-Service [-Name] <String[]> [-Force] [-Pa...
Cmdlet Resume-Service Resume-Service [-Name] <String[]> [-PassThru] [-...
Cmdlet Set-Service Set-Service [-Name] <String> [-DisplayName <Stri...
Cmdlet Start-Service Start-Service [-Name] <String[]> [-PassThru] [-I...
Cmdlet Stop-Service Stop-Service [-Name] <String[]> [-Force] [-PassT...
Cmdlet Suspend-Service Suspend-Service [-Name] <String[]> [-PassThru] [...
From here we can see what services are available for SQL Server:
PS C:\Clients\Falafel\Projects\FalafelCmdletLibrary\bin\Debug> get-service MSSQL*
Status Name DisplayName
------ ---- -----------
Running MSSQL$NRLAPTOP2 MSSQL$NRLAPTOP2
Running MSSQL$SQLEXPRESS SQL Server (SQLEXPRESS)
Running MSSQL$TELERIK MSSQL$TELERIK
Running MSSQLSERVER SQL Server (MSSQLSERVER)
Stopped MSSQLServerADHe... SQL Server Active Directory Helper
Running MSSQLServerOLAP... SQL Server Analysis Services (MSSQL...
Now we want to stop the MSSQLSERVER service and any dependant services:
PS C:\Clients\Falafel\Projects\FalafelCmdletLibrary\bin\Debug> stop-service "MSSQLSERVER" -force
If we re-run get-service we can see that the service is stopped:
PS C:\Clients\Falafel\Projects\FalafelCmdletLibrary\bin\Debug> get-service mssql*
Status Name DisplayName
------ ---- -----------
Running MSSQL$NRLAPTOP2 MSSQL$NRLAPTOP2
Running MSSQL$SQLEXPRESS SQL Server (SQLEXPRESS)
Running MSSQL$TELERIK MSSQL$TELERIK
Stopped MSSQLSERVER SQL Server (MSSQLSERVER)
Stopped MSSQLServerADHe... SQL Server Active Directory Helper
Running MSSQLServerOLAP... SQL Server Analysis Services (MSSQL...
You can also interrogate the service objects using the get-member command. For example you could take the service objects returned by get-service and direct them to the get-member command using the "|" pipe symbol. The following is only a partial listing.
PS C:\Clients\Falafel\Projects\FalafelCmdletLibrary\bin\Debug> get-service | get-member
TypeName: System.ServiceProcess.ServiceController
Name MemberType Definition
---- ---------- ----------
Name AliasProperty Name = ServiceName
Close Method System.Void Close()
Continue Method System.Void Continue()
CreateObjRef Method System.Runtime.Remoting.ObjRef CreateObjRef(Type requestedType)
Dispose Method System.Void Dispose()
Equals Method System.Boolean Equals(Object obj)
ExecuteCommand Method System.Void ExecuteCommand(Int32 command)
get_DependentServices Method System.ServiceProcess.ServiceController[] get_DependentServices()
get_DisplayName Method System.String get_DisplayName()
get_MachineName Method System.String get_MachineName()
get_ServiceHandle Method System.Runtime.InteropServices.SafeHandle get_ServiceHandle()
What about navigation? If I want to change locations in the file system of course there's "CD" or the PS native "set-location". What's unique here is that you can navigate the registry, environmental variables, certificate stores or any other system that PS has a provider for (yes, you can write your own providers). For example the following is perfectly legal:
PS C:\Clients\Falafel\Projects\FalafelCmdletLibrary\bin\Debug> cd env:
PS Env:\> dir
Name Value
---- -----
Path C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\Program Files\ATI Technolo...
TEMP C:\DOCUME~1\NOELRI~1\LOCALS~1\Temp
SESSIONNAME RDP-Tcp#1
PATHEXT .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.PSC1
USERDOMAIN NRLAPTOP
PROCESSOR_ARCHITECTURE x86
You could image using CD to navigate hiearchical database information in this way (to what practical end I do not know, but it is amusing). Find out what PowerShell drives are available on your machine by using get-psdrive:
PS C:\Clients\Falafel\Projects\FalafelCmdletLibrary\bin\Debug> get-psdrive
Name Provider Root CurrentLocation
---- -------- ---- ---------------
Alias Alias
C FileSystem C:\ Clients\Falafel\Projects\FalafelCmdletLibrary\bin\Debug
cert Certificate \
D FileSystem D:\
Env Environment
Function Function
HKCU Registry HKEY_CURRENT_USER
HKLM Registry HKEY_LOCAL_MACHINE
Variable Variable
Use get-psprovider to find the providers on your system. See the MSDN for examples of writing your own provider.
PS C:\Clients\Falafel\Projects\FalafelCmdletLibrary\bin\Debug> Get-PSProvider
Name Capabilities Drives
---- ------------ ------
Alias ShouldProcess {Alias}
Environment ShouldProcess {Env}
FileSystem Filter, ShouldProcess {C, D}
Function ShouldProcess {Function}
Registry ShouldProcess {HKLM, HKCU}
Variable ShouldProcess {Variable}
Certificate ShouldProcess {cert}
You can download PowerShell at http://www.microsoft.com/technet/scriptcenter/topics/msh/download.mspx. It comes with the install and docs for "Getting Started", "Quick Reference" and "Users Guide".