as I can not Link to the Attachement in the NG I will post the Text here as reference.
about_Switch
SHORT DESCRIPTION Using a switch to handle multiple if statements.
LONG DESCRIPTION
You use an If statement to make a decision in a script or program. Essentially it says; “If this condition exists, do this action. Otherwise do that action.” You can perform that operation as many times as you want but if you have a long list of conditions, an If statement quickly gets unwieldy. With a long list of conditions you can combine them in a switch statement. As in all branching statements, braces ({}) are required to enclose script blocks.
A switch statement is, in effect, a series of If statements. It matches the expression with each of the conditions case by case. If a match is found, the action associated with that condition is performed. The switch statement, very basically, takes this form:
This simple example takes a value and compares it with each condition in the list. The action just echoes a string from the match. But you could face a problem if you check all of the conditions. For example:
MSH> $day = "day5" MSH> switch ($day){ day1 {"They call it stormy Monday"; break} day2 {"Tuesday's just as bad"; break} day3 {"Wednesday's worse"; break} day4 {"Thursday's oh so sad"; break} day5 {"The eagle flies on Friday"; break} day6 {"Saturday I go out to play"; break} day7 {"Sunday I go out to play"; break} day5 {"Wait, too many days."; break} }
The eagle flies on Friday
There are 2 day5 conditions in the list. But the break at the end of each condition tells the switch to stop looking further and do the action it finds. If the break statements were not there, then both day5 actions would take place.
If the value to switch against is an array, then each element in the array will be evaluated in order, starting at element 0. At least one element must be present that meets at least one condition or an error will result. If there is more than one default clause, an error will result.
The complete switch syntax is as follows:
switch [-regex-wildcard-exact][-casesensitive] ( pipeline ) or switch [-regex-wildcard-exact][-casesensitive] -file filename followed by { "string"numbervariable{ expression } { statementlist } default { statementlist } }
By default, if no options are used, switch behaves as if a case insensitive exact match is in effect. If "pipeline" results in an array, each element of the array shall be evaluated in ascending offset order (starting at 0).
At least one conditional element must be present in the switch codeblock and only one default clause may be present. If more than one default clause is present, a ParseException shall be thrown.
Switch has the following options:
-regex Indicates that the match clause, if a string, is treated as a regex string. Use of this parameter disables -wildcard and -exact. If not a string, this option is ignored.
-wildcard Indicates that the match clause, if a string, is treated as a wildcard string. Use of this parameter disables -regex and -exact. If not a string, this option is ignored.
-exact Indicates that the match clause, if a string, must match exactly. Use of this parameter disables -wildcard and -regex.. If not a string, this option is ignored.
-casesensitive Modify the match clause, if a string, to be case sensitive. If not a string, this is ignored.
-file Take input from a file (or representative) rather than statement. If multiple -file parameters are used, the last one is be used. Each line of the file is read and passed through the switch block.
Multiple uses of -regex, -wildcard or -exact are allowed, however only the last parameter used governs the behavior.
The keyword "break" indicates that no more processing shall occur and the switch statement shall exit.
The keyword "continue" indicates that no processing shall continue against the current token and the next token in the conditional will be evaluated. If no tokens are available, the switch statement will exit.
The “{ expression }” block may be a code block that will be evaluated at the time of the comparison. The object under scrutiny is bound to the automatic variable "$_" and is available during the evaluation of the expression. A comparison is considered a match if the expression evaluations to "true". This expression is evaluated in a new scope.
The “default” keyword within the switch statement indicates that if no matches are found, the code block that follows the keyword shall be evaluated. Program flow shall not be allowed from stanza to stanza (e.g., the closing “}” in the compound-list is an explicit "break". )
If multiple matches are found, each match shall result in the expression being executed. To avoid this, the break or continue keywords may be used to halt further comparisons.
SEE ALSO For information about break, enter the following command at the MSH command prompt:
help about_break
For information about continue, enter the following command at the MSH command prompt:
help about_continue
For information about the if conditional, enter the following command at the MSH command prompt:
help about_if
For information about script blocks, enter the following command at the MSH command prompt:
The Switch statement has an handy option -Regex to use a Regular expresion in it.
the About_Switch help seems missing in Beta 3 but, there is some info in the About_break Help about it.
when you type :
Help about_Break
Part of the Help contains this Example :
In this example, $var is created and initialized to a string value of "word2". The switch statement uses regex (a regular expression .NET class) to match the variable value first with the term "word2". Because the variable value and the first test in the switch statement match, the first code block in the switch statement runs. When MSH reaches the first break statement, the switch statement exits. If the four break statements were removed from the example, then all four conditions would be met. Thus, this example uses the break statement to display results when the most specific condition is met.
"word.*" { write-host "Match on the prefix" $_ break }
"w.*" { write-host "Match on at least the first letter" $_ break }
default { write-host "No match" $_ break } }
This was wat I was looking for in the Dir example in Last post, Hence I came up with the work-around with scriptblocks and -Match.
I found this by using the following command :
MSH>ls $MSHHOME\*.txt | match-string"switch" about_break.help.txt:5: A statement for immediately exiting foreach, for, while, do, or switch about_break.help.txt:10: or do loop or in a switch statement, ends the code block. In the case about_break.help.txt:12: In the case of the switch statement, the break statement causes a code about_break.help.txt:13: block inside of a switch statement to exit and thus the entire switch about_break.help.txt:69: A switch statement is not a looping construct, but the break statement about_break.help.txt:71: met. For example, the following switch statement uses break statements about_break.help.txt:75: switch -regex ($var) about_break.help.txt:103: "word2". The switch statement uses regex (a regular expression .NET about_break.help.txt:105: the variable value and the first test in the switch statement match, about_break.help.txt:106: the first code block in the switch statement runs. When MSH reaches the about_break.help.txt:107: first break statement, the switch statement exits. If the four break about_break.help.txt:119: For information about the switch statement, enter the following about_break.help.txt:122: help about_switch about_if.help.txt:35: elseif statements within it, consider using a switch statement instead. about_if.help.txt:87: For information about the switch statement, enter the following command about_if.help.txt:90: help about_switch about_Reserved_words.help.txt:20: foreachwhileifswitch
I did find it this way before in Beta 2 but could not find it yesterday.
that made me write this script, maybe I will add some more parameters later, or autoadd -Force if H or S is found, and combine it with the colored Dir replacement elswhere on my blog)
This function, will show a Image as background of a Form.
this makes it a small Picture viewer,
the static method fromFile of the .NET system.drawing.image class is used to get the Image from the filename.
The script will set the Image as background of the Form and it will size the form to the Size of the picture, if you pull it wider the picture gets tiled.
Also I Implemented a new trick to fix the focus problem, if you do not set the TopMost property of the Form to $true the form shows "hidden" behind the other forms. I did this in all the form examples for this reason.
Grzegorz Niemirowski, pointed me to a way to set this back again after the form is loaded, by using Add_shown in the NG Bringing form to front
(Oops, only when I did look up the link, I see he did the same thing allready , using a Picturebox.)
hmmm,
Strange I had to pick this as an example, without thinking about it, but I will post anyway, for the work and the picture of my niece ;-)
This function will add files to a "Compressed (zipped) Folder" or will make a new ZIP file if the file does not exists.
you can use the Shell.application COM Object to add files or folders to a Compressed folder, so you can also use the CopyGUI ScriptMethod from Update-TypeData (Democracy to the types) , to add files or folders to a ZIP file, as this uses this object also.
I wanted to do this in 4 lines from MSH, but I had some problems getting the IADsLargeInteger value (the LastLogon property is stored like one), but as I have written a Snap-in for this, (See MSH snap-in to Translate IADsLargeInteger to Int64 ), I could now finish it.
This script is not 4 lines, first for readability, and I decided to do some timing in the script also.
the script will list the last logontime from every domaincontroller and keeps a counter running that keeps the time, as I was running this on a worldwide 200 + DC's Domain, I was interested in timing this.
the Output looks like this :
00:00 Site172DC002.Domain.mow.com Never 00:00 Site173dc002.Domain.mow.com Never 00:00 Site172dc001.Domain.mow.com Never 00:03 Site101dc000.Domain.mow.com Never ... ... 06:25 Site101dc002.Domain.mow.com 2005-12-2713:40:45 06:25 Site101dc001.Domain.mow.com 2005-12-2713:41:25 06:25 Site102dc000.Domain.mow.com Never 06:25 Site105dc002.Domain.mow.com Never 06:27 Site107dc001.Domain.mow.com Never 06:30 Site123dc000.Domain.mow.com Never 06:35 Site143dc001.Domain.mow.com Never 06:39 Site153dc001.Domain.mow.com Never 06:41 Site163dc001.Domain.mow.com Never 06:42 Site101dc001.Domain.mow.com Never 06:43 Site105dc001.Domain.mow.com Never 06:45 Site144dc001.Domain.mow.com Never 06:45 Site108dc002.Domain.mow.com 2006-01-2312:10:35 06:45 Site154dc000.Domain.mow.com Never 06:46 Site113dc001.Domain.mow.com Never 06:46 Site183dc001.Domain.mow.com Never 06:46 Site133dc001.Domain.mow.com Never
Checked 231 DC's for CN=Mow08946,OU=Users,OU=MowOU,DC=Domain,DC=Mow,DC=com in06:47 Minutes
Server Last Logon : Site108dc002.Domain.mow.com at 2006-01-2312:10:35
(ofcourse I scrabled this a bit, any double DC's are my mistake, not Monads ;-) )
the final script looks like this :
# Check-LastLogon.MSH # check all Domaincontrollers for the lastlogontime of a user # # Uses the Get-IADsLargeInteger Snapin you can find here : # http://mow001.blogspot.com/2006/01/msh-snap-in-to-translate.html # # /\/\o\/\/ 2006 # http://mow001.blogspot.com
"`nChecked $($dcs.count) DC's for $dn in $timeRunning Minutes" "`nServer Last Logon : $LastServer at $maxlogon"
what did you say !!, ... 5 Lines ???
Oops, I overdid the commenting since then LOL :-)
but, remember the scripting guys example only outputs the lastlogon time in the end, if you remove the comments, timekeeping and status output there is not much left ;-)
This command lets you add you Custom Members to an MSHObject (the wrapper MSH uses). It works a bit like adding ScriptMethods and Properties in the Typedata (See : Update-TypeData (Democracy to the types)), but now you can do this on-the-fly.
Also it's a bit like using the Select-Object statement to make Custom Properties, I used before here : Report MP3 count and size by User from MSH , I going to use the Same Data (A list of MP3 files on a Disk) to show some Examples of Add-Member to get some more info from them as Artist, Title and add a Play Method.
Now we have a list of MP3 files, but I do not like the Standard Output. For MP3 files I would like Other Properties, like Author, that the standard output does not provide but as I know that the Shell.Application COM-object can provide this Info I can Add it with Add-Member using a scriptProperty, like this :
Now I added that ScriptProperty and can do like this :
MSH>$files[50].author Dire Straits
Now every time I ask for the Author scriptproperty like that, the scriptMethod gets called, and gets the Author.
I would like to add some more properties, but would not like every time I check them the Script will run, So I will add some more properties but now I use a NoteProperty, that I fill only one time with the script(I add an ID too, you see why later ;-)).
# Add some More Properties, but use NoteProperties this Time
Now I added some more Properties, If you do a get-member you can see that, but We can make it even more Handy we can group our properties in a propertyset.
ID : 50 Title : Skateaway Artist : Dire Straits FileType : MP3 Format Sound AlbumTitle : Making Movies Path : \mp3\dire straits\dire straits (1980) - making movies\
Nice or not ?, but Wait we are not ready yet, We can also add ScriptMethods, so to make it even more handy, let's Add this :
MSH>$files | where {$_.artist -like "*Brood*"} | ft mp3info
ID Title Artist FileType AlbumTitle Path -- ----- ------ -------- ---------- ---- 623 Never Be Clever Herman Brood MP3 Format Sound Nederpop Top 100 Go... \MP3\NL\Neder.... 647 Still Believe Herman Brood & His ... MP3 Format Sound Nederpop Top 100 Go... \MP3\NL\Neder.... 666 Saturday Night Herman Brood & His ... MP3 Format Sound Nederpop Top 100 Go... \MP3\NL\Neder.... MSH>$files[623].play()
You can see Add-Member is a very Powerfull way to extend Objects in MSH. And remember if you want them permanent you can also use the MSHXML files and update-typedata.
I could not read the Com-Object from MSH, see also this Thread : accesing IADsLargeInteger As I needed the Logon date from AD that is a LargeInteger Value.
I still did not find a way, but since MSH now supports snap-in's I decided to write one for it.
Get-IADsLargeInteger
I't will cast the IADsLargeInteger COM-object to a Long (Int64) so we can use it from MSH, from there it's easy to get the Date,
So now I can get to the PwdLastset property like this (as I'm using Adam for testing, this accounts Logon values are not filled, that's why I use that in this example)
Let's get to the making of the Snap-in, I First made the Snap-in in C#, following the example in the getting started.
it looks like this :
//getIADsLargeInteger.cs // MSH snapin to get an IADsLargeInteger object to an Int64 // /\/\o\/\/ 2006 // http://mow001.blogspot.com
using System; using System.ComponentModel; using System.Management.Automation; using System.Reflection;
namespace mow { // This class defines the properties of a snap-in [RunInstaller(true)] publicclass getIADsLargeInteger : MshSnapIn { /// Creates instance of DemonSnapin class. public getIADsLargeInteger() : base() { } ///Snapin name is used for registration publicoverridestring Name { get { return"getIADsLargeInteger"; } } /// Gets vendor of the snap-in. publicoverridestring Vendor { get { return"MOW (http://mow001.blogspot.com)"; } } /// Gets description of the snap-in. publicoverridestring Description { get { return"Gets a IADsLargeInteger"; } } } /// Gets a IADsLargeInteger [Cmdlet("Get", "IADsLargeInteger")] publicclass getIADsLargeIntegerCommand : Cmdlet { [Parameter(Position = 0, Mandatory = true)] publicobject LargeInteger { get { return largeInt; } set { largeInt = value; } }
privateobject largeInt;
protectedoverridevoid EndProcessing() { ActiveDs.IADsLargeInteger li = (ActiveDs.IADsLargeInteger)largeInt ; long lng = (long)((uint)li.LowPart +(((long)li.HighPart) << 32)); WriteObject(lng); } } }
But how to get this into MSH as a working snap-in, this takes a few steps.
First save the C# code above in getIADsLargeInteger.cs, in the MSH program directory, e.g. : "C:\Program Files\Microsoft Command Shell\v1.0"
then, It uses the ADSI typelibrary to "translate" the ADSI Com-object so We need to provide that also, it is the following DLL,
Interop.ActiveDs.dll
the most easy way is to get this DLL, is to start a project in VS 2005 and add the ADSI typelibrary as a reference.( Project -> Add reference -> COM)
if you then build the project the DLL is generated in the Bin directory, also you can use the commandline too tblImp for this.
Copy this DLL to the Monad Directory also. Now we can past the following code into the MSH Console to compile the Snap-in :
And now we are ready to use the Snap-in as in the Example we started with, and are able to get the Dates we need from AD. and as this snap-in is loaded in MSH now, it will even show up in get-command :
I still hope there will be a way to do this from MSH, I can load the typelibrary, I do not know why the same trick does not work in MSH, but this will get me going, and making my first Snap-in in MSH was also a nice adventure, as this was also my first C# project.
There is a discussion going on now, and has been before at the newsgroup about the Commandline editing posibilities in MSH,
MSH runs on the cmd.exe console(at least till V2), hence has the same capabilities and limitations, and yes they are a bit oldfasioned and limited as CMD.exe was neglected a (whole) bit (to much) in windows.
And now with the power of MSH on the Commandline, we notice that even more, the Monad team has also pointed this out as a high priority for V2 in the NG.
but still I think CMD console is not as limited as most people think.
so I will give some tricks I find handy here,
I hear a lot of complains about the Cut-and-Past handing in the Console, but I realy love it ;-) but not in it's "standard" form, I set it in Quick-edit Mode, It's realy the first thing I do change.
The complaint is the Ctrl-C ctrl-V does not work, you need to use the mouse to choose copy or Past from the Menu.
or you can use the keyboard shortcut
Copy : Alt-Enter -> E -> (Y or Enter)
Paste : Alt-Enter -> E -> P
As the scrolling Example, I made a work-a-round function for in last post, MSH Scroll-host function , (I Edited it, to remove the Key-echo workaround) that's not very handy
But here there is a better solution this time , setting QuickEdit Mode :
And while I'm at it, I also set the Buffer and Window Size. set the buffer to 9999 (ignore the warning) to keep a long history of output.
Now you can just left-click and drag to select, and just right-click to paste.
that's what I realy like, while writing a script I do this a lot to past tested lines to Notepad.
also in MSH I just paste complete scripts to the console. (that get's it in my history also) MSH will Nicely parse them, anly look out for Tabs in the Pasted code they will be parsed as typed so this wil trigger Tab-Completion !! this will give very strange effects, but I never use tabs in my code so it's not a problem for me, only sometimes when I past in "Strange" code from somewhere that does.
another Tip I want to mention is using the function key's and arrows.
try F7 this will give a list of the command history,
In this Image you see the List shown as you press F7 in the console. you can use the arrows and page-up page down to walk, Enter to run the Line and Right-arrow to just copy the line to the console.
Also note that in this session, I First tested a single line of the script of last post, when it was OK I pasted it to notedpad, and Just pasted the whole script back into the MSH shell to test.
also all the variables are in the Global scope (as MSH does think I did type them) so I can chack the values or paste in parts of the code again when I changed variables)
the QuickEdit Mode makes this very Quick and because can select rectangles in MSH you can leave out the prompt.
I love this way to work.
only gotha is for example a foreach you can not do this $a foreach { "do something" }
as when you work "interactive" (as we fake this by just pating code in) you need to provide the { on the same line
$a foreach { "do something" }
so thats why you see me do that a lot in my code, it's a bit less readable but much more handy in testing as the last example I can just past on the commandline to test. for the first example I need to save the textfile and run the script.
then if you have to change a past of the current command you can use use delete, change the part of the line and use F1 or the right arrow to fill it on with characters of the old line, this is very handy also.
So you see, QuickEdit needs some getting used to, but if you get the hang of it, its very easy to work with. or even can't live without it again (I would not want to change it for Ctrl-C / crtl-V).
and there are also some handy shortcuts for editing lines in CMD (try the other Function key's but most you can do also with the arrows)
if ($script:pos.y -lt 0) {$script:pos.y = 0} if ($script:pos.x -lt 0) {$script:pos.x = 0} if ($script:pos.y -gt ($host.ui.rawui.buffersize.Height - 1)) { $script:pos.y = ($host.ui.rawui.buffersize.Height - 1)}
$host.ui.rawui.CursorPosition = $script:pos } }
set-alias s scroll-host
the trick part was that I could not get rid of the Key press echoed to the screen, so I remove it after, by buffering the character that was there before.
*edit* , I got a helpfull comment from "Monad Jim", so I could remove the "ugly" character removing work-around :
PS. Yes, I could have used a switch statement for the keycheck, also you could add enter to quit also as in the original, it's that lazy thing again ;-).
*Edit*as I removed the echo comment I did those changes also.
On computerworld a 4 part series about Monad has started, Hands On: Learning Monad, the scripting language for Windows Vista it is Excerpted from the O'Reilly Media Inc. book Monad by Andy Oakley so its a good read if you are starting with Monad and will give you an impression of the book also.
I used Get-WmiClasses from Wmi-Help Part 1 , to list them (we installed nothing more on the R2 server as FSRM)
(its easy to use this script remote by filling in the Path in the Managementscope declaration) e.g. $MS = new-object system.management.ManagementScope(\\server\root\cimv2)
I made 2 hashTables from this script, and did compare them like this :
this gives the possibility do handle the events a custom way, a very powerfull capability.
as we are testing R2 FSRM for Quota management, it is likely we need to script some policies and reports also, this is also very powerfull but there are commandlinetools for it.
main reason is we need more flexibility in mail scheduling. (Standard 1 hour) and policy configuration.
but the scripting possibilities of FSRM look very promising for this.
I did not know the Right word for "Jeugd Sentiment" in english , but it's strange how much "Old stuff" comes up while playing with Monad, and how much it made me think back.
my BBS time (RA ASCI graphics) MSH Welcome screen (*edit* b.t.w. I was looking for a Drawing program for ASCI to draw boxes etc, I remember one from that time, but the Welcome screen was made from a Bitmap converter I find while searching for one, I did not found it Yet any recomendations ? plz leave a comment.)
my IRC time (running #dutch (nick still MRC then) Monad IRC Bot
remembers me about the "Open Dagen" (introduction days) at school, where we did some Logo Demos, to interest new students for the Computerlessons.
how longer I play with Monad, the more I remember how much I misssed a good Shell to play with.
gr /\/\o\/\/
*edit* Oops I did almost forget VIM, as I used to carry a diskette with VI.exe (or Com) with me all the time at school, after starting with it programming INFORMIX on my Stage. I slided back into notepad, but going back to it with VIM now with MSH.
Page 82 - 83 - Added Extending the shell with MshSnapins
Page 84 - Added Appendix D - Creating a MshSnapin.
Note that this list does not pretend to be complete, I only posted it as a help for a Quickscan of the documentation changes, I did not list small changes in sentence structure etc. I I did this by hand so I can have missed something.
I did think of this function a while ago but this did not work in Beta 2, There used to be a bug where MSH wouldn't find nested types (note the + sign)