Archive for February, 2009

So earlier today someone asked how they could tell if PowerBoots graphics would be hardware accelerated on their system … and I found the question painful to answer because the answer is that you take the high-order word of the RenderCapability.Tier property, and that indicates 0, 1, or 2 … where a higher number indicates a higher level of hardware acceleration:

  • Rendering Tier 0 No graphics hardware acceleration. The DirectX version level is less than version 7.0.
  • Rendering Tier 1 Partial graphics hardware acceleration. The DirectX version level is greater than or equal to version 7.0, and lesser than version 9.0.
  • Rendering Tier 2 Most graphics features use graphics hardware acceleration. The DirectX version level is greater than or equal to version 9.0.
Logical and arithmetic rotate one bit left
Shift-Left 1, via Wikipedia

The problem is that in PowerShell, getting the “high-order word” of an integer is a little annoying, because the normal way to do that is to right-shift the integer to throw away the low-order word … and PowerShell is missing the shift operators. Why? I don’t know. In any case, I figured, well, I’ll just write it as a function with a call out to C# to make my life simpler. The one catch is that the Add-Type cmdlet that lets you inject C# classes is new in PowerShell 2.0, so if you want to use this script in PowerShell 1.0 you need to get the New-Type function from PoshCode and replace Add-Type with New-Type in the script.

Read the rest of this entry »

Just in the last week, I’ve seen at least four people asking about SSH from PowerShell, and at least three of those specifically were looking for something they could script. That is, they needed a way to make an SSH connection, and then run commands on the remote PC and do switches in their script based on the output of those commands, so they could automate complicated server-side tasks.

Generally, the simplest answer to that is to write the scripts on the server, and then invoke them from PowerShell using the PLink executable which comes with Putty. However, that’s not very satisfactory, and it requires you to know a Linux scripting language like Perl or Python, and also requires you to have uploaded and tested that script ahead of time. Not always practical.

It’s also possible to do this using the NetCmdlets from /n and I’m constantly surprised at how unwilling people are to pay for them.

Well, I’ve already written my own little workaround using SharpSSH, a library I found on SourceForge from years ago, so I figured I’d share it with you. You might want to read the CodeProject Article about the first release of SharpSSH if you want more information about it, but otherwise, just download the binaries, extract them, and put the three dll’s somewhere handy. I keep mine in a “Libraries” folder within my WindowsPowerShell profile directory, so they’re easy to include in a backup of my scripts.

Now, lets say that your task is to ssh into a server, do a process check to see if anyone else is logged in, and if not, restart the server immediately, otherwise, schedule a reboot for midnight. Here’s the script for that:


New-SshSession jaykul huddledmasses.org ## You'll be prompted for a password
if( Invoke-Ssh who '\$'| select-string "^(?!jaykul).*pts/\d"  ) {
   Invoke-Ssh "shutdown -r 0:00"  '\$'
}
else {
   Invoke-Ssh "shutdown -r now"  '\$'
}
Remove-SshSession
 

Notice that I use \$ (backslash dollar-sign) as my “expect” text. That’s the last character on my prompt. It occasionally backfires, so you might want to use something more precise, in my case, I usually would store a patters for the full prompt (as a regular expression):

$prompt = '\[jaykul@peace.*\]\$'

Here’s the script module with the functions you’ll need. Read the rest of this entry »

Awhile back I wrote a series of posts about WPF From PowerShell From PowerShell” which were about how you could load XAML in previous PowerShell 2 CTPs to create WPF user interfaces … a few people have mentioned loading XAML in PowerBoots, and a couple of people have posted other samples showing XAML even since I published the most recent release, so I figure it’s time to point out that you really can load that XAML into Boots, and get all the threading and other support.

Just for fun, I’m going to rehash an earlier post about updating windows to show how you can go about this using PowerBoots, and hopefully show that it’s a little easier (and a lot more async). Compare and contrast the code in this article with that one, just for fun.

This works with any version of PowerShell

Unlike the original article, most this code (except where explicitly mentioned) works on either PowerShell v2 with PowerBoots, or PowerShell 1.0 with PoshWPF, a snapin that is part of the PowerBoots module but is also released separately… Also, unlike those previous posts, this does not require you to be running PowerShell.exe with the -STA switch, since the New-BootsWindow cmdlet takes care of threading for us.

Read the rest of this entry »

WPF uses a concept called “Attached Properties” to handle certain things, like when you put controls into a DockPanel. Basically, anything you put inside a DockPanel has a property “Dock” which you can set … but because the property is actually defined by the DockPanel, it doesn’t show up in PowerBoots, so you can’t just say -Dock "Bottom" when you create the child items … at least, not yet.

I’m still thinking about the best way for me to expose this in PowerBoots, because the problem is that attached properties can get attached several ways, and not just on direct children of an element. So I wanted to show you a way that you can do it for now so you can at least use the DockPanel effectively:

Boots {
   DockPanel -LastChildFill $true {
      DockPanel -LastChildFill $true {
         Button "OK" -Padding "2,0,2,0" |
            ForEach-Object { $_.SetValue(
               [System.Windows.Controls.DockPanel]::DockProperty,
               [System.Windows.Controls.Dock]::Right)
               $_
            }
         TextBox -HorizontalAlignment Stretch
      } | ForEach-Object { $_.SetValue(
               [System.Windows.Controls.DockPanel]::DockProperty,
               [System.Windows.Controls.Dock]::Bottom)
               $_
            }
      TextBox -AcceptsReturn $true -minWidth 300 -minHeight 200
   }
}

A better way …

Here’s what I’m thinking about for the next release of PowerBoots (you can take this and use it now, if you like it, but I’m really looking for, uhm … better ideas). Basically, I have written a function: Set-AttachedProperty, which takes an attached property and a value, and passes through the element on the pipeline. You may want to use this in conjunction with the module I published awhile back for creating type accelerators, because it lets you run a line like this:

Add-Accelerator DockPanel System.Windows.Controls.DockPanel

Which will let you substitute [DockPanel] for [System.Windows.Controls.DockPanel] … and of course, you can use it for all the types you want to use attached properties from, and it’s a real lifesaver if you need to use a bunch of them. Of course, in this particular example, we really only need to use a single attached property, so it’s enough to define that property ahead of time:

$DockProperty = [System.Windows.Controls.DockPanel]::DockProperty

Then you can use the Set-AttachedProperty function through an alias sap, and rewrite that huge block above like this:

Boots {
   DockPanel -LastChildFill $true {
      DockPanel -LastChildFill $true {
         Button "OK" -Padding "2,0,2,0" | sap $DockProperty Right
         TextBox -HorizontalAlignment Stretch
      } | sap $DockProperty Bottom
      TextBox -AcceptsReturn $true -minWidth 300 -minHeight 200
   }
}

Pretty slick, right? And it will even print out the list of values in the error message if you invoke it with an invalid value against an enum property like dock: sap $DockProperty "" … The problem I have with it is that you have to predefine your $DockProperty variable, and you can’t just define it against the root class. So I’m trying to find a way to tweak the dynamic property generation to make it so that the pipe into | sap $DockProperty Bottom can just be a parameter to the original element: -Dock Bottom … if I can’t find that, in the worst case scenario, I’ll just add an -AttachedProperties parameter with a hashtable of $DockProperty,“Bottom” or something … what do you think?

In any case, here’s the sap function, for now, and remember to use it as part of the pipeline:


function Set-AttachedProperty {
[CmdletBinding()]
PARAM(
   [Parameter(Position=0,Mandatory=$true)
   [System.Windows.DependencyProperty]
   $Property
,
   [Parameter(Mandatory=$true,ValueFromPipeline=$true)
   $Element
)
DYNAMICPARAM {
   $paramDictionary = new-object System.Management.Automation.RuntimeDefinedParameterDictionary
   $Param1 = new-object System.Management.Automation.RuntimeDefinedParameter
   $Param1.Name = "Value"
   # $Param1.Attributes.Add( (New-ParameterAttribute -Position 1) )
   $Param1.Attributes.Add( (New-Object System.Management.Automation.ParameterAttribute -Property @{ Position = 1 }) )
   $Param1.ParameterType = $Property.PropertyType
           
   $paramDictionary.Add("Value", $Param1)
   
   return $paramDictionary
}
PROCESS {
   $Element.SetValue($Property, $Param1.Value)
   $Element
}
}

New-Alias sap Set-AttachedProperty
 

Announcing the release of PowerBoots 0.1

This release of PowerBoots is the most exciting release software I’ve cranked out in awhile. It finally has almost all of the features that I have thought of so far (we’re still missing proper support for attached properties).

  • You can create pretty much any WPF element, including ones I haven’t thought of adding yet (use Add-BootsFunction to add a new assembly or a single type).
  • You can create graphical user interfaces from PowerShell 1.0 all the way to the latest PowerShell 2.0 CTP.
  • You can create your WPF GUIs -Async in their own threads, or inline in PoshConsole, or as synchronous dialogs that return values when they close.
  • You can capture screenshots of your UIs (eg: generate .jpg charts from Visifire). You can even do so without displaying them!
  • You can take advantage of XAML Data Templates to generate graphical representations of any objects in the PowerShell pipeline.
  • You can add to, or modify your running GUIs from the command line.

You can read the “and much much more” between the lines right?

Read the rest of this entry »

I’ve finally finished the first public release of PoshWpf, and was getting ready to ship it as part of a new release of my PowerBoots module. The idea is that I need PoshWpf itself to be a stand-alone module so that it can be used in production with PowerShell 1.0, until such time as PowerShell 2.0 goes gold, and we can get that into production use, so we can use PowerBoots. PowerBoots is a script module, and it uses dynamic parameters, so most of it can’t really be done in v1, but you can use PoshWpf as a snapin, including the New-PowerBoots cmdlet, to do asynchronous multi-threaded UIs like my “ping monitor demo.”

So I need to update the .psd1 Module Metadata file for PowerBoots to include PoshWpf … I read up on Oisin Grehan’s blog about the possible properties in the module manifest, and decide that I could do this by packaging PoshWpf as a NestedModule in PowerBoots. There’s not a whole lot of point in distributing PoshWpf as it’s own module — Version 1 users will need to install it as a Snapin anyway, since PowerShell 1.0 doesn’t support modules, and I expect PowerShell 2.0 users to use it with PowerBoots.

Nested Modules

So I open up the PowerBoots.psd1 file, and add the line: NestedModules="PoshWpf" and fire up PowerShell and run Import-Module PowerBoots … and get this Error:
Import-Module : The module to process ‘PowerBoots’, listed in module manifest ‘C:\Users\Joel\Documents\WindowsPowerShell\Modules\PowerBoots\PowerBoots.psd1’ was not processed because no valid module was found in any module directory.

Now, I have no idea what that’s supposed to mean, except that I know the way that the PowerBoots.psm1 script gets parsed is that the PowerBoots.psd1 metadata includes a line: ModuleToProcess="PowerBoots.psm1" … I don’t know why the error doesn’t say “.psm1”, and I don’t know why that would be the error when what I added was the PoshWpf line, but I comment my line out and everything works, so I decide that maybe I need to say “PoshWpf.dll” (following the example that works of loading the PowerBoots script by specifying the full extension).

So I move PoshWpf.dll from it’s subdirectory right into the PowerBoots folder, and I change my line to: NestedModules="PoshWpf.dll" and fire up PowerShell and run Import-Module PowerBoots … and get this Error: Import-Module : An item with the same key has already been added.

Wow, I’m two for two: two attempts to load my module, two completely incomprehensible errors.

Read the rest of this entry »

So, last year around April, I wrote this module I called “HuddledTricks” ... it has a function for hiding windows, and another for showing them, along with a function called Wiggle-Mouse which, well, wiggles your mouse cursor (and one called Steady-Mouse to stop it).

So anyway, today I was playing with something else and with my WASP module, and discovered that you can hide the Windows 7 taskbar without hiding the start menu or button.

This seemed cool enough to motivate me to finally actually publish my HuddledTricks module, so have fun, and don’t prank too many people. :D

Reblog this post [with Zemanta]

So we found a problem recently with a certain scripting language’s argument parsing:


function Test-Argument($a) {
   $a.GetType().FullName
}

[Test 1]: Test-Argument 4
System.Int32
[Test 2]: Test-Argument .5
System.Double
[Test 3]: Test-Argument "hello"
System.String
[Test 4]: Test-Argument Goodbye
System.String
[Test 5]: Test-Argument -42
System.String
[Test 6]: Test-Argument (-42)
System.Int32
 

Why can’t it properly parse -42 as an integer, when it can parse .5 as a double? Well, according to the development team of a certain Fortune 100 company, this behavior is by-design ... Apparently, “.” can be a number, but “-” can’t.

When you know you’ve got it all wrong, but you can’t be bothered to get it right, document it — make it look intentional, and most people won’t question you.

I’m sorry folks, but I’ve had it up to here with the “it’s by design” excuse. I don’t care who you are, and I don’t care who wrote the design spec — when something is as obviously wrong as this, you need to fix it, not just give us platitudes.

I had the same thing happen recently with a bug I filed about the way wildcard behavior impedes matching file-names with square brackets in them in PowerShell. They told me this was by design, and that I could use the -LiteralPath parameter. Well, if any of you have tried this, you already know what I’m going to say: it’s broken.


## This works if the file already exists
## But fails completely if it doesn't exist
set-content -LiteralPath "logs [www.example.com].txt" -Value " help "
 

And yet, I was initially told it was supposed to be this way. Now, in this case, I happened to have the email address of the software architect, and they’ve reopened my bug after I sent him an email with lots of examples of how this bug defied the behavior that a user expects.

We software developers need to be very careful about saying “that’s by design” ... because it sometimes makes us sound stupid. When a user says “this is broken,” and your reply is “that’s by design,” what the user hears is “we broke it on purpose.” We should not be willing to excuse bad design.

Listen up: If you want to be a successful software developer, you need to learn this, and learn it well: the fact that it was DESIGNED WRONG is NOT AN EXCUSE for shipping broken software. Regardless of whether it’s your design, or someone else’s, even if it was designed this way by your manager’s boss. When you create software that doesn’t behave the way the user expects it to, you need to consider the possibility that you’re doing it wrong.

Imagine if architectural engineers were to behave in a similar manner … Suppose the original architect of the golden gate bridge had left a gap in the middle of the bridge, with a little ramp: you could drive up the bridge, but you couldn’t get across unless you were comfortable jumping your car across a four foot opening.

When you complained about it, the engineers would say: it’s by design — if you don’t like jumping your car (and yes, we know that jumping is bad for maintainability), there is a workaround: just wait for the ferry we put in last year. There are several boats, running continuously, so the wait is at maximum about 20 minutes, and it only takes a little longer to cross by boat than it would on the bridge.

That analogy is obviously not perfect, but the point is: just because someone decided it should be done a certain way doesn’t mean that’s the right thing to do — sometimes the design is just wrong. Perhaps the designer and architects overlooked something, or perhaps the circumstances have changed, but in any case, if the software doesn’t work the way people expect it to work, or requires different workarounds depending on the situation … you need to question the design.

All I’m asking is this: don’t turn your brain off: when someone complains about the way something works (or doesn’t work), think about what they’re asking, and if the complaint makes sense, don’t say “this misbehavior is by design” until you’ve reconsidered the design.

Search My Content