/\/\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 "," ")

Wednesday, March 29, 2006

 


working with CSV files in MSH (part two)



In this second part of this serie, I will do some more combining with the Dataset generated in part 1 : working with CSV files in MSH (part one)

this will get you back to the status we here last time,
You need the helper functions from last post loaded for this !

MSH>. connect-csv c:\CsvExample

TABLE_NAME
----------
ADComputers#csv
AdActive#csv
AdActive2#csv
Inventaris#csv
SmsResources#csv


Note that, as mentioned in the former post, you can connect all sorts of DB's(or datasources) using this method.

I made this function for commandline usage, I don't realy mind overwriting the $conn object, hence breaking the connection.

You can leave out the last 2 lines of the script, generating the tables list, and replace it by :

return $conn

then you can do this :

$CsvConnCsvExample = connect-csv c:\CsvExample

if you then also change the get-DataTable function to take $conn as a parameter, by changing this line :

Param ($name )

into

Param ($name , $conn)

now $conn is not in the $global scope but we need to provide it :

$AdActive = get-DataTable AdActive#csv $CsvConnCsvExample

but this makes us flexible with more connections, but for commandline usage I prefer the way I did them in the last post, but if you use them as script functions, the changes mentioned could be more handy.

as I get the dataTables offline (and just use export-csv to write), I don't bother, so I go ahead using the functions as the where in last post).

Only I added one column to the SmsResources.csv file to make next examples more clear.

name,ResourceID,Obsolete
PC42,62301,1
PC73,62370,0
PC64,62360,1
PC76,62380,0
PC80,62381,0
PC64,62390,0


after those changes we do a complete reload:

# just past this into the CLI to get back to the status we here last time
# You need the helper functions from last post loaded for this !!

. connect-csv c:\CsvExample

$AdActive = get-DataTable AdActive#csv
$Inventaris = get-DataTable Inventaris#csv
$SmsResources = get-DataTable SmsResources#csv

$ds = new-object System.Data.dataSet
$ds.merge($AdActive)
$ds.merge($Inventaris)
$ds.merge($SmsResources) 

$parent = $ds.tables.item("ADActive").columns.item('name')
$child = $ds.tables.item("SmsResources").columns.item('name')
$rel = new-object System.Data.DataRelation("Ad_SMS",$Parent,$child,$false)


now we can go one where we were, getting only the records from the other table is easy :

name,ResourceID,Obsolete
PC42,62301,1
PC73,62370,0
PC64,62360,1
PC76,62380,0
PC80,62381,0
PC64,62390,0


to combine them we can use this :

$ds.tables.item("AdActive") | select name,logon,
  @{e={$_.getchildrows("Ad_sms").count};n='count'},
  @{e={$_.getchildrows("Ad_SMS") | foreach {$_.ResourceID}};n='ResourceID'},
  @{e={$_.getchildrows("Ad_SMS") | foreach {$_.Obsolete}};n='Obsolete'} | ft -auto


Note the adding of Format-table (FT) at the and of the line, leave it out and you see why I did this ;-)

Copied to the shell (handy with Quick edit on ;-)) you get this result:

MSH>$ds.tables.item("AdActive") | select name,logon,
>>   @{e={$_.getchildrows("Ad_sms").count};n='count'},
>>   @{e={$_.getchildrows("Ad_SMS") | foreach {$_.ResourceID}};n='ResourceID'},
>>   @{e={$_.getchildrows("Ad_SMS") | foreach {$_.Obsolete}};n='Obsolete'} | ft
-auto
>>

name logon                count ResourceID     Obsolete
---- -----                ----- ----------     --------
PC64 3/13/2006 7:49:31 AM     2 {6236062390} {10}
PC80 3/20/2006 7:49:31 AM     1 62381          0
PC76 3/20/2006 8:14:59 AM     1 62380          0
PC79 3/20/2006 7:49:31 AM     0 {}             {}



Ok Cofee and Chess waiting got to run again,

$ds.tables.item("AdActive") | select name,logon,
  @{e={$_.getchildrows("Ad_sms").count};n='count'},
  @{e={$_.getchildrows("Ad_SMS") | foreach {$_.ResourceID}};n='ResourceID'},
  @{e={$_.getchildrows("Ad_SMS") | foreach {$_.Obsolete}};n='Obsolete'} | where {$_.obsolete -contains 0} | ft -auto

# save to a new CSV and show again

$ds.tables.item("AdActive") | select name,logon,
  @{e={$_.getchildrows("Ad_SMS") | where {$_.obsolete -eq 0} | foreach {$_.ResourceID}};n='ResourceID'} | export-csv -no c:\CsvExample\AdSmsActive.csv

get-DataTable AdSmsActive.csv


those are witout expl.

gr /\/\o\/\/

Tags :


 0 comments

Tuesday, March 28, 2006

 


working with CSV files in MSH (part one)



This post is about working with CSV files in MSH,

I wil again use OleDb connection and a dataset to work with as I did with :

Access :
scripting games Last Day MSH answers for event 7 and 8

Excel :
Using ADO to get data from Excel to Dataset in Monad.

SQL (SQL Provider) :
Getting and Working With SQL Server data in Monad

Also I'm going to use relations as I did in :

More DataTables and joining them in Monad

As from the import into the datatable all data is the same so also all other sources could be mixed. I will go on the joining example above (it will only show the row in the second table to combine the sources to a new CSV.

(See the Access example from the scripting games series also for a way to sum and group using the compute method of the dataset and more info about the select statement with expression see also Report MP3 count and size by User from MSH ) and in Some fun With Monads Add-Member, MP3 files and COM you can see another powerfull way to extend MSH objects Get-Member.

so you find the examples a bit chryptic you can find more info about the methods used in the scripts in those posts, also handy if your gonna play with datasets from monad could be this post : Strange behavour of get-member on DataTables , (it's not strange to me anymore as I'm used to it but is a bit confusing as you also can see in the NG as the topic keeps coming up.

a nice quote from Keith Hill about it just posted there :

What I am getting at is *perhaps* this is a case of what's logical
in the abstract verus useful on a daily basis.


--
Keith


but enough links, on with the CSV scripts ;-)

CSV :

for the example I take 3 CSV files to combine,

1) Computers in AD (selected on logonTime)
2) A list of Computers in SMS
3) A Inventory (CDMB) List in CSV format.

I will supply the way to get the first 2 files, but for if you not have SMS or AD I will supply samples of the 3 files below, and as mentioned you also can take other sources as input. :

Save the files with content in the folder c:\CsvExample :

ADComputers.csv

name,logon,description
PC42,"10/17/2005 11:02:32 AM",Foo
PC81,,monad
PC64,"3/13/2006 7:49:31 AM",Bar
PC80,"3/20/2006 7:49:31 AM",bar
PC76,"3/20/2006 8:14:59 AM",Mow
PC79,"3/20/2006 7:49:31 AM",niets

SmsResources.csv

name,ResourceID
PC42,62301
PC73,62370
PC64,62360
PC76,62380
PC80,62381
PC64,62390


Inventaris.csv

PC73,void
PC64,bar
PC76,mow
PC80,bar
PC81,monad
PC79,niets


Now we first start by declaring a helper function

# Connect CSV helper function

function connect-csv {
  Param ($Path = ".")
  $ConnString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=$path;Extended properties='text;HDR=Yes;FMT=Delimited'"
  $Conn = new-object System.Data.OleDb.OleDbConnection($connString)
  $conn.open()
  $Tables = $Conn.GetOleDbSchemaTable([System.Data.OleDb.OleDbSchemaGuid]::tables,$null)
  $Tables | select TABLE_NAME


After you have loaded this helper function (just past the code in your MSH window)

you can connect to a Directory (database of CSV's) like this :

MSH>. connect-csv c:\CsvExample

TABLE_NAME
----------
ADComputers#csv
Inventaris#csv
SmsResources#csv


Note, that I start the function with a dot, so in the current scope so I keep the connection, an other way to do this is to return the connection.

as a helper I show the files we created :

but this only makes the connection

now we want to get the CSV files, I made another helper function for that :

# helper function to get a CSV file into a dataset :

function get-DataTable {
  Param ($name )
  $cmd = new-object System.Data.OleDb.OleDbCommand("Select * from [$name]",$Conn)
  $da = new-object System.Data.OleDb.OleDbDataAdapter($cmd)
  $dt = new-object System.Data.dataTable
  [void]$da.fill($dt)
  $dt.TableName = $name.split("#")[0]
  return $dt


after we loaded that function (rember if you put it to a file you need to dot source it also when you run it to keep it available)

after you have loaded the helperfunction we can allready use it like this :

MSH>get-datatable ADComputers#csv

name                       logon                      description
----                       -----                      -----------
PC42                       10/17/2005 11:02:32 AM     Foo
PC81                                                  monad
PC64                       3/13/2006 7:49:31 AM       Bar
PC80                       3/20/2006 7:49:31 AM       bar
PC76                       3/20/2006 8:14:59 AM       Mow
PC79                       3/20/2006 7:49:31 AM       niets


But we also can do this :

MSH>import-csv ADComputers.csv | where {$_.logon -gt (get-date).AddDays(-30)}

name                       logon                      description
----                       -----                      -----------
PC64                       3/13/2006 7:49:31 AM       Bar
PC80                       3/20/2006 7:49:31 AM       bar
PC76                       3/20/2006 8:14:59 AM       Mow
PC79                       3/20/2006 7:49:31 AM       niets


MSH>import-csv ADComputers.csv | where {$_.logon -gt (get-date).AddDays(-30)} |export-csv -no c:\CsvExample\AdActive.csv


Note that on the Second line the output get's redirected to a New CSV file.
that only contains the computers that where actualy seen this Month.

this file we will use in the rest of your example.

now lets readin the rest of the CSV files :

# Get CSV files into DataTables

$AdActive = get-DataTable AdActive#csv
$Inventaris = get-DataTable Inventaris#csv
$SmsResources = get-DataTable SmsResources#csv

# Join all Tables in a DataSet

$ds = new-object System.Data.dataSet

$ds.merge($AdActive)
$ds.merge($Inventaris)
$ds.merge($SmsResources) 

# Add Relation from AD to SMS resource

$parent = $ds.tables.item("ADActive").columns.item('name')
$child = $ds.tables.item("SmsResources").columns.item('name')
$rel = new-object System.Data.DataRelation("Ad_SMS",$Parent,$child,$false)
$ds.Relations.add($rel) 


Now we are able to compare those 2 files :

MSH>$ds.tables.item("AdActive") | select name,{$_.getchildrows("Ad_sms").count}


name                                            $_.getchildrows("Ad_sms").count
----                                            -------------------------------
PC64                                                                          2
PC80                                                                          1
PC76                                                                          1
PC79                                                                          0

# more nice formatted and filtered not in SMS 
MSH>$ds.tables.item("AdActive") | select name,logon,@{e={$_.getchildrows("Ad_sms").count};n='count'} | where {$_.count -eq 0}

name                       logon                                          count
----                       -----                                          -----
PC79                       3/20/2006 7:49:31 AM                               0

# Count active and not in SMS

MSH>$ds.tables.item("AdActive") | select name,logon,@{e={$_.getchildrows("Ad_sms").count};n='count'} | where {$_.count -eq 1} | measure-Object


Count    : 2
Average  :
Sum      :
Max      :
Min      :
Property :


I will do the further combining (in a next post,
as it it getting a bit to much for one post.)

but you can already see how handy it it to compare

but I will add the script that created the AD listing (not it uses the replicated logontime, so it's 2 weeks acurate, if you need to check all domaincontrollers to be sure you can use another example on my blog (search for AD on blog).

# get all user or Computer logontimes in an OU from a AD
# /\/\o\/\/ 2006
# http://mow001.blogspot.com

$Root = New-Object DirectoryServices.DirectoryEntry 'LDAP://server/ou=computers,dc=domain, dc=COM'
$Searcher = New-Object DirectoryServices.DirectorySearcher
$Searcher.SearchRoot = $root
$searcher.PageSize = 900

$searchItem = "CN"
$searchValue = "*"
$searchClass = "User"
$SearchCat = "*"
$searcher.Filter = "(&($($searchItem)=$($searchValue))(objectClass=$($searchClass))(objectCategory=$($SearchCat)))"

$PropList = "CN","ObjectClass","ObjectCategory","distinguishedName","lastLogonTimestamp","description"
$PropList | foreach {[void]$searcher.PropertiesToLoad.Add($_)}


$logon = $searcher.findAll() | select @{e={$_.properties.cn};n='name'},
  @{e={[datetime]::FromFileTimeUtc([int64]$_.properties.lastlogontimestamp[0])};n='logon'},
  @{e={$_.properties.description};n='description'}

# export to CSV files :

$logon | export-csv -no c:\CsvExample\ADComputers.csv

# Only seen last Month :

$logon | where {$_.logon -gt (get-date).AddDays(-30)} | export-csv -no c:\CsvExample\AdActive.csv 


and the script that created the SMS listing (with some more properties ;-):

# get SMS Resources

$oq = new system.management.objectquery
$oq.QueryString = "select Name,NetbiosName,Obsolete,ResourceId,Client,ClientType from  SMS_R_System"
$mos = new-object system.management.ManagementObjectSearcher($oq)
$mos.scope.path = "\\sms001\root\sms\Site_mow"
$mos.get() | select [a-z]* | export-csv -no c:\CsvExample\SmsResources.csv


with the obsolete property in SMS we can see why one is double in SMS.

more on combining and more advanced select queries in next post.

enjoy your querying in MSH,

Greetings /\/\o\/\/

Tags :


posted by /\/\o\/\/
 1 comments
 


and another source for MSH scripts is born



and another source for MSH scripts is born

See :
Introducing Readify's MSH script site.

the site is : http://scripts.readify.net

Also you can find an article about the Exchange Management Shell (Monad + tip of the day and Exchange snapins ) on : msExchange.org.

b.t.w. on Monad source in the script section you can find a script from James Truher to get logontimes from AD, as I did in get a Users LastLogontime and Domaincontroller from MSH ", but without the Snap-In I created as a work-around for the LargeInt problem see :MSH snap-in to Translate IADsLargeInteger to Int64 (also the ManagementObjectSearcher will translate it I will show it in the next post as a bonus item ;-)

I wanted to start on an item about working with CSV files, (I will will include the logontime script to create one of the CSV files), when I noticed the links I did mention here,
so I need to go on, to be able to post it today ;-)


greetings /\/\o\/\/
Tags :


posted by /\/\o\/\/
 0 comments

Monday, March 27, 2006

 


VBscript hosting in MSH, Inputbox in Monad part 2



In the comments of my last post Jeffrey Snover, made my com example for a fileOpen-dialog into a complete function (.

As I did say in my comment the reason this is handy is that .NET forms do not get the focus when they are started and are hidden (for a workaround for a form see : out-dataGrid function for Monad ) but for a .NET dialog I have no solution yet, so that function is very handy

*note* in some other GUI examples on my blog I use the topmost = $true method, this is not that elegant, and more important not working anymore since beta 3.
you should replace the method in those scripts.

before I also did some hacks to get an inputbox from MSH,

getting an Inputbox in MOnad,

also in the Newsgroup thread : MSH - Is it possible to show a message box and and get input ... James Truher made the vbscript solution a bit cleaner with genarating a temp file.

But using Com and the MSScriptControl, I found yet a better way :

# get-inputBox
# Inputbox from MSH using MSScriptControl
# /\/\o\/\/ 2006
# http://mow001.blogspot.com

function get-input {
  param ($message = "Input : ",
         $Title = "Inputbox")
  $vbs = new -com MSScriptControl.ScriptControl
  $vbs.language = 'vbscript'
  $vbs.addcode("function getInput() getInput = inputbox(`"$message`",`"$title`") end function")
  $result = $vbs.Eval('getInput')
  $result
}


you can add the functions you need with addcode() and than call them with eval() to get the result.

As you can see in the msgbox example below, if you do not need the input back
you can just use ExecuteStatement method, but to get a value back you need to wrap it into a function and use the eval method, like in the inputbox function

# make control

$vbs = new -com MSScriptControl.ScriptControl
$vbs.language = 'vbscript'

# display msgbox :

$vbs.ExecuteStatement('msgbox "Hello MSH World",,"Message from VBscript"')

# Vbscript evaluations and functions

$vbs.Eval('2^16')

$vbs.Eval('strreverse("This is a test string.")')



this eval method is "normaly" to evaluate expressions using vbscript :
(so you can use al the vbscript math functions you are used to, also very handy ;-) )
thats why we wrap the inputbox in get-input into a function, to be able to use it with eval().

b.t.w. the last line above is also another solution to the last question in the scripting games, 2006 Winter Scripting Games (part 2) , if you can't beat them, join them ;-)



b.t.w. you do not have access to the Wscript object, so for example wscript.echo will not work, you need cscript for that, but for the rest you have the full vbscript access, or jscript, or even python I think if its registered (not tried that).

Enjoy

greetings /\/\o\/\/
Tags :


posted by /\/\o\/\/
 4 comments

Sunday, March 26, 2006

 


Some Monad Com hacks



Just some Com hacks in MSH I think are nice :
*edit* I keep on forgetting, you will need this alias, or change the new to new-object,
set-alias new new-object


# Some COM hacks

# local user management

MSH>(new -com shell.users).create('foo')

isLoggedOn               : False
passwordRequired         : False
interactiveLogonAllowed  : True
isProfilePrivate         :
isPasswordResetAvailable : False

MSH>(new -com shell.users).item('foo').changePassword('Secret','')
True

MSH>(new -com shell.users).item('foo')

isLoggedOn               : False
passwordRequired         : True
interactiveLogonAllowed  : True
isProfilePrivate         :
isPasswordResetAvailable : False

MSH>(new -com shell.users).remove('foo')
True

MSH>(new -com shell.users).item('foo')
Exception calling "item" with "1" argument(s): "The parameter is 
incorrect. (Exception from HRESULT: 0x80070057 (E_INVALIDARG))"
At line:1 char:28

# File Dialog

$c = new -com UserAccounts.CommonDialog

MSH>$c.ShowOpen()
True
MSH>$c


Filter      :
FilterIndex : 0
FileName    : C:\Documents and Settings\mow\My 
Documents\msh_transcript.20051129213303.txt
Flags       : 0
Owner       :
InitialDir  :

# Make a CAB file

$m = new -com  makecab.makecab
$m.CreateCab('c:\mow.cab',$false,$false,!-1)
$m.addfile('c:\test.txt','test.txt')
$m.CloseCab()


enjoy,

gr /\/\o\/\/
Tags :


posted by /\/\o\/\/
 2 comments

Thursday, March 23, 2006

 


It's busy at the Monad front



It's busy at the Monad front lately, so again I have a buch of links :

Keith got Scott Hanselman on Monad and how ;-)

Loving Mush - I mean Monad

( also check the podcast )

Also Keith has a Range Code Camp Presentation on Monad soon, read more on his blog Keith Hill's Blog

PS if you came from his blog looking for WMI examples, the script in my latest post about it generates scripttemplates for calling WMI Methods MSH get-WmiMethodHelp function Update 3
Also try a search on WMI on my blog, you will find some more examples I did in the past (as showing the WMI items in a GUI )

Monad source features some Monad downloads, scripts, forums and more to come.
Monad source

Karl Prosser is very busy on his MSH anallyzer
$MSHHOME in MSH ANALYZER

on The lazy admin also more and more monad stuff
Using MSH With Exchange 2003
TheLazyadmin.com MSH Category

also a nice example if you use I-tumes on opinionatedgeek
Using Monad/MSH to parse iTunes playlists [.NET]

Tony did some updates on his remote host
Monad Remoting - Now Can Read SecureString From Remote Client


also on IRC (irc.freenode.net channel #monad), there is MSH activity.

also the Monad Beta program moved to Connect for the bug reporting, you can read more about it on Lee Holmes blog Precision Computing

you also can find an item about an issue I posted about in the NG
Monad (Monad Technology Blog)
Finding out what determines which properties are displayed

I changed it to this, I think would be better (showing the main item CurrentUsage)

root\cimv2\Win32_PageFileUsage

Caption
Name
CurrentUsage
PeakUsage

I generated some lists to check the other properties defined like this :

# list of all defined types :

([xml](gc $MSHHOME\types.mshxml)).types.type foreach {$_.name}

# list of WMI default properties

([xml](gc $MSHHOME\types.mshxml)).types.type foreach {"`n$($_.name.split('#')[1])`n";$_.members.memberset.members.PropertySet.ReferencedProperties foreach {$_.name}}

(Little bit of garbage at begin and end)

and this one also gets all properties of an instance for each WMI class in the list (to compare)

Take care !!! as cim_datafile is one of them this takes a long time, its better to get the names fro m the list and get the ones needed , I did this 2 times (second time to text file) just as I was lazy but it took 20 minutes !! (at will show only the first but gets all) it was just a quick oneliner to greate the 35 page list to compare)

if MSH seems to hang , (its not but scanning all your disks) and you want to stop it crtl-C does not work , you can break with ctrl-break this will stop the script but also closes the MSH session so use at own risk ;-)

the one-liner looks like this :

([xml](gc $MSHHOME\types.mshxml)).types.type foreach {"`n$($_.name.split('#')[1])";get-wmiobject ($_.name.split('#')[1].split('\')[2]) select -first 1 fl [a-z]*;$_.members.memberset.members.PropertySet.ReferencedProperties foreach {$_.name}}

Append this to output it to file -> out-file c:\wmiformat.txt

that's it for now

enjoy,

greetings /\/\o\/\/
Tags :


posted by /\/\o\/\/
 1 comments

Saturday, March 18, 2006

 


Monad Remoting



Monad does not support remoting yet,
this is planned for V2.

but there is help !

Tony posted a remotehost for Monad on GotDotNet,
you can read about it on his blog here :

Securely Extend Msh Host User Interface over Network

I did play with it a bit and I think it works great.
well done Tony !

enjoy,

gr /\/\o\/\/

Tags :


posted by /\/\o\/\/
 0 comments

Wednesday, March 15, 2006

 


How MSH Works



In the Microsoft Command Shell (MSH) Programmer's Guide,

you can find the chapter How MSH works :

http://windowssdk.msdn.microsoft.com/library/en-us/Monad_Prog/html/ced30e23-10af-4700-8933-49873bd84d58.asp?frame=true

I think this is a very good chapter also for not programmers (the second half of the chapter is about the MSH console itself with examples of export-clixml and good info about the Code singning modes of MSH)
and much more pieces of this guide are also usefull when you are "just" an admin using Monad like myself, and also if you want to write a small snapin for a specific task when needed , like I did here MSH snap-in to Translate IADsLargeInteger to Int64 .

enjoy,

gr /\/\o\/\/


posted by /\/\o\/\/
 0 comments

Wednesday, March 08, 2006

 


Hosting an MSH runspace from Monad



While I started my Monad hosting project, (redoing a management application I did in VB.NET 2002 to C# using an embedded MSH runspace), I did think - Hey, I think I can also do this from MSH, so I did build this example in MSH.

Tare a lot of MSH hosting examples already (hosting VB.NET / C# / Iron Phyton / Vbscripts) inline in an MSH script , but I think there was any about hosting MSH from MSH Yet ;-)

The script will create an MSH runspace, and creates a form to host it, it is only a basic example that will take the input in one RTBbox (the upper) and outputs the result on the other rtbbox (the lower).
you can use the menu to start the script in the upper inputbox, a button would be more handy but I wanted to keep the example simple (You can do ALT + F-R as a shortcut) .

Note that we are realy creating another monad engine here, not using the original MSH environment.

In the mean time the code in Lee Holms blog, in the last part of the LOGO series solved my problem interacting with object on the form I mentioned in former post, as you can give variables to the sessionstate, you can use on the form .

I implemented this in my C# host (much more usefull there), but it could also be done here I added the $os variable as an example.

the example looks like this :

# HostingDemo.MSH   
# Hosting MSH in a form from MSH 
#   
# /\/\o\/\/ 2006   
# http://mow001.blogspot.com 
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms"

# make a runspace for processing commands from hosting form 

$rc = [System.Management.Automation.Runspaces.RunspaceConfiguration]::Create()
$r = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace($rc)

$ri = new-object System.Management.Automation.RunspaceInvoke($r)
$r.OpenAsync()

# Make form 

$form = new-object System.Windows.Forms.form  
$form2 = new-object System.Windows.Forms.form  
$Form.text = "Monad Hosting from a Form in MSH Demo"  
$form.Size =  new-object System.Drawing.Size(810,410

# Build Menu   

$MS = new-object System.Windows.Forms.MenuStrip  
$Mi = new-object System.Windows.Forms.ToolStripMenuItem("&File")  

$Msi1 = new-object System.Windows.Forms.ToolStripMenuItem("&Run")  
$msi1.add_Click({$result = $ri.invoke($rtbInput.text);$rtbOutput.appendtext($($result | out-string))  ; $result | out-host})   
$Mi.DropDownItems.Add($msi1)  

$Msi2 = new-object System.Windows.Forms.ToolStripMenuItem("&Quit")  
$msi2.add_Click({$form.close()})   
$Mi.DropDownItems.Add($msi2)  

$ms.Items.Add($mi)  
$form.Controls.Add($ms)  

# Add Rich Text Box for Input

$rtbInput = new-object System.Windows.Forms.RichTextBox 
$rtbInput.Location = new-object System.Drawing.Size(10,30
$rtbInput.size = new-object System.Drawing.Size(780,170
$rtbInput.Anchor = "top, left, right" 
$form.Controls.Add($rtbInput)

# Add Rich Text Box for output

$rtbOutput = new-object System.Windows.Forms.RichTextBox 
$rtbOutput.Location = new-object System.Drawing.Size(10,210
$rtbOutput.size = new-object System.Drawing.Size(780,150
$rtbOutput.Anchor = "top, bottom, left, right" 
$form.Controls.Add($rtbOutput)

# Import some variables to MSH

$os = get-wmiobject win32_operatingsystem
$r.SessionStateProxy.SetVariable("os",$os)

# show Form 

$Form.Add_Shown({$form.Activate()})
$form.showdialog()  


as we give the $os variable to the sessionstate you can use the $os variable in your script in the form (not other variables from the host).

it's very basic and ofcourse the use of doing this from MSH is is a bit questionable, but I think it is a nice example to show how easy that it is to host monad in an .NET application.

my C# project is not of any use yet, but for another sample of hosting MSH from a .NET application see Karl Prossers MSH hosting example here MshAnalyzer , you can find a binary (altough not the latest at the moment) there also

enjoy your hosting,

Greetings /\/\o\/\/
Tags :


posted by /\/\o\/\/
 0 comments

Monday, March 06, 2006

 


MSH get-WmiMethodHelp function Update 3



Another update on the get-WmiMethodHelp function, to get help on WMI methods and to generate template scripts for calling them.

the last version is broken in Beta 3 of Monad.

Reason for this is the change of behavior of -EQ - NE on an array, in Beta 2 this would return $true or $false in beta 3 they will return the members of the array that
do match. e.g. :

MSH>1,2,3,4 -eq 2
2
MSH>1,2,3,4 -ne 2
1
3
4

so I replaced them on a couple of places by -contains statements.
I also had to redo some other constructions for this and the overloads for the $de object seem to have changed in .NET RTM, I fixed that also. And did some more small changes, e.g. use of the $mp (I first planned a compleet rewrite but I will leave at this for now) , so that everything works again and a little but more cleaning is done.

after playing with the generated scripts (see also the example about filling a generated template in the WMI links), it is also nice to look into the workings of the get-WmiMethodHelp function how you can use the GetMethodParameters to get information about what parameters to pass to the WMI method and generate the script.

and here the revisited script :

# GetWmiMethodInfo.MSH (V3) 
# Gets Method Parameters with descriptions from WMI class  
# it also Creates an Example script.  
# /\/\o\/\/ 2006  
# http://mow001.blogspot.com 

Function get-WMIMethodHelp{  
  Param ([string] $WmiClass = "",[string] $WmiMethod = "")    
  if ($wmiClass -eq "") {"No WMIClass given";Return}  

  # Set Options  

  $opt = new-object management.ObjectGetOptions  
  $opt.UseAmendedQualifiers = $true  

  # Connect to Class 

  $MS = new-object management.ManagementScope
  $MP = $MS.Path  
  $MC = $Null 
  &  {  
       Trap {Continue
       $script:MC = new-object management.ManagementClass($MP,$WMIClass,$opt)  
     }
  if (! $script:mc) {"WMI Class not found";Return

  # Check if Method does Exist 
  $M = $script:mc.Get_Methods() | foreach {$_.name} 
  if (!($M -contains $WMIMethod)) {"Method not found, Methods are :";$m;return

  # Make a stringBuilder to make a Template Script  

  $SB = new-Object text.stringbuilder  
  $SB = $SB.Append('$Class = "') ; $SB = $SB.AppendLine("$WMIClass`"")  
  $SB = $SB.Append('$Method = "') ; $SB = $SB.AppendLine("$WMIMethod`"")  

  # Check for Static Qualifier (If not present then Method Needs Instance)  

  $Qualifiers=@()
  $script:mc.Get_Methods()[$wmiMethod].get_Qualifiers() | foreach {$qualifiers += $_.name}
  $static = $Qualifiers -Contains "Static" 

  If ($static) {  

    $SB = $SB.AppendLine('$MP = new-object system.management.ManagementPath')  
    $SB = $SB.Append('$MP.Server = "') ; $SB = $SB.AppendLine("$($MP.Server)`"")  
    $SB = $SB.Append('$MP.NamespacePath = "') ; $SB = $SB.AppendLine("$($MP.NamespacePath)`"")  
    $SB = $SB.AppendLine('$MP.ClassName = $Class`n')  
    $SB = $SB.AppendLine('$MC = new-object system.management.ManagementClass($MP)')  

  }Else{  
    # IF not static We need to provide The Key Properties to get the instance.  

    $SB = $SB.AppendLine('$Computer = "."')  
    $SB = $SB.AppendLine("`n#$wmiClass Key Properties :")  

    $Filter = ""  
    $script:mc.get_Properties() | foreach {  
      $Q = @()
      $_.get_Qualifiers() | foreach {$Q += $_.name} 

      $key = $Q -Contains "key" 
      If ($key) {  
        $CIMType = $_.get_Qualifiers()["Cimtype"].Value  
        $SB = $SB.AppendLine("`$$($_.Name) = [$CIMType]")  
        $Filter += "$($_.name) = `'`$$($_.name)`'"   
      }  
    }  

    $SB = $SB.Append('`n$filter = ');$SB = $SB.AppendLine("`"$filter`"")  
    $SB = $SB.AppendLine('$MC = get-WMIObject $class -computer $Computer -filter $filter`n')  

  }  
  $SB = $SB.AppendLine('$InParams = $mc.GetMethodParameters($Method)`n')  

  # output the Helptext   


  "$WMIClass : $WMIMethod :`n"  

   $q = $script:mc.Get_Methods()[$WMIMethod].get_Qualifiers() | foreach {$_.name} 
   if ($q -eq "Description") {$script:mc.Get_Methods()[$WMIMethod].get_Qualifiers()["Description"].Value}  
  

  "`n$WMIMethod Parameters :"  
  # get the Parameters  
   
  $inParam = $script:mc.Get_Methods()[$WMIMethod].get_InParameters()  

  $HasParams = $False  
  if ($true) {  
    trap{'[None]';continue}   

    $inParam.get_Properties() | foreach {  
      $HasParams = $true  
      $Q = $_.get_Qualifiers() | foreach {$_.name} 

      # if Optional Qualifier is not present then Parameter is Mandatory  
      $Optional = $q -contains "Optional" 

      $CIMType = $_.get_Qualifiers()["Cimtype"].Value  
      "`nName = $($_.Name) `nType = $CIMType `nOptional = $Optional"  

      # write Parameters to Example script  

      if ($Optional -eq $TRUE) {$SB = $SB.Append('# ')}  
      $SB = $SB.Append('$InParams["');$SB = $SB.Append("$($_.Name)`"] = ");$SB = $SB.AppendLine("[$CIMType]")  
      if ($q -eq "Description") {$_.get_Qualifiers()["Description"].Value}  
    }  
  }  

  # Call diferent Overload as Method has No Parameters  

  If ($HasParams -eq $True) {  
    $SB = $SB.AppendLine("`n`"Calling $WMIClass : $WMIMethod with Parameters :`"")  
    $SB = $SB.AppendLine('$inparams.get_properties() | select name,Value')  
    $SB = $SB.AppendLine('`n$R = $mc.InvokeMethod($Method, $inParams, $Null)')  
  }Else{  
    $SB = $SB.AppendLine("`n`"Calling $WMIClass : $WMIMethod `"")  
    $SB = $SB.AppendLine('`n$R = $mc.InvokeMethod($Method,$Null)')  
  }  

  $SB = $SB.AppendLine('`"Result : `"')  
  $SB = $SB.AppendLine('$R')  

  # Write the Sample Script :  

  "`nSample Script :`n"  
  "# $WMIclass $WMIMethod-Method Sample Script"  
  "# Created by Get-WmiMethodHelp (v3)"  
  "# /\/\o\/\/ 2006"  
  "# Fill InParams values before Executing"  
  "# InParams that are Remarked (#) are Optional`n"  

  $SB.ToString()  
}  

set-alias gwm get-WMIMethodHelp 




(load the function "dotsourced" like this :

. .\get-WmiMethodhelp.msh

after that the function is loaded and you can use it on the Command prompt, see also examples in the former posts in the series, links are below)

you can past the generated script to notepad, edit it and then past it back to the console or save it a script, and then call it

for more info about using WMI from MSH :

The 3 part series About Discovering WMI in MSH and Getting Help from WMI :

" Wmi-Help Part 1 " Getting All the WMI Classes and Descriptions in a HashTable (getWmiClasses.MSH)"
WMI help Part 2 ",Getting Help on WMI classes, ( get-WmiHelp (GWH) Function)"
WMI help Part 3 (Methods) ", Getting Help on Methods and generating Sample Scripts. (updated by the script posted now)

and :

WMI viewer script for MSH (GUI) (here you can also use this : out-dataGrid function for Monad , that will output almost any MSH commands output to a datagrid, there you also can find another change in Beta 3, the $form.topmost = $true does not work anymore, I did find another workaround for this here.this would work for all GUI scripts.)
Lets Query WMI from MSH (WMI queries on more (related) classes)
Passing (not so) mandatory Parameters to WMI methods in MSH (example use of generated script-template)
Saving a WMI instance to a XML-file from MSH (save a WMI instance for later use)

greetings /\/\o\/\/
Tags :

PS if you do find more scripts that do not work (anymore) , please leave a comment.


posted by /\/\o\/\/
 0 comments

Archives

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.
Google
 
Web mow001.blogspot.com

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