MonadThe New Microsoft Command Shell
Peter [email protected]://www.peterprovost.org/
Unix Shell Example
List a file in a directory with details# ls –l hosts-rw-r—r-- 1 root root 41 Mar 18 2005 hosts
Modify fields displayed# ls –go hosts-rw-r—r-- 1 41 Mar 18 2005 hosts
Extract size and filename# ls –l hosts | cut –c 24-27,41- 41 hosts
Unix Shell Example (continued)
Show access time?# ls –lu
Sort by size?# ls –lS
Sort by modification time?# ls -lt
Monad Example
List a file in a directory with detailsMSH> ls hosts
Mode LastWriteTime Length Name---- ------------- ------ -----a--- 8/29/2002 5:00 AM 734 hosts
Modify fields displayedMSH> ls hosts | format-table LastWriteTime,Name
LastWriteTime Name------------- ----8/29/2002 5:00:00 AM hosts
Extract size and filenameMSH> ls –l hosts | format-table Length,Name
Length Name------ ---- 734 hosts
Monad Example (continued)
Show access time?MSH> ls hosts | format-table Name,LastAccessTime
Sort by size?MSH> ls hosts | sort-object Length
Sort by modification time?MSH> ls hosts | sort-object LastWriteTime
More Monad Examples!
Show files modified in last 7 daysMSH> ls | where-object { $_.LastWriteTime –ge [System.DateTime]::Now.AddDays(-7) }
Show processes using 500 handles, sorted by IdMSH> ps | where-object { $_.HandleCount –ge 500 } |
sort-object Id Show signer of each process binary
MSH> ps | foreach-object { $p = $_.MainModule.FileName $sig = get-authenticodesignature $p echo ($p + ": “ + $sig.SignerCertificate.Issuer)
}
Monad is a New Shell
Similar to Unix shells, but… Pipelines of .Net objects Object properties/methods directly accessible
and discoverable COM, WMI, XML, etc. accessed with same
semantics User-controlled formatting of objects Standardized command parameter processing Rich scripting language Providers extend the navigation namespace
Commands
Verb-NounMSH> verb-noun –param1 value1 –param2 value2a,value2b –param3:value3
You can aliasMSH> set-alias gps get-processls and dir are aliases for get-childitemps is alias for get-process
Parameters can be positionalMSH> get-process –processname lsassMSH> get-process lsass
Many parameters can be wildcardedMSH> get-process c*
Partial parameter names allowedMSH> get-process -p lsass
Commands Emit Objects
Traditional text parsing replaced with direct object manipulation
A default text view of objects is dynamically computedTable for objects with < 5 propertiesList for objects with 5 or more properties
Get-Member tells you about the objects MSH> get-process | get-member
Finding Information
Finding CommandsMSH> get-command i*MSH> get-command –verb processMSH> get-command –type {Alias | Function | Filter | Cmdlet | ExternalScript | Application | Script | All }
Man-page style help on language and commandsMSH> get-helpMSH> get-help <command>MSH> <command> -?MSH> get-help about_whileMSH> get-help * | where {$_.Synopsis -match "process"}
Object Manipulation
Objects can be pipelined to other functions Related commands
MSH> get-process notep* | stop-process Object utilities
MSH> get-process | where {$_.Handles –ge 500} |group-object Company | sort-object Count
Your functions Direct object manipulation
MSH> $np = get-process notepadMSH> $np.Workingset / 1024MSH> $np.WaitForExit()
Ubiquitous Parameters
-Debug Programmer-level information
-ErrorAction SilentlyContinue | Stop | Continue | Inquire What to do if an error occurs?
-ErrorVariable VariableName Assign errors to a variable
-OutputVariable VariableName Output assigned to a variable
-Verbose Additional information about the activities being
performed
Trusting Operations
Commands with side-effects support:-Whatif
MSH> get-process | where-object {$_.Handles –ge 500} | stop-process –whatif
-ConfirmMSH> stop-process –pr s* -confirm
Can also use -VerboseMSH> stop-process –pr [a-x]*[q]*[r-t] -verbose
Extending the Namespace
Providers allow namespace navigation to go beyond the filesystem
Monad includes a default setFileSystem, Registry, Certificate, Alias,
Environment, Function, Variable You can write your own Navigation commands work
MSH> cd Registry::\MSH> dir YourProvider::\foo
Finding Data Data stores surfaced as “drives” in providers
MSH> get-driveMSH> dir HKLM:\SOFTWARE\Microsoft
Drive is a namespace with numerous pieces of information Item, ChildItem, Content, Property, ACL, etc.
New navigation/interaction model supported with aliases for existing commands
get-childItem dir ls
get-location cd pwd
get-content type cat
new-item –type Directory md mkdir
set-location cd cd
Namespace Functions
Mounting new drives with namesMSH> new-drive -name SRC -provider FileSystem
-root c:\development\cab\main -description “CAB source code”
MSH> cd SRC:\parser Great wildcarding
MSH> dir [a-f]*[tc]MSH> dir T?.msh
Rich common semanticsMSH> dir \logs –include *.txt –exclude A* -recurse
-force Drive specific extensions
MSH> dir cert: -recurse –codesigning Tab-Completion in all Drives
MSH> dir HKLM:\So<TAB>\Mi<TAB> => HLKM:\Software\Microsoft
Scripting
A script is executed the same as if the commands were typed interactively
Supports scripting .NET objects Loose, strong, and extensible typing models Uniform syntax for wide range of types
WMI, XML, COM, ADSI, ADO Rich variable semantics (typed, read-only, constraints,
descriptions) Rich operators and control structures (C#-like with
access to commands & utilities) Functions (positional, named, typed,
constrained params)
Scripting .NET
Creating .Net objectsMSH> $d=New-Object System.DateTime 2005,4,20MSH> [DateTime]"4-20-2005"Will try Parse() method, Constructor, Converter
Inspecting properties and methodsMSH> [DateTime]"4-20-2005" | get-memberMSH> [DateTime] | get-member -static
Accessing properties-methods Instance
MSH> $d.DayOfWeekMSH> $d.AddMonths(6)
StaticMSH> [DateTime]::NowMSH> [DateTime]::IsLeapYear(2005)
Typing
LooseMSH> $d="4/20/2005“MSH> Function foo() {$args[0]}
“Strong”MSH> [datetime]$d=“4/20/2005”MSH> function foo([datetime]$date) {$date}MSH> [int] [char] “a”
Extensible Can extend types via $MSHHOME\types.mshxml See .NET DateTime class – DateTime property
MSH works on any .NET type - not a fixed set of “scripting types”
Typing Examples
MSH> [char] “a”MSH> [int] [char] “a”MSH> [char] ([int][char]"a" - 32)
MSH> $w = get-wmiobject win32_bios
MSH> $w.VersionMSH> (dir)[0].mshPath
Text Processing Model
.NET String class is the foundation Contains(), EndsWith(), Equals(), IndexOf(), Insert(),
Join(), LastIndexOf(), Length, PadLeft(), PadRight(), Remove(), Replace(), Split(), StartsWith(), Substring(), ToLower(), ToUpper(), Trim(), TrimEnd(), TrimStart()
Native support for useful datatypes Regular expressions, XML, arrays, hash tables
Rich string operators +, *, -replace, -match, -like, -eq, -ne, gt, -ge, -lt, -le Implicit/explicit casting and coercion
Rich utilities match-string, foreach, group, select, sort, where
Leveraging .Net classes
Script to rotate every image in a directory
[System.Reflection.Assembly]:: LoadWithPartialName("System.Drawing") | out-null foreach ($f in resolve-path *) { trap [OutOfMemoryException] { write-host "Error processing" $f; continue } { $img = [System.Drawing.Image]::FromFile($f) $format = $img.RawFormat $img.RotateFlip("Rotate90FlipNone") $fi = get-childitem $f $newname = combine-path ($fi.DirectoryName)
("rot." + $fi.Name) $img.Save($newname,$format) } }
Uniform Data Access Syntax
Provides a common user interface to objects of different typesystems
XMLMSH> $x = [xml]"<a><b><c>TEST</c></b></a>"MSH> $x.a.b.cMSH> $wc = new-object System.Net.WebClientMSH> $rssdata = [xml]$wc.DownloadString ("http://slashdot.org/index.rss")
MSH> if ($rssdata.rss.version –eq "2.0") { echo $rssdata.rss.channel.title }
COM Automation (Internet Explorer) Bind to Internet Explorer COM object
MSH> $ie = new-object –com InternetExplorer.Application
Reflect against properties/methodsMSH> $ie | get-member
Display propertiesMSH> $ie.Visible
Invoke methods/set propertiesMSH> $ie.Navigate2("www.uiuc.edu")MSH> $ie.Visible = $trueMSH> $ie.StatusText = "Hello World"
COM Automation (Word)
Bind to Word COM ObjectMSH> $word = new-object –com Word.Application
Use in pipelinesMSH> $word.RecentFiles | sort name | format-table name,index,path –auto
Access document propertiesMSH> $doc = $word.Documents.Open("c:\foo.doc")
MSH> $doc.characters.count MSH> $doc.sentences.count
COM Automation (WScript)
Bind to WScript objectMSH> $ws = new-object -com Wscript.Shell
Display popupMSH> $ws.popup("This is a popup",100,"Title",64) Last parameter is a button/icon bit mask: 0 OK 1 OK and Cancel 2 Abort, Retry, and Ignore 3 Yes, No, and Cancel 4 Yes and No 5 Retry and Cancel
Access other shell functionalityMSH> $ws | get-member CreateShortcut(), LogEvent(), etc.
16 “Stop Mark”16 “Stop Mark”32 “Question Mark”32 “Question Mark”48 “Exclamation Mark”48 “Exclamation Mark”64 “Information Marl”64 “Information Marl”
Writing Cmdlets
.Net class, inherits from Cmdlet Declare parameters as class members Override methods BeginProcessing(),
ProcessRecord(), EndProcessing() Monad provides
Parameter parsing/binding Ubiquitous parameters -Confirm/-Whatif (if you call ShouldProcess()) Access to session state Invoke other cmdlets, providers, and host API
Cmdlet Example (C#)
1 [Cmdlet("stop", "ps", SupportsShouldProcess=true)]2 public class StopPs: Cmdlet 3 {4 [Parameter(Mandatory=true)]5 public string Name;6 protected override void ProcessRecord() {7 Process [] ps = Process.GetProcessesByName(Name);8 foreach (Process p in ps) {9 if (ShouldProcess(p.ProcessName + "ID= " +
p.Id))10 {11 p.Kill();12 }13 }14 }15 }
Get Monad!
Monad Shell Beta 2 available from Microsoft Download Center
Search for “Monad” Supported on x86 and x64 platforms Documentation Pack also available Requires .Net 2.0 Beta 2 (also available
from Download Center)
Shameless Plug
patterns & practices is hiring
See me after the talk or e-mailDarrel Snow – [email protected]
Top Related