postheadericon Using alternate credentials with the FileSystem in PowerShell

In PowerShell, cmdlets like Get-ChildItem and Get-Content support a -Credential parameter so you can access resources that require you to log in… the problem is that the built-in FileSystem provider does not. So as an example, if you have a server on a different domain and you want to copy files off of it, you can’t do this:

$cred = Get-Credential
Copy-Item \Server\Share\Folder\*.log C:\Logs -Credential $cred

That will throw an error: “Cannot retrieve the dynamic parameters for the cmdlet. The provider does not support the use of credentials. Perform the operation again without specifying credentials.”

Impersonation

To solve this problem at work, I’ve written an impersonation module. It basically has two methods: Push-ImpersonationContext and Pop-ImpersonationContext. There is one catch: you need to be running in single-threaded apartment mode for it to work, because the impersonation only affects the current thread (if you’re not running PowerShell.exe -STA, your commands execute on a thread pool, so you never know from one to the next what thread you’ll be on). In any case, you use it like this:

$cred = Get-Credential
Push-ImpersonationContext $cred
Copy-Item \Server\Share\Folder\*.log C:\Logs
Pop-ImpersonationContext
 

It’s really very simple, and works great for when you need to access resources across multiple domains. Particularly files, for which PowerShell doesn’t support alternate credentials at all. :( Anyway the module code is on PoshCode, save it to your Documents\WindowsPowerShell\Modules\Impersonation\Impersonation.psm1 and use Import-Module Impersonation to load it. Here you go:

Reblog this post [with Zemanta]

postheadericon Pay for tasks, not results?

Time Magazine has an article entitled Pay For Grades: Should Kids Be Bribed to Do Well in School? It’s about a very rare thing: a genuine research project done by a Harvard economist named Roland Fryer Jr. in hundreds of classrooms in multiple cities around the nation to study the effects of paying kids for grades or school work. They tried different schemes in different places, and some of them were successful, and others were not. I’ll leave it to you to read the article if you’re interested in the specifics …

The interesting thing to me was the difference between the systems they judged successful and those they didn’t. Universally, what worked was to pay children for small tasks and behavior patterns: get to class on time, do your homework, read a book, have a positive attitude in class. What didn’t work was paying for test scores and grades.

A friend of mine pointed out that basically, what they discovered was Getting Things Done … In fact, what they inadvertently discovered is what we in the business world have been (re)learning in droves over the last few years in the form of GTD, Scrum, and Agile Methodologies in general:

  • Small achievable tasks are easier to get done.
  • Larger tasks need to be broken down into achievable sub-tasks.
  • Focus on what you need to accomplish right now, today, this week…
Reblog this post [with Zemanta]

postheadericon FYI: Visual Studio 2010 Technical Readiness Training

I got an email about this earlier, and figured I’d share it. There’s a four-part technical readiness Live Meeting series for Visual Studio 2010 coming up in a couple of weeks.

Visual Studio 2010 became available on April 12. To help you get started and get the most value from this release, Microsoft has picked the four technical sessions below to allow you to attend any or all sessions that apply to you. You can read more details by following the links below:



Topic

Date

Visual Studio 2010 Tips & Tricks Thursday, May 20
12:00 PM-1:00 PM EST
Visual Studio 2010 Architectural Tools Thursday, May 27
12:00 PM-1:00 PM EST
Improving Development Practices with Visual Studio 2010 Thursday, June 3
12:00 PM-1:00 PM EST
Streamlining Testing with Visual Studio 2010 ALM Tools Thursday, June 10
11:00 AM-12:00 PM EST

Everyone who attends a session will entered to win a Microsoft Visual Studio logo Fun Prize Pack (ERV $60)!!


Reblog this post [with Zemanta]

postheadericon Visual Studio Not Responding (beeping) when editing ASPX

I’m just going to share the solution, in case anyone else encounters this after installing Office 2007 or 2010

Yesterday I came across a very strange bug which was causing Visual Studio to lock up after a few (30?) seconds every time I opened an ASPX file for editing. I even uninstalled a few VS addons I thought might have caused it… but that didn’t help (I’m reinstalling Resharper as I type this).

After much frustration and a couple of Bing searches … it turned out to be a problem with MS Office 2007 components. This was a bit of a surprise, since I do not have Office 2007 installed. However, I do have Office Communicator and Live Meeting which are Office 2007 products — and I had just installed Office 2010, which may have actually caused the problem.

Rinat Abdullin wrote about the problem earlier and there’s a thread on StackOverflow which is at least related.

Basically: you get “beeping” when you try to click in the text editor for aspx, or on the Solution Explorer … (sometimes, but not always, Visual Studio will actually be marked as “Not Responding” by Windows) – and, when this happens, you look in your TaskManager and see this Setup.exe process.

This one — in your %CommonProgramFiles% or %CommonProgramFiles(x86)%:
C:\Program Files (x86)\Common Files\Microsoft Shared\OFFICE12\Office Setup Controller\SETUP.EXE

Shutting down Visual Studio and then running that installer “as administrator” manually has solved the problem for me. I just hit “Repair” and that was that. Others (including Rinat) have said they had to reinstall Office — I suspect that probably depends on whether or not you had Office 2007 installed in the first place.

Reblog this post [with Zemanta]

postheadericon Creating WPF UIs for PowerShell with PowerBoots and Visual Studio WPF Designer

I’ve had several people ask me how PowerBoots compares to PrimalForms, or ask for a visual designer for PowerBoots. I usually answer something along the lines of the fact that Microsoft has already created a very good WPF/XAML designer in Visual Studio (including the free Express editions), particularly in 2010, so I don’t see why I should duplicate their efforts. However, up until now I haven’t written or published any sort of walk through about how to make that work …

So crank up your Visual Studio Express Edition and make yourself some user interfaces!

Basically, you just create a WPF project in C# or VB.Net or whatever … I chose to name my project “XamlForBoots” — your project will start off with an empty MainWindow.xaml file which will look something like this:

This is what the Main Window looks like at first

After you drag a few more controls onto the form, and you’ve created a complete user interface, you should delete the x:Class attribute. You need to make sure you know the name of the controls you want to interact with, so you might end up with something like this (I used the property pane, which you can’t see in this shot, to name each textbox and the button):

Once you've dragged some controls onto it

At this point, we’re ready to drop into PowerShell and write some script. Now … there is one catch here. The first script I’m going to show you here is for PowerBoots 0.3 (which will be the first release candidate for a gold 1.0 release, and will be out soon™). However, I’ll post below some code to make it work on the current release, but it requires an external function.

So, in the next release, you can just do something like this:

New-BootsWindow -FileTemplate $pwd\MainWindow.xaml -On_Loaded {
   Register-BootsEvent -InputObject $Calculate -EventName Click -Action {
      $Total.Text = '${0:n2}' -f (($Miles.Text -as [Double]) / ($Mpg.Text -as [Double]) * ($Cost.Text -as [Double]))
   }
}

The key thing you’re supposed to notice here is that the named controls in the XAML are automatically surfaced as variables in the event handlers, and all you have to do is write your logic and hook it up to the controls. We provide a Register-BootsEvent cmdlet which is like Register-ObjectEvent except that it executes the event handlers on the UI thread (so they can do things to the UI) instead of in a new runspace, but basically it’s like calling Add_Click. Of course, you can use Register-ObjectEvent if you just want to spin off PowerShell tasks that don’t read/write the UI.

Backwards compatibility

To get this to work in the current release, you need a function Export-NamedControl to create variables for each of those named controls as variables. Once you’ve defined that function, you can write code very much like I did before, but you have to call Export-NamedControl yourself, and you won’t have that Register-BootsEvent cmdlet. You don’t really need it for this anyway, so that’s not a big deal, at least in this case. Here’s the function. and the actual code to create the window. You can just paste this into a script file:

function global:Export-NamedControl {
[CmdletBinding()]
param(
   [Parameter(ValueFromPipeline=$true, Position=1, Mandatory=$true)]
   $Root = $BootsWindow
)
process {
   Invoke-BootsWindow $Root {
      $control = $BootsWindow
      while($control) {
         $control = $control | ForEach-Object {
            $Element = $_
            if(!$Element) { return }
   
            Write-Verbose "This $($Element.GetType().Name) is $Element"
 
            if($Element.Name) {
               Write-Verbose "Defining $($Element.Name) = $Element"
               Set-Variable "$($Element.Name)" $Element -Scope 2
            }
            ## Return all the child controls ...
            @($Element.Children) + @($Element.Child) + @($Element.Content) +
            @($Element.Items) + @($Element.Inlines) + @($Element.Blocks)
         }
      }
   }
}
}

####################################################################################################################
## Create the window and hook the click. Make sure to use full paths
New-BootsWindow {} -FileTemplate $pwd\MainWindow.xaml -On_Loaded {
   Export-NamedControl -Root $Args[0]
   $Calculate.Add_Click({
      $Total.Text = '${0:n2}' -f (($Miles.Text -as [Double]) / ($Mpg.Text -as [Double]) * ($Cost.Text -as [Double]))
   })
}

And in order to try my demo, you’re going to need that MainWindow.xaml file:

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       Title="Trip Cost">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="28" />
            <RowDefinition Height="28" />
            <RowDefinition Height="28" />
            <RowDefinition Height="28" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="110" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Label Content="Miles" VerticalAlignment="Top" />
        <TextBox Grid.Column="1" Height="23" Width="200" Name="miles" HorizontalAlignment="Stretch" />
        <Label Grid.Row="1" Content="Miles per Gallon" VerticalAlignment="Top" />
        <TextBox Grid.Column="1" Grid.Row="1" Height="23" Width="200" HorizontalAlignment="Stretch" Name="mpg" />
        <Label Grid.Row="2" Content="Cost per Gallon"  VerticalAlignment="Top" />
        <TextBox Grid.Column="1" Grid.Row="2" Height="23" Width="200" HorizontalAlignment="Stretch" Name="cost"  />
        <Button Name="calculate" Grid.Row="3" Content="_Calculate" HorizontalAlignment="Center" />
        <TextBlock Grid.Column="1" Grid.Row="3" Height="23" Width="200" HorizontalAlignment="Stretch" Name="total" />
    </Grid>
</Window>

postheadericon Logging Robocopy errors to the Event Log using PowerShell

Someone came into IRC last week asking for help converting a rather large vbscript into PowerShell, and got me interested in turning Robocopy logs into Windows Events…

The original VBScript is about 68 lines of code, and writes one event per log file. We duplicated it’s functionality with the following 11 lines of code:

Param($LogPath, $LogName, $ArchiveDays)
[string]$Log = Join-Path $LogPath $LogName
if(Select-String -Path $Log -pattern "0x0000") {
   $logError = "$Log.ERROR.$(get-date -format 'yyyy-MM-dd-hhmmss')"
   write-eventlog Application -Source Robocopy -EventId 12 -EntryType Error -Message "Robocopy Job Failed -please check log file $LogError"
   move-item $log $logError
} else {
   # If you do not want to send Success Events to the Application Log, comment out the following line
   write-eventlog Application -Source Robocopy -EventId 1 -EntryType Information -Message "Robocopy Job Failed -please check log file $LogError"
   move-item $Log "$Log.ARCHIVE.$(Get-Date -f 'yyyy-MM-dd-hhmmss')"
}
## Remove archive logs older than $archiveDate
Get-ChildItem "$Log.ARCHIVE.*" | Where { $_.CreationTime -lt (Get-Date).AddDays(-$archiveDays) } | Remove-Item

Actually, even that first attempt extended the functionality a little, because we potentially make multiple archive copies which we only delete once they pass the archive date.

New-EventLog Application Robocopy

There are two catches. First, you need PowerShell 2.0. Second, before you can run that script the first time, you have to create the “Robocopy” event source for the machine by running this command in an elevated PowerShell console (that is, you have to run it “as Administrator”):

New-EventLog Application Robocopy

Of course, being a good geek, I couldn’t leave well enough alone, so we changed the script so that it would log each unique error to the event log (including the line following the error, which has more details), so that there’s no need to go “check the log file” on the machine, since you can retrieve the event logs remotely. The finished script looks like this:

#requires -Version 2.0
## BEFORE you use this the FIRST time (only once per machine)
## you must run the following command elevated (as Administrator):
## New-EventLog Application Robocopy

Param(  [string]$LogPath  = "C:\Logs\",
        [string]$LogName  = "Robocopy-log-file.log",
        [int]$ArchiveDays = 30
)
[string]$Log = Join-Path $LogPath $LogName

$Archive = "ARCHIVE"
foreach($errorEvent in Select-String -Path $Log -Pattern 'ERROR .*0x0000.*$' -context 0,1 | sort {$_.matches[0].value} -Unique )
{
        $Archive = "ERROR"
        write-eventlog Application -Source Robocopy -EventId 12 -EntryType Error -Message $($errorEvent.Line + "`n" + $errorEvent.Context.PostContext)
}

switch($Archive) {
        "ERROR" { ## Archive the log file as an ERROR (we never delete these automatically)
                move $Log "$Log.ERROR.$(get-date -format 'yyyy-MM-dd-hhmmss')"
        }
        "ARCHIVE" {
                write-eventlog Application -Source Robocopy -EventId 1 -EntryType Information  -Message "Robocopy successful"
                ## Archive the log file
                move-item $Log "$Log.ARCHIVE.$(Get-Date -f 'yyyy-MM-dd-hhmmss')" -Force
        }
}

## Remove archive logs older than $archiveDate
$archiveDate = (Get-Date).AddDays(-$archiveDays)
Get-ChildItem "$Log.ARCHIVE.*" | Where { $_.CreationTime -lt $archiveDate } | Remove-Item

Notice that we cleaned up the parameters a little bit, and put some defaults in, but we still haven’t written “help” ... that’s partly because I still am not sure that’s the best option for logging :) Another way would be to just write one log event, but with details about the errors like:

#requires -Version 2.0
## BEFORE you use this the FIRST time (only once per machine)
## you must run the following command elevated (as Administrator):
## New-EventLog Application Robocopy

Param(  [string]$LogPath  = "C:\Logs\",
        [string]$LogName  = "Robocopy-log-file.log",
        [int]$ArchiveDays = 30
)
[string]$Log = Join-Path $LogPath $LogName
[string]$LogError = "$Log.ERROR.$(get-date -format 'yyyy-MM-dd-hhmmss')"
[string]$LogArchive = "$Log.ARCHIVE.$(get-date -format 'yyyy-MM-dd-hhmmss')"

$Errors = Select-String -Path $Log -Pattern 'ERROR .*0x0000.*$' -context 0,1 |
          Group-Object { $_.Context.PostContext } |
          Format-Table Count, Name -HideTableHeaders -AutoSize | Out-String
if($Errors) {
        write-eventlog Application -Source Robocopy -EventId 12 -EntryType Error -Message "$errors`n`nPlease check: $LogError"
        move $Log $LogError
} else {
        write-eventlog Application -Source Robocopy -EventId 1 -EntryType Information  -Message "Robocopy successful. Log archived: $LogArchive"
        move-item $Log $LogArchive
}

## Remove archive logs older than $archiveDate
$archiveDate = (Get-Date).AddDays(-$archiveDays)
Get-ChildItem "$Log.ARCHIVE.*" | Where { $_.CreationTime -lt $archiveDate } | Remove-Item

postheadericon Moving to a new job … staying with Xerox.

Well, it’s past time I posted this, since I know a lot of you have been aware through various sources that I’ve been looking for a job — I’ve accepted an offer from Xerox Global Services (XGS), a wholly owned subsidiary of Xerox Corporation. So basically, I’m staying at Xerox for now, but at the same time, I’m going to work for a medium-sized startup, with all the strange benefits that entails: like late nights and 25¢ soda machines.

Anyway, I start the new job on Monday, but although I’m excited, I don’t actually know much about what I’m in for, other than that this group is a Microsoft TAP partner and a heavy and early adopter of Microsoft technology, and that I’m expecting to work on platform development for XGS’s core product: the Xerox Services Manager.

Consider yourself up-to-date (more about me next week, after I’ve got myself oriented).

postheadericon Format-PoshTable – A Video

Format-PoshTable (PowerBoots + DataGrid from WPFToolkit + PoshConsole) on ScreenCast or Vimeo (and PoshCode).

If you can’t view that (it requires Windows Media Player), you can check it out through Vimeo below. I apologize for the size and quality of that, I didn’t read the HD instructions ahead of time. Skip to the end for the code :)

A simple demo of some of the capabilities of PowerBoots and PoshConsole in the form of a grid-output function...

postheadericon A DSL for XML in PowerShell: New-XDocument

In July of last year I wrote a PowerShell script with the goal of allowing me to generate XML from PowerShell with a simple markup that would look a little like the resulting XML ... this week I was using that script again, and had a couple of issues that made me go back and look at the source.

While I was playing with the source and tweaking things a little bit to improve the way it handles namespaces, I started playing with the idea that I could improve the syntax. At the very least, I thought, I ought to be able to do away with all those “xe” aliases…

Well, I was able to. ( [new] new version) And what’s more, I managed to dramatically clean up the way namespaces work, and make it so that really, the only ugly part of the syntax is the initial declaration of namespaces! I’m going to start with two examples, and use them to walk you through the features :)

Example 1

The simplest example I could think of is to list all the files in a folder, with the file size and last modified stamp:

[string]$xml = New-XDocument folder -path $pwd {
   foreach($file in Get-ChildItem) {
      file -Modified $file.LastWriteTimeUtc -Size $file.Length { $file.Name }
   }
}

The output of that, when run on my formats folder, looks like this:

<folder path="C:\Users\Jaykul\Documents\WindowsPowerShell\formats">
  <file modified="2009-11-07T07:27:00Z" size="30474">CliXml.xsd</file>
  <file modified="2009-11-07T07:27:40.48001Z" size="14314">format.xsd</file>
  <file modified="2010-01-16T21:30:06.0562796Z" size="18275">NppExternalLexers.xml</file>
  <file modified="2009-03-18T21:28:51.6579351Z" size="5802">Recommender.Types.Format.ps1xml</file>
  <file modified="2009-11-07T07:27:40.518029Z" size="5107">types.xsd</file>
</folder>

You can immediately see what the script does: New-XDocument (which is aliased as ‘xml’) actually generates the root xml node, so the first argument to it is the name of that node, and any other arguments become attributes … except for the script block. That script block turns into the contents of the node.

Inside the script block, PowerShell code is parsed as usual, but whenever a command that doesn’t exist is encountered, it is turned into an xml node! Pretty simple, right? Of course, if you wanted to create a node with a name that’s already taken by a PowerShell command, you can just replace file with New-XElement file, or (using aliases) xe 'file', which explicitly creates an xml node with the given name.

That’s pretty much it for our first example, so let’s look at a more complicated example, with multiple namespaces, and deeper nesting.

Example 2

This time, we’ll create an Atom document, and we’ll include some namespace extensions (including a made up one for listing my files as we did above):

New-XDocument (([XNamespace]"http://www.w3.org/2005/Atom") + "feed")          `
              -fi ([XNamespace]"http://huddledmasses.org/schemas/FileInfo")   `
              -dc ([XNamespace]"http://purl.org/dc/elements/1.1")             `
              -$([XNamespace]::Xml +'lang') "en-US" -Encoding "UTF-16"        `
{
   title {"Huddled Masses: You can do more than breathe for free..."}
   link {"http://HuddledMasses.org/"}
   updated {(Get-Date -f u) -replace " ","T"}
   author {
      name {"Joel Bennett"}
      uri {"http://HuddledMasses.org/"}
   }
   id {"http://HuddledMasses.org/" }

   entry {
      title {"A DSL for XML in PowerShell: New-XDocument"}
      link {"http://HuddledMasses.org/A-DSL-for-XML-in-PowerShell-New-XDocument/" }
      id {"http://HuddledMasses.org/A-DSL-for-XML-in-PowerShell-New-XDocument/" }
      updated {(Get-Date 2010/03/03 -f u) -replace " ","T"}
      summary {"A while back, I posted a simple mini language for generating XML from PowerShell script. However, I was using it the other day, and I really just felt that the markup was ugly, since it was littered with 'xe' marks and such."}
      link -rel license -href "http://creativecommons.org/licenses/by/3.0/" -title "CC By-Attribution"
      dc:rights { "Copyright 2010, Some rights reserved (licensed under the Creative Commons Attribution 3.0 Unported license)" }
      category -scheme "http://huddledmasses.org/tag/" -term "xml"
      category -scheme "http://huddledmasses.org/tag/" -term "PowerShell"
      category -scheme "http://huddledmasses.org/tag/" -term "DSL"
      fi:folder -Path "~\Formats" {
         foreach($file in Get-ChildItem (Join-Path (Split-Path $profile) Formats)) {
            fi:file -Created $file.CreationTimeUtc -Modified $file.LastWriteTimeUtc -Size $file.Length { $file.Name }
         }
      }
   }
} | % { $_.Declaration.ToString(); $_.ToString() }

There are four things you should notice, in particular:

First: the initial tag has a [XNamespace] added to it. You can specify a tag name that has a namespace by adding them together this way, or by embedding the namespace in the string like "{http://www.w3.org/2005/Atom}feed" instead. Either way works. This initial namespace becomes the default namespace for the document. If you don’t specify a namespace on tags later, they automatically belong to that one.

Second: when you want to add additional namespaces, you can do so with a custom prefix like: -dc ([XNamespace]"http://purl.org/dc/elements/1.1"), and that prefix (dc) takes on a special meaning. When you want to have a tag later on that is part of that namespace, you just prefix the tag, like dc:rights —the same way you would in XML.

Third: any number of attributes can be specified using the -name value syntax, but anything in a {scriptblock} becomes the content — and is subject to the same rules as the outer sections.

Fourth: This generates an XDocument. When you cast an XDocument to string, the xml declaration is left off, so if you want it, you need to manually add it via $XDocument.Declaration. Incidentally, XDocuments are not XMLDocuments, but they are trivially castable to them.

The output of that particular section of New-XDocument is this:

<feed xmlns:dc="http://purl.org/dc/elements/1.1" xmlns:fi="http://huddledmasses.org/schemas/FileInfo" xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
 
  <link />http://HuddledMasses.org/
  <updated>2010-03-04T00:44:31Z</updated>
  <author>
    <name>Joel Bennett</name>
    <uri>http://HuddledMasses.org/</uri>
  </author>
  <id>http://HuddledMasses.org/</id>
  <entry>
   
    <link />http://HuddledMasses.org/A-DSL-for-XML-in-PowerShell-New-XDocument/
    <id>http://HuddledMasses.org/A-DSL-for-XML-in-PowerShell-New-XDocument/</id>
    <updated>2010-03-03T00:00:00Z</updated>
    <summary>A while back, I posted a simple mini language for generating XML from PowerShell script. However, I was using it the other day, and I really just felt that the markup was ugly, since it was littered with 'xe' marks and such.</summary>
    <link rel="license" href="http://creativecommons.org/licenses/by/3.0/" title="CC By-Attribution" />
    <dc:rights>Copyright 2010, Some rights reserved (licensed under the Creative Commons Attribution 3.0 Unported license)</dc:rights>
    <category scheme="http://huddledmasses.org/tag/" term="xml">
    <category scheme="http://huddledmasses.org/tag/" term="PowerShell">
    <category scheme="http://huddledmasses.org/tag/" term="DSL">
    <fi:folder path="~\Formats">
      <fi:file created="2009-11-07T07:27:00Z" modified="2009-11-07T07:27:00Z" size="30474">CliXml.xsd</fi:file>
      <fi:file created="2009-11-07T07:27:40.4529965Z" modified="2009-11-07T07:27:40.48001Z" size="14314">format.xsd</fi:file>
      <fi:file created="2009-02-07T13:56:12Z" modified="2010-01-16T21:30:06.0562796Z" size="18275">NppExternalLexers.xml</fi:file>
      <fi:file created="2009-08-09T19:10:06.3647094Z" modified="2009-03-18T21:28:51.6579351Z" size="5802">Recommender.Types.Format.ps1xml</fi:file>
      <fi:file created="2009-11-07T07:27:40.4970185Z" modified="2009-11-07T07:27:40.518029Z" size="5107">types.xsd</fi:file>
    </fi:folder>
  </category></category></category></entry>
</feed>

The New-XDocument script itself is on PoshCode in the Xml Module 4 along with a few interesting functions like Select-XML (which improves over the built-in by being able to ignore namespaces when you write XPath) and Remove-XmlNamespace (which was instrumental in removing namespaces for Select-Xml). There’s also a Format-Xml for pretty-printing, and a Convert-Xml for processing XSL transformations.

I’ll probably post some more examples of this in the next week or two, and I really should write some commentary about the function itself, which uses the tokenizer to discover which “commands” are really xml nodes … but for now, I’ll leave you to enjoy.

Reblog this post [with Zemanta]

postheadericon Are you interested in a virtual PowerShell brown-bag event?

I just put up a poll on the PowerShell Virtual Group to see if people are interested in a low-planning brown-bag event.

The initial question is: would you attend a weekly (or monthly) virtual brown-bag lunch if I put one together.

The idea is that we would start each session with a short collection of interesting links, tips and tricks, or connect issues, and then have a presentation or discussion or script club or open-mic session, depending on interest.

Basically, this is meant to flow, on a week-to-week basis, from script-club to formal user group presentations.

Some weeks we would have presenters from various local user groups share content they had prepared for their local groups. We would encourage you to take ownership of this time, request topics, and prepare presentations (no matter how short).

Some weeks we would have an open-format script club using our private pastebin, IRC channel, and LiveMeeting voice chat. This time could vary from real-world problem solving to scripting games and “project Euler”-style challenges.

Some weeks we would have open-mic time and solicit feedback for the PowerShell team from anyone who cared to give it. I would make an effort to make sure I wasn’t the only MVP there, so you could feel that even if there wasn’t a Microsoft employee present on a given day, your voice could be heard when you make suggestions or vent frustrations …

The point is: the format would vary a bit, and we would adjust it over time to fit whatever works the best within our virtual meeting and time constraints.

So, what do you think? Are you interested?

Archives