/\/\o\/\/ PowerShelled

This blog has moved to http://ThePowerShellGuy.com Greetings /\/\o\/\/
$AtomFeed = ("Atom.xml")
$PreviousItems = (" Moving to ThePowerShellGuy.com "," PowerShell Code formatting test for my new Blog "," PowerShell Code formatting test for my new Blog "," PowerShell Community Extensions V1.0 "," PowerShell : Access remote eventlogs "," Windows PowerShell Scripting Sweepstakes! "," PowerShell : making Custum Enums "," TechNet Webcast: An Overview of Windows PowerShell "," "Windows PowerShell: TFM" goes "Gold" "," PowerShell : Advanced renaming of files "," ")

Monday, October 31, 2005



A liked this link where you can put your own text on an Einstein Picture.


gr /\/\o\/\/

PS sorry, bout this non-MSH post but There is MSH on the blackboard, and I did like the picture ;-)


Runas with loading Profile script in MSH

In the Last post do the MSH - CMD- MSH loop. & RunAs in MSH ,

I descibed a way to do a Runas in MSH, but your profile does not get loaded.

to do this You need anOther Object a System.Diagnostics.ProcessStartInfo Object
You can fill the properties and then do a : [System.Diagnostics.Process]::start on the Object.

as you can see in the properties list I posted Below Also You have Compleet Control of the Process.

Before I did not see the use of the Get-Credential CMD-let (as for WMI) but here it is KEWL !!!

gr /\/\o\/\/

MSH> $PSI = new-object System.Diagnostics.ProcessStartInfo

MSH> $psi.LoadUserProfile = $true

MSH> $psi.filename = "MSH.exe"

MSH> $psi.UseShellExecute = $false

MSH> $cred = get-credential

Cmdlet get-credential at command pipeline position 1

Supply values for the following parameters:


User: Test

Password for user Test: *******

MSH> $psi.Username = $cred.userName

MSH> $psi.Password = $cred.Password

MSH> [System.Diagnostics.Process]::start($PSI)

Handles NPM(K) PM(K) WS(K) VS(M) CPU(s) Id ProcessName

------- ------ ----- ----- ----- ------ -- -----------

0 0 60 76 2 0,02 2220 msh


Other Properties you can Set are :

MSH C:\Documents and Settings\mow> $psi

Verb :
Arguments :
CreateNoWindow : False
EnvironmentVariables : {pathext, homepath, sdktoolpath, lapi, clientname, systemroot, comspec, appdata, allusersprofile, processor_archi
tecture, commonprogramfiles, lib, number_of_processors, homedrive, username, temp, processor_identifier, processo
r_revision, sessionname, path, processor_level, include, computername, winfxsdk, os, systemdrive, vs71comntools,
logonserver, userprofile, wcp, programfiles, userdomain, tmp, fp_no_host_check, windir}
RedirectStandardInput : False
RedirectStandardOutput : False
RedirectStandardError : False
StandardErrorEncoding :
StandardOutputEncoding :
UseShellExecute : False
Verbs : {open, runas}
UserName : Test
Password : System.Security.SecureString
Domain :
LoadUserProfile : True
FileName : MSH.exe
WorkingDirectory :
ErrorDialog : False
ErrorDialogParentHandle : 0
WindowStyle : Normal

posted by /\/\o\/\/

do the MSH - CMD- MSH loop. & RunAs in MSH

while I was looping at the get-process on remote machine, I saw this nice overload of the Start function :

Public Shared Function Start(ByVal fileName As String, ByVal arguments As String, ByVal userName As String, ByVal password As SecureString, ByVal domain As String) As Process

While I was testing with this I entered the folowing line :


I was thinking about making a Run-as function but did not fill the credential object yet.

the result was a loop between MSH and CMD if the Prompt indicates your in HMS you are in CMD and if the prompt says CMD your are in MSH ;-)

you should try this !, and play with it a bit, realy funny (see example after signature )
you also loose history I think.

If you fill the Credetials it works as expected, and you have (the base of) a secure run-as function.

MSH C:\Documents and Settings\mow> $cred = get-credential ; [System.Diagnostics.Process]::start("cmd.exe",$null,$cred.UserName,$cred.passwor

Cmdlet get-credential at command pipeline position 1
Supply values for the following parameters:
User: mow
Password for user mow: *********

Handles NPM(K) PM(K) WS(K) VS(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
0 0 1196 84 2 0,03 740 cmd
you can also use MSH for this so you can do a runas on the commandline.

gr /\/\o\/\/

Sample of the loop between MSH and the CMD

(while you at it try this with MSH and do this :)
MSH c:\>cd windows
MSH c:\windows\>LS
MSH c:\>LS
MSH G:\Monad> [System.Diagnostics.Process]::start("cmd.exe",$null,$cred.name,$cred.password,$null)
Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

C:\Documents and Settings\mow>
Handles NPM(K) PM(K) WS(K) VS(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
29 2 1944 2384 29 0,03 3944 cmd

MSH G:\Monad> ver

Microsoft Windows XP [Version 5.1.2600]

C:\Documents and Settings\mow>ver
'ver' is not recognized as a Cmdlet, function, operable program, or script file.
At line:1 char:3
+ ver <<<<
MSH G:\Monad>

posted by /\/\o\/\/

list processes of remote computer from MSH

as GPS does not have a - computer parameter, you can not use it on a remote computer.

so when asked in the NG, I came to this first (using WMI).

$RemoteProcess = get-wmiObject -computer Computername win32_process

but then I did think about the ".net"-way and came up with this :


this is also more like get-Process does, I don't know why they did not add the switch ?
lookt trival to me.

gr /\/\o\/\/

posted by /\/\o\/\/

MSH Error message line number and Trap.

An Other issue that did cost me a lot of time was that if you trap an Error,
and there is an Error in the TRAP MSH will point you at the wrong place
(at the foreach, that had the trap in it.)

See example below.

as my function was a bit bigger,and I did not have the helper Writes ($_.name and "Trap") that I put in the Example to point me the way. ( WMI viewer script for MSH (GUI) ), It took me some time to find this out.

So don't make errors in your TRAP's !!!

gr /\/\o\/\/

PS I know that it is a bit ugly this way, but still the error is confusing.
(in productioncode I would check first and not Trap the Error)

$MC = new-object system.management.ManagementClass win32_share
$MOC = $MC.GetInstances()
$MOC foreach {
$null.name() = "Trap Me Please"
trap{"Trap";$null.name() = "Find Me Please"}
Trapforeach-object : You cannot call a method on a null-valued expression.
At line:1 char:15
+ $MOC  foreach  <<<< {

posted by /\/\o\/\/

Strange behavour of get-member on DataTables

When working on the get_WMIdatagrid

See : WMI viewer script for MSH (GUI)

I noticed some strange behavour of Get-Member :

Get-Member will not show me DataTables or collections.
how do I look at there methods and properties?
as you can see in the example below that MSH will not even give me A get Member on a DataTable (say's I have no Object, but as you see I can work with it only I can't see wat I'm doing ;-()

That is Till I add a Datarows to it
then it will not give me the dataRowCollection but a dataRow,
that's 3 levels deeper than tat I asked for !

( DataTable -> DataRowCollection -> DataRow )

$dt = new-object system.data.datatable

if you try this in the MSH Object Viewer


it WILL work !

I recently noticed that this works also :

MSH G:\Monad> new-object system.data.dataTable  gm

TypeName: System.Data.DataTable

Name MemberType Definition
---- ---------- ----------
AcceptChanges Method System.Void AcceptChanges()
add_ColumnChanged Method System.Void add_ColumnChanged(DataColumnChangeEventHandler value)

But ofcourse this is not handy while working.
this has cost me a lot of time while testing.

gr /\/\o\/\/

PS I posted this in the NG also if I hear something about i I will post again.
*Edit* I got an asnwer : See Create System Variable From MSH (Part2)

MSH > $dt = new-object system.data.datatable
MSH > $dt
MSH > $dt gm
get-member : No object has been specified to get-member.
At line:1 char:8

MSH > $DT.TableName = "test"
MSH > $dt
MSH > $dt.tablename

MSH > $dt gm
get-member : No object has been specified to get-member.
At line:1 char:8

MSH > $Col = new-object System.Data.DataColumn
MSH > $Col.ColumnName = "col1"
MSH > $DT.Columns.Add($Col)

MSH > $Col = new-object System.Data.DataColumn
MSH > $Col.ColumnName = "col2"
MSH > $DT.Columns.Add($Col)

MSH > $dt.columns

MSH > $dt.columns gm

TypeName: System.Data.DataColumn

Name MemberType Definition
---- ---------- ----------

MSH > $dt gm
get-member : No object has been specified to get-member.
At line:1 char:8

MSH > $dr = $dt.newrow()
MSH > $dr.col1 = "val1"
MSH > $dr.col2 = "1"

MSH > $dr = $dt.newrow()
MSH > $dr.col1 = "val2"
MSH > $dr.col2 = "2"
MSH > $DT.Rows.Add($DR)

MSH > $dt gm

TypeName: System.Data.DataRow

$MC = new-object system.management.ManagementClass win32_share
$MOC = $MC.GetInstances()
$MOC foreach {
$null = "Trap Me Please"
trap{"Trap";$null[$null] = "Find Me Please"}

posted by /\/\o\/\/

CodeSigning in Monad" Shell Beta 2 (for .NET Framework 2.0 RC/RTM)

in Monad" Shell Beta 2 (for .NET Framework 2.0 RC/RTM),
the default execution policy is set to a mode called "Restricted."
The first time you run a script in the new shell, you’ll see the following error message:

The file C:\my_script.msh cannot be loaded. The execution of scripts is disabled on this system. Please see "get-help about_signing" for more details.

but the Help is not there yet.

the following Links will help you further

gr /\/\o\/\/

The Bogentry on ProudlyServing about it.

the actual about_signing Help

the BlogEntry of Lee Homes, who wrote the Help

posted by /\/\o\/\/

Sunday, October 30, 2005


WMI viewer script for MSH (GUI)

I Like sometimes a quick overview of I WMI class,
the MSH script below adds the Function :

get-WMIDatagrid (GWD)

to MSH, with this function you can look at the Instances of a WMI Object in a Datagrid.
I will first grab all Instances of the Class and add all the properties to a DataTable.
then it will launce a form with a Datagrid linked to the Generated DataTable.
this gives you a quick overview of the Class and the instances.

for example :

MSH> GWD win32_share

gr /\/\o\/\/

PS as I get All the Data you can get problems with a few classes (for example the Eventlog) that have very much data in them.(but there are only a few of them)

# WmiDatagrid.msh
# Shows Instances of WMIClass in Datagrid
# /\/\o\/\/ 2005


function get-WMIDatagrid {
  Param ([string] $WmiClass = "")

  if ($wmiClass -eq "") {Throw "No WMIClass given"}

  $MC = new-object system.management.ManagementClass $wmiCLass
  $MOC = $MC.GetInstances()

  trap{"Class Not found";break}

  $DT =  new-object  System.Data.DataTable
  $DT.TableName = $wmiClass

  $i = 0
  $MOC | foreach {
    $MO = $_

    # Make a DataRow
    $DR = $DT.NewRow()

    $MO.get_properties() | foreach {

      $prop = $_

      If ($i -eq 0)  {
        # Only On First Row make The Headers

        $Col =  new-object System.Data.DataColumn
        $Col.ColumnName = $prop.Name.ToString()
        $prop.get_Qualifiers() | foreach {
          If ($_.Name.ToLower() -eq "key") {
            $Col.ColumnName = $Col.ColumnName + "*"

      #fill dataRow 

      if ($prop.value -eq $null) {
        $DR.Item($prop.Name) = "[empty]"
      ElseIf ($prop.IsArray) {
        $DR.Item($prop.Name) =[string]::Join($prop.value ,";")
      Else {
        $DR.Item($prop.Name) = $prop.value
        #Item is Key try again with *
        trap{$DR.Item("$($prop.Name)*") = $prop.Value.tostring();continue}
    # Add the row to the DataTable
    $i += 1
  $form = new-object "System.Windows.Forms.Form"
  $form.Size = new-object System.Drawing.Size @(800,400)
  $DG = new-object "System.windows.forms.DataGrid"
  $DG.CaptionText = "$wmiClass $($DT.Count)"
  $DG.AllowSorting = $True
  $DG.DataSource = $DT.mshobject.baseobject
  $DG.Dock = [System.Windows.Forms.DockStyle]::Fill

  #show the Form

  $form.text = "$wmiCLass"
  $form.topmost = $true

set-alias gwd get-WMIDatagrid

posted by /\/\o\/\/

Saturday, October 29, 2005


Monad Release for Whidbey RTM

You can find :

the new MSH bit here :

Monad" Shell Beta 2 (for .NET Framework 2.0 RC/RTM) x86

The Framework here :

Microsoft .NET Framework Version 2.0 Redistributable Package Release Candidate (x86)

gr /\/\o\/\/

posted by /\/\o\/\/

Thow Dices in MSH

Bored, ore just into some fun ?
Ask Monad to throw you some dices ;-)

Just load this script and type :

MSH> Throw-Dices


MSH> td 5

Have fun,

gr /\/\o\/\/

# throws some dices
#/\/\o\/\/ 2005
function Throw-Dices{
Param ([int] $NumOfDice = 1)
  $R = new-object system.random([datetime]::now.Millisecond)
  $raw  = $host.ui.rawui
  $pos  = $raw.windowposition
  $size = $raw.buffersize

  # save old info 
  $rect = "system.management.automation.host.rectangle"
  $posOld = $pos
  $re = new-object $rect $pos.x,$pos.y,$size.width,($pos.y + 5)
  $buffer = $raw.getbuffercontents($re)
  #make some dice :
  for ( $i = 1; $i -le $NumOfDice; $i++ ){

    # get a Random number
    $dice = $R.next(1,7)

    # Write the Dice
    WriteDice $pos $dice
    # Move a bit   
    $pos.x = $pos.x + 6
    trap {"To many dices";$host.ui.rawui.SetBufferContents($posOld,$buffer);break}
  # wait
  # put back old info

Function WriteDice {

  $pos = $args[0]
  $Num = $args[1]
  #possible Rows

  $rt0 = "     "
  $rt1 = " o   "
  $rt2 = "  o  "
  $rt3 = "   o "
  $rt4 = " o o "

  Switch ($num){
    1 {$r1 = $rt0; $r2 = $rt2; $r3 = $rt0}
    2 {$r1 = $rt1; $r2 = $rt0; $r3 = $rt3}
    3 {$r1 = $rt1; $r2 = $rt2; $r3 = $rt3}
    4 {$r1 = $rt4; $r2 = $rt0; $r3 = $rt4}
    5 {$r1 = $rt4; $r2 = $rt2; $r3 = $rt4}
    6 {$r1 = $rt4; $r2 = $rt2; $r3 = $rt4}

  WriteDiceLine $rt0
  WriteDiceLine $r1
  WriteDiceLine $r2
  WriteDiceLine $r3
  WriteDiceLine $rt0

Function WriteDiceLine {
  $fgc = [system.consolecolor]"gray"
  $bgc = [system.consolecolor]"red"
  $row = $host.ui.rawui.NewBufferCellArray($args[0],$fgc,$bgc)
  $pos.y = $pos.y +1

Set-Alias td Throw-Dices

posted by /\/\o\/\/

Friday, October 28, 2005


when to change your clock ? ask Monad !!

Almost time to change my clocks ;-)

Start End Delta
----- --- -----
3/27/2005 2:00:00 AM 10/30/2005 3:00:00 AM 01:00:00

gr /\/\o\/\/

PS if you want to make shure you don't forget

function Prompt {$sec = [int](($t.GetDaylightChanges(2005)).end - ([datetime]::now)).totalseconds;"$sec sec to go >"}

posted by /\/\o\/\/

AD Infastructure exploring with MSH

while working in AD with MSH, I noticed the new (.NET 2.0) namesspace :


there are some very Handy classes there, that make working with AD,(especialy the infrastructure part) a lot easier.
Some Examples below (but do a get-member on the Object, there are a lot more handy properties and methods here !!)

gr /\/\o\/\/

#Get ADSI connection to the CurrentDomain
$dom = [System.DirectoryServices.ActiveDirectory.Domain]::getcurrentdomain()

#get some info


#get domain password policy


#Get trust relations

$dom.GetAllTrustRelationships() fl

#find a domaincontroller and connect to it
$dc = $dom.finddomaincontroller()

# Get the Forrest
$for = [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()

#Find ONE GC
$gc = $for.FindGlobalCatalog()

#find all GC in yourSite

# without using a DomainObject.
$dt = [System.DirectoryServices.ActiveDirectory.DirectoryContexttype]"domain"
$c = new-object System.DirectoryServices.ActiveDirectory.DirectoryContext($dt)

posted by /\/\o\/\/

Get Current dir in MSH consoleTtitle

I like to know my position in MSH, but sometimes my prompt get's to long. (Especialy when walking the registry)
that's why I made this Prompt that Sets the Current Directory in the Title.

function prompt { $Dir = get-location $host.ui.rawui.windowtitle = "/\/\o\/\/SH - $dir" Write-Host -nonewline -ForeGroundColor Red MSH;">" }

gr /\/\o\/\/

posted by /\/\o\/\/

MSH ASCII translator

Just type :


and hit a key, you get the ASCII code back.

gr /\/\o\/\/

posted by /\/\o\/\/

red MSH> prompt

to get that cool red prompt of the PDC 05 presentation.

Simple, but took me some time (and the NG) to figure out.

first tryed
$host.ui.rawui.foregroundcolor = "Red", but you can not set it back in the prompt.
(works on the cmd-line), and the backgound is also handy but for the promt It would not work.

and you need at least one char on the last line (the Prompt)

so the function is :

function prompt{Write-Host -nonewline -ForeGroundColor Red MSH;">"}

gr /\/\o\/\/

posted by /\/\o\/\/

Thursday, October 27, 2005


Monad presentation on PDC05 available,

Monad presentation on PDC05 available,

watch @ :
Jeffrey and Jim's Monad presentation on PDC05

along with the other Presentaions
available on http://microsoft.sitestream.com/PDC05/.

gr /\/\o\/\/

posted by /\/\o\/\/

Wednesday, October 26, 2005


A guided tour of the MSH on arstechnica.com

Nice Article about MSH :

gr /\/\o\/\/

A guided tour of the Microsoft Command Shell

1 - Introduction 2 - MSH syntax 3 - More syntax: plumbing and conditionals 4 - Syntax: loops and iteration, SQL-inspired syntax 5 - Syntax: regular expressions 6 - How to leverage the .NET API in MSH 7 - Import and export data 8 - Output formats 9 - Functions 10 - Providers 11 - Security issues 12 - Windows administration with MSH 13 - Conclusion
By Ryan Paul
Sunday, October 23, 2005

posted by /\/\o\/\/

Tuesday, October 25, 2005


Lets Query WMI from MSH


as I was answering a post in the NG,
about a vbscript to get dependent services

the (corrected) script looks like this :

Dim UnArgs
Set UnArgs = WScript.Arguments.Unnamed
WScript.Echo UnArgs(0)

strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colServiceList = objWMIService.ExecQuery("Associators of " _
& "{Win32_Service.Name='" & UnArgs(0) & "'} Where " _
& "AssocClass=Win32_DependentService " & "Role=Antecedent" )

for each s in colServiceList
WScript.Echo s.name

this is a bit more as the standard WMI get propery, and involves more than 1 WMI-class.

I decided to make it in MSH also :.

at first I came with this :

Function GetDep {
$mos = (new-object system.management.ManagementObjectSearcher)
$mos.Query = "Associators of {Win32_Service.Name='" + $Args[0] + "'} Where AssocClass=Win32_DependentService Role=Antecedent"

(you can not use a Moniker to connect to WMI as in VBscript)

But after that I thought .. this may be correct but not realy MSH.
Hence, I did look at the get-WMIObject function.

first how to get only the wanted Class.

the get-WMIObject uses - filter for this :

then how to get the related class

a Get-Method on the Object revealed the GetRelated Property

hence ,

Function GetServiceDeps {($s = get-wmiObject win32_service -filter "Name = '$($args[0])'").GetRelated("win32_service")}

And Ready ..

Much more Clean, shorter and more MSH

but then again .....maybe NOT..... (c) LSL

I did forget the Role-part this does not matter for "lanmanserver" so I did not see it at first but this will give also the relations the service is dependend on.

OK, lets look again at that Method :

MSH G:\Monad> (get-wmiObject win32_service -filter "Name = 'lanmanserver'").GetRelated.OverloadDefinitions
System.Management.ManagementObjectCollection GetRelated()
System.Management.ManagementObjectCollection GetRelated(String relatedClass)
System.Management.ManagementObjectCollection GetRelated(String relatedClass, String relationshipClass, String relationshipQualifier, String relatedQualifier,String relatedRole, String thisRole, Boolean classDefinitionsOnly, EnumerationOptions options)
(I left out the ASync Methods)
Oops, IMNSHO that is not a nice Overload !!!
(Quiz Question : You know them All  well enough to fill the 3th overload ?)
I do now ;-) (see later in post) and it seems that you can keep the ones you don't need empty.
it is : 
MSH G:\Monad> (get-wmiObject win32_service -filter "Name = 'lanmanserver'").GetRelated($null,"Win32_DependentService",$null,$null,$null,"Antecedent",$false,$null)

But then I did not know what to fill in,
but I saw another Method called

after playing a bit I stopped at :

 ((($s = get-wmiObject win32_service -filter "Name = 'lanmanserver'").GetRelationships("win32_Dependentservice"))  foreach {$_.dependent}).split("=")[1]

What do you think ? , In this case I would more like the ".NET" solution ;-)

But.. help was on the way ;-)

while searching SDK's etc for the WQL language specs,
I stumbled upon System.Management.RelationshipQuery
after playing with it (more about how later) I could only make a

So I needed his brother-class : System.Management.RelatedObjectQuery(System.Management.RelatedObjectQuery is related to GetRelated
and RelationshipQuery to GetRelationships)

.So ... and what can we do with thos 2 classes ?

Translate WQL Query's to Properties and Back !!!

MSH G:\Monad> $roq = new-object System.Management.RelatedObjectQuery
MSH G:\Monad> $roq.QueryString = "associators of {Win32_Service.name='lanmanserver'} where resultclass = win32_service role = Antecedent"
MSH G:\Monad> $roq

IsSchemaQuery : False
SourceObject : Win32_Service.name='lanmanserver'
RelatedClass : win32_service
RelationshipClass :
RelatedQualifier :
RelationshipQualifier :
RelatedRole :
ThisRole : Antecedent
ClassDefinitionsOnly : False
QueryLanguage : WQL
QueryString : associators of {Win32_Service.name='lanmanserver'} wher
e resultclass = win32_service role = Antecedent

So, Now you know How I filled in that 3th Overload of GetRelated ;-)

but at the End, I don't know if i want to, because you can get put the RelatedObjectQuery into a
ManagementObjectSearcher directly. (see last "bonus"-script.)

so until you need more as only the relatedClass (1st/2nd Overload of GetRelated)
get-wmiObject is nice but after that I prefer the "system.management"-Way

And .. as final "Bonus" - script to learn the WMI Queries, I coupled to on my Objectviewer-script, to get a GUI WQL-Querytool :
$roq = new-object System.Management.RelatedObjectQuery
$mos = new-object system.management.ManagementObjectSearcher($roq)
In the MSHObjectviewer you can change the Properties (or the Query), and you will see the effect in the Query(or the properties). You have to change to another field to see the reaction.

I think now you have enough tools to get some more heavy work done in WMI

Doe er iets leuks mee (have Fun)

gr /\/\o\/\/

PS IF you do not have OV(MSHObject-Viewer), go here : MSH Object Viewer

for more info about WQL queries go to : http://msdn.microsoft.com/library/en-us/wmisdk/wmi/wql_sql_for_wmi.asp?frame=true

posted by /\/\o\/\/

Monday, October 24, 2005


Getting and using a SecurityPrincipal from MSH

Sometimes you look way to far to get something,

I was searching for getting a SecurityPrincipal, from AD (see former posts)
I could not find it (I can get the Owner of the AD-Object as securityPrincipal, but that is Domain\Administrators.)

the trick was just declare them :

$Account = new-object system.security.principal.ntaccount("User")


$Account = new-object system.security.principal.ntaccount ("Domain", "User")

(this will not fail if user does not exists, error only comes when You use it)

to get the SID for this Account :

$SID = $Account.translate([system.security.principal.securityidentifier])

(if you get no error your user DOES exist ;-) so this is a good way to check if you have a valid user.

so now I can realy use my set_Owner function :

MSH C:\> $Account = new-object system.security.principal.ntaccount("administrators")
MSH C:\> (gi test.txt).set_owner($Account)
MSH C:\> (gi test.txt).get_owner($Account)

MSH C:\> $nt = new-object system.security.principal.ntaccount("foo")
MSH C:\> (gi test.txt).set_owner($nt)
Exception calling "Set_Owner" with "1" argument(s): "Exception calling "SetOwner" with "1" argument(s): "Some or all identity references could not be translated.".".At line:1 char:24+ (gi test.txt).set_owner( <<<< $nt)

gr /\/\o\/\/

PS if you are admin you can GiveOwnership to any account you want with this.

posted by /\/\o\/\/

Line Breaks

I noticed that if you past the Colorcode code to notepad or MSH from the Blogger page, the line breaks are gone.

This does not happen if I read the blog in Thunderbird and past from there, but does again Pasting from Bloglines ( no color-coding there either).

Untill I solve this the workaround is past the text in wordpad than save as text or just copy to the clipboard again.

gr /\/\o\/\/

PS Links are back below the posts
(a bit hidden, but without a sidebar I have not much room)

posted by /\/\o\/\/

Sunday, October 23, 2005


MSH Clipboard part 2 (of 3 ?)

ls, I started on my MSH ClipBoard object.

after my POC, it was a bit more work as I did expect at first.
because I needed threads,Hence I needed events to put the data back.
also I needed a ParameterizedThreadStart, to get input to the thread.

basicly I made 2 classes, one I call from MSH (ClipBoard), and 1 class STA that gets called by the Clipboard class on a STA thread.

if it has to return something, it will Raise a Ready Event that ClipBoard will Handle.

the function in the Clipboard-class will loop until the STA tread is ready, and then returns the result to MSH.

As for every function in the original Class, I had to make 2 functions in my wrapper, and I needed some EventHandlers there is a lot of boilerCode.
so I did not (yet ?) do All Methods of te original object.
but the rest is more of the same (.. and boring)
I did all the Contains except data, and the get / set as Text.

gr /\/\o\/\/

you can find the wrapper (MowClipboard.dll) here
After you load it you can do things like this :

MSH G:\Monad> [System.Reflection.Assembly]::LoadFile("g:\monad\MowClipBoard.dll"

GAC Version Location
--- ------- --------
False v2.0.50215 g:\monad\MowClipBoard.dll

MSH G:\Monad> $clip = new-object mow.clipboard
MSH G:\Monad> $clip.SetText("Hello ClipBoard")
MSH G:\Monad> $clip.ContainsText()
MSH G:\Monad> $clip.GetText()
Hello ClipBoard
MSH G:\Monad> $clip gm

TypeName: mow.ClipBoard

Name MemberType Definition
---- ---------- ----------
Clear Method System.Void Clear()
ContainsAudio Method System.Boolean ContainsAudio()
ContainsFileDropList Method System.Boolean ContainsFileDropList()
ContainsImage Method System.Boolean ContainsImage()
ContainsText Method System.Boolean ContainsText()
Equals Method System.Boolean Equals(Object obj)
GetHashCode Method System.Int32 GetHashCode()
GetText Method System.String GetText()
GetType Method System.Type GetType()
SetText Method System.Void SetText(String Text)
ToString Method System.String ToString()

MSH G:\Monad>

posted by /\/\o\/\/

MSH TakeOwner working

I got some help from the newsgroup on My CurrentPrincipal problem.
(thx, again William)

so now I can use GiveOwner to do a TakeOwner.

See Also :

the Principal Problem :
playing with MY-object from MSH
the Get / set Owner Methods :
Update-TypeData (Democracy to the types)

I pasted the newsgrouppost, below

gr /\/\o\/\/

William Stacey [MVP] wrote:

> I believe you need to set the principle policy to WindowsPrinciple first,
> otherwise you get a GenericPrinciple by default:
> > AppDomain myDomain = Thread.GetDomain();
> myDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
> WindowsPrincipal myPrincipal = >(WindowsPrincipal)Thread.CurrentPrincipal;>

Great !it works :

MSH > $d = [system.threading.thread]::getdomain()
MSH > $d.SetPrincipalPolicy([ System.Security.Principal.PrincipalPolicy]::WindowsPrincipal)
MSH > $p = [system.threading.thread]::currentPrincipal
MSH > $u = $p.identity.get_user()
MSH > (gi test.txt).get_owner()


MSH> (gi test.txt).set_owner($U)
MSH> (gi test.txt).Get_owner()


thank You
gr /\/\o\/\/

posted by /\/\o\/\/

MSH Clipboard use workaround

while playing with the MY object in a former post,
I noticed that the MSH will exit if called from MSH.

I posted this on the newsgroup, and got the following aswer :

Sorry - this is a known problem. Execution threads in the monad engine are
created MTA and you can't create an object that requires STA from an MTA
thread. We have workaround code in the new-object cmdlet that let's you
create an STA COM object when you create the object explicitly. Unfortunately
this doesn't work for objects that are created implicitly by a .NET object.
We instantiate the .NET object and some time later it instantiates the COM
object. We can't use the same workaround because we don't get the exception
until the first time the object is used instead of when it's created. Anyway
- we're still working on this and will hopefully have a solution soon.
Bruce Payette
Monad Development
Microsoft Corporation
This posting is provided "AS IS" with no warranties, and confers no rights.

I have found the following workaround for it :

gr /\/\o\/\/

PS, it's more a POC (proof-of-Concept), it will only write the line "Hello Clip" (hard-coded),
You need to make it a function that takes arguments, or better yet a CMDlet. to make it realy usefull ;-)
$provider = new-object Microsoft.VisualBasic.VBCodeProvider
$params = new-object System.CodeDom.Compiler.CompilerParameters
$params.GenerateInMemory = $True
$refs = "System.dll","Microsoft.VisualBasic.dll","System.Data.DLL","System.management.dll","System.DirectoryServices.dll"

$txtCode = @'

Imports Microsoft.VisualBasic
Imports System
Imports System.Threading

Public Class mow

Sub Main()

Dim newThread As Thread = New Thread(AddressOf ThreadMethod)
newThread.ApartmentState = ApartmentState.STA
End Sub

Shared Sub ThreadMethod()
dim Comp as new Microsoft.VisualBasic.Devices.computer
comp.clipboard.setText("hello Clip")
End Sub

End Class


$results = $provider.CompileAssemblyFromSource($params, $txtCode)
$mAssembly = $results.CompiledAssembly
$i = $mAssembly.CreateInstance("mow")
$r = $i.main()

posted by /\/\o\/\/

Saturday, October 22, 2005


[MSH] keyboard status

while playing with MY.Computer (see previous post)

I discovered another nice one :
it will work realtime (second time I did hold the SHIFT)

I'm sure this will be handy sometime :

MSH C:\> $mycomputer.keyboard
ShiftKeyDown : False
AltKeyDown : False
CtrlKeyDown : False
CapsLock : False
NumLock : False
ScrollLock : False

MSH C:\> $mycomputer.keyboard
ShiftKeyDown : True
AltKeyDown : False
CtrlKeyDown : False
CapsLock : False
NumLock : False
ScrollLock : False

gr /\/\o\/\/

posted by /\/\o\/\/

playing with MY-object from MSH

I did some playing with the MY-namespace from VB.NET

a lot we have already but there are some nice tricks,
for example the audio

to bad the clipboard does not work, also that the user-object can not be used.
(I'm realy looking for that for my SetOwner function)

gr /\/\o\/\/

PS. I past all as code, as it has alot if pasted info and I lose all linebreaks if I do not.

$myComputer = new-object Microsoft.VisualBasic.Devices.computer

this give you acces to the following :

Audio : Microsoft.VisualBasic.Devices.Audio
Clipboard : Microsoft.VisualBasic.MyServices.ClipboardProxy
Ports : Microsoft.VisualBasic.Devices.Ports
Mouse : Microsoft.VisualBasic.Devices.Mouse
Keyboard : Microsoft.VisualBasic.Devices.Keyboard
Screen : Screen[Bounds={X=0,Y=0,Width=1280,Height=1024} WorkingArea={X=0,Y=
0,Width=1280,Height=960} Primary=True DeviceName=\\.\DISPLAY2 ?
O?????? ??☺ ?
Clock : Microsoft.VisualBasic.Devices.Clock
FileSystem : Microsoft.VisualBasic.MyServices.FileSystemProxy
Info : Microsoft.VisualBasic.Devices.ComputerInfo
Network : Microsoft.VisualBasic.Devices.Network
Name : computername
Registry : Microsoft.VisualBasic.MyServices.RegistryProxy

so now you can do !


MSH C:\> $mycomputer.info

TotalPhysicalMemory : 2145816576
AvailablePhysicalMemory : 1505857536
TotalVirtualMemory : 2147352576
AvailableVirtualMemory : 1913438208
InstalledUICulture : en-US
OSFullName : Microsoft Windows XP Professional
OSPlatform : Win32NT
OSVersion : 5.1.2600.131072

MSH C:\> $mycomputer.network.isAvailable


not so nice :

MSH C:\> $MyComputer.network.ping("foo")
Exception calling "Ping" with "1" argument(s): "An exception occurred during a
Ping request.".
At line:1 char:25

MSH C:\> $mycomputer.clock

LocalTime GmtTime TickCount
--------- ------- ---------
10/22/2005 8:04:33 PM 10/22/2005 6:04:33 PM 423435437

also .NET has another path as MSH !!!

MSH C:\> $mycomputer.filesystem.CurrentDirectory
C:\Documents and Settings\mow

MSH C:\> $mycomputer.filesystem.SpecialDirectories

MSH C:\> $mycomputer.mouse

ButtonsSwapped WheelExists WheelScrollLines
-------------- ----------- ----------------
False True 3

you can also get the user object but that does not seem to work.

$me = new-object Microsoft.VisualBasic.ApplicationServices.user

MSH C:\> $me.InitializeWithWindowsUser()
MSH C:\> $me

Name CurrentPrincipal IsAuthenticated
---- ---------------- ---------------
System.Security.Princip... False

MSH C:\> [system.threading.thread]::currentPrincipal
realy not so nice :

MSH C:\> $mycomputer.clipboard.setText("hello Clip")
Exception calling "SetText" with "1" argument(s): "Current thread must set to s
ingle thread apartment (STA) mode before OLE calls can be made. Ensure that you
r Main function has STAThreadAttribute marked on it.".
At line:1 char:30
+ $mycomputer.clipboard.setText( <<<< "hello Clip")


looks like we have no indentity in MSH

but there is alot to play again ;-)

posted by /\/\o\/\/

MSH access NT provider

I started this afer reading a post from Alex K. Angelopoulos (MVP)
in m.p.w.s.scripting

MSH: Accessing ADSI interfaces and Q on WinNT Provider

He concluded getting the NT provider from MSH is not possible.
you can connect to AD LDAP:// GC://, but not the NT provider :

this will all fail :

$entryPC = New-object System.DirectoryServices.DirectoryEntry
$entryPC.set_Path = "WinNT:\\."
$entryPC.mshbase.Path = "WinNT:\\."
$entryPC.path = "WinNT:\\."

Strange thing is that if you do the same thing from .NET it WILL work.
(code below will show this:)

I used the Microsoft.VisualBasic.VBCodeProvider to compile
some inline VB.NET code on the fly and return the object back to MSH.

and if you pass back the created object to MSH it will work.

so after running this code, you can do things like this :
MSH C:\> $r.get_path()

MSH C:\> $r.get_children() foreach {$_.name} select -first 5

MSH C:\> $r.get_path()


MSH C:\> $r.set_path("WinNT://./administrators,group")
MSH C:\> $r.get_path()


so far so good.

but then :
Now I did want the members of the Group. hmm, because we still have the .NET wrapper (DirectoryEntry) around the WinNT provider I didn't see the Members .

but I can call Invoke and I get the Members Back (as Com Object)

MSH C:\> $r.Invoke("members").getType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------True False __ComObject System.MarshalByR...

I can't do anything with it again ;-(

so I got to the winFX SDK-dir and imported the TypeLib :
F:\Data\PrepRoom>tlbimp c:\windows\system32\activeds.tlb /out:activedsNET.dll /namespace:ActiveDS

and loaded it into MSH [System.Reflection.Assembly]::LoadFile("g:\monad\activeDSnet.dll") GAC Version Location
--- ------- --------
False v2.0.50215 g:\monad\activeDSnet.dll

MSH C:\> [System.DirectoryServices.DirectoryEntry]$m = $r.Invoke("Members")
Cannot convert "System.__ComObject" to "System.DirectoryServices.DirectoryEntry". Error: "The value provided for adsObject does not implement IADs.".At line:1 char:44+ [System.DirectoryServices.DirectoryEntry]$m <<<< = $r.Invoke("Members")

MSH C:\> [ActiveDS.IADsMembers]$m = $r.Invoke("Members")
Cannot convert "System.__ComObject" to "ActiveDS.IADsMembers".At line:1 char:25+ [ActiveDS.IADsMembers]$m <<<< = $r.Invoke("Members")

Ofcourse it does work in the @' VD.NET block

'@. (dim group as ActiveDS.IADsGroup = entryPC.nativeobject)

PS 2 returning the ActiveDS.IADsGroup,TLB loaded also in MSH). gives this fine red error, and the shell will exit ( but the message is fair enough (only why quit the shell)

MSH G:\> $r gm An error has occurred that was not properly handled. Additional information is shown below. The command shell will exit. Unhandled Exception: System.Runtime.InteropServices.InvalidComObjectException: C OM object that has been separated from its underlying RCW cannot be used. .............. .............

so we need a way to bind the RCW in MSH,
anyone some Idees ?

anyway you still can do alot of things from the current workaraund :
start stop services, get local SID's etc. on the Winnt: provider.

only if you get an IADs object back it will not work.

for the rest I like the Way I can put the "VB.NET code online, ofcourse if you implemt this i na function you can better complile the DLL but this is nice for testing.

gr /\/\o\/\/
$provider = new-object Microsoft.VisualBasic.VBCodeProvider
$params = new-object System.CodeDom.Compiler.CompilerParameters
$params.GenerateInMemory = $True
$refs = "System.dll","Microsoft.VisualBasic.dll","System.Data.DLL","System.management.dll","System.DirectoryServices.dll"

$txtCode = @'

imports system
Class mow
function main() as System.DirectoryServices.DirectoryEntry

Dim entryPC As New System.DirectoryServices.DirectoryEntry
entryPC.Path = "WinNT://."
return entryPC
end function

end class


$results = $provider.CompileAssemblyFromSource($params, $txtCode)
$mAssembly = $results.CompiledAssembly
$i = $mAssembly.CreateInstance("mow")
$r = $i.main()

posted by /\/\o\/\/

Update-TypeData (Democracy to the types)

If you have a function that always acts op the same type,
you can add that function to the Type, you can do this by making a MSHXML-file, and loading that file.

If you have seen the channel 9 video "More Talking on Monad",
this is the "Democracy to the types" Jeffrey Snover was talking about.

Making the MSHXML file :

Copy the TapeData below in a file with the extension .MSHXML

to make a new scriptmethod just copy or make a scriptmethod-block give
it a name in the name-block and place your script in the script-

in a ScriptMethod you can access the object with the $this variable.

" for more info look for the "An Extensible Type System" paragraph on this page :
(You can also do the same for the formatting see An Extensible Mechanism for Formatting below that)


or download the Beta doc-set here :

You can update the created file by using update-typedata.

Update-TypeData Mow.Types.IO.MshXml

The TypeDatafile below is an extension to the System.IO.FileSystemInfo Class
the class we work with in MSH when we are working with files.

you can see that by doing the following

MSH> echo "test" > test.txt
MSH> (gi test.txt) gm

TypeName: System.IO.FileInfo
Name MemberType Definition
---- ---------- ----------
AppendText Method System.IO.StreamWriter AppendText()
CopyTo Method System.IO.FileInfo CopyTo(String de

If you load the typdatset below you get the following extra members

CopyGUI ScriptMethod System.Object CopyGUI();
Get_Group ScriptMethod System.Object Get_Group();
Get_GroupSID ScriptMethod System.Object Get_GroupSID();
Get_Owner ScriptMethod System.Object Get_Owner();
Get_OwnerSID ScriptMethod System.Object Get_OwnerSID();
GetWmi ScriptMethod System.Object GetWmi();
Set_Owner ScriptMethod System.Object Set_Owner();

Now you can do things like this :

Copy files / dirs with a GUI (like if copying form explorer.

MSH> (gi test.txt).copygui("c:\test")

will give you a message if you would want to replace the file ;-)

MSH C:\> (gi test.txt).get_Owner()

same for the get_OwnerSid get_Group get_groupSid.

they are reachable from the fileSystemObject, but a bit hidden and you need a .NET (2.0) class [System.Security.Principal.ntaccount]to get to them. (took me to the winFX SDK to find it, its new in .NET 2.0.

* tip as usual in MSH you get an Object back so try a get-member on the returned SID !

the Set_owner : will take a security principal and set the owner with it
(I will look where you can get them later, for now I just coppied the owner from 1 file to Another.

the last one Gets the WMI_info from the file. (this I got from a newsgroup post from Jeffrey Snover )
this gives you alot more info then the FileSystemInfo class alone.

MSH C:\> (gi test.txt).getWmi()
Compressed : False
Encrypted : False
Size :
Hidden : False
Name : c:\test.txt
Readable : True
System File :
Version :
Writeable : True

MSH C:\> (gi test.txt).getWmi() gm

MSH>dir ft name,{$_.getWmi().Writeable},{$_.GetWmi().Encrypted} -auto

etc. etc.


gr /\/\o\/\/

PS the CopyGUI could use some work in the error-handling,
but they are examples (you can always extend them), I'm just exploring MSH and publish my test scripts.

<?xml version="1.0" encoding="utf-8" ?>
$name= $args[0]
#$target = (read-host "Enter Target: ")
$(new-object -com shell.application).NameSpace($name).CopyHere($this.fullname)
trap {"Error Copying"; continue }
$SP = $args[0]
$a = $this.GetAccessControl()
<Script>get-WmiObject CIM_DATAFILE -filter "Name = `"$($this.fullname.replace(`"\`",`"\\`"))`""</Script>

posted by /\/\o\/\/

Friday, October 21, 2005


MSH directory watcher with popup-balloon

there are some troubles with using the Filewatcher class for monitoring file changes.
in MSH.

Main problem is that the filewatcher is on another Thread, hence you can't (yet) use a delegate .

"Jeff Jones [MSFT]" wrote:
This is a known issue where if the
ScriptBlock gets called on a different thread then it cannot be invoked.
It looks like the plan for V1 is to improve the error message and then possibly
take a fix in V2.

you still can do this :

$fsw = New-object System.IO.FileSystemWatcher
$r = new-object System.IO.WaitForChangedResult
$r = $fsw.WaitForChanged($all)

but then you can't quit no more (only with ctrl-break but that will exit MSH)a workaround a made for this was :

while ($True) {
write-host -noNewLine "."
$fsw = New-object System.IO.FileSystemWatcher
$r = new-object System.IO.WaitForChangedResult
$fsw.path = $args[0]
$r = $fsw.WaitForChanged($all,10000)
if ($r.timedOut -eq $False){
$changed = $True
$r fl out-string

so you can quit every 10 seconds.
But the looping is not verry elegant, soI did not really like this

The trick with the solution below is to use a form for the Filesystemwatcher to sync with.( a form has an interface for that)

I have got a lot of help with this issue in the newsgroup from Bruce Payette [MSFT]
he made a nice script to make a form with a quit button(some nice lay-out tricks also)

but in this case I didn't want to see the form.
so I made this version that uses a notify-icon,so now you can quit from the notify-icon, hence I was able to hide the form.

nice site-effect of Using the Notify-Icon for this was that I could Use Balloons to.
And I have a Context-menu, so I can add More functions (to add an other watcher / change the dir etc.)

(*TIP if you have the MSHObjectViewer function, from other post. you could do OV($FSW) here ;-)

So I think It's a nice base for allot of functions.

enjoy ...

gr /\/\o\/\/

# Watches Directory for changes,
# and you can Quit !!
# (and a balloon as a bonus ;-)
# /\/\o\/\/ 2005
# http://mow001.blogspot.com


function watch {
      $dir = $args[0]
      if ($dir -eq $null){$dir=$((gi .).Fullname)}
      if ($dir -eq "."){$dir=$((gi .).Fullname)}
      if ([system.io.directory]::exists($dir)) {

        "watching $dir ... Use systray to quit"

        $form = new-object System.Windows.Forms.form
        $cm = new-object System.Windows.Forms.ContextMenu
        $mi = new-object System.Windows.Forms.MenuItem
        $ni = new-object System.Windows.Forms.NotifyIcon

        $form.contextMenu = $cm
        $form.ShowInTaskbar = $False
        $form.WindowState = "minimized"  

        $mi.Index = 0
        $mi.Text = "E&xit"
          #Clean up
          $fsw.EnableRaisingEvents = $False;$NI.Visible = $False

        $ni = $ni
        $ni.Icon = New-object System.Drawing.Icon("g:\monad\mow.ico")
        $NI.ContextMenu = $cm
        $NI.Text = "Watching $dir"

        $fsw = new-object System.IO.FileSystemWatcher $dir
        $fsw.IncludeSubDirectories = $true
        $fsw.SynchronizingObject = $form
          write-host "$((get-date).ToShortTimeString()) : $($_.FullPath)$($_.ChangeType)"

        #Fire it up
        $fsw.EnableRaisingEvents = $true;$NI.Visible = $True;$form.showdialog()
  else {"Directory $dir does not exist"}


posted by /\/\o\/\/

StartRDP script

A MSH script to connect to a client with "remote Desktop" even if RDP is not enabled,
if its not enabled then the script will enable it and it will be disabled again after RDP session closes.

I did remote registry access in MSH witch the .NET class.
don't know how to do a remote registry in "Native" MSH

gr /\/\o\/\/
# StartRDP.msh
# /\/\o\/\/ 2005
# Script to connect to RDP client even if RDP is not enabled
# if RDP was disabled the script will disable RDP again after session.

Function StartRdp {

$MachineName = $Args[0]

$regKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, $MachineName)

# $True makes regKey writable
$regKey= $regKey.OpenSubKey("SYSTEM\\CurrentControlSet\\Control\\Terminal Server" ,$True)

# the Setting is Deny so I reverse it first with ! to set $RDPenabled
$RDPEnabled = !([system.boolean]$regkey.getvalue('fDenyTSConnections'))

write-host "$MachineName RDP = $RDPEnabled"
If (!$RDPEnabled) {
#write changes without closing key
write-Host "enabled RDP on $MachineName"
sleep 1
"Starting the remote Desktop Connection"
cmd /c mstsc /v: $MachineName

#If changed set the Key back to original value :
if (!$RDPEnabled) {
write-Host "Disabled RDP again on $MachineName"

#Close the Reg Key

posted by /\/\o\/\/

convert images in MSH

James W. Truher[MS] posted a nice MSH scipt to convert images in MSH
in the newsgroup and on the Monad blog



gr /\/\o\/\/

PS (not mentioned on the blog) you have to load the DLL first :


posted by /\/\o\/\/

Style Problems

I did switch to a very Simple stlyle template,
because I had some problems with the layout.

the Posts did break out of there frame messing the layout up.
(linebreak related in the posts I think .

and the black background for the color-coded scripts.
(they where also getting smaller.)

I'm not realy in to HTML,
so I'm using the standard templates of Blogger.

the current style is the most simple there was in the templates.
not very visualy atractive, but easy to read.

at the moment I think that's the more important thing.
when I figure out a good way / template for adding code to the posts, I will switch back to a more appealing layout.

gr /\/\o\/\/

posted by /\/\o\/\/

ColorCoding MSH scripts on blog

I just added ColorCoding to the MSH scripts on my blog.

I did this online with CodeHTMLer,
verry Cool !!,
also because the MSH text is difficult to past in the Blogger web-interface.
(linebreaks are gone, and screenlines get broken )
I think It's alot more readable this way

I found the link to this this here,


and a link to a blog with also MSH info :
(a.o. nice script to convert doskey macros to Monad functions)


the link to the online CodeHTMLer :


gr /\/\o\/\/

posted by /\/\o\/\/

GUI folder copy tool

The following MSH one-liner wil give you a GUI folder copy-tool
by using the Shell.Application COM-Object

(new-object -com Shell.application).NameSpace((new-object -com Shell.application).browseforFolder(0, "Select Target", 0, 0x11)).CopyHere((new-object -com Shell.application).browseforFolder(0,"Select Source", 0, 0x11))

gr /\/\o\/\/

PS If you got any nice One-liners plz post them as a comment.
(bit like the good old Atari - one-liner compititions ;-)
easy to play "False" in Monad by using ; LOL,
did someOne reached the limit (is it 256 ?) yet ?

posted by /\/\o\/\/

Thursday, October 20, 2005


MSHObjectViewer mentioned in More talking about Monad


my Objectviewer script (see former post) got mentioned in the Jeffrey Snover - More talking about Monad on channel 9 (also see former post)

gr /\/\o\/\/

PS as you think its only 10 lines ;-)

the original sample as posted in the newsgroup was :

# MSH object viewer by /\/\o\/\/
$form = new-object "System.Windows.Forms.Form"
$form.Size = new-object System.Drawing.Size @(600,600)
$PG = new-object "System.Windows.Forms.PropertyGrid"
$PG.Dock = [System.Windows.Forms.DockStyle]::Fill

#WMi Browser $form.text = "/\/\o\/\/ WMI Browser"
$i = new-object system.management.managementclass("win32_share")
$PG.selectedobject = $i.mshobject.baseobject

#Try this also !!
#$form.text = "/\/\o\/\/ Magic form"
#$PG.selectedobject = $form.mshobject.baseobject

$form.topmost = $true $form.showdialog()

posted by /\/\o\/\/

MSH registry access

I needed to Change Default view in explorer,for Ca 1500 XP clients and reset the views.
(changing this when Grouppolicy is applied a.o. "Classic Shell" (that messed up the settings in the first place - reason for the request) etc. is another topic - and not funny ! - if you need too.. good luck ... search the unattended newsgroups for the registry-settings.. and check the GPO settings - the code below works at my home box but still not on my client in the customers domain - so we stopped by removing the "Classic shell"-GP setting, but ok, other story)

and I could not use MSH for this anyway (Yet),
but as I'm already getting used to prototyping in MSH. (I think the Guys who already played a bit with it know why ;-)),
hence I started there :

but the proto-typing in MSH (changing the reg was a nice adventure)

First getting there :

Change to the CurrentUser key :

MSH C:\> cd HKCU:

nice and easy ;-) so now to the softwarekey

cd so[tab]

MSH HKCU:\> cd Software

cd mi/[tab]\wi[tab]\cu[tab]\ex[tab]\Str[tab][tab]

MSH HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Streams>

Tab completion in the Regprovider so it realy browses like a dir (I realy like this)

So do a Dir
Hive: Registry::HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Streams
SKC VC Name Property
--- -- ---- --------
0 2Defaults {{20D04FE0-3AEA-1069-A2D8-08002B30309...
0 2 Desktop {TaskbarWinXP, Toolbars}

Hmm, should there not be a RegistryValue settings here ?
so I tryed :

MSH HKCU:\...> gi .
Hive: Registry::HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer
SKC VC Name Property--- -- ---- -------- 3 1 Streams {Settings}

I see the setting, but not realy as expected (thinking Commandline),try this 1 level higher in Explorer to realy see what I mean

so think Object .....

MSH HKCU:\> gp .
MshPath : Registry::HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\streamsMshParentPath : Registry::HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\ExplorerMshChildName : streamsMshDrive : HKCU
MshProvider : System.Management.Automation.ProviderInfo
Settings : {8, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 119, 126, 19, 115, 53, 207, 17, 174, 105, 8, 0, 43, 46, 18, 98, 4, 0, 0, 0, 4, 0, 0, 0 , 67, 0, 0, 0}

GP = get-Property, we are getting the properties of the current Key.
looks a bit strange maybe, because we are (still) thinking filesystem when in the reg-provider when navigating but if you come to the place you want to be and going to the actions it comes clear then the fun starts :

I first make a location variable :

$location = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Streams'
and get the settings.
$Settings = (get-property $location).settings

to only view the property at the commandline I could do this

MSH HKCU:\..> (gp .).settings

, but since I copy the line to a script that I want to be able to run form anywhere I do it this way (and I can do "cd C:" to get a short prompt - you can change the prompt but thats also dangerous IMHO because you will not see wat you do)

MSH > $settings gm

TypeName: System.Byte

Name MemberType Definition
---- ---------- ----------
CompareTo Method System.Int32 CompareTo(Object value), System.Int32 Co...
Equals Method System.Boolean Equals(Object obj), System.Boolean Equ...
GetHashCode Method System.Int32 GetHashCode()
GetType Method System.Type GetType()
GetTypeCode Method System.TypeCode GetTypeCode()
ToString Method System.String ToString(), System.String ToString(Stri...

so we can see that MSH neatly provided us with a byte-array !!

so we can just do this :

$Settings[4] = 4

... set the 5th (bytearry starts with 0) and set it to 4 (details)
and write it back.

set-property $Location -property settings -value $settings

Cool .. thats al it took to set only 1 byte of an Byte-array in the registry.

almost done, just do the same trick on the following key :
$location = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Streams\Defaults'

Oops, it has {} around it (MSH script-block)

$Settings = get-property $Location -property "{20D04FE0-3AEA-1069-A2D8-08002B30309D}"

so far so good ..

MSH C:\> $settings[4] = 5

Unable to index into an object of type System.Management.Automation.MshObject.At line:1 char:11+ $settings[4 <<<< ] = 5

the problem is MSH will wrap this in a custom object
TypeName: System.Management.Automation.MshCustomObject

the trick is : you have to specify the name again :
$Settings."{20D04FE0-3AEA-1069-A2D8-08002B30309D}"[4] = $args[0]

watch out ALSO when writing it back :

so like this :

set-property $Location -property "{20D04FE0-3AEA-1069-A2D8-08002B30309D}" -value $settings."{20D04FE0-3AEA-1069-A2D8-08002B30309D}"

NOT LIKE THIS !!! (it will write a string to your registry !!)

set-property $Location -property "{20D04FE0-3AEA-1069-A2D8-08002B30309D}" -value $settings

so to be save first save it in another variable !

so the total function will be :

Function SetDefView{
# set byte array
$location = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Streams' $Settings = (get-property $location).settings
$Settings[4] = $args[0]
set-property $Location -property settings -value $settings

# set byte array in special key (that needs quotes like 123 or {6})
$location = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Streams\Defaults' $SettingsWrapper= get-property $Location -property "{20D04FE0-3AEA-1069-A2D8-08002B30309D}"
$settings = $SettingsWrapper."{20D04FE0-3AEA-1069-A2D8-08002B30309D}"
$settings[4] = $args[0] set-property $Location -property "{20D04FE0-3AEA-1069-A2D8-08002B30309D}" -value $settings
"Done ! (you have to logon / logoff to see the change)"

you see that the last part is a bit more complex since you have to deal with the wrapper, and easy to do wrong (use the 2 step variable declaration to avoid confusion). this can also happen with "simpler" keys like 123.

I hope this post will help you exploring the Reg with MSH

enjoy ..

gr /\/\o\/\/

PS. thx to Jeff Jones [MSFT] for helping me with this in mp.w.s.scripting

PS remember if testing that it will not always work in a GPO env.

posted by /\/\o\/\/

Unix => MSH Translations: find and grep

Nice post at Geek Noise about getting find / grep functionality by using
get-childitem and match-string in MSH

Unix => MSH Translations: find and grep

gr /\/\o\/\/

posted by /\/\o\/\/

MSH Object Viewer

Fuction to see/Change members of Objects in a Gui.
(a bit as get-member does on the Commandline)

it is a great help exploring MSH for me

some examples of usage :

ov (gi test.txt) -> file properties

ov(new-object system.management.managementclass)<- you can change class from GUI so this is giving you a WMI browser. Look at the difference between the following commands !: (in the latter you don't see the methods, and MSH is taking the instance already) ov(new-object system.management.managementclass("win32_operatingsystem")) ov (get-wmiObject win32_operatingSystem) ov(gps[0]) -> info of first process
ov ($var) -> Info on variable.
ov(dir) -> dir in GUI

gr /\/\o\/\/

# will show an Object in a PropertyGrid (propertywindow in Visual Studio)
# this is an easy way to look at MSH objects.
# you can read / write the object properties.
# and it has some nice editors for some properties
# eg. ov (gi test.txt)will let you change the date by a calendarview
# /\/\o\/\/ 2005


function ObjectViewer {
$form = new-object "System.Windows.Forms.Form"
$form.Size = new-object System.Drawing.Size @(600,600)
$PG = new-object "System.Windows.Forms.PropertyGrid"
$PG.Dock = [System.Windows.Forms.DockStyle]::Fill
$form.text = "$args"
$PG.selectedobject = $args[0].mshObject.baseobject
$form.topmost = $true
set-Alias OV ObjectViewer 

posted by /\/\o\/\/

Windows "Monad" Shell Beta 2 Documentation Pack

While a lot of people are looking for a Offline version of the MSH getting started guide as found in the winfx SDK site :


I so added the link "Monad Beta 2 Docs"
that will point to the Windows "Monad" Shell Beta 2 Documentation Pack download page.


The documents included are:
The "Getting Started" guide, an 80-page introduction to using the shell and the MSH language supported by the Windows "Monad" Shell (GettingStarted.doc).
A single-page summary of the MSH language, formatted as a tri-fold (LanguageQuickReferenceTriFold.doc).
A quick-start guide to tracing in the Windows "Monad" Shell (TracingQuickStart.doc).
The three Hands-On Labs from the 2005 Professional Developers Conference: "Monad Scripting" (MonadScripting-HandsOnLab.doc), "Building Monad Cmdlets" (BuildingMonadCmdlets-HandsOnLab.doc) and "Creating Monad Providers" (CreatingMonadProviders-HandsOnLab.doc).

gr /\/\o\/\/

posted by /\/\o\/\/

sample of mine used at reskit.net

sample of mine (workaround for "Copy con") posted in the newsgroup is now used as sample on www.reskit.net:

as mentioned at Under the Stairs (Thomas Lee's Web log)


I added a link to the Monad page of reskit.net in the links session

gr /\/\o\/\/

PS will add the blogs I have found till now in the links later.
on the reskit.net page has also a good list of MSH links.

posted by /\/\o\/\/

Another Channel9 Interview With Jeffrey Snover.

Jeffry Snover mentioned in the Micrisoft.public.server.scripting newsgroup
that he did another interview with Channel9

you can find it here :

Jeffrey Snover wrote in Newsgroup :

recently did a channel9 interview. I wanted to discuss the recent wave of innovation around Whidbey but ended up discussing lots of stuff including an update on Monad, the democratization of type systems, epistemology, Exchange, economics, SMASH, the needs of admins, the last mile, and much more. As such, it isn't a very structured, planned, or linear conversation. You might find that an good thing or a bad thing. Anyway - you are forewarned and if you are interested you can see it at:http://channel9.msdn.com/Showpost.aspx?postid=127819--

Jeffrey Snover [MSFT]

Windows Command Shell Architect
Microsoft Corporation
This posting is provided "AS IS" with no warranties, and confers no rights.

posted by /\/\o\/\/


October 2005   November 2005   December 2005   January 2006   February 2006   March 2006   April 2006   May 2006   June 2006   July 2006   August 2006   September 2006   October 2006   November 2006   December 2006  

$Links = ("PowerShell RC1 Docs"," PowerShell RC1 X86"," PowerShell RC1 X64"," Monad GettingStarted guide"," Monad Progamming Guide"," Monad SDK"," Monad videos on Channel 9"," MSH Community Workspace"," scripts.readify.net "," MonadSource"," www.reskit.net"," PowerShell Blog"," Under The Stairs"," computerperformance powershell Home"," proudlyserving"," MSH on wikipedia"," MSHWiki Channel 9"," Keith Hill's Blog"," Precision Computing"," PowerShell for fun"," MSH Memo (Japanese)"," monadblog")

find-blog -about "PowerShell","Monad" | out-Technorati.
find-blog -contains "","" | out-Technorati.
Web mow001.blogspot.com

This page is powered by Blogger. Isn't yours?