Windows PowerShell Team Blog

  1. Intel vPro PowerShell Module -

    Intel has released version 1.0 of their Intel Core vPro PowerShell Module.  This set of cmdlets do Out-of-Band hardware management of devices that are equipped with the vPro chip.  What that means is that you can do a certain amount of management on devices that don’t have an OS or whose OS is hung (if you are using one of our competitor’s OSes .. or haven’t upgraded to the awesome W7 Smile).   This allows you do things like turn machines on or off, change the boot sequence, change power plans etc.

    Now in all honesty, this module provides you nothing new.    You could always use the WINRM executable to perform these functions.  So too, you could use PowerShell *-WSMAN* cmdlets to do everything you can do with this module.  More precisely, maybe YOU could do this – honestly I never could and that points out why PowerShell is so important.  You might have noticed that in my talks, I love to have a HW mgmt demonstration but I never do the demo.  The reason for that is that to that when you use WINRM or the *-WSMAN* cmdlets, you need to understand so many low level details that it makes my head explode.  Literally – I will not do this demo because I have no confidence that I could get all those things right in an environment where getting it right really mattered. 

    So now think about that a second.  Like your IT shop isn’t an environment where it matters whether you get it right or not?  It absolutely does have to be right.  The nice thing about that environment is that often you have more time/less pressure than a demo in a talk and you can capture the procedure in a script and have people review the script.  BUT… other times you don’t have those luxuries.

    The thing we keep hammering over and over again is that PowerShell is all about delivering “high level task oriented abstractions using common naming and consistent syntax”.  The mechanisms I mentioned above are very low level abstractions.  What Intel is bringing to the table is the high-level task oriented abstractions!  The things where you think about what you want to accomplish, type it, and thanks to all the hard work of the superstar engineers at Intel – it just works!  And if you have a question, it has rich help with lots of examples.  And if you want to manage multiple machines, they adhered to the PowerShell guidelines so doing multi-machine management is seamless.

    It’s really nice stuff and you should check it out.  You can get more details and view a cool HD video HERE.

    The version 1 module does not cover the full function of vPro but it looks like a great start:

    image

    Oh and I almost forgot the best part – the cost … FREE.

    Enjoy! 

    Jeffrey Snover [MSFT]
    Distinguished Engineer

  2. PowerShell V2.0 Book Available in Italian -

    Efran Cobisi has published a PowerShell V2 book in Italian.  The title is “Windows PowerShell 2.0 – Guida completa” and is a 448 pages long.  Efran describes it as “a collection of theory, insides and hints on the scripting environment, the programming language and the most used cmdlets. It’s targeted to both developers and IT professionals and contains many sections devoted to help people with previous experiences "with other shells (CMD, COMMAND.COM, BASH, KSH, CSH, ...) as well.” 

    If you can read Italian, you can find out more about it HERE.

    Sadly I don’t read Italian but I’ve visited Rome a number of times and fell in love with the sound of the language.  As such, I’m going to wait for the audiobook.  Smile

    Enjoy!

    Jeffrey Snover [MSFT]
    Distinguished Engineer
    Visit the Windows PowerShell Team blog at:    <a href="http://blogs.msdn.com/PowerShell">http://blogs.msdn.com/PowerShell</a>
    Visit the Windows PowerShell ScriptCenter at:  <a href="http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx">http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx</a>

  3. Improving Parameter Set Design -

    Designing useable cmdlets is part engineering and part art. It’s not an easy task to define the conceptual boundaries of a cmdlet (where does one cmdlet end and the next begin) or to provide great feature control without inundating the user with parameters.

    However, you can improve the usability of your cmdlets by avoiding two common parameter set design flaws.

    • A parameter set with no mandatory parameters in a cmdlet that requires parameters
    • Mandatory parameters with position numbers that are higher than the position numbers of optional parameters

    Parameter sets with no mandatory parameters

    Some cmdlets, like Get-Process, can be run without any parameters, so you'd expect them to have at least one parameter set with no mandatory parameters.

    But look at the syntax of Get-WmiObject. The first three parameter sets have no mandatory parameters, which implies that there is at least one valid command without parameters. But you cannot run Get-WmiObject without parameters. If you try, you get the default parameter set, which has the Class mandatory parameter.

    But it's worse. To use any of the first three parameter sets, you have to specify one of the parameters that is unique to those parameter sets. And good luck finding the unique parameter in the syntax block. It's like playing Where's Waldo when you're on deadline.

    Unless you can run the cmdlet without parameters, be sure that there is at least one mandatory parameter in each parameter set. This better reflects the use of the cmdlet and makes it easier for users to interpret the parameter sets in the syntax block.

    Mandatory parameters with high position numbers

    When Get-Command displays command syntax, it uses the following rule to determine the order of parameters in the syntax block:

    1. Mandatory
    2. Position
    3. Alphabetical by name

    So, all of the mandatory parameters appear before any of the optional ones. Which is what users expect.

    But users also expect the parameters to be listed in position order. They expect to be able to construct a valid command by following the syntax diagram from left to right.

    However, if a mandatory parameter has a higher position number than an optional parameter, the parameters are not in position order in the syntax block.

    I was recently asked to review a cmdlet spec where the mandatory parameter in the parameter set had position 2 and an optional parameter had position 1. We quickly swapped them, resulting in a much improved user experience.

     

    Cmdlet design is an art. But a little engineering guidance goes a long way, too.

     

    June Blender [MSFT]
    Windows PowerShell Documentation

  4. Using New-WebServiceProxy to get, modify, and add items to a list in SharePoint 2007 -

    The motivation

    Let’s say that you want to retrieve and modify a list in a SharePoint site, but you don’t have access to Microsoft.SharePoint.dll. One possible solution is to try to search online or ask someone to let you copy the dll. If you are able to get a hold of it, you will quickly realize that the Microsoft.SharePoint.dll has some dependencies and that you are stuck again. Well, I will show you how you can get, modify and add items to a list in SharePoint using PowerShell V2.

    Pre requisites: First, you need a SharePoint site and credentials to modify that particular list. The illustration below shows the list (DemoList) that I want to modify.

    DemoSite1

    Get List Items

    The New-WebServiceProxy Cmdlet creates a web service proxy object which lets you use and manage the web service.

    # The uri refers to the path of the service description, e.g. the .asmx page            
    $uri = "http://powershell/TeamSite/TestTeamSite/Demos/_vti_bin/lists.asmx?WSDL"             
                
    # Create the service            
    $service = New-WebServiceProxy -Uri $uri  -Namespace SpWs  -UseDefaultCredential            
                
    # The name of the list             
    $listName = "My Demo List"             
                
    # Create xml query to retrieve list.             
    $xmlDoc = new-object System.Xml.XmlDocument            
    $query = $xmlDoc.CreateElement("Query")            
    $viewFields = $xmlDoc.CreateElement("ViewFields")            
    $queryOptions = $xmlDoc.CreateElement("QueryOptions")            
    $query.set_InnerXml("FieldRef Name='Full Name'")             
    $rowLimit = "10"            
                
    $list = $null             
    $service = $null              
                
    try{            
        $service = New-WebServiceProxy -Uri $uri  -Namespace SpWs  -UseDefaultCredential              
    }            
    catch{             
        Write-Error $_ -ErrorAction:'SilentlyContinue'             
    }

    Now, we use the service object to retrieve the list.

    if($service -ne $null){            
        try{                    
            $list = $service.GetListItems($listName, "", $query, $viewFields, $rowLimit, $queryOptions, "")             
        }            
        catch{             
            Write-Error $_ -ErrorAction:'SilentlyContinue'            
        }            
    }

    Let’s take a look at the $list object. 

    $list

    s           : uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882
    dt          : uuid:C2F41010-65B3-11d1-A29F-00AA00C14882
    rs          : urn:schemas-microsoft-com:rowset
    z           : #RowsetSchema
    #whitespace : {
                  ,
                  }
    data        : data

     

    The items of the DemoList are located in $list.data.row.

    $list.data.row

    ows_ContentTypeId       : 0x0100F20992473D85F74DBAFD4159A55805FB
    ows_Title               : Francisco
    ows_Car                 : Impreza
    ows_IceCream            : Chocolate
    ows_Sport               : Basketball
    ows_ID                  : 1
    ows_ContentType         : Item
    ows_Modified            : 2010-06-24 14:58:17
    ... (more data) ...

    For more information on getting list items visit http://msdn.microsoft.com/en-us/library/lists.lists.getlistitems.aspx

    Update List Items

    We want to modify the sport field value from “basketball” to “soccer”. to do this, we use the $service and $list from the example above.

    # Get name attribute values (guids) for list and view            
    $ndlistview = $service.getlistandview($listname, "")            
    $strlistid = $ndlistview.childnodes.item(0).name            
    $strviewid = $ndlistview.childnodes.item(1).name            
                
                    
    # Create an xmldocument object and construct a batch element and its attributes.             
    $xmldoc = new-object system.xml.xmldocument             
                
    # note that an empty viewname parameter causes the method to use the default view               
    $batchelement = $xmldoc.createelement("batch")            
    $batchelement.setattribute("onerror", "continue")            
    $batchelement.setattribute("listversion", "1")            
    $batchelement.setattribute("viewname", $strviewid)            
                
                
    # Specify methods for the batch post using caml. to update or delete, specify the id of the item,             
    # and to update or add, specify the value to place in the specified column            
    $id = 1            
    $xml = ""            
                
    # The row to be modified            
    $rowId = $list.data.row.ows_id            
                
    # New field value            
    $newsport ="soccer"               
                
    $xml += <method id='$id' cmd='Update'>" +            
            "<field name='ID'>$rowId</field>" +            
            "<field name='Sport'>$newsport</field>" +            
            "</method>"            
                        
    # Set the xml content                    
    $batchelement.innerxml = $xml            
                
    $ndreturn = $null             
    try {            
        $ndreturn = $service.updatelistitems($listname, $batchelement)             
    }            
    catch {             
        write-error $_ -erroraction:'SilentlyContinue'            
    }

    For more information on updating list items visit http://msdn.microsoft.com/en-us/library/ms440289.aspx.

    Add New Items to the List

    To add a new row to the list, everything is the same as in the update list items example above, the only difference is the xml content.

    In this case, the new row will contain the following information:
    Title: James
    Car: A4
    Sport: Swimming
    Icecream: Strawberry Cheese Cake

    $xml = "<method id='$id' cmd='New'>" +            
            "<field name='Title'>James</field>"+            
            "<field name='Car'>A4</field>"+            
            "<field name='Sport'>Swimming</field>" +            
            "<field name='IceCream'>Strawberry cheese Cake</field>" +            
            "</method>""

    At the end, our SharePoint list looks like this.

    DemoSite2

    Cheers,
    Francisco Gomez Gamino [MSFT]

  5. Windows PowerShell 2.0 on Windows Update -

    Today, we released Windows PowerShell 2.0 and WinRM 2.0 for pre-Windows 7 operating systems on Windows Update. This non-security, optional update is designed for Windows Server 2008 SP2, Windows Vista SP2, Windows Server 2003 SP2, and Windows XP SP3.

    Windows PowerShell 2.0 and WinRM 2.0 are also available as part of  the Windows Management Framework (WMF) Core Package on the  Microsoft Download Center and Windows Server Update Services (WSUS).

    The WMF Core Package available on the Microsoft Download Center and the Windows Update release contain the same binaries of the products, so you can now download them from either source. Because Windows PowerShell 2.0 is in-place upgrade to Windows PowerShell 1.0, we will no longer be offering Windows PowerShell 1.0 on Windows Update.

    Windows PowerShell 2.0 appears as an option in a Windows Update scan only if the computer meets the following conditions.

    • The computer has at least Microsoft .NET Framework 2.0 SP1
    • The computer does not have a non-RTM (CTP, Beta, RCs etc.) release of Windows PowerShell. (Windows PowerShell 1.0 RTM can be installed.)

    Hemant Mahawar [MSFT]
    Program Manager

  6. Specifying a View in TechNet and MSDN URIs -

    [This isn't only a PowerShell topic, but I've been asked a few times, so I thought I post the answer here.]

    If you've visited TechNet or MSDN lately, you'll notice that there are new view options for the pages. TechNet has a new ScriptFree view, in addition to the familiar Classic view. MSDN has two new views, ScriptFree and Lightweight.

    When you change your page view, your preference is saved and new pages that you open are shown in the saved view until you change your view again.

    If you are linking to a page, you can specify a view in the link. This allows you to determine how users see the linked page. For example, the lightweight view might make MSDN reference pages easier for non-programmers to read. However, using a view-specific link changes the user's view preference, so some users might not appreciate your efforts.

    To specify a view in a URI link, add a view specifier in parentheses before the .aspx.

    · To specify Classic view: (classic)
    For example, http://technet.microsoft.com/en-us/library/dd347576(classic).aspx

    · To specify ScriptFree view: (loband)
    For example, http://technet.microsoft.com/en-us/library/dd347576(loband).aspx

    · To specify Lightweight view (MSDN only): (lightweight)
    For example, http://msdn.microsoft.com/en-us/library/system.io.fileinfo(lightweight).aspx

    To change your page view:

    · In Classic or ScriptFree view, in the upper right corner of the page, click the view name.

    · In Lightweight view, in the upper right corner of the page, click Preferences, and then click the view name.

    We haven't yet found a way to specify a view in a redirectible link, such as http://go.microsoft.com/fwlink/?LinkID=113309, but if you find a method that works, please add it to the comments below and I'll update the blog.

    June Blender [MSFT]
    Windows PowerShell Documentation

  7. PowerShell Integration Into Visual Studio -

    Quest has released a beta of PowerGUI Visual Studio (aka PowerGUI VSX). 

    Check out Kirk Munro’s blog entry HERE for more details.  Check out this screenshot:

     screenshot.png

    I can’t wait to install it and kick the tires!

    Jeffrey Snover [MSFT]
    Distinguished Engineer
    Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
    Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

     

  8. Kudos to NetApp for Data ONTAP PowerShell ToolKit -

    Kudos to NetApp for releasing the Data ONTAP PowerShell Toolkit last week at TechEd.

    I was monitoring the twitter feeds last week and saw a flurry of activity talking about NetApp’s broad adoption of PowerShell and release of the Data ONTAP PowerShell Toolkit surfacing all of their management functionality through cmdlets. I decided to investigate and headed to the NetApp booth where I saw an awesome, live automated, disaster recovery demo driven entirely by PowerShell. We’re talking automated failover to a remote site in less than three minutes using a combination of the NetApp cmdlets, cluster cmdlets and what appeared to be superstar James O’Neil’s Hyper-V cmdlets (James’ cmdlets saved my butt in Europe last year so I’m going to be thankful forever).

    I really liked NetApp’s messages around the demo:

    1. You reduce total cost of ownership through automation.
    2. When you have a fail-over situation, you cannot afford any mistakes. You have to build the automation well in advance, make sure it works and then just use it. No ”judgment calls”, no “click a series of menus and dialogue boxes in the right order”, no “try this and see what happens”, no drama! Maybe that is what we should call it, “Drama-free disaster recovery”. I like that phrase.
    1. One of the NetApps guys told me about a customer that asked for a copy of the Disaster Recovery Demo scripts so he could modify them to implement when he got home from TechEd.
    • Once you have an automated solution, you can/should run it every month or two to certify that it actually works.

    I have not had an opportunity to sit down and really kick the tires on the cmdlets and get them in focus but when I do, I’m going to allocate a good chuck of time because the ONTAP toolkit has more than 350 cmdlets. But wait – it gets better. When I talked the guys at NetApp they told me that the entire toolkit was developed by a single engineer in about 3 months! This proved another point we had from the very beginning - namely that cmdlets should be super easy to develop. Still – 350 cmdlets in 3 months – that guy/gal deserves a beer.

    But wait – it gets better (seriously). The NetApps guys figured out a key PowerShell play that I’ve just recently begun to see companies start to figure out. To succeed in the management business, it is all about integration. Some customers need you to integrate your functions into System Center. Others will want Tivoli or HP or the next guy or the next one or a workflow system and on and on and on. It really makes your head spin. BUT all those systems have some level of PowerShell integration (some better than others) so when a vendor like NetApps exposes everything through PowerShell, it automatically gets integrated into everything their customers are using for no additional effort. It is an instant light up story. I can guarantee you that as soon as companies get this in focus, they’ll have PowerShell support in short order.

    This was, all up, a great TechEd. In particular, it was a great TechEd for PowerShell because there was a quantum leap in the number of customers and vendors actually the sort of production-quality, run-your-business automation that we had in mind when we started PowerShell so many years ago. I couldn’t grab a meal, ride a bus, or attend a party without having people come up to me and tell me how PowerShell had “transformed” the way they managed their systems. For me, the high point was the NetApp Disaster Recover demo because it was the fruition of so many things the PowerShell team has been working on. It took a long time to get all the pieces in place but as Colonel John Hannibal Smith (from the A-Team) says, “I love it when a plan comes together!”

    I’m looking forward to spending more time digging into the details of the ONTAP toolkit and what other scenarios are enabled by this. This is a great start, and I’m expecting to see even more great things from NetApp and other vendors at TechEd Europe in November.

    Here are some links to find our more about ONTAP Powershell support:

    ONTAP PowerShell ToolKit Community

    NetApps Team Blog

    Jeffrey Snover [MSFT]
    Distinguished Engineer
    Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
    Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

  9. Export and Import PowerShell ISE Opened Files -

    Unlike other tools, PowerShell ISE doesn’t have project files. Project files are a good way to set your environment up with a well known state.

    Thanks to the ISE Object Model, it is possible to add some project functionality.

    The script below has two main functions “Export-ISEState” and “Import-ISEState”. They can be used to save files and PowerShellTabs and reopen them later.

    Even script contents for untitled files are saved.

    To save the current state (state = files and PowerShellTabs), use something like:

        Export-ISEState c:\temp\files.isexml

    To load the state later run:

        Import-ISEState c:\temp\files.isexml

    When exporting the current state the all titled files are saved with the script from my last post. This ensures you will have the same content when importing the state later.

    For untitled files, the contents are saved. When untitled files are reloaded, new untitled files are created, if their contents are not already present in some untitled file.

    If you like it, you can add it to your profile (psedit $profile will edit the ISE profile) or to a module imported in your profile.

    Lucio Silveira [MSFT]

    function Save-AllISEFiles

    {

    <#

    .SYNOPSIS

        Saves all ISE Files except for untitled files. If You have multiple PowerShellTabs, saves files in all tabs.

    #>

        foreach($tab in $psISE.PowerShellTabs)

        {

            foreach($file in $tab.Files)

            {

                if(!$file.IsUntitled)

                {

                    $file.Save()

                }

            }

        }

    }

     

    function Export-ISEState

    {

    <#

    .SYNOPSIS

        Stores the opened files in a serialized xml so that later the same set can be opened

     

    .DESCRIPTION

        Creates an xml file with all PowerShell tabs and file information

       

    .PARAMETER fileName

        The name of the project to create a new version from. This will also be the name of the new project, but with a different version

     

    .EXAMPLE

        Stores current state into c:\temp\files.isexml

        Export-ISEState c:\temp\files.isexml

    #>

     

        Param

        (

            [Parameter(Position=0, Mandatory=$true)]

            [ValidateNotNullOrEmpty()]

            [string]$fileName

        )

       

        # We are exporting a "tree" worth of information like this:

        #

        #  SelectedTabDisplayName: PowerShellTab 1

        #  SelectedFilePath: c:\temp\a.ps1

        #  TabInformation:

        #      PowerShellTab 1:

        #           File 1:

        #                FullPath:     c:\temp\a.ps1

        #                FileContents: $null

        #           File 2:

        #                FullPath:     Untitled.ps1

        #                FileContents: $a=0...

        #       PowerShellTab 2:

        #       ...

        #  Hashtables and arraylists serialize rather well with export-clixml

        #  We will keep the list of PowerShellTabs in one ArrayList and the list of files

        #  and contents(for untitled files) inside each tab in a couple of ArrayList.

        #  We will use Hashtables to group the information.

        $tabs=new-object collections.arraylist

       

        # before getting file information, save all untitled files to make sure their latest

        # text is on disk

        Save-AllISEFiles

     

        foreach ($tab in $psISE.PowerShellTabs)

        {

            $files=new-object collections.arraylist

            $filesContents=new-object collections.arraylist

            foreach($file in $tab.Files)

            {

                # $null = will avoid $files.Add from showing in the output

                $null = $files.Add($file.FullPath)

               

                if($file.IsUntitled)

                {

                    # untitled files are not yet on disk so we will save the file contents inside the xml

                    # export-clixml performs the appropriate escaping for the contents to be inside the xml

                    $null = $filesContents.Add($file.Editor.Text)

                }

                else

                {

                    # titled files get their content from disk

                    $null = $filesContents.Add($null)  

                }

            }

            $simpleTab=new-object collections.hashtable

           

            # The DisplayName of a PowerShellTab can only be change with scripting

            # we want to maintain the chosen name       

            $simpleTab["DisplayName"]=$tab.DisplayName

           

            # $files and $filesContents is the information gathered in the foreach $file above

            $simpleTab["Files"]=$files

            $simpleTab["FilesContents"]=$filesContents

           

            # add to the list of tabs

            $null = $tabs.Add($simpleTab)

           

        }

       

        # tabsToSerialize will be a hashtable with all the information we want

        # it is the "root" of the information to be serialized in the hashtable we store...

        $tabToSerialize=new-object collections.hashtable

       

        # the $tabs information gathered in the foreach $tab above...

        $tabToSerialize["TabInformation"] = $tabs

       

        # ...and the selected tab and file.

        $tabToSerialize["SelectedTabDisplayName"] = $psISE.CurrentPowerShellTab.DisplayName

        $tabToSerialize["SelectedFilePath"] = $psISE.CurrentFile.FullPath

       

        # now we just export it to $fileName

        $tabToSerialize | export-clixml -path $fileName

    }

     

     

    function Import-ISEState

    {

    <#

    .SYNOPSIS

        Reads a file with ISE state information about which files to open and opens them

     

    .DESCRIPTION

        Reads a file created by Export-ISEState with the PowerShell tabs and files to open

       

    .PARAMETER fileName

        The name of the file created with Export-ISEState

     

    .EXAMPLE

        Restores current state from c:\temp\files.isexml

        Import-ISEState c:\temp\files.isexml

    #>

     

        Param

        (

            [Parameter(Position=0, Mandatory=$true)]

            [ValidateNotNullOrEmpty()]

            [string]$fileName

        )

       

       

        # currentTabs is used to keep track of the tabs currently opened.

        # If "PowerShellTab 1" is opened and $fileName contains files for it, we

        # want to open them in "PowerShellTab 1"

        $currentTabs=new-object collections.hashtable

        foreach ($tab in $psISE.PowerShellTabs)

        {

            $currentTabs[$tab.DisplayName]=$tab

        }

       

        $tabs=import-cliXml -path $fileName

     

        # those will keep track of selected tab and files   

        $selectedTab=$null

        $selectedFile=$null

     

        foreach ($tab in $tabs.TabInformation)

        {

            $newTab=$currentTabs[$tab.DisplayName]

            if($newTab -eq $null)

            {

                $newTab=$psISE.PowerShellTabs.Add()

                $newTab.DisplayName=$tab.DisplayName

            }

            #newTab now has a brand new or a previouslly existing PowerShell tab with the same name as the one in the file

           

            # if the tab is the selected tab save it for later selection

            if($newTab.DisplayName -eq $tabs.SelectedTabDisplayName)

            {

                $selectedTab=$newTab

            }

           

            # currentUntitledFileContents keeps track of the contents for untitled files

            # if you already have the content in one of your untitled files

            # there is no reason to add the same content again

            # this will make sure calling import-ISEState multiple times

            # does not keep on adding untitled files

            $currentUntitledFileContents=new-object collections.hashtable

            foreach ($newTabFile in $newTab.Files)

            {

                if($newTabFile.IsUntitled)

                {

                    $currentUntitledFileContents[$newTabFile.Editor.Text]=$newTabFile

                }

            }

           

            # since we will want both file and fileContents we need to use a for instead of a foreach

            for($i=0;$i -lt $tab.Files.Count;$i++)

            {

                $file = $tab.Files[$i]

                $fileContents = $tab.FilesContents[$i]

     

                #fileContents will be $null for titled files

                if($fileContents -eq $null)

                {

                    # the overload of Add taking one string opens the file identified by the string

                    $newFile = $newTab.Files.Add($file)

                }

                else # the file is untitled

                {

                    #see if the content is already present in $newTab

                    $newFile=$currentUntitledFileContents[$fileContents]

                   

                    if($newFile -eq $null)

                    {

                        # the overload of Add taking no arguments creates a new untitled file

                        # The number for untitled files is determined by the application so we

                        # don't try to keep the untitled number, we just create a new untitled.

                        $newFile = $newTab.Files.Add()

                   

                        # and here we restore the contents

                        $newFile.Editor.Text=$fileContents

                    }

                }

           

                # if the file is the selected file in the selected tab save it for later selection   

                if(($selectedTab -eq $newTab) -and ($tabs.SelectedFilePath -eq $file))

                {

                    $selectedFile = $newFile

                }

            }

        }

       

        #finally we selected the PowerShellTab that was selected and the file that was selected on it.

        $psISE.PowerShellTabs.SetSelectedPowerShellTab($selectedTab)

        if($selectedFile -ne $null)

        {

            $selectedTab.Files.SetSelectedFile($selectedFile)

        }

    }

     

     

  10. Save All PowerShell ISE files -

    PowerShell ISE is a simple tool and in some cases it has the bare essentials. For instance, it does not have an option to save all files.

    On the flipside, it offers an Object Model from its first version that allows adding features beyond the essentials like this one and many more. 

    If we had the "Save All" option in the ISE, one interesting question is what to do about untitled files. They are supposed to be transient. One could argue that Save All could just skip untitled files. Another could argue that we should just pick a name for untitled, but I would disagree with "another" :-) Picking a name would soon fill some place in disk (which we would also have to pick) with a bunch of untitled files, which were supposed to be transient in the first place. We could prompt the user to pick a name for the untitled files, or show where we save them like we do in the PowerShell exit, but that doesn’t look like the very autonomous Save All in other applications.

    The code below should be self explanatory and it skips untitled files as I thought better.

    If you like it, you can add it to your profile (psedit $profile will edit the ISE profile) or to a module imported in your profile.

    Lucio Silveira [MSFT]

    function Save-AllISEFiles

    {

    <#

    .SYNOPSIS

        Saves all ISE Files except for untitled files. If You have       multiple PowerShellTabs, saves files in all tabs.

    #>

        foreach($tab in $psISE.PowerShellTabs)

        {

            foreach($file in $tab.Files)

            {

                if(!$file.IsUntitled)

                {

                    $file.Save()

                }

            }

        }

    }

     

    # This line will add a new option in the Add-ons menu to save all ISE files with the Ctrl+Shift+S shortcut.

    # If you try to run it a second time it will complain that Ctrl+Shift+S is already in use

    $psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Save All",{Save-AllISEFiles},"Ctrl+Shift+S")

     

     

     

  11. Renaming Tabs in the ISE -

    When you have multiple PowerShell tabs open in the ISE, it may be handy to rename them, so you can tell which is which.  This is especially useful when using Remoting with Enter-PSSession.  The problem when using Enter-PSSession is that you have no access to the root ISE object ($psise) when remoting, so you should use another (local) tab and enter the following:

       $psise.PowerShellTabs[0].DisplayName = 'myRemoteMachine'

    Needless to say, if you want to rename the second tab, you'd use PowerShellTabs[1] ... and so on

    To rename the current PowerShell tab, enter:

       $psise.CurrentPowerShellTab.DisplayName = 'PowerShellRocks'

    ref@

    Refaat Issa [MSFT]

  12. PowerShell V2 IS Available -

    Superstar Tobias Weltner (of PowerShell.com and Powershell Plus fame) sent me some mail today pointing to this May 14th article Three Essential PowerShell 2.0 Remote Management Features.  It is a very good article except for this part:

    “PowerShell 2.0 is built into Windows Server 2008 R2 and Windows 7. For older operating systems, PowerShell 2.0 is scheduled to be available a few months down the road and will include support for Windows XP SP3, Windows Server 2003 SP2, Windows Vista SP1 and Windows Server 2008.”

     

    That is not right.  PowerShell V2 has been available for these OS for quite some time now.  You can download the packages here: http://go.microsoft.com/fwlink/?LinkID=151321

    We are responsible for the confusion because our redistribution is not called PowerShell V2, its called Windows Management Framework.  Let’s talk about what motivated that change.  In the past, we had a dogs breakfast of management technologies, each releasing on it’s own schedule with it’s own installer, it own approach to supporting downlevel OSes etc.  We were trying “shipping our organization”.  What is worse is that we never had anyone making sure that these things worked together (they did  but if they didn’t, there was no one to hold accountable).  Having spent the majority of my career building management products and solutions, I knew that this inconsistency was a problem for the very community we were trying to help.

    What we needed to do is to provide a single package with all the management technologies that customers needed.  That is what we developed and we called it the Windows Management Framework. 

    That is why you don’t have a “downlevel package for PowerShell V2”, you have a downlevel package for management.

    Enjoy!

    Jeffrey Snover [MSFT]
    Distinguished Engineer
    Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
    Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

  13. PowerShell Resource Page at Windows IT Pro -

    Windows IT Pro magazine has created a PowerShell Resource Page HERE.  It provides a nice easy way to get at all of Don Jones’ articles.  Don is a superstar explainer of all things PowerShell so if you aren’t already following him, do yourself a favor and go read his stuff over on Windows It Pro. 

    Enjoy!

    Jeffrey Snover [MSFT]
    Distinguished Engineer
    Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
    Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

  14. Smiling, Crying, and Scripting -

    I once heard that everyone in the world smiles and cries the same way - that language and culture had no effect on these.

    I thought of that when I navigated to: http://www.computerworld.jp/topics/mws/180709.html

    I have ABSOLUTELY no clue what they are saying but in the middle of the article I saw this:

    【リスト11:WakeOnLan.ps1】
    1 param($MacAddress) 
    2 [byte[]] $MagicPacket = 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
    3 $MagicPacket += (($MacAddress.split('-') | foreach {[byte] 
    ('0x' + $_)}) * 16)
    4 $UdpClient = New-Object System.Net.Sockets.UdpClient
    5 $UdpClient.Connect(([System.Net.IPAddress]::Broadcast) ,9)
    6 $UdpClient.Send($MagicPacket,$MagicPacket.length)

     

    I guess everyone in the world scripts the same way too. 

    Given that they are scripting in PowerShell, I bet they are also smiling!  :-)

    Experiment!  Enjoy!  Engage!

    Jeffrey Snover [MSFT]
    Distinguished Engineer
    Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
    Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

  15. Select-String -Context -

    A lot of people use Select-String but I haven’t seen much discussion of the –Context parameter.   This is an awesome feature that we added in V2.  If you haven’t tried it, you should spend a few minutes experimenting.  I can guarantee you that will you be glad you did.

    Let’s see what the HELP has to say about the Context parameter:

     

    PS> Get-Help Select-String -Parameter Context

    -Context <Int32[]>
        Captures the specified number of lines before and after the line with the m
        atch. This allows you to view the match in context.

        If you enter one number as the value of this parameter, that number determi
        nes the number of lines captured before and after the match. If you enter t
        wo numbers as the value, the first number determines the number of lines be
        fore the match and the second number determines the number of lines after t
        he match.

        In the default display, lines with a match are indicated by a right angle b
        racket (ASCII 62) in the first column of the display. Unmarked lines are th
        e context.

        This parameter does not change the number of objects generated by Select-St
        ring. Select-String generates one MatchInfo (Microsoft.PowerShell.Commands.
        MatchInfo) object for each match. The context is stored as an array of stri
        ngs in the Context property of the object.

        When you pipe the output of a Select-String command to another Select-Strin
        g command, the receiving command searches only the text in the matched line
         (the value of the Line property of the MatchInfo object), not the text in
        the context lines. As a result, the Context parameter is not valid on the r
        eceiving Select-String command.

        When the context includes a match, the MatchInfo object for each match incl
        udes all of the context lines, but the overlapping lines appear only once i
        n the display.

        Required?                    false
        Position?                    named
        Default value
        Accept pipeline input?       false
        Accept wildcard characters?  false

     

    Let’s have some fun.  I’m going to use Superstar James O’Neil’s Hypervisor Management Library to experiment with.  He has a number of functions the work with NICs.  Let’s party.

    PS> #First Let's find the functions
    PS> dir *.ps1 |Select-String function.*NIC

    network.ps1:3:Function Add-VMNIC
    network.ps1:64:Function Get-VMNic
    network.ps1:94:Function Get-VMNicport
    network.ps1:104:Function Get-VMnicSwitch
    network.ps1:121:Function Get-VMNICVLAN
    network.ps1:282:Function Remove-VMNIC
    network.ps1:332:Function remove-VMSwitchNIC
    network.ps1:366:Function Select-VMNIC
    network.ps1:392:Function Set-VMNICAddress
    network.ps1:422:Function Set-VMNICSwitch
    network.ps1:459:Function Set-VMNICVLAN

    PS> # That gave me too many so let's add a $ to the end of the SEARCH STRING
    PS> # That indicates a Line end
    PS> dir *.ps1 |Select-String function.*NIC$

    network.ps1:3:Function Add-VMNIC
    network.ps1:64:Function Get-VMNic
    network.ps1:282:Function Remove-VMNIC
    network.ps1:366:Function Select-VMNIC

    PS> # Let's see 1 line before and after each matching line
    PS> dir *.ps1 |Select-String function.*NIC$ -Context 1

      network.ps1:2:
    > network.ps1:3:Function Add-VMNIC
      network.ps1:4:{# .ExternalHelp  MAML-VMNetwork.XML
      network.ps1:63:
    > network.ps1:64:Function Get-VMNic
      network.ps1:65:{# .ExternalHelp  MAML-VMNetwork.XML
      network.ps1:281:
    > network.ps1:282:Function Remove-VMNIC
      network.ps1:283:{# .ExternalHelp  MAML-VMNetwork.XML
      network.ps1:365:
    > network.ps1:366:Function Select-VMNIC
      network.ps1:367:{# .ExternalHelp  MAML-VMNetwork.XML

    PS> # Notice the line numbers and that the matching line has a > in front


    PS> # Now let's try 3 lines before and after the matching line
    PS> dir *.ps1 |Select-String function.*NIC$ -Context 3

      network.ps1:1:
      network.ps1:2:
    > network.ps1:3:Function Add-VMNIC
      network.ps1:4:{# .ExternalHelp  MAML-VMNetwork.XML
      network.ps1:5:    [CmdletBinding(SupportsShouldProcess=$true)]
      network.ps1:6:    param(
      network.ps1:61:}
      network.ps1:62:
      network.ps1:63:
    > network.ps1:64:Function Get-VMNic
      network.ps1:65:{# .ExternalHelp  MAML-VMNetwork.XML
      network.ps1:66:    param(
      network.ps1:67:        [parameter(ValueFromPipeline = $true)]
      network.ps1:279:}
      network.ps1:280:
      network.ps1:281:
    > network.ps1:282:Function Remove-VMNIC
      network.ps1:283:{# .ExternalHelp  MAML-VMNetwork.XML
      network.ps1:284:    [CmdletBinding(SupportsShouldProcess=$true)]
      network.ps1:285:    param(
      network.ps1:363:
      network.ps1:364:
      network.ps1:365:
    > network.ps1:366:Function Select-VMNIC
      network.ps1:367:{# .ExternalHelp  MAML-VMNetwork.XML
      network.ps1:368:    param(
      network.ps1:369:        [parameter(ValueFromPipeline = $true)]

    PS> # The line before is boring so let's get rid of that and then see a
    PS> # few lines after
    PS> dir *.ps1 |Select-String function.*NIC$ -Context 0,3

    > network.ps1:3:Function Add-VMNIC
      network.ps1:4:{# .ExternalHelp  MAML-VMNetwork.XML
      network.ps1:5:    [CmdletBinding(SupportsShouldProcess=$true)]
      network.ps1:6:    param(
    > network.ps1:64:Function Get-VMNic
      network.ps1:65:{# .ExternalHelp  MAML-VMNetwork.XML
      network.ps1:66:    param(
      network.ps1:67:        [parameter(ValueFromPipeline = $true)]
    > network.ps1:282:Function Remove-VMNIC
      network.ps1:283:{# .ExternalHelp  MAML-VMNetwork.XML
      network.ps1:284:    [CmdletBinding(SupportsShouldProcess=$true)]
      network.ps1:285:    param(
    > network.ps1:366:Function Select-VMNIC
      network.ps1:367:{# .ExternalHelp  MAML-VMNetwork.XML
      network.ps1:368:    param(
      network.ps1:369:        [parameter(ValueFromPipeline = $true)]

     

     

    PS> # Let's take a look at the body of Remove-VMNIC
    PS> dir *.ps1 |Select-String function.*Remove-VMNIC$ -Context 0,20

    > network.ps1:282:Function Remove-VMNIC
      network.ps1:283:{# .ExternalHelp  MAML-VMNetwork.XML
      network.ps1:284:    [CmdletBinding(SupportsShouldProcess=$true)]
      network.ps1:285:    param(
      network.ps1:286:        [parameter(Mandatory = $true ,  ValueFromPipeline = $true)]
      network.ps1:287:        $Nic,
      network.ps1:288:
      network.ps1:289:        $PSC,
      network.ps1:290:        [switch]$force,
      network.ps1:291:
      network.ps1:292:        $VM, $Server #VM no longer required, but preserved for compatibility with V1
      network.ps1:293:    )
      network.ps1:294:    process {
      network.ps1:295:        if ($psc -eq $null)  {$psc = $pscmdlet} ; if (-not $PSBoundParameters.psc) {$PSBoundParameter
    s.add("psc",$psc)}
      network.ps1:296:        if ($NIC -is [Array] ) {[Void]$PSBoundParameters.Remove("NIC") ;  $NIC | ForEach-object {Remo
    ve-VMNIC  -NIC $_  @PSBoundParameters}}
      network.ps1:297:        if ($nic -is [System.Management.ManagementObject])  {remove-VMRasd -rasd $NIC -PSC $psc }
      network.ps1:298:            # note: In V1 the switch port was removed before removing the NIC, but this is done autom
    atically.
      network.ps1:299:    }
      network.ps1:300:}
      network.ps1:301:
      network.ps1:302:

     

    Party on your own.  You are going to love –Context!

    Experiment!  Enjoy!  Engage!

    Jeffrey Snover [MSFT]
    Distinguished Engineer
    Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
    Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

  16. Configuring WSMAN Limits -

    As you probably know by now, all of PowerShell remoting is done via streaming extensions to WSMAN.  WSMAN is the SOAP-based DMTF standard protocol for managing everything.  As you explore the limits of what you can do with WSMAN or PowerShell remoting, you may encounter errors like this:

    [7592:0]PS> New-PSSession
    [localhost] Connecting to remote server failed with the following error me
    ssage : The WS-Management service cannot process the request. This user is
    allowed a maximum number of 5 concurrent shells, which has been exceeded.
    Close existing shells or raise the quota for this user. For more informat
    ion, see the about_Remote_Troubleshooting Help topic.
        + CategoryInfo          : OpenError: (System.Manageme....RemoteRunspa
       ce:RemoteRunspace) [], PSRemotingTransportException
        + FullyQualifiedErrorId : PSSessionOpenFailed

    What is going on here is that we put in a number of default constraints into the system to protect your systems from accidental misuse.  We didn’t want a beginner PowerShell user writing a script which accidentally consumed all the resources on your servers.  We can’t protect against everything but we spent some time thinking about the common mishaps and put some default guardrails in.  

    I like the story (it might even be true :-) ) about software controls on some of the fighter jets.  The SW developers knew what the design limits of the planes where so they wrote the control software so that it wouldn’t exceed the capabilities of the plane.  The pilot’s reaction was, “we’d only be pushing the plane to that degree when the other alternative was getting shot down – I’d rather risk having the wings tear off then being guaranteed to get shot down.”  So while we put in guardrails, we also put in the ability to move those guardrails.  Look, they are your machines.  You are smart people.  You often know more than we do.  We allow you to make decisions which may be great and may hurt yourself.   (NOTE: In my opinion we set some of the Maximum’s too low.  We may reevaluate some of these in the future on the grounds of general principles but let me know if you have any concrete situations where the maximums are too small.)

    If you want to change the controls, all you have to do is to CD into the WSMAN: drive and the LOCALHOST subdirectory and change things.  It’s as easy as this:

    PS> cd WSMan:\localhost\Shell
    PS> dir

       WSManConfig: Microsoft.WSMan.Management\WSMan::localhost\Shell

    WARNING: column "Type" does not fit into the display and was removed.

    Name                      Value
    ----                      -----
    AllowRemoteShellAccess    true
    IdleTimeout               180000
    MaxConcurrentUsers        5
    MaxShellRunTime           2147483647
    MaxProcessesPerShell      15
    MaxMemoryPerShellMB       150
    MaxShellsPerUser          5

    PS> Set-Item .\MaxShellsPerUser 25

    It is worth spending a little bit of time exploring the WSMAN drive and what you can do with it.

    To find out more about the drive and what the values mean do the following:

    PS> Get-Help WSMAN

    PS> Get-Help About_WSMAN

    <Update - not all the settings are documented there.  The full list is available HERE >

    Enjoy!

    Jeffrey Snover [MSFT]
    Distinguished Engineer
    Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
    Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

  17. A PowerShell Wander: ToolBox Mindset, –ExpandProperty, DMZs and Remote Profiles -

    I was reading PowerShell remoting in Windows Server 2008 R2.  The great thing about this article is that it documents how to use Group Policy to enable PSRemoting on lots of machines automatically.  In the article there was the following heads up:

    Warning:
    Commands that are executed against a remote machine do not have access to information defined within your local profile. As such, commands that use a function or alias defined in your local profile will fail unless they are defined on the remote machine as well.

    The great thing about PowerShell is that it is a toolbox

    The great thing about toolboxes is that they have general purpose utilities that creative people can use their inspiration to do things that the tool designers didn’t think of when they developed the tool.  One of my favorite examples of this came from a problem with SELECT.  SELECT is a utility which selects a set of properties from the incoming object.  It creates a new object and adds those selected properties as NoteProperties on that new object.  e.g.

    PS> Get-Process *ss

    Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
    -------  ------    -----      ----- -----   ------     -- -----------
        917      14     3420       2364    52     9.97    424 csrss
        771      27     3484      13428   189   108.02    512 csrss
       1989      45    18272      17820    87    95.83    556 lsass
         30       2      476        124     5     0.06    320 smss


    PS> Get-Process *ss |Select ID,Handles,ProcessName

                          Id                  Handles ProcessName
                          --                  ------- -----------
                         424                      930 csrss
                         512                      770 csrss
                         556                     1984 lsass
                         320                       30 smss


    PS> Get-Process *ss |Select ID,Handles,ProcessName |Get-Member

       TypeName: Selected.System.Diagnostics.Process

    Name        MemberType   Definition
    ----        ----------   ----------
    Equals      Method       bool Equals(System.Object obj)
    GetHashCode Method       int GetHashCode()
    GetType     Method       type GetType()
    ToString    Method       string ToString()
    Handles     NoteProperty System.Int32 Handles=925
    Id          NoteProperty System.Int32 Id=424
    ProcessName NoteProperty System.String ProcessName=csrss

    PS> Get-Process *ss |Select ProcessName

    ProcessName
    -----------
    csrss
    csrss
    lsass
    smss

    Sidenote: notice that the TYPE of the result is Selected.System.Diagnostics.Process.  We did that in V2 to be consistent with our principle of always trying to help you keep track of where information came from.  The idea is that if you are debugging a script and have an examine an object and see this typename, you have more information about where it came from to help debug your script.

    Anyway, that is great but notice what happens when you select a single property you get an object with a single property.  Often you just want the values of the property not an object with a single property.  The solution to that has been:

    PS> Get-Process *ss |foreach {$_.ProcessName}
    csrss
    csrss
    lsass
    smss

    That works but I don’t like it very much.  We had lots of discussions about what to do about this.  Some people wrote a function which did this operation and thought we should include it in the next version.  Others felt like we ought to put a switch on Select which say something like –VALUEONLY.  It was Lee Holmes that pointed out that we already support this.  I looked at him like he had a rat’s tail hanging out of his mouth when he said that.  He said that Select –ExpandProperty did the trick.  This switch was designed to work with objects that have properties which are collections.  For instance: 

    PS> Get-Service WinMgmt |Select DependentServices

    DependentServices
    -----------------
    {wscsvc, SharedAccess, iphlpsvc}

    PS> Get-Service WinMgmt |Select -ExpandProperty DependentServices

    Status   Name               DisplayName
    ------   ----               -----------
    Running  wscsvc             Security Center
    Stopped  SharedAccess       Internet Connection Sharing (ICS)
    Running  iphlpsvc           IP Helper

    Pretty cool right?  This tool was designed to work on properties which are collections.  Lee Holmes wondered, “What would it do on a property which wasn’t a collection?”.

    PS> Get-Process *ss |Select -ExpandProperty ProcessName
    csrss
    csrss
    lsass
    smss

    OH YEAH BABY!  You asked for it you got it!  Using the toolkit mindset, Lee was able to figure out that we already supported this function.  (You might point out that this is longer than the foreach but it turns out to be a ton easier because of tab completion.)

    So – what does this have to do with the remoting warning about not having access to any of the functions you defined in your profile file?  Well, it turns out that the command Invoke-Command has a parameter –FILEPATH which allows you to specify a file that you want to run on the remote machine.  We added this feature to help people machine machines in DMZs where it can be difficult to ensure that the script you want to run will be on that machine and it can be difficult for that machine to have access to a shared folder of scripts.  We send the file across and execute it so there is deployment free script execution.  (This is a super important feature that people haven’t quite tuned into yet.  I’m going to write a blog in the future about how to use this capability to use PowerShell as a bootstrap management agent to do all of your management functions.)  So the example of this is something like

    PS> $DmzMachines = New-PSSession -ComputerName (cat DmzMachines.txt)
    PS> Invoke-Command $DmzMachines -FilePath c:\scripts\Get-Inventory.ps1
    ….

    PowerShell transfers and executes the Get-Inventory.ps1 script to all the machines.  From there, you can connect the dots to putting the functions you want everywhere into a file called RemoteProfile and doing the following:

    PS> Invoke-Command $DmzMachines -FilePath c:\scripts\RemoteProfile.ps1


    Be aware that this mechanism has limitations.  In a local profile, you can invoke other files on your system.  Using this technique, those files aren’t on the other system so that won’t work – the files have to be self contained.  That is why I called it RemoteProfile.ps1 .  I keep it separate from my normal profile.

    Enjoy!

    Jeffrey Snover [MSFT]
    Distinguished Engineer
    Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
    Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

  18. MMS Partner Presentation: Windows Management Framework -

    MMS Partner Day focuses on ISVs that produce products for Windows and System Center.  I talked to them about the Windows Management Framework (WMF) and encouraged them all to check it out and begin using it to build their products.  WMF is a download which combines PowerShell V2,  WINRM 2.0 and BITS 4.0 and is available on XP SP3 and above machines. 

    I’ve attached the PPT below.  The Call to Action for this talk was:

    • Provide your managed components as:
      • WMI providers
      • CIM schema surfaced via WSMAN (if you aren’t running on windows e.g. a network device)
      • PowerShell Cmdlets
    • Consume BOTH WMI and PowerShell managed objects
    • Evaluate how WMF can help you provide/consume remote management capabilities
    • Use the WMF and MBCA V2.0 in your products
    • Let us know what you need.

    Enjoy!

    Jeffrey Snover [MSFT]
    Distinguished Engineer
    Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
    Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

  19. Windows PowerShell in Bing Visual Search -

    Beginning today, there's a new way to look at Windows PowerShell cmdlets.

    You're used to looking at them this way:

    clip_image002

    Or, perhaps, this way:

    clip_image004

    But would you like to look at them this way?

    clip_image006

    What if getting a list of the remoting cmdlets was as easy as clicking a category name? And you could filter to display only the remoting configuration cmdlets?

    clip_image008

    What if you could get a quick peek at a cmdlet help topic by clicking a Bing Visual Search tile?
    (See the "Help Online" link?)

    clip_image010

    Welcome to the Windows PowerShell Cmdlets Gallery in Bing Visual Search.

    To see it, go to http://go.microsoft.com/fwlink/?LinkID=190436 or outside the U.S., go to http://go.microsoft.com/fwlink/?LinkID=190439

    -or-

    1. Go to Bing: http://www.bing.com.

    2. From the menu on the left, click Visual Search.

    3. Click Reference, and scroll down to Scripting.

    4. Click Windows PowerShell Cmdlets

    If you're attending Microsoft Management Summit 2010, you can see a presentation of the Windows PowerShell Cmdlet Gallery and other innovative ways to present information at the "Creating an Information Experience for Windows and Management Customers" breakout session (BJ01) on Monday, April 19 from 3:00 – 4:00 PM in Bellini 2005.

    The current version of the gallery is a prototype that still has a few bugs. We're new at this and ironing them out over time. If you have suggestions, please leave comments or send them to me at juneb@microsoft.com.

    Thanks,
    June Blender [MSFT]
    Windows PowerShell Documentation

  20. PowerShell V2 Open Panel Discussion Tonight -

    Tonight’s version of the PowerScripting Podcast is going to be an Open Panel discussing PowerShell V2 including the following topics:

  21. PowerShell 2.0 adoption
  22. Are you happy with version 2?
  23. Favorite v2 resources: books, bloggers, tools, etc.
  24. PS v2 Remoting vs administering remote PCs without PowerShell installed (lead into PowerShell myths?)
  25. And anything else YOU can come up with by show time.
  26.  

    If you’ve never tuned into the PowerScripting Podcast, you should.  It is both fun and informative. 

    Tonight’s podcast is happening at 9:30 EDT (6:30 PST).  You can find out more information HERE.

    You can listen in on USTREAM HERE.

    I hope to see you there tonight!.

    Enjoy!

    Jeffrey Snover [MSFT]
    Distinguished Engineer
    Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
    Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

  27. Announcing Scripting games 2010 -

    Scripting Guys have set the ball rolling for another fun filled and intresting edition of Scripting Games.

    You can see details here http://blogs.technet.com/heyscriptingguy/archive/2010/04/05/2010-scripting-games-all-links-on-one-page.aspx

    2010 Scripting Games

    Grab this badge here!

     

  28. Testing cmdlets with FxCop -

    Windows PowerShell wouldn’t be very useful without all the great cmdlets that actually manage specific technologies.  We want to help cmdlet developers to create high-quality cmdlets.  Today we announce availability of FxCop rules that can be used to verify compliance with some of the Cmdlet Design Guidelines as well as to find some of the common bugs.

    Installation

    Use the following procedure to download the required components:

    1. Download Microsoft FxCop 1.36 from the Microsoft Download Center at http://go.microsoft.com/fwlink/?LinkID=185006.
    2. Download Microsoft.PowerShell.CodeAnalysis.dll from the MSDN Code Gallery at http://go.microsoft.com/fwlink/?LinkId=185007. Save the file in any location.

    Use the following procedure to configure Microsoft FxCop to run FxCop Rules for Windows PowerShell on your code:

    1. Click Start and then click Microsoft FxCop 1.36.
    2. From the Project menu, select Add Rules, navigate to the Microsoft.PowerShell.CodeAnalysis.dll file, and click Open.
    3. From the Project menu, select Add Targets, navigate to the .dll file that implements your cmdlets, and click Open.
    4. From the Project menu, select Analyze or press F5.

    Please refer to the FxCop Rules for Windows PowerShell project on Code Gallery for more details.

    List of rules

    Thanks,

    Lukasz Anforowicz [MSFT]
    Windows PowerShell Developer
    Microsoft Corporation

  29. “Falling is Learning – Just Focus on Having Fun” -

    Back in the days when our hair was on fire with security issues, we brought in a number of industry experts to educate us on developing secure software.  This resulted in the Security Development Lifecycle which all our products now use.  One of the best talks was a from a guy from the NSA who had a talk that was something along the lines of, “The zen of secure software”.  In this talk he argued against the all-or-nothing mindset in favor of a model of constantly expanding the envelope.  Any given moment, you evaluate what you need to do (in this case – to address security issues),  you do it and then … you do a bit more.  Then do it again.  And again.  And again.  And with constant vigilance and time, you would achieve excellence.

     

    And so it is with using PowerShell.  I’ve recently had a number of engagements with people just getting started with PowerShell and getting frustrated with the syntax or some of the semantics and then they look at these thick PowerShell books and feel a bit overwhelmed. 

     

    Don’t be overwhelmed.

     

    PowerShell is meant to be an fun environment to experiment with what is possible.  That means  you’ll try some things and they’ll fail – don’t let that freak you out (it is one of the reasons we added –WHATIF to everything!).  I’ve been trying to learn to do yoga for a while now.  In yoga there are lots of positions that require balance and I’m not particularly good at that.  I used to get super frustrated with these poses until one day my teacher quoted someone saying,  “falling is learning – just focus on having fun”.  That phrase transformed my experience and while I wish I didn’t fall, now when I do, I smile, laugh and get up and try it again.

     

    All you need to do is to learn what you need to do to accomplish the task at hand … and a bit more. Then do it again.  And again.  And again.  Have fun with it and push the envelope.

     

    Now I’m late for yoga – gotta run.   Experiment!  Enjoy!  Engage!

    Jeffrey Snover [MSFT]
    Distinguished Engineer
    Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
    Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

  30. Fun – Is W7 Too Good? -

    Sean Kearney (aka Ye110beard of Highway to PowersHell fame ) sent me a pointer to a fun video which posits that maybe W7 is TOO good.  Just maybe it is so good that it will put IT Pros out of business.  I think the exact opposite is true - I think PowerShell and the ability script the OS and products allows IT Pros to generate a ton of value and increase their integrated lifetime earnings.  Still it is a fun video.  You can catch it HERE.

    Enjoy!

    Jeffrey Snover [MSFT]
    Distinguished Engineer
    Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
    Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

  31. PSStandardMembers – The Stealth Property -

    Today I got the question

    I’ve looked into all of my.format.ps1xml files but I can’t find out where Format-List is getting its default view for, say, System.Diagnostics.Process:

    PS> ps |select -first 1 |fl

    Id      : 7616
    Handles : 543
    CPU     : 10.6860685
    Name    : CmdletDesigner

    How does it know it should display just these four properties?
    It seems there isn’t any ListControl view selected by this type within those formatting files...

    Excellent question!  Let’s pick behind the curtain and see how it works.  When an object gets to one of our formatting commands, we use its type to look and see if there is a VIEW defined for it.  These views are defined in our formatting files in $PSHOME directory.  They have filenames like xxx.Format.ps1xml .  If we find it, we use it.  If we don’t find it, we look to see whether this type has a DefaultDisplayPropertySet defined.  If it does, we use it.  If it doesn’t we emit all the properties either as a table or a list depending upon how many properties there are.

     

    But wait a minute – let’s go back and look at this DefaultDisplayPropertySet – what’s that all about?  If you’ve been using PowerShell a while, you’ll realize that PowerShell uses a type mashup system.  Mashups are really just an identity space and a mechanism for 3rd parties to add addition information into an identity space.  For map mashups, the identity space is latitude/longitude and a mechanism for someone to provide the lat/long for all the Starbucks in the world.  For PowerShell, we use TYPEs as an identity space and then have various mechanisms for 3rd parties to add extra information.  One of those mechanisms is TYPE files (e.g. $pshome/types.ps1xml ).  If you take a look at the file, you’ll see that we have a set of entries which are keyed off of a typename and can add extra information.  If you search for System.Diagnostics.Process – you’ll see a bunch of stuff.   One of the things you can add to a type is a MemberSet

     

    One of the things you’ll see is a super double secret MemberSet called PSStandardMembers.   This is a hidden memberset that PowerShell uses for it’s own purposes.  In that memberset, you (we) can define something called DefaultDisplayPropertertySet which provides a set of properties that should be displayed if there isn’t a view defined.  Let me show you that it is really there (you can follow along at home):

    PS> $x = Get-Process |Select -First 1
    PS> $x |Format-List

    Id      : 7616
    Handles : 543
    CPU     : 10.7172687
    Name    : CmdletDesigner

    PS> # Let me prove to you that it is hidden
    PS> $x |Get-Member PSStandardMembers


    PS> # It's really there, just hidden.  You can show hidden things using -Force
    PS> $x |Get-Member PSStandardMembers -Force

       TypeName: System.Diagnostics.Process

    Name              MemberType Definition
    ----              ---------- ----------
    PSStandardMembers MemberSet  PSStandardMembers {DefaultDisplayPropertySet}

    PS> $x.PSStandardMembers
    PSStandardMembers {DefaultDisplayPropertySet}


    PS> $x.PSStandardMembers.DefaultDisplayPropertySet

    ReferencedPropertyNames : {Id, Handles, CPU, Name}
    MemberType              : PropertySet
    Value                   : DefaultDisplayPropertySet {Id, Handles, CPU, Name}
    TypeNameOfValue         : System.Management.Automation.PSPropertySet
    Name                    : DefaultDisplayPropertySet
    IsInstance              : False


    PS> $x.PSStandardMembers.DefaultDisplayPropertySet.ReferencedPropertyNames
    Id
    Handles
    CPU
    Name
    PS>

     

    Now it really isn’t secret we just haven’t talked about it much.  It is documented @ MSDN HERE .

    PSStandardMembers is used for a number of things in addition to DefaultDisplayProperties.  In particular, it is used to control object serialization.  You can find out more about that in my blog entry HERE.

     

    Enjoy!

    Jeffrey Snover [MSFT]
    Distinguished Engineer
    Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
    Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

Leave a Response

Spam protection by WP Captcha-Free