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.
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.
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 :
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/200511:02:32 AM Foo PC81 monad PC64 3/13/20067:49:31 AM Bar PC80 3/20/20067:49:31 AM bar PC76 3/20/20068:14:59 AM Mow PC79 3/20/20067: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/20067:49:31 AM Bar PC80 3/20/20067:49:31 AM bar PC76 3/20/20068:14:59 AM Mow PC79 3/20/20067: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.
# 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/20067:49:31 AM 0
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
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 ;-)
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,
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).
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
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:1char:28
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
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 ;-)
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 .
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
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
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}
$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}
"`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)