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 !!!
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 :
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>ver 'ver' is not recognized as a Cmdlet, function, operable program, or script file. At line:1char:3 + ver <<<< MSH G:\Monad>
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)
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 !
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.
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
# 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 [void]$host.ui.rawui.ReadKey() # put back old info $host.ui.rawui.SetBufferContents($posOld,$buffer) }
Function WriteDice {
$pos = $args[0] $Num = $args[1] #possible Rows
$rt0 = " " $rt1 = " o " $rt2 = " o " $rt3 = " o " $rt4 = " o o "
while working in AD with MSH, I noticed the new (.NET 2.0) namesspace :
System.DirectoryServices.ActiveDirectory
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
$dom.Forest.name $dom.DomainMode
#get domain password policy
$dom.GetDirectoryEntry().pwdHistoryLength
#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 $for.FindAllGlobalCatalogs("YourSite")
# without using a DomainObject. $dt = [System.DirectoryServices.ActiveDirectory.DirectoryContexttype]"domain" $c = new-object System.DirectoryServices.ActiveDirectory.DirectoryContext($dt) $dc::findone($c)
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;">" }
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;">"}
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 http://arstechnica.com/guides/other/msh.ars
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.
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
references of -query.
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
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 :
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
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.)
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 :
> 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;>
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 -- 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 ;-)
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 True
$MyComputer.network.ping("localhost") True
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:1char:25
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:1char:30 + $mycomputer.clipboard.setText( <<<< "hello Clip")
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) $r.Invoke("members")
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")
'@. (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.
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- block.
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)
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() Value ----- Client\mow
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.
Enjoy
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.
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.
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\/\/
#WatchDir.msh # # 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)) {
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.
# $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) { $regkey.SetValue('fDenyTSConnections',0) #write changes without closing key $regKey.flush() 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) { $regkey.SetValue('fDenyTSConnections',[int]!$RDPEnabled); write-Host "Disabled RDP again on $MachineName" }
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.
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
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 ?
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)
Tab completion in the Regprovider so it realy browses like a dir (I realy like this)
So do a Dir MSH HKCU:\...>LS 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
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)
# 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.
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\/\/
#Objectviewer.msh # 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
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).
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.