Get-World | ConvertTo-PowerShell
makovec
This user hasn't shared any biographical information
Homepage: http://www.powershell.cz
Posts by makovec
My presentations
May 7th
I was asked by my friend to point him to presentations I delivered this year. As it should be useful also for others I decided to summarize it to this post. Please note that all my presentations were in Czech so maybe not so useful for English speaking people. But at least you can can my demo files as I added it to all sessions.
PowerShell Virtual Academy
Whole show was started in December when I agreed with my local IT Pro Evangelist that we’ll create four sessions over Live meeting. This was planned as beginning for people interested in PowerShell.
Every part contains link to video, presentation, scripts I used and whole transcription of the session. If there were some questions during session, it’s answered also in the article. General overview of the academy is accessible on TechNet.
TechDays 2012
It was a great pleasure when I was asked to give a session about PowerShell v3 during Microsoft’s Czech biggest conference – TechDays. The conference was held in two cities – Brno and Praha. I really enjoyed both shows. There was a lot of questions after my sessions and in Prague I spent more than hour with answering. At the moment there is available only presentation from this conference.
Microsoft Virtual Academy
Maybe you already heard about Microsoft Virtual Academy (MVA). It contains free lessons for different Microsoft related topics. I definitely recommend you to try some lesson related to your work. Anyway – we decided that we’ll move PowerShell Academy to MVA to allow people to use MVA environment for knowledge testing. Every MVA lesson contains also test at the end. So you can immediately check if you listened with open eyes and ears. You can find it at MVA web under PowerShell akademie.
Future
I was already asked to continue with PowerShell Virtual Academy, so at the moment I am building an outline for additional (probably again four) lessons.
Measure presentation length
Mar 12th
Last weeks I spent most of my time preparing the presentation for TechDays 2012. Not surprisingly – I was talking about PowerShell v3 in new Windows 8. As there was strict requirement for presentation length (60 minutes) I had to plan carefully. Therefore I decided to create small script to measure my presentation length. It reports time for every topic I discussed.
Function uses simple comparison of two time stamps with New-TimeStamp cmdlet. Then it just shows it in console but also writes it to text file for future reference. Everything is hardcoded in function now. Maybe will change it in future, now it’s here just for future reference.
function Show-PresentationLength
{
BEGIN
{
$Global:Presentation=@{}
$path = "$env:USERPROFILE" + '\Documents\PresentationTiming.txt'
Out-File -FilePath $path -InputObject (Get-Date) -Append
}
PROCESS
{
Read-Host "Start ($_)"
$start = Get-Date
Write-Host "Running $_ ..." -Fore Yellow -NoNewline
Read-Host "Stop ($_)"
$end = Get-Date
$cycle = New-TimeSpan -Start $start -End $end
$Global:Presentation[[int]$_]=$cycle
$Presentation.GetEnumerator() |% -Begin {$sum=0} -Process {$sum+=$_.Value}
"Time ($_): {0:mm}:{0:ss}" -f $cycle
Out-File -FilePath $path -InputObject "Time ($_): $cycle of ($sum)" -Append
}
END
{
Clear-Host
"Total Time: {0:hh}:{0:mm}:{0:ss}" -f $sum
Out-File -FilePath $path -InputObject "Total Time: $sum" -Append
foreach ( $s in $($Global:Presentation.GetEnumerator() | Sort Name) )
{
"Slide {0}: {1:mm}:{1:ss}" -f $s.Name, $s.Value
}
}
}
When I wanted to test length of some topic I discussed, I just started it this way (checking time for first three slides):
PS C:\> 1..3|Show-PresentationLength
Start (1):
Running 1 …Stop (1):
Time (1): 00:10
Start (2):
Running 2 …Stop (2):
Time (2): 00:14
Start (3):
Running 3 …Stop (3):
Time (3): 00:14
Total Time: 00:00:39
Slide 1: 00:10
Slide 2: 00:14
Slide 3: 00:14
And can also see result in mentioned file (it also contains history).

BTW: Also because of this script I was able to finish both my presentations on time
See Enums for last failed command
Feb 27th
During last PowerShell Academy session I received a question if it’s possible to have own color as argument for ForegroundColor parameter of Write-Host cmdlet. My answer was – no, and I then showed how to see available values – either in console directly (by providing non-existed value) or to check MSDN help for System.ConsoleColor.
I like the idea of console way – anytime you provide some non-existing value, PowerShell will show you correct values as part of exception raised. I was then thinking about something more – hmm – elegant (?). Usually I just copy name of used enumeration and paste it to GetValues() method of Enum class.
[206]: Write-Host 'text' -ForegroundColor SomeColor Write-Host : Cannot bind parameter 'ForegroundColor'. Cannot convert value "SomeColor" to type "System.ConsoleColor" du e to invalid enumeration values. Specify one of the following enumeration values and try again. The possible enumeratio n values are "Black, DarkBlue, DarkGreen, DarkCyan, DarkRed, DarkMagenta, DarkYellow, Gray, DarkGray, Blue, Green, Cyan , Red, Magenta, Yellow, White". At line:1 char:35 + Write-Host 'text' -ForegroundColor <<<< SomeColor + CategoryInfo : InvalidArgument: (:) [Write-Host], ParameterBindingException + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.WriteHostCommand [207]: [enum]::GetValues([System.ConsoleColor]) Black DarkBlue DarkGreen DarkCyan DarkRed DarkMagenta DarkYellow Gray DarkGray Blue Green Cyan Red Magenta Yellow White
Then I came with following function.
function Get-EnumValue { [CmdletBinding()] param() Write-Verbose 'Checking last error.' $e = $Global:Error[0].Exception if ($e.ParameterType.IsEnum) { Write-Verbose 'Is Enum.' Write-Verbose "Enum name: $($e.ParameterType)" [enum]::GetValues($e.ParameterType.FullName) } else { Write-Verbose 'Not Enum!' } }
Run it every time you receive an error mentioning that you used bad value for enumeration. Function will check last error (stored in $Error[0]) and if it contains notice that it’s related to enum, function will return all enum values. I created alias genum for that and put it to my profile.
[208]: Write-Host 'text' -ForegroundColor SomeColor Write-Host : Cannot bind parameter 'ForegroundColor'. Cannot convert value "SomeColor" to type "System.ConsoleColor" du e to invalid enumeration values. Specify one of the following enumeration values and try again. The possible enumeratio n values are "Black, DarkBlue, DarkGreen, DarkCyan, DarkRed, DarkMagenta, DarkYellow, Gray, DarkGray, Blue, Green, Cyan , Red, Magenta, Yellow, White". At line:1 char:35 + Write-Host 'text' -ForegroundColor <<<< SomeColor + CategoryInfo : InvalidArgument: (:) [Write-Host], ParameterBindingException + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.WriteHostCommand [209]: Get-EnumValue Black DarkBlue DarkGreen DarkCyan DarkRed DarkMagenta DarkYellow Gray DarkGray Blue Green Cyan Red Magenta Yellow White [210]: Get-Command -CommandType Something Get-Command : Cannot bind parameter 'CommandType'. Cannot convert value "Something" to type "System.Management.Automation.Com mandTypes" due to invalid enumeration values. Specify one of the following enumeration values and try again. The possib le enumeration values are "Alias, Function, Filter, Cmdlet, ExternalScript, Application, Script, All". At line:1 char:25 + Get-Command -CommandType <<<< sgd + CategoryInfo : InvalidArgument: (:) [Get-Command], ParameterBindingException + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.GetCommandCommand [211]: genum Alias Function Filter Cmdlet ExternalScript Application Script All [212]: gc notExists Get-Content : Cannot find path 'Dropbox:\PowerShell\Scripts\notExists' because it does not exist. At line:1 char:3 + gc <<<< notExists + CategoryInfo : ObjectNotFound: (Dropbox:\PowerShell\Scripts\notExists:String) [Get-Content], ItemNotFou ndException + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand [213]: genum [214]:
Auto complete for about_* topics
Jan 7th
Today I was heavily working with PowerShell help system. And was tired to call it using Get-Help cmdlet. So I created small function which I put to my profile:
function Show-HelpAboutFunction { $topics = Get-Help about_* foreach ($t in $topics) { $tn = $t.Name -replace 'about_', 'abt-' $text = "function global:$($tn) { Get-Help $($t.Name) }" Invoke-Expression "$text" } }
So when in console I can write: abt-func<Tab> and can circulate help topics till have the one I need. I know that for some topics is better to write Get-Help with partial help topic name, but in some cases I like my solution more.
Note: I know that abt is not approved verb
ISE: List variables in active Script Pane
Jan 1st
I was working in ISE pretty much during last two days (oh yes, was nice end of 2011 and beginning of 2012). During script creation I was checking values of variables frequently. Wouldn’t be nice to see variables value and not just write it’s name to Command Pane? So I came with another menu Add-on command.
function GetValues { $content = $psISE.CurrentFile.Editor.Text $tokens = [System.Management.Automation.PsParser]::Tokenize($content, [ref] $null) |? {$_.Type -eq 'Variable'} | Sort Content -Unique foreach ($t in $tokens) { $prop = @{ Name = $t.Content Value = Get-Variable -Name $($t.Content) -ValueOnly -ErrorAction SilentlyContinue } New-Object -TypeName PSObject -Property $prop | Select Name, Value } } $psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add('Show values',{GetValues},'CTRL+SHIFT+V') | Out-Null
When you work with any script, you can run it and will see all actual script variables in Output Pane.

Using Tokenizer API I received all variables from current script and created new object with variable name and value. Then it’s send to output. I am thinking about some graphical output (WPF or ShowUI) or just to Out-GridView. There are also some another points to update but for my current needs it’s OK.
ISE: Run current line without selecting, AKA v3 feature
Jan 1st
I like one of new PowerShell v3 features. When you are in ISE and want to run current line, just press F8, it’s no more necessary to select the line and then use Run Selection (F8). I’d like to have it in v2 also so I created another quick function:
function RunLine { $editor = $psISE.CurrentFile.Editor $currentLine = $editor.CaretLine $currentLineLength = $editor.GetLineLength($currentLine) $currentPosition = $editor.CaretColumn $psISE.CurrentFile.Editor.Select( $currentLine, 1, $currentLine, $currentLineLength + 1 ) "Running >> $($psISE.CurrentFile.Editor.SelectedText)" Invoke-Expression $psISE.CurrentFile.Editor.SelectedText $psISE.CurrentFile.Editor.Select( $currentLine, $currentPosition, $currentLine, $currentPosition ) } $makovecRoot = $psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Makovec", $null, $null) $makovecRoot.Submenus.Add('Run line',{RunLine},'CTRL+F8') | Out-Null
It allows me to be at some line and by pressing Ctrl+F8 just run it:

If you want to see another cool new features in ISE v3, go to Windows Management Framework 3.0 CTP2 page and download document named Windows PowerShell ISE.pdf.
ISE: Add new line below/above current
Dec 28th
Today I was playing with PowerShell v3 and was frequently working inside ISE (love it’s Intellisense feature). I was in this situation few times:

As you can see, cursor is at position 0. At this time I want to add new line, so it means go to end of current line and press Enter. I wanted to automate it. Fortunately ISE object model is self-descriptive, so I created this small Add-on:
$psise.CurrentPowerShellTab.AddOnsMenu.Submenus.Add(
'Insert line below',
{
$psise.CurrentFile.Editor.Select(
$psise.CurrentFile.Editor.CaretLine,
$psise.CurrentFile.Editor.GetLineLength($psise.CurrentFile.Editor.CaretLine)+1,
$psise.CurrentFile.Editor.CaretLine,
$psise.CurrentFile.Editor.GetLineLength($psise.CurrentFile.Editor.CaretLine)+1)
$psise.CurrentFile.Editor.InsertText("`n")
}, "CTRL+ENTER")
$psise.CurrentPowerShellTab.AddOnsMenu.Submenus.Add(
'Shift line',
{
$psise.CurrentFile.Editor.Select(
$psise.CurrentFile.Editor.CaretLine, 1,
$psise.CurrentFile.Editor.CaretLine, 1)
$psise.CurrentFile.Editor.InsertText("`n")
$psise.CurrentFile.Editor.Select(
$psise.CurrentFile.Editor.CaretLine-1, 1,
$psise.CurrentFile.Editor.CaretLine-1, 1)
}, "CTRL+SHIFT+ENTER")
I added two features: add line below and before (shift line). You can call it either from menu:

or via keyboard shortcuts.
if ($PSVersionTable.PSVersion.Major -eq 3) { Start-Fun }
Sep 15th
As you all already read during last day, Microsoft showed Windows 8 at it’s Build conference. There are big changes in OS and I am sure there will be tons of articles about it. But for PowerShell enthusiasts in means something else. PowerShell version 3 is a part of new OS
Today, lot of people mentioned the most obvious changes/news/thoughts. To name a few:
- Dmitry Sotnikov – First Glimpse at PowerShell v3
- Jonathan Medd: PowerShell v3 – A Quick First Look and PowerShell ISE v3 – Now With IntelliSense
- @Jaykul – had some great tweets about short (and clever as usual) hints
After first check, I like following points:
- IntelliSense in ISE – it works in both - Script Pane and Command Pane. Watch different icons for different types.
- Commands Add-on in ISE - for me it looks like great tool for people new to PowerShell. They are able to see all possible parameters at one place and can easily fill/add it to current session. It contains question mark button which opens help for active cmdlet. When you fill all necessary parameters, you can insert result to your session. Unfortunately – it looks to me that it fully works only for cmdlets from core modules (Microsoft.PowerShell.*) and not for functions.
- Support for #region, #endregion in ISE – collapsible.
- ISE also support collapsing of expressions in brackets. As you can see on the picture it’s also highlighting matching braces.
- New way how modules loading work. You can use tab completion for functions even the module is not loaded. Again one point – what I tested till now it looks that it not work for script module (but need to test more with Export-ModuleMember).
- There is a module CimCmdlets - have to check it as it should be useful for my work.
Unfortunately I had to work today, so had not as many time as I wanted for some searching
Fortunately – will have holiday for next three weeks, so there will be enough time for other posts.
ChmToMobi Module
Sep 11th
It’s a year now since I bought Kindle for me. I have it still with me and frequently need to check PowerShell documentation. It led me to previous articles (1st and 2nd part) where I described in general, how to convert CHM file to MOBI. As I needed to automate it a bit, I created simple module for conversion process. Whole process is simple:
- Download ZIP file and unzip in to your module folder.
- Import module to your session (Import-Module chm2mobi).
- Run Convert-ChmToMobi <your_chm_file>.
- Copy MOBI to your e-reader and enjoy
To run it successfully, you need to have kindlegen installed on your computer and need to set alias kg to point to EXE file. On my PC I did it this way:
[11]: Get-Alias kg | ft -auto CommandType Name Definition ----------- ---- ---------- Alias kg Dropbox:\Ruzne\KindleGen\kindlegen.exe
This is example output when generating file for PowerShell help topics (I recommend to use -Verbose parameter so you’ll see actual state of processing):
[16]: Convert-ChmToMobi .\PSHelp.chm *********************************************** * Amazon.com kindlegen(Windows) V1.1 build 99 * * A command line e-book compiler * * Copyright Amazon.com 2010 * *********************************************** opt version: try to minimize (default) Info(prcgen): Added metadata dc:Title "Title" Info(prcgen): Added metadata dc:Date "2011/09/11" Info(prcgen): Added metadata dc:Creator "moravec" Info(prcgen): Added metadata dc:Subject "Subject" Info(prcgen): Added metadata dc:Description "Description" Info(prcgen): Parsing files 0000374 Warning(prcgen): <INPUT>, <SELECT> or <TEXTAREA> tag does no Info(prcgen): Resolving hyperlinks Info(prcgen): Resolving start reading location Info(prcgen): Added metadata Start reading "5098" Info(prcgen): Computing UNICODE ranges used in the book Info(prcgen): Found UNICODE range: Basic Latin [20..7E] Info(prcgen): Found UNICODE range: General Punctuation - Windows 1252 [201C..201E] Info(prcgen): Found UNICODE range: Latin-1 Supplement [A0..FF] Info(prcgen): Building MOBI file, record count: 0001986 Info(prcgen): Compiling HTML Parser restart information Info(prcgen): Final stats - text compressed to (in % of original size): 040.46% Info(prcgen): The document identifier is: "Title" Info(prcgen): The file format version is V6 Info(prcgen): Saving MOBI file Info(prcgen): MOBI File successfully generated!
There are still some points I need to update or change. For example:
- Easily add own Subject and Description.
- Resolve problems when kindlegen alias not presented.
- Add more control over generating files – generate only some files.
- Not show kindlegen output when not requested.
- Remove files at the end when requested.
A quick file processing
Aug 14th
I received DVDs from MMS on Monday. What a nice day
As I wasn’t in Vegas, these DVDs are opportunity to see all those interesting presentations at home. My wife was out of town this weekend so I had a plan – MMS party
Wanted to watch everything I marked as interesting. My idea was to create one DVD with presentations I selected and play it on TV (and preferably do not leave my bed).
I moved selected folders to one place, you can see structure of BA02 session folder here (it’s the same for all sessions):

In directory with session code is places file video.wmv. Eh – not so good to place every video to root of DVD. So I opened explorer and copied every WMV file to specific location, changed it’s name to session code and did the same for all sessions I selected used PowerShell to process all files. BTW: If you like Show-Tree, it’s part of PowerShell Community Extensions.
First I wanted to save session names so I’ll be able to check session content based on file name (ba02.wmv). One place, where the session name is mentioned, is second line of media.js file:

PS ToBurn:\> Get-ChildItem -Include media.js -Recurse |% { (Get-Content $_)[1] -match ‘^{“title”:”(.*?)”,’ | Out-Null; $matches[1] }
BA01 – Configuration Manager State of the Union
BA02 – Configuration Manager 2007 R3: Technical Update
BA03 – Configuration Manager 2012 – Technical Overview
BA04 – Configuration Manager 2012: Application Management (Part 1 of 3)
BA05 – Configuration Manager 2012: Application Management (Part 2 of 3)
BA06 – Configuration Manager 2012: Migrating from 2007 to 2012
…
As I was working in console (I use aliases as much as possible) and wanted to store this list for future check, my actual command was:
PS ToBurn:\> ls -i media.js -r |% { (gc $_)[1] -match ‘^{“title”:”(.*?)”,’ | Out-Null; $matches[1] } | Out-Printer
Voila – Out-Printer useful again
Second I needed to move video files to my burn folder and rename it.
PS ToBurn:\> ls -i video.wmv -r |% { Move-Item $_ -Destination $(‘ToBurn:\’+$(Split-path $_.DirectoryName -Leaf)+’.wmv’) }
For all WMV files, I moved them to root of ToBurn PSDrive and renamed based on pattern <folder_name>.wmv.
Last point was to remove everything except video files:
PS ToBurn:\> ls * -r |? {$_.name -notlike ‘*.wmv’} | del -force
OK – then just burn what I just selected and MMS party can begin.
Conclusion: When I put DVD to my player, it reported: “Resolution not supported.” So I used my common solution: notebook + VGA cable.
