What do you code your PowerShell scripts in?

Having come from a VBScript background I have always been impressed by Sapien’s PrimalScript Profressional as an IDE. As I have been getting into PowerShell recently I checked out the new version (4.1) which has PS support. I thought perhaps it was time to break open the piggy bank and purchase myself a copy. Now don’t get me wrong, this is quite a spendy piece of software, which I’ve road tested heavily for VBS and loved. But how would it fair for PowerShell?

Well to be honest it was ok. It might have actually been quite good, but it had stiff competition: the PowerShell shell itself. I’ve found that PrimalScript just didn’t seem to have the same depth of intellisense as that provided by the shell. Since playing with PS I’ve found that the way I develop scripts has had a radical change. No longer do I hack some code blocks together in a script, and run it *fingers-crossed* to see if it works. Followed by wscript.echo statements to see where I’ve gone logically wrong.

No, now I hack happily away in the PS Shell with excellent intellisense support, and when I have my code block working nicely I cut and paste it out to a text editor. Now its always nice to have pretty colours and brace matching, so I’ve been using Flo’s notepad2 configured with the C# Scheme. I have to say I’ve been really happy with the combination though we’ll have to see how I go when I start trying to debug more complex code ;)

What IDE do you prefer for PS1? Any tips and tricks anyone would like to pass on?

Taking the PSH?

I read somewhere that the first 4 days of using PowerShell is the toughest. Once you get over this hurdle, and try and go back to using another language you kinda resent it. Well I have been using PS for about 2 weeks now, and I have to agree. I used to be quite a previlent VBScript writer, but not any longer.

Once you can get over the hurdle of trying to work out “how” to do what you want to do in PS, the actual code is blindingly easy. Now I generally don’t do anything too involved (read:complex). Remember I’m looking at this puzzle from an admin/automation slant.

I have to say though that from this non-programmer perspective I have had the most issues trying to work out the “how”. Now that probably sounds pretty obvious, but let me clarify. When something is new to you, you can stumble into frustration quite easily when you learn a technique, and then go to apply it again in a similiar situation only to find it doesn’t work. Now there is probably a really good programtic reason behind this, but from the “new guy” perspective it is really annoying.

Now this post isn’t a flame thread, or “what I hate about PowerShell” because if I’m truthful I think it’s bloody great, and when I’ve worked something out I’m really stoked with how easy it is to do quite complex stuff. That being said below are the things that frustrate me most about PowerShell from my two week old perspective:

[1] A single element array no longer behaves like an array:
I used to have a habit of enumerating array using:


for i = 1 to ubound(MyArray)

To be fair this isn’t probably the best way to process arrays, but you know, each to their own and all that. Besides people are creatures of habit ;)

I found pretty quickly that this kinda sucks in PS. If you have an array with a single element it’s pretty much just treated as a string. So far I’ve found this kind of behaviour keeps cropping up.

Trying to create the first child element, in an XML document, for example isn’t treated as System.Xml.XmlDocument, but instead reverts to System.String. I think this is somehow pointing to the #text part of the element.I’m not sure if this is a bug or not? I noticed Adrian Milliner identify this in the comments on this on the MS PS Blog here and kindly mentioned the fix!

[2] PSBase method/class:
I guess this is where the non-programmer in me wonders just what exactly is going on there? I have to admit since implementing MOW’s community Tab Completion cmdlet I seem to be able to work my way through psbase implementations a bit better. Still it does primarily appear to obsfucate the whole thing, but maybe I’ll see the light further down the road.

There’s a good explanation of it here I’ve stumbled across psbase while doing ADSI scripting with PS, so I’ll highlight it during a post where it pops up.

[3] Microsoft Script Center
I’m not going to harp on about this as I have raised it in a previous post. Suffice to say most newcomers will look there for assistance and currently it’s just not a help. The PowerShell Team blog however is saving the day and those guys put up some excellent stuff that does help!

[4] Documentation
My issue here is accuracy. I could be alone in this so take this observation with a pinch of salt. I seem to keep finding discrepencies with the MS documentation for PowerShell. Now this is occuring in severalplaces. I downloaded the PowerShell Documentation Pack in case it had updated since RTM.

In the Working with Software Installations section of the User Guide I find that the syntax for installing MSI applications just doesn’t work!

The in-shell help is really really great. As a Linux user (Debian and Ubuntu) I find the Man-like approach to be a good idea. I tend to develop my scripts in-shell and then cut-and-paste them when they are working (more on this in another post).

Now the get-history invoke-history cmdlets are very useful, but I can’t seem to get some of the functionality to work correctly? In Example 4 of the detailed get-help out for Invoke-history is the following line:


C:\PS>invoke-history (16..24), 27

Whenever I try this I get this error:


PoSh> ghy

Id CommandLine
— ———–
1 cd ~
2 dir
3 [xml]$root = gc D:\coding\ps\th-ad.xml
4 $root.Post.ad
5 $root.Post.ad.OrgUnit
6 $root.CreateElement(“test”)
7 $ou = $root.CreateElement(“test”)
8 $ou.set_InnerText(“blah”)
9 $root | gm | more
10 get-help get-history
11 get-help get-history -detailed | more
12 get-help *-history
13 get-help invoke-history -detailed | more

PoSh> ihy (3..5)
Invoke-History : A parameter cannot be found that matches parameter name ‘System.Object[]
At line:1 char:4
+ ihy <<<< (3..5)

[5] No PowerShell availablity in WinPE
Not exactly a fait comment considering PS sits ontop of .NET and of course there is no .NET for PE. From an Admin perspective though this really does bite. You go through the effort of buying into the new technology. You get used to how cool, and easy it is to do stuff, and then you find that you can’t use it in one of the most useful scenarious.

Now this will in all likelihood stirr the big debate on WinPE anyway. I’ve always liked to boot into PE and have an HTA interface available to navigate through my build/recovery situations. Currently though I’m forced to use VBscript and C++. I want to move forwards it really should be PS and C#! ;)

I would like to caveat this post. I am a bif advocate of PowerShell. I’m trying to raise awareness within my organisation of what it can achieve, and I have found that the “Pro’s” massively outweigh the “Con’s”.

This post was just to highlight my issues. What have you’re issues been? Does the above work, and I’ve just not RTFM’ed, or have these just slipped through the cracks somewhere?

Setting Filesystem permissions using SDDL format

When it comes to setting the permission on the filesystem there has already been some interesting conversation between Tony (MSHforFun blog) and Marc (MOW):
http://mshforfun.blogspot.com/2005/12/play-with-acl-in-msh.html

This is fine if you want to add your ACE into an existing DACL. But what if you want to completely overwrite the DACL and “roll-your-own”? I posed this question on the MS Powershell newsgroup recently, and the reply was spot on (cheers Rob!). Basically you need to specify the DACL in SDDL format.

After about half a days googling for information on SDDL I found a few URL’s that provide some good information on the subject. I have posted the links on the Further Reading page (I’m having a few link issues here *sighs*. Spot the n00b!)
OK, so let’s try it out:


function replace-acl
{
Param (
$sObject,
$sSDDL
)
$acl = Get-Acl $sObject
$acl.SetSecurityDescriptorSddlForm($sSDDL)

Set-Acl -aclObject $acl $sObject
}
replace-acl “d:\” “O:BAG:BAD:AI(A;OICI;0x1301bf;;;AU)(A;OICI;FA;;;BA)(A;OICI;FA;;;SY)”

Basically we’re passing the function the folder we want to apply the permissions to, and then our complete DACL in SDDL format.
The first portion of the SDDL sets the Owner as Builtin-Administrators (O:BA), the POSIX compliant group to the same (G:BA) and the 3 ACE’s with the inherit flag on, and : Builtin-Administrators FullControl, System FullControl, and AuthenticatedUsers with a hex flag set, which equates to Modify.

The DACL will cascade down the directory tree to any child folders, which is great. However if any of these children have manual ACE’s added, or if inheritence has been turned of (by the inherit from parent flag being unticked) then the permissions will either merge in the case of the former, or not be applied at all in the case of the latter.

This can be rectified with a simple get-children function:


function flush-acl
{
Param (
$sObject
)

$col = Get-ChildItem $sObject -Recurse
foreach ($item in $col)
{

replace-acl $item.FullName “O:BAG:BAD:”

}
}
flush-acl “d:\”

I’ve found that by rewriting the DACL on each child folder, with just the Owner and Group information has the effect of dropping the existing manual ACE entries, and the bonus of turning the inheritence back on again. By applying the flush function and then replacing the DACL at the required level is a very effective way of repermissioning a directory tree, knowing that there’s no hidden surprises further down the tree!