Monday, June 20, 2005 1:45 PM
bart
Adventures in Monad - part 2
Okay, let's resume where we suspended :-). In the previous Monad adventure episode I've been talking about the concept of cmdlets or "command-lets" as the atomic units of work in the Monad system. Now, let's dive deeper into this stuff and show some examples of working with cmdlets.
Obtaining a list of cmdlets
In RDBMSs you can query the databases on the system using a database itself (the catalog). In a similar fashion there's a cmdlet in Monad to display all of the cmdlets on the system. It's called Get-Command:
MSH> get-command
Command Type Name Definition
------------ ---- ----------
Cmdlet get-command get-command [-Verb String[]] [-Nou...
Cmdlet get-help get-help [[-Name] String] [-Catego...
Cmdlet get-history get-history [[-Id] Int64[]] [[-Cou...
Cmdlet invoke-history invoke-history [[-Id] String] [-Ve...
Cmdlet add-history add-history [[-InputObject] Object...
Cmdlet foreach-object foreach-object [-Process] ScriptBl...
Cmdlet where-object where-object [-ScriptToApply] Scri...
Cmdlet set-mshdebug set-mshdebug [-Trace Int32] [-Step...
Cmdlet add-content add-content [-Path] String[] [-Val...
Cmdlet clear-content clear-content [-Path] String[] [-P...
Cmdlet clear-property clear-property [-Path] String[] [-...
Cmdlet combine-path combine-path [-Path] String[] [-Ch...
Cmdlet convert-path convert-path [-Path] String[] [-Ve...
Cmdlet copy-property copy-property [-Path] String[] [[-...
Cmdlet get-eventlog get-eventlog [-LogName] String [-N...
Cmdlet get-childitem get-childitem [[-Path] String[]] [...
Cmdlet get-content get-content [-Path] String[] [-Rea...
Cmdlet get-property get-property [-Path] String[] [[-P...
Cmdlet get-WMIObject get-WMIObject [-Class] String [[-P...
Cmdlet move-property move-property [-Path] String[] [-D...
Cmdlet get-location get-location [-Provider String[]] ...
Cmdlet set-location set-location [[-Path] String] [-Pa...
Cmdlet push-location push-location [[-Path] String] [-P...
Cmdlet pop-location pop-location [-PassThru] [-StackNa...
Cmdlet new-drive new-drive [-Name] String [-Provide...
Cmdlet remove-drive remove-drive [-Name] String[] [-Pr...
Cmdlet get-drive get-drive [[-Name] String[]] [-Sco...
Cmdlet get-item get-item [-Path] String[] [-Filter...
Cmdlet new-item new-item [-Path] String[] [-Type S...
Cmdlet set-item set-item [-Path] String[] [[-Value...
Cmdlet remove-item remove-item [-Path] String[] [-Fil...
Cmdlet move-item move-item [-Path] String[] [[-Dest...
Cmdlet rename-item rename-item [-Path] String [-Name]...
Cmdlet copy-item copy-item [-Path] String[] [[-Dest...
Cmdlet clear-item clear-item [-Path] String[] [-Forc...
Cmdlet invoke-item invoke-item [-Path] String[] [-Fil...
Cmdlet get-provider get-provider [[-Provider] String[]...
Cmdlet new-property new-property [-Path] String[] [-Pr...
Cmdlet parse-path parse-path [-Path] String[] [-Pare...
Cmdlet test-path test-path [-Path] String[] [-Filte...
Cmdlet get-process get-process [[-ProcessName] String...
Cmdlet stop-process stop-process [-Id] Int32[] [-PassT...
Cmdlet remove-property remove-property [-Path] String[] [...
Cmdlet rename-property rename-property [-Path] String [-P...
Cmdlet resolve-path resolve-path [-Path] String[] [-Cr...
Cmdlet get-service get-service [[-ServiceName] String...
Cmdlet stop-service stop-service [-ServiceName] String...
Cmdlet start-service start-service [-ServiceName] Strin...
Cmdlet suspend-service suspend-service [-ServiceName] Str...
Cmdlet resume-service resume-service [-ServiceName] Stri...
Cmdlet restart-service restart-service [-ServiceName] Str...
Cmdlet set-service set-service [-ServiceName] String ...
Cmdlet new-service new-service [-ServiceName] String ...
Cmdlet set-content set-content [-Path] String[] [-Val...
Cmdlet set-property set-property [-Path] String[] -Pro...
Cmdlet format-list format-list [[-Property] Object[]]...
Cmdlet format-custom format-custom [[-Property] Object[...
Cmdlet format-table format-table [[-Property] Object[]...
Cmdlet format-wide format-wide [[-Property] Object] [...
Cmdlet out-null out-null [-InputObject MshObject] ...
Cmdlet out-default out-default [-InputObject MshObjec...
Cmdlet out-host out-host [-Paging] [-InputObject M...
Cmdlet out-file out-file [-Path] String [[-Encodin...
Cmdlet out-printer out-printer [[-Printer] String] [-...
Cmdlet out-string out-string [-Stream] [-Width Int32...
Cmdlet update-formatdata update-formatdata [-Trace] [-Force...
Cmdlet export-csv export-csv [-Path] String -InputOb...
Cmdlet import-csv import-csv [-Path] String[] [-Verb...
Cmdlet export-alias export-alias [-Path] String [[-Nam...
Cmdlet Invoke-Command Invoke-Command [-Command] String [...
Cmdlet get-alias get-alias [[-Name] String[]] [-Exc...
Cmdlet get-Culture get-Culture [-Verbose] [-Debug] [-...
Cmdlet get-Date get-Date [[-To] DateTime] [-Year I...
Cmdlet get-host get-host [-Verbose] [-Debug] [-Err...
Cmdlet get-member get-member [[-Name] String[]] [-In...
Cmdlet get-UICulture get-UICulture [-Verbose] [-Debug] ...
Cmdlet get-unique get-unique [-InputObject MshObject...
Cmdlet import-alias import-alias [-Path] String [-Scop...
Cmdlet match-string match-string [-Pattern] String[] -...
Cmdlet Measure-Object Measure-Object [-InputObject MshOb...
Cmdlet new-alias new-alias [-Name] String [-Value] ...
Cmdlet new-Timespan new-Timespan [[-From] DateTime] [[...
Cmdlet read-host read-host [[-Prompt] Object] [-Sec...
Cmdlet set-alias set-alias [-Name] String [-Value] ...
Cmdlet set-Date set-Date [-To] DateTime [-DisplayH...
Cmdlet Start-Sleep Start-Sleep [-Seconds] Int32 [-Ver...
Cmdlet tee-object tee-object [-FileName] String [-In...
Cmdlet Time-Expression Time-Expression [[-Expression] Scr...
Cmdlet write-host write-host [[-Object] Object] [-No...
Cmdlet write-progress write-progress [-Activity] String ...
Cmdlet new-object new-object [-TypeName] String [[-A...
Cmdlet select-object select-object [[-Property] Object[...
Cmdlet group-object group-object [[-Property] Object[]...
Cmdlet sort-object sort-object [[-Property] Object[]]...
Cmdlet get-variable get-variable [[-Name] String[]] [-...
Cmdlet new-variable new-variable [-Name] String [[-Val...
Cmdlet set-variable set-variable [-Name] String[] [[-V...
Cmdlet remove-variable remove-variable [-Name] String[] [...
Cmdlet clear-variable clear-variable [-Name] String[] [-...
Cmdlet Write-debug Write-debug [-Message] String [-Ve...
Cmdlet Write-verbose Write-verbose [-Message] String [-...
Cmdlet Write-Error Write-Error [-Message] String [-Ca...
Cmdlet Write-Object Write-Object [-InputObject] Object...
Cmdlet get-tracesource get-tracesource [[-Name] String[]]...
Cmdlet set-tracesource set-tracesource [-Name] String[] [...
Cmdlet trace-expression trace-expression [-Name] String[] ...
Cmdlet get-acl get-acl [[-Path] String[]] [-Audit...
Cmdlet set-acl set-acl [-Path] String[] [-ACLObje...
Cmdlet get-PfxCertificate get-PfxCertificate [-Path] String[...
Cmdlet get-credential get-credential [-Credential] MshCr...
Cmdlet get-AuthenticodeSignature get-AuthenticodeSignature [-Path] ...
Cmdlet set-AuthenticodeSignature set-AuthenticodeSignature [-Path] ...
Cmdlet new-SecureString new-SecureString [-Verbose] [-Debu...
Cmdlet export-SecureString export-SecureString [-SecureString...
Cmdlet import-SecureString import-SecureString [-String] Stri...
MSH>
Quite some stuff, right? Now, Get-Process can be used to limit this list, based on the verb, the noun, or a wildcard:
MSH> get-command -verb set
Command Type Name Definition
------------ ---- ----------
Cmdlet set-mshdebug set-mshdebug [-Trace Int32] [-Step...
Cmdlet set-location set-location [[-Path] String] [-Pa...
Cmdlet set-item set-item [-Path] String[] [[-Value...
Cmdlet set-service set-service [-ServiceName] String ...
Cmdlet set-content set-content [-Path] String[] [-Val...
Cmdlet set-property set-property [-Path] String[] -Pro...
Cmdlet set-alias set-alias [-Name] String [-Value] ...
Cmdlet set-Date set-Date [-To] DateTime [-DisplayH...
Cmdlet set-variable set-variable [-Name] String[] [[-V...
Cmdlet set-tracesource set-tracesource [-Name] String[] [...
Cmdlet set-acl set-acl [-Path] String[] [-ACLObje...
Cmdlet set-AuthenticodeSignature set-AuthenticodeSignature [-Path] ...
MSH> get-command -noun acl
Command Type Name Definition
------------ ---- ----------
Cmdlet get-acl get-acl [[-Path] String[]] [-Audit...
Cmdlet set-acl set-acl [-Path] String[] [-ACLObje...
MSH> get-command *service
Command Type Name Definition
------------ ---- ----------
Cmdlet get-service get-service [[-ServiceName] String...
Cmdlet stop-service stop-service [-ServiceName] String...
Cmdlet start-service start-service [-ServiceName] Strin...
Cmdlet suspend-service suspend-service [-ServiceName] Str...
Cmdlet resume-service resume-service [-ServiceName] Stri...
Cmdlet restart-service restart-service [-ServiceName] Str...
Cmdlet set-service set-service [-ServiceName] String ...
Cmdlet new-service new-service [-ServiceName] String ...
MSH>
Right, there's apparently more to see about cmdlets than what is displayed (look at the ellipsis on the right-hand side). How to show this? The Format-List cmdlet should be your friend in this kind of scenarios:
MSH> get-command get-service | format-list
Name : get-service
CommandType : Cmdlet
Definition : get-service [[-ServiceName] String[]] [-Include String[]] [-Exc
lude String[]] [-Verbose] [-Debug] [-ErrorAction ActionPreferen
ce] [-ErrorVariable String] [-OutVariable String] [-OutBuffer I
nt32]
get-service -DisplayName String[] [-Include String[]] [-Exclude
String[]] [-Verbose] [-Debug] [-ErrorAction ActionPreference]
[-ErrorVariable String] [-OutVariable String] [-OutBuffer Int32
]
get-service [-Include String[]] [-Exclude String[]] [-Input Ser
viceController[]] [-Verbose] [-Debug] [-ErrorAction ActionPrefe
rence] [-ErrorVariable String] [-OutVariable String] [-OutBuffe
r Int32]
Path :
AssemblyInfo :
DLL : C:\Program Files\Microsoft Command Shell\System.Management.Auto
mation.Commands.Management.DLL
HelpFile : System.Management.Automation.Commands.Management.dll-Help.xml
ParameterSets : {Default, DisplayName, Input}
Type : System.Management.Automation.Commands.GetServiceCommand
Verb : get
Noun : service
MSH>
Pipelines
The previous sample showed you two things: how to use Format-List and how to use the pipe symbol (|) to combine cmdlets by redirecting the output of one cmdlet to the input of another one in kind of a chain structure. Now, let's try to apply some filtering with Where-Object:
MSH> get-service | where-object { $_.status -eq "Running" }
Status Name DisplayName
------ ---- -----------
Running 1-vmsrvc Virtual Machine Additions Services ...
Running ADAM_BISGSS BISGSS
Running AeLookupSvc Application Experience Lookup Service
Running AudioSrv Windows Audio
Running Browser Computer Browser
Running CiSvc Indexing Service
Running CryptSvc Cryptographic Services
Running DcomLaunch DCOM Server Process Launcher
Running Dhcp DHCP Client
Running dmserver Logical Disk Manager
Running Dnscache DNS Client
Running ERSvc Error Reporting Service
Running Eventlog Event Log
Running EventSystem COM+ Event System
Running helpsvc Help and Support
Running HTTPFilter HTTP SSL
Running IISADMIN IIS Admin Service
Running lanmanserver Server
Running lanmanworkstation Workstation
Running LmHosts TCP/IP NetBIOS Helper
Running MSDTC Distributed Transaction Coordinator
Running MSSQL$SHAREPOINT MSSQL$SHAREPOINT
Running MSSQL$SQLEXPRESS SQL Server (SQLEXPRESS)
Running MSSQLSERVER SQL Server (MSSQLSERVER)
Running MSSQLServerOLAP... Analysis Server (MSSQLSERVER)
Running Netman Network Connections
Running Nla Network Location Awareness (NLA)
Running PlugPlay Plug and Play
Running PolicyAgent IPSEC Services
Running ProtectedStorage Protected Storage
Running RemoteRegistry Remote Registry
Running ReportServer Report Server (MSSQLSERVER)
Running RpcSs Remote Procedure Call (RPC)
Running SamSs Security Accounts Manager
Running Schedule Task Scheduler
Running seclogon Secondary Logon
Running SENS System Event Notification
Running ShellHWDetection Shell Hardware Detection
Running Spooler Print Spooler
Running SPTimer SharePoint Timer Service
Running SQLBrowser SQL Browser
Running SQLSERVERAGENT SQL Server Agent (MSSQLSERVER)
Running TermService Terminal Services
Running TFSServerScheduler TFSServerScheduler
Running TrkWks Distributed Link Tracking Client
Running W32Time Windows Time
Running W3SVC World Wide Web Publishing Service
Running winmgmt Windows Management Instrumentation
Running wuauserv Automatic Updates
Running WZCSVC Wireless Configuration
MSH>
This deserves some extra explanation. The parameter of where-object contains the condition to filter for. In this case, we obtain a reference to every item in the list using the $_ operator. Using the dot operator we can select a property, in this case we choose for status. This value is then compared to the string "Running" for equality (-eq). To show some other operators, consider the following example:
MSH> get-service | where-object { $_.status -eq "Running" -and $_.name -like "MSSQL*" }
Status Name DisplayName
------ ---- -----------
Running MSSQL$SHAREPOINT MSSQL$SHAREPOINT
Running MSSQL$SQLEXPRESS SQL Server (SQLEXPRESS)
Running MSSQLSERVER SQL Server (MSSQLSERVER)
Running MSSQLServerOLAP... Analysis Server (MSSQLSERVER)
MSH>
Should be clear I guess? Now, what can we query on the output of a Get-Service invocation? To find out about this, together wit the types, use Get-Member:
MSH> Get-Service | Get-Member -MemberType property
TypeName: System.ServiceProcess.ServiceController
Name MemberType Definition
---- ---------- ----------
CanPauseAndContinue Property System.Boolean CanPauseAndContinue {get;}
CanShutdown Property System.Boolean CanShutdown {get;}
CanStop Property System.Boolean CanStop {get;}
Container Property System.ComponentModel.IContainer Container {g...
DependentServices Property System.ServiceProcess.ServiceController[] Dep...
DisplayName Property System.String DisplayName {get;set;}
MachineName Property System.String MachineName {get;set;}
ServiceHandle Property System.Runtime.InteropServices.SafeHandle Ser...
ServiceName Property System.String ServiceName {get;set;}
ServicesDependedOn Property System.ServiceProcess.ServiceController[] Ser...
ServiceType Property System.ServiceProcess.ServiceType ServiceType...
Site Property System.ComponentModel.ISite Site {get;set;}
Status Property System.ServiceProcess.ServiceControllerStatus...
MSH>
This is where the .NET types become visible.
Whatif? Confirm!
Now assume we want to take some action for the selected services (e.g. all MSSQL* services as explained above), for example to stop these services. This can be accomplished by piping the output of the Get-Service cmdlet to the input of the Stop-Service cmdlet. However, this can be a little too agressive, we want more control. There are various ways to do this, e.g. by using a foreach construct together with Read-Host to ask the user for input. Monad has built-in functionality however to see the "showplan" of the execution, by using the -whatif parameter:
MSH> get-service | where-object { $_.status -eq "Running" -and $_.name -like "MSSQL*" } | stop-service -whatif
What if: Operation "stop-service" on Target "MSSQL$SHAREPOINT (MSSQL$SHAREPOINT)"
What if: Operation "stop-service" on Target "SQL Server (SQLEXPRESS) (MSSQL$SQLEXPRESS)"
What if: Operation "stop-service" on Target "SQL Server (MSSQLSERVER) (MSSQLSERVER)"
What if: Operation "stop-service" on Target "Analysis Server (MSSQLSERVER) (MSSQLServerOLAPService)"
MSH>
Okay, that's fine. Let's execute it, but we don't want to stop the SHAREPOINT instance. We could extend the filter or ask for manual user intervention using -confirm. Let's use the latter one:
MSH> get-service | where-object { $_.status -eq "Running" -and $_.name -like "MSSQL*" } | stop-service -confirm
Continue with this operation?
Operation "stop-service" on Target "MSSQL$SHAREPOINT (MSSQL$SHAREPOINT)"
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help
(default is "N") :N
Continue with this operation?
Operation "stop-service" on Target "SQL Server (SQLEXPRESS) (MSSQL$SQLEXPRESS)"
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help
(default is "N") :Y
Continue with this operation?
Operation "stop-service" on Target "SQL Server (MSSQLSERVER) (MSSQLSERVER)"
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help
(default is "N") :Y
stop-service : Cannot stop service 'SQL Server (MSSQLSERVER) (MSSQLSERVER)' bec
ause it has dependent services. It can only be stopped if the Force flag is set
.
At line:1 char:98
+ get-service | where-object { $_.status -eq "Running" -and $_.name -like "MSSQ
L*" } | stop-service <<<< -confirm
Continue with this operation?
Operation "stop-service" on Target "Analysis Server (MSSQLSERVER)
(MSSQLServerOLAPService)"
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help
(default is "N") :Y
MSH>
Okay, SQL Server couldn't be stopped because it has a dependency but it draws the overall picture of the principles of pipelines in Monad.
Aliasing
Right, we saw the use of Where-Object in the previous samples. Pretty powerful but nasty to type. An interesting concept in Monad to solve this problem is the use of aliases. The Get-Alias cmdlet show us all of the defined aliases:
MSH> get-alias
Command Type Name Definition
------------ ---- ----------
Alias ac add-content
Alias clc clear-content
Alias cli clear-item
Alias clp clear-property
Alias cpi copy-item
Alias cpp copy-property
Alias cv clear-variable
Alias cvpa convert-path
Alias epal export-alias
Alias fc format-custom
Alias fl format-list
Alias foreach foreach-object
Alias ft format-table
Alias fw format-wide
Alias gal get-alias
Alias gc get-content
Alias gci get-childitem
Alias gcm get-command
Alias gdr get-drive
Alias ghy get-history
Alias gi get-item
Alias gl get-location
Alias gm get-member
Alias gp get-property
Alias gps get-process
Alias group group-object
Alias gsv get-service
Alias gu get-unique
Alias gv get-variable
Alias help get-help
Alias ic invoke-command
Alias ihy invoke-history
Alias ii invoke-item
Alias ipal import-alias
Alias ipcsv import-csv
Alias mi move-item
Alias mp move-property
Alias nal new-alias
Alias ndr new-drive
Alias ni new-item
Alias nv new-variable
Alias oh out-host
Alias rdr remove-drive
Alias ri remove-item
Alias rmi rename-item
Alias rmp rename-property
Alias rp remove-property
Alias rv remove-variable
Alias rvpa resolve-path
Alias sal set-alias
Alias sasv start-service
Alias sc set-content
Alias select select-object
Alias si set-item
Alias sl set-location
Alias sleep start-sleep
Alias sort sort-object
Alias sp set-property
Alias spps stop-process
Alias spsv stop-service
Alias sv set-variable
Alias where where-object
Alias cat get-content
Alias cd set-location
Alias clear clear-host
Alias cp copy-item
Alias h get-history
Alias history get-history
Alias kill stop-process
Alias lp out-printer
Alias ls get-childitem
Alias man get-help
Alias mount new-drive
Alias mv move-item
Alias popd pop-location
Alias ps get-process
Alias pushd push-location
Alias pwd get-location
Alias r invoke-history
Alias rm remove-item
Alias rmdir remove-item
Alias echo write-object
Alias cls clear-host
Alias chdir set-location
Alias copy copy-item
Alias del remove-item
Alias dir get-childitem
Alias erase remove-item
Alias move move-item
Alias rd remove-item
Alias ren rename-item
Alias set set-variable
Alias type get-content
MSH>
Nice, so Where-Object can be abbreviated to "where". Maybe you'd like to abbreviate it further down to just w:
MSH> new-alias
Cmdlet new-alias at command pipeline position 1
Supply values for the following parameters:
(Type !? for Help.)
Name: w
Value: where-object
MSH>
So, now w stands for where-object.
What's coming next?
In the next episodes I'll show you how to use various "utility cmdlets", how to create scripts, how to access the registry and other "providers" and how to create your own cmdlets in .NET.
Del.icio.us |
Digg It |
Technorati |
Blinklist |
Furl |
reddit |
DotNetKicks
Filed under: Windows PowerShell