# Wednesday, April 02, 2008

Now this is barely worth blogging, but one of the things I used a lot when I was confined to cmd.exe (yes, "confined" is the word I would use, 4NT aside) is the wonderfully simple copy con filename.txt then type a few lines and end it all with CTRL+Z and enter. So, if you're a PowerShell noob and yearn for this olden-days simplicity like dead parrots pine for the fjords, then this is for you:

  1. rm function:copy-console -ea 0 # silentlycontinue   
  2. rm alias:cc -ea 0   
  3.   
  4. # encoding can be String, Unicode, Byte, BigEndianUnicode, UTF8, UTF7, Ascii   
  5. function global:copy-console {   
  6.        
  7.     param(   
  8.         [string]$Filename = $(Throw "Need output filename."),   
  9.         $Encoding = "ASCII"  
  10.     )   
  11.        
  12.     $out = [io.path]::combine($pwd$Filename)   
  13.   
  14.     $buffer = @()   
  15.     $crlf = "`r`n"  
  16.        
  17.     do {   
  18.         $line = [console]::readline()   
  19.         if ($line -eq $null) { break; }   
  20.         $buffer += $line  
  21.     } while ($TRUE)   
  22.   
  23.     $buffer | set-content $out -Encoding $Encoding  
  24. }   
  25. new-alias cc copy-console   
  26.   
  27. # Usage:   
  28. #   
  29. # PS> cc test.txt -Encoding utf8   
  30. # bleh   
  31. # moop   
  32. # vlorg   
  33. # ^Z   
  34. # PS> cat test.txt   
  35. # bleh   
  36. # ...   
  37.   

I saved this to copy-console.ps1 and aliased it to "cc." Of course, you can do whatever you want - it's probably easier to just put it into a function in your profile. Just place the script above into your profile and remember: CTRL+Z then enter to save.

UPDATE 2008-04-04: Somehow I completely broke this in my attempts to "clean it up" before posting. I've reposted a better version (imho), and implemented encoding support as suggested out in Jason's comment below ;-)

posted on Wednesday, April 02, 2008 4:28:46 PM (Eastern Standard Time, UTC-05:00)  #    Comments [1] Trackback
# Thursday, March 27, 2008

PowerShell has several "type accelerators" which are used exactly like a casting operation. Examples of these special operators are [xml] and [wmi]. The former is used for quickly converting a string of xml into a fully-fledged System.Xml.XmlDocument object.

Often I find myself converting things to and from hexadecimal using the -f operator, but this always seemed like just a little too much typing for me. Enter the [hex] accelerator type:

image

As you can see from the source below, there's no magic here. This is just a straight cast, but I have no namespace. If I had a namespace, say, like "Nivot.PowerShell", we'd have to cast using [nivot.powershell.hex] instead of just [hex]. All of the trickery is done using operator overloads in C#. These tells .NET (and in turn, powershell) how to behave should someone try to add, subtract, remove or divide our instances.

  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Text;  
  4.  
  5. public class Hex  
  6. {  
  7.     private readonly int _value = 0;  
  8.  
  9.     private Hex(int value)  
  10.     {  
  11.         _value = value;  
  12.     }  
  13.  
  14.     private Hex(string value)  
  15.     {  
  16.         _value = Convert.ToInt32(value, 16);  
  17.     }  
  18.  
  19.     public static implicit operator Hex(int value)  
  20.     {  
  21.         return new Hex(value);  
  22.     }  
  23.  
  24.     public static implicit operator int(Hex value)  
  25.     {  
  26.         return value._value;  
  27.     }  
  28.  
  29.     public static explicit operator Hex(string value)  
  30.     {  
  31.         return new Hex(value);  
  32.     }  
  33.  
  34.     public static Hex operator +(Hex op1, Hex op2)  
  35.     {  
  36.         return new Hex(op1._value + op2._value);  
  37.     }  
  38.  
  39.     public static Hex operator -(Hex op1, Hex op2)  
  40.     {  
  41.         return new Hex(op1._value - op2._value);  
  42.     }  
  43.  
  44.     public static Hex operator *(Hex op1, Hex op2)  
  45.     {  
  46.         return new Hex(op1._value * op2._value);  
  47.     }  
  48.  
  49.     public static Hex operator /(Hex op1, Hex op2)  
  50.     {  
  51.         return new Hex(op1._value / op2._value);  
  52.     }  
  53.  
  54.     public override string ToString()  
  55.     {  
  56.         return "0x" + _value.ToString("X");
  57.     }  

The next step is to tell PowerShell's formatter what to do with the new type. Here's a simple format definition that tells the formatter to call ToString() on the Hex instance. This is the method that does the conversion by calling ToString("X") on the integer field. "X" means format the integer as hexadecimal using upper case. A lower-case "x" would output the value using lower-case (if you couldn't guess ;-)).

  1. <Configuration> 
  2.   <ViewDefinitions> 
  3.     <View> 
  4.       <Name>Hex</Name> 
  5.       <ViewSelectedBy> 
  6.         <TypeName>Hex</TypeName> 
  7.       </ViewSelectedBy> 
  8.       <CustomControl> 
  9.         <CustomEntries> 
  10.           <CustomEntry> 
  11.             <CustomItem> 
  12.               <ExpressionBinding> 
  13.                 <ScriptBlock>$_.ToString()</ScriptBlock> 
  14.               </ExpressionBinding> 
  15.             </CustomItem> 
  16.           </CustomEntry> 
  17.         </CustomEntries> 
  18.       </CustomControl> 
  19.     </View> 
  20.   </ViewDefinitions> 
  21. </Configuration> 

If we don't load this format file, PowerShell just emits a couple of blank lines when you try to use it.  You'll notice from the screenshot above that the blank lines still appear. I'm not sure how to remove these - it looks pretty ugly compared to the output of the [int] object. If you want to play with this, you can download the zip file below and unzip the contents into a single folder and run "hex.ps1". I didn't bother with a full Snap-In, it just loads the DLL using reflection. It also loads the format ps1xml too. Have fun.

HexAccelerator1.zip (2.4 KB)
posted on Thursday, March 27, 2008 8:19:15 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0] Trackback
# Thursday, March 06, 2008

Just a minor thing, but this is a filter I've been using for a while now as a replacement for Get-Member. It's always annoyed me that the Get_ and Set_ methods are returned along with the actual properties. The only place that's actual useful is when you're using an object wrapped in the [xml] adapter since those objects do not expose the XmlDocument's properties in the adapted member set.

update: if you use (of course you do!) MoW's PowerTab, you can disable display of the accessor methods with $PowerTabConfig.ShowAccessorMethods = $false.

  1. filter get-memberex {   
  2.     $_ | gm | ? { -not($_.name -match "^[gs]et_.+") }   
  3. }   
  4. new-alias gmx get-memberex  
posted on Thursday, March 06, 2008 11:35:21 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0] Trackback
# Wednesday, March 05, 2008

Discovered while playing around with the new SPUserToken class and associated goodness that is the new impersonation APIs in WSS 3.0 / SPS 2007. from Reflector:

public static void SetApplicationCendentialKey(SecureString password)
{
    SPCredentialManager.CreateApplicationCendentialKey(password);
}

Ouch! how did that get past QA? there are only five methods on the class - looks like it was a late night for whomever wrote these bits. Unless I'm very much mistaken, shouldn't that read Credential?

microsoft.sharepoint.spsecurity.setapplicationcendentialkey

posted on Wednesday, March 05, 2008 7:50:44 PM (Eastern Standard Time, UTC-05:00)  #    Comments [0] Trackback
# Friday, February 29, 2008
Someone on the PowerShell usenet group asked if it was possible to interact with SharePoint lists through our favourite little shell. Marco Shaw responded and put the pressure on by saying this was my bag of tricks. Who am I to say otherwise? so lets take a look at the recipe.
posted on Friday, February 29, 2008 10:11:39 AM (Eastern Standard Time, UTC-05:00)  #    Comments [0] Trackback