ISE is cool! :)

I’ve seen many interesting things done with PowerShell ISE, so I decided to play with it myself. One thing I don’t like about any powershell host: if you Import-Module or Add-PsSnapin to session in $profile it usually takes some time before you can do anything. And from time to time you do not really need those modules/ snapins. So what could one do? Well, because of ISE functionality you can have few cosole-tabs (as far as I can tell up to 8). So my idea was to create 2 powershell tabs on start: one ‘empty’, and next one – with everything loaded, and switch to first one while second is loading ‘stuff’. After that I decided that it would be cool to have an option to switch between tabs. At first I’ve just created functions, f#, that would move me to tab no #. But that was not enough for me – so I played a bit with ISE menus and got Alt + # shortcuts for each new tab, together with menu option to switch to different tabs. Whole $profile can be seen below:

PowerShell, using GeSHi 1.0.8.8
  1. $tabs = $psISE.PowerShellTabs
  2. $curtab = $tabs[$tabs.Count1]
  3. $ISEOpt = $psISE.Options
  4. $ISEOpt.OutputPaneBackgroundColor = ‘black’
  5. $ISEOpt.OutputPaneTextBackgroundColor = ‘black’
  6. $ISEOpt.OutputPaneForegroundColor = ‘white’
  7. $TabsMenu = $curtab.AddOnsMenu.Submenus.Add(‘Tabs’,$null,$null)
  8. if ($curtab -eq $tabs[0]) {
  9. $curtab.DisplayName = ‘NoProfile’
  10. $newTab = $tabs.Add()
  11. } else {
  12. $curtab.DisplayName = “PoSh # $($tabs.IndexOf($curtab))”
  13. $NewTabIndex = $tabs.Count
  14. Invoke-Expression `$SwitchToMe = { `$tabs.SetSelectedPowerShellTab(`$tabs[$NewTabIndex-1]) }”
  15. for ($i = 0; $i -lt $tabs.Count 1; $i++) {
  16. if ($NewTabIndex -le 9) {
  17. Invoke-Expression `$SwitchTo = { `$tabs.SetSelectedPowerShellTab(`$tabs[$i]) }”
  18. $MyMenu = $tabs[$i].AddOnsMenu.Submenus | Where { $_.DisplayName -eq ‘Tabs’ }
  19. [void] $Mymenu.Submenus.Add($curtab.DisplayName, $SwitchToMe ,“ALT + $NewTabIndex”)
  20. } else {
  21. # That should not happen cause limit is 8
  22. Write-Host -ForegroundColor Red “Can not add this tab to menu – move to it using CTRL + TAB”
  23. }
  24. [void] $TabsMenu.Submenus.Add($tabs[$i].DisplayName, $Switchto, “ALT + $($i+1)”)
  25. }
  26. $tabs.SetSelectedPowerShellTab($tabs[0])
  27. Add-PsSnapin Quest*
  28. ImportModule @(‘WPK’,‘IsePack’)
  29. . “C:\Program Files\Quest Software\Management Shell for ADqsft.ps1”
  30. }

It also changes default colours in OutPutPane to black background – white foreground.

The main problem I had was with “action” part of Submenus.Add method – it takes scriptblock, but I was not able to force it to expand variables, and got unpredictable results. Once I used Invoke-Expression to get proper [scriptblock] variable it all went fine. Two things I would like to fix:

* when I press alt + # I get method displayed – would love to make it ‘silent’

* if I close some tab and add next it all get messed up (two tabs with same name if it was in a middle, errors when adding new tab…)

But it does most of things I needed, and now I get my prompt very quick and if I need WPK, IsePack or Quest cmdlets – all I need to do is switch to second tab. 🙂 ISE rocks. 😀

 

Advertisement

Careful with VersionInfo…

Last week I volunteered to write PowerShell script that meant to test image (Win7) against a set of requirements. As a base I used JScript that was used for Windows XP machines in a past. When writing this code I wanted to do as much as I can using dot.net rather than com objects (that was common for JScript/ VBScript). But I failed with file version for winzip. Why? Let’s see…

PowerShell, using GeSHi 1.0.8.8
  1. PS C:> ls ‘C:Program FilesWinZipWINZIP32.EXE’ | select -ExpandProperty VersionInfo
  2.  
  3. ProductVersion   FileVersion      FileName                                                                       
  4. ————–   ———–      ——–                                                                       
  5. 9.0 SR1 (6224)  18.0 (32bit)    C:Program FilesWinZipWINZIP32.EXE                                           

Yak. Where is my version number? What the heck that (32-bit) is doing there? So… I eventually used $fso for that..:

PowerShell, using GeSHi 1.0.8.8
  1. PS C:> $fso = New-Object -ComObject Scripting.FileSystemObject
  2. $fso.GetFileVersion(‘C:Program FilesWinZipWINZIP32.EXE’)
  3. 18.0.6224.0

Much better. But I was digging deeper – where those properties are hidden in .NET? And I found it… :

PowerShell, using GeSHi 1.0.8.8
  1. PS C:> ls ‘C:Program FilesWinZipWINZIP32.EXE’ | select -ExpandProperty VersionInfo | select File*Part
  2.  
  3.            FileBuildPart           FileMajorPart           FileMinorPart         FilePrivatePart
  4.            ————-           ————-           ————-         —————
  5.                     6224                      18                       0                       0

All is there, only divided. But to be honest $fso version was easier for me to consume, so I left it like that. Job done, so I’m fine with that. 🙂

Life in a colour – part 2. :)

OK, it’s not fine and tuned and it uses regex for simple task, and it’s slow, BUT – it works! 🙂

Most of time, of course: as long as your column names are left-aligned. And it also kills pipe, so it has to be improved! 😉

Results first:

Out-colour-columnsNice, colourful output. You decide which colours to use, how many of them will be displayed, in which order. It is all up to you! 🙂

Code:

PowerShell, using GeSHi 1.0.8.8
  1. function outcolour {
  2.         if ($Input) {
  3.                 [int[]]$columns = @()
  4.                 # select colours you prefer and the one that a readable on your console.. 🙂
  5.                 $colours = @(‘Magenta’,‘Yellow’,‘Cyan’,‘Green’)
  6.                 foreach ($obj in ($Input | Out-String -Stream)) {
  7.                         if ($columns.count -eq 0) {
  8.                                 $match = $obj | Select-String AllMatches -Pattern ‘[^|s]-{2,}’ | Select-Object -ExpandProperty Matches
  9.                                 if ( ($match | Measure-Object | Select-Object -ExpandProperty Count) -ge 2) {
  10.                                         $columns = $match | Select-Object -ExpandProperty Index
  11.                                 }
  12.                                 Write-Host $obj
  13.                         } else {
  14.                                 foreach ($char in $obj.ToCharArray()) {
  15.                                         $colour = $null
  16.                                         $X = $Host.UI.RawUI.CursorPosition.X
  17.                                         for ($i=0; $i -lt $columns.count 1; $i++) {
  18.                                                 Write-Verbose "i = $i ; X = $X"
  19.                                                 if ( ( $X -ge $columns[$i]) -and ( $X -lt $columns[$i+1] ) ) {
  20.                                                         $colour = $colours[($i % $colours.count)]
  21.                                                 }
  22.                                         }
  23.                                         if (!$colour) {
  24.                                                 $colour = $colours[(($columns.count 1) % $colours.count)]
  25.                                         }
  26.                                         Write-Host -ForegroundColor $colour $char -NoNewline
  27.                                 }
  28.                         "`r"
  29.                         }
  30.                 }
  31.         }
  32. }

It was fun to write it, and fun to play with it! 🙂 PowerShell is Ring of Power for sure! Wonder if I become a Nazgul one day… 😉

Life in a colour… :)

Yesterday I was in a strange mood. I had a lot of work, some repetitive yet not easy to automate tasks. You know, one of those boring and yet busy days. It usually helps me to do something silly on those days. Create a script or a function that does not do anything useful, but shows how flexible powershell is. So… I was thinking about the way to make PowerShell output colourful. At first – randomly colourful:

PowerShell, using GeSHi 1.0.8.8
  1. function outcolour {
  2.         if ($Input) {
  3.                 foreach ($obj in ($Input | Out-String -Stream)) {
  4.                         foreach ($char in $obj.ToCharArray()) {
  5.                                 Write-Host -ForegroundColor $(GetRandom -InputObject $( (0..15) | ? { $_ -ne $Host.UI.RawUI.BackgroundColor.value__ } ) )   $char -NoNewline
  6.                         }
  7.                         "`r"
  8.                 }
  9.         }
  10. }
  11.  

The result is…. chaotic, to say the least. 😀 And it’s really SLOW, so there is probably a lot of space for performance improvement here. 😉

Out-Colour

Next step – make it more clear and easier to use. First – what was easier to achieve – make each row have random colour:

PowerShell, using GeSHi 1.0.8.8
  1. function outcolourByLine {
  2.         if ($Input) {
  3.                 foreach ($obj in ($Input | Out-String -Stream)) {
  4.                                 Write-Host -ForegroundColor $(GetRandom -InputObject $( (0..15) | ? { $_ -ne $Host.UI.RawUI.BackgroundColor.value__ } ) )   $obj
  5.                 }
  6.         }
  7. }
  8.  

Results more readable for sure:

Out-ColourByLine But I guess the best would be to have columns single-coloured. But to get it I would probably need to dig more into formatting system, and it makes it not so silly and so entertaining any more. 😉 So I leave it to the experts. 😉 BTW: I wish I could dot-source stuff in PowerShellPlus library, I have that functions there and I have to edit/ paste it into console to get it to work. In that area ISE is more… intuitive. Select, hit F8 and you are done. 😉 I hope that this is only my ignorance and this tool actually supports such actions… :>

Episode 117 of PowerScripting Podcast.

Friday, middle of the night. Got to work, got fresh cofee, write down my questions I was thinking about for about month. And then it all started. Yes, I’ve enjoyed it. Every single minute of it. 🙂 Maybe didn’t asked everything I wanted to, but that was not the point. I had a chance to speak to Jeffrey, Ed, Hal and Jonathan. It was surely grand prize for me. If I would get TechEd pass I would not use it – price of the trip to US, hotel, week off… I would be sad and sorry. But 1 hour call to US is totally different story.

I hope Polish listeners of the Podcast won’t hunt me for calling us (Polish PowerShell users) mutants. 😉 Forgive me, it was not exactly what I was going to say… 😀 And for those who listened to the podcast and have no idea who this Witcher is, two links:

English version of book on Amazon.com

The Witcher (game) official website

Back to the podcast: I’m glad that I mentioned few things: challenges (I guess Scripting Wife is somewhat right that answering peoples questions on forum is something like that, but I would prefer some spirit of competition that such forum answers should not bring). Naming – I’m not all that sure that scripts should use verb-noun, but I somehow like the idea, and I think that Jeffrey was closer to the point in that area. BTW: there is a way to suppress warning about names when you load a module:

PowerShell, using GeSHi 1.0.8.8
  1. PS C:UsersBartekB> ImportModule .Test.psm1
  2. WARNING: Some imported command names include unapproved verbs which might make them less discoverable.  Use the
  3. Verbose parameter for more detail or type GetVerb to see the list of approved verbs.
  4. PS C:UsersBartekB> ImportModule .Test.psm1 DisableNameChecking
  5. PS C:UsersBartekB>

But you can not be sure that everybody will use that parameter, so you better watch out and name your functions with the –verbs you get-

And that leads me to last thought I would like to share: it would actually help to add one more property to get-verb results: alias prefix. I’m almost sure that those are common, and all imports aliases are ip(noun-part), exports are ep(noun-part) and gets are g(noun-part), and so long, and so forth.

And last but not least: hearing Jeffrey’s passion about the product is almost like listening to the parent, so without any doubt you can call Powershell “his baby”. It was a real fun to listen to it live, to interact with it in a way I had never chance before (and probably will not have in future). Definitely a day to remember. Now I wait for final version of this episode so that I can download it and save it somewhere for my descendants… 😉

CMD and SG 2010 – Part 5.

This is today… Today I will have a chance to speak to THEM. Good day to finalize my series. Not the best day to do shopping, since my bank card expired. 😉 So no real breakfast today.

Last two events were not very hard, but I had two problems to move them to CMD.

Event 9 required array manipulation but… there is no array in CMD! So what should I do? Well, I tried to ‘pretend’ I was playing with arrays. So it’s not a script I could easily defend. Probably one star only. 😉

CMD, using GeSHi 1.0.8.8 – Beginner Event 9
  1. @echo off
  2. SET Arr1=a b c d
  3. SET Arr2=d e f g
  4.  
  5. echo Array 1 = %Arr1%
  6. echo Array 2 = %Arr2%
  7. set Arr3=
  8.  
  9. call :Conc %Arr1%
  10. call :Conc %Arr2%
  11.  
  12. echo Final Array = %Arr3%
  13. goto :EOF
  14.  
  15.   :Conc
  16.   if [%1]==[] goto :EOF
  17.   echo %Arr3% | findstr /r "%1," > nul || (SET Arr3=%Arr3%%1, & echo %1)
  18.   goto :Conc
  19.  

Second was even harder: how to debug .vbs or .ps1 when I use cmd only? I decided to take other route: OK boss, I’m not fluent in either, I will get your message box in cmd, and leave those broken scripts alone. 😉 There is no ‘silentlycontinue’ in cmd (unless you redirect 2> nul) so if I hit error – I will know it. So that’s what I came up with:

CMD, using GeSHi 1.0.8.8 – Beginner Event 10
  1. @echo off
  2. for /f %%M in (‘wmic ComputerSystem Get UserName ^| findstr /r ".*\.*"’) do @SET msg=%%M
  3. msg %USERNAME% %msg%

See? Message box as you expected. Title may be a little confusing, but who would read title in a window like that? 😉 So again: not exactly what Scripting Guys asked for, but I had to limit my self to command line tools only.

And now I have few long hours ahead. I plan to get to bed early and today (tomorrow my time) wake up in the middle of the night, drive to work (so that I would not wake up my family while recording podcast). So two big issues ahead of me: how to concentrate on what I’m doing when at work, and how to fall asleep when at home. 😉 I usually go to bed around 1-2, so it may be a real problem. So plan B is stay at home, and call podcast team from bathroom 😉 Will see how it all works out for me.