Archive for the 'Extensibility' Category

Select-Object with Subproperties

Get-Process | Select ProcessName, StartTime.DayOfWeek” – if you ever wanted this notation to work to give you subproperties of objects – read on. ūüôā

This short notation for subproperties (in this particular case:¬† StartTime.DayOfWeekto get the DayOfWeek property of process start time) is unfortunately not supported in PowerShell out of the box. Instead you have to type something like: “@{Name=”Start Day”; Expression = {$_.StartTime.DayOfWeek}}” which is kind of long and scary.

Luckily PowerShell 2.0 has so called proxy functions and I have just implemented my overload of Select-Object which add the ability to directly reference subproperties as in the example above. You can find the code at PoshCode here.

Frankly, using PowerShell 2.0 code snippet for proxy functions this was quite trivial to implement. All I have to do was to check whether any Property parameters have dots, and if they do – substitute them with the long and scary expression notation. ūüôā

In the code below, everything is default output from the snippet except for a dozen of lines after: “#region: Dmitry Sotnikov: substitute dotted properties with expressions

Here’s the code you need to load in your PowerShell session to enhance the Select-Object behavior:

function Select-Object {
[CmdletBinding(DefaultParameterSetName='DefaultParameter')]
param(
  [Parameter(ValueFromPipeline=$true)]
  [System.Management.Automation.PSObject]
  ${InputObject},

  [Parameter(ParameterSetName='DefaultParameter', Position=0)]
  [System.Object[]]
  ${Property},

  [Parameter(ParameterSetName='DefaultParameter')]
  [System.String[]]
  ${ExcludeProperty},

  [Parameter(ParameterSetName='DefaultParameter')]
  [System.String]
  ${ExpandProperty},

  [Switch]
  ${Unique},

  [Parameter(ParameterSetName='DefaultParameter')]
  [ValidateRange(0, 2147483647)]
  [System.Int32]
  ${Last},

  [Parameter(ParameterSetName='DefaultParameter')]
  [ValidateRange(0, 2147483647)]
  [System.Int32]
  ${First},

  [Parameter(ParameterSetName='DefaultParameter')]
  [ValidateRange(0, 2147483647)]
  [System.Int32]
  ${Skip},

  [Parameter(ParameterSetName='IndexParameter')]
  [ValidateRange(0, 2147483647)]
  [System.Int32[]]
  ${Index})

begin
{
 try {
     $outBuffer = $null
     if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
     {
         $PSBoundParameters['OutBuffer'] = 1
     }

     #region: Dmitry Sotnikov: substitute dotted properties with expressions
     if ($Property -ne $null) {
      # Iterate through properties and substitute those with dots
      $NewProperty = @()
      foreach ( $prop in $Property ) {
       if ($prop.GetType().Name -eq 'String') {
        if ($prop.Contains('.')) {
         [String] $exp = '$_.' + $prop
         $prop = @{Name=$prop; Expression = {Invoke-Expression ($exp)}}
        }
       }
       $NewProperty += $prop
      }
      $PSBoundParameters['Property'] = $NewProperty
     }
     #endregion

     $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Select-Object',
         [System.Management.Automation.CommandTypes]::Cmdlet)
     $scriptCmd = {& $wrappedCmd @PSBoundParameters }
     $steppablePipeline =
         $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
     $steppablePipeline.Begin($PSCmdlet)
 } catch {
     throw
 }
}

process
{
    try {
        $steppablePipeline.Process($_)
    } catch {
        throw
    }
}

end
{
    try {
        $steppablePipeline.End()
    } catch {
        throw
    }
}
<#

.ForwardHelpTargetName Select-Object
.ForwardHelpCategory Cmdlet

#>
}

MobileShell SDK

Developers, here’s your chance to create exciting applications on top of PowerGUI MobileShell server backend! That’s right: everything you see in MobileShell including settings dialog boxes and intellisense is exposed as web services. Your application will be able to execute any PowerShell scripts in production environment over HTTP/HTTPS, preserve session state and even get meta information such as intellisense.

Which means that if you don’t like our in-browser implementation and want to develop a native iPhone/Blackberry/Symbian/Android/Windows Mobile client – you can quite easily do that (and probably even make some money out of the respective app stores ;))

Below is a sample in C# that uses the PowerGUI MobileShell API to:

  • Create, list, join and close sessions
  • Work with IntelliSense autocompletion lists
  • Manage favorite scripts

Hopefully it is straightforward enough to figure out how to perform similar calls in your development platform of choice.

For this particular example to work in Visual Studio, you need to add the MobileShell Web service as a Web reference to the .NET project you are working with. The URL of the service looks like: https://<MobileShell_server_name>/MobileShell/MobileShell/MobileShellWebService.asmx.

For details about adding Web references to Visual Studio, see http://msdn.microsoft.com/en-us/library/d9w023sx.aspx.

If you are using tools other than Visual Studio to run .NET code against the MobileShell Web service, you need to generate a Web service proxy using the wsdl.exe utility, which is distributed with .NET Framework 3.5. For details, refer to the help screen for the utility.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MobileShellExamples
{
 class Program
 {
  static void Main(string[] args)
  {
    ScriptExecutionExample();
    FavoritesExample();
    IntelliSenseExample();
    SessionsExample();
  }

  static void ScriptExecutionExample()
  {
   MobileShellWebService webService = GetWebServiceInstance();
   webService.CreateSession();

   string strScript = "while ( $true ) { $i++; \"Hello $i\"; sleep -m 300 }";
   ScriptState state = webService.ExecuteScript(strScript);

   System.Threading.Thread.Sleep(5000);

   webService.TerminateCurrentScript();

   state = webService.GetCurrentScriptState();
   Console.WriteLine((state.Command as WriteCommand).Text);
  }

  static void SessionsExample()
  {
   // Create the first session
   MobileShellWebService webService1 = GetWebServiceInstance();
   webService1.CreateSession();

   // Create the second session
   MobileShellWebService webService2 = GetWebServiceInstance();
   webService2.CreateSession();

   // Get a list of active sessions
   MobileShellWebService webService3 = GetWebServiceInstance();
   SessionDetails[] arrSessionIDs = webService3.GetSessions();

   // Close all sessions except the first
   for (int i = 1; i < arrSessionIDs.Length; i++)
   {
    webService3.CloseSession(arrSessionIDs[i].SessionID);
   }
   // Join the first session
   webService3.JoinSession(arrSessionIDs[0].SessionID);
  }

  static void IntelliSenseExample()
  {
   MobileShellWebService webService = GetWebServiceInstance();

   // Get autocompletion list for the "Get-" string (e. g. get all Get-* cmdlets)
   string strScript = "Get-";
   foreach (IntelliSenseItem item in
           webService.GetIntelliSenseCompletionList(strScript, strScript.Length-1))
   {
    Console.WriteLine(item.AutoCompleteEnding);
   }
   Console.WriteLine("");

   // Get autocompletion list for "Get-Help -" string.
   // (e.g. get all Get-Help cmdlet parameters)
   strScript = "Get-Help -";
   foreach (IntelliSenseItem item in
           webService.GetIntelliSenseCompletionList(strScript,strScript.Length-1))
   {
    Console.WriteLine(item.AutoCompleteEnding);
   }
  }

 static void FavoritesExample()
 {
   MobileShellWebService webService = GetWebServiceInstance();
   // List current favorites
   Console.WriteLine("### Initial list");
   foreach (FavoriteScript cmdFavorite in webService.GetFavoriteScripts())
   {
     Console.WriteLine("Name: " + cmdFavorite.Name);
     Console.WriteLine("Script: " + cmdFavorite.Script);
     Console.WriteLine("");
   }

   // Add a new favorite script named "Hello World"
   webService.AddFavoriteScript("Hello World", "\"Hello World!\"");

   // List current favorites
   Console.WriteLine("### New favorite script added");
   foreach (FavoriteScript cmdFavorite in webService.GetFavoriteScripts())
   {
    Console.WriteLine("Name: " + cmdFavorite.Name);
    Console.WriteLine("Script: " + cmdFavorite.Script);
    Console.WriteLine("");
   }

   // Find the favorite script named "Hello World"
   FavoriteScript cmdNewScript = webService.GetFavoriteScripts().First(
                                     fav => fav.Name == "Hello World");

   // Modify the script name and content
   webService.EditFavoriteScript(cmdNewScript.Name,
                                 "Time keeper", cmdNewScript.Script);

   // List current favorites
   Console.WriteLine("### Favorite script modified");
   foreach (FavoriteScript cmdFavorite in webService.GetFavoriteScripts())
   {
    Console.WriteLine("Name: " + cmdFavorite.Name);
    Console.WriteLine("Script: " + cmdFavorite.Script);
    Console.WriteLine("");
   }
  }

  static MobileShellWebService GetWebServiceInstance()
  {
   return GetWebServiceInstance(
       "http://myserver/MobileShell/MobileShell/MobileShellWebService.asmx",
       "mydomain\\administrator", "=1qwerty");
  }

  static MobileShellWebService GetWebServiceInstance(string strUrl,
                                         string strUser, string strPassword)
  {
   MobileShellWebService webService = new MobileShellWebService();
   webService.CookieContainer = new System.Net.CookieContainer();
   webService.Url = strUrl;
   webService.Credentials = new System.Net.NetworkCredential(strUser, strPassword);
   return webService;
  }
 }
}

Detailed SDK documentation (all methods and classes) can be found in the “PowerGUI Pro MobileShell 2.0 SDK” document posted here.

Give a try and let us know what you think. And obviously whichever apps you create we will be extremely glad to promote them whichever way we can!

Case study: Custom Helpdesk UI

Want to see how to get real savings, reduce risks and dramatically improve efficiency with PowerShell and PowerGUI? Check out Jonathan’s story here.

Jonathan has to provide helpdesk team at his company with the tools they need to get their job done. Obviously no out-of-the-box product had that – they would have had to use multiple different consoles and scripts, be careful not to use all the extra functionality in there, need extensive training so they know where is what, be exposed to risks of clicking something they were not supposed to click, and so on.

Jonathan’s solution was to develop all the functionality they need as PowerShell scripts and oneliners, and plug them into PowerGUI admin console. This gave the helpdesk team customized easy to use graphical tool tailored exactly for their specific needs:

No need to read all of my boring documentation beforehand since its pretty obvious what clicking on script nodes such as ‘Find Expired AD users’ or ‘How many users in Active Directory?’ will do.

Effective, very simple solutions which save people time, make them more efficient and its makes me feel good to leave something useful like that behind for them to use. Thank you PowerGUI!

Check out full Jonathan’s story here. See Kirk’s quick demo on creating such custom UIs here.

Tags: , , , , , ,

HOWTO: Add custom cmdlets to PowerGUI

PowerGUI works great with cmdlets from Microsoft, VMware, Quest and other vendors, but what if it does not seem to “see” the ones which you created on your own?

Fear not, the issue is most likely very straight-forward and easy to resolve. Most likely you either don’t have the your PowerShell snapin selected in PowerGUI’s File/PowerShell Libraries, or you forgot to supply a help file for your cmdlets.

So here are the steps to take to make sure your cmdlets show up in PowerGUI admin console and editor as first-class citizens:

1. Make sure your cmdlets have help (creating a help file in PowerShell is very straight-forward with this utility). To check that the help is working open a PowerShell prompt and type:

Get-Help your_cmdlet_name

2. Make sure PowerGUI is using your cmdlets by going to the File/PowerShell Libraries and selecting your PowerShell snapin.

That’s it. Now if you add a node in the PowerGUI admin console all your get-* cmdlets should be there. In the editor, your cmdlets should get tooltips, intellisense, and F1 help. Your snapin is now as good as everybody’s else! ūüôā

Tags: , , ,

PowerShell & PowerGUI tutorial in Portuguese

I’ve just found this great PowerShell and PowerGUI step-by-step tutorial by Anderson Patricio and Jos√© Rodas: AP407 – Using PowerGUI for Windows PowerShell

The guys are taking you step-by-step (providing screenshots for all of them!) on:

  • Importing PowerPacks from the PowerGUI Library,
  • Connecting to the AD cmdlets library,
  • Using the native functionality to get mailbox statistics,
  • And then extending the UI to manage Exchange queues.

This is very cool and highly recommended!

Here’s the list of other tutorials they have on the site (“Learn Spanish¬†Portuguese¬†with Windows PowerShell!”):

AP400 РIntrodução ao Monad

AP401 – Utilizando pipes no Monad

AP402 – Utilizando o registry no Monad

AP403 РTrabalhando com Serviços

AP404 – Trabalhando com o Event Viewer

AP405 – Windows PowerShell: Utilizando Transcript

AP406 – Windows PowerShell: Ordenando dados

AP407 – Usando o PowerGUI for Windows PowerShell

Tags: , , , , , , , ,

UPDATE: Just got a comment from Anderson saying that the demos were actually in Portuguese. I should learn the languages better I guess…

Extend AD cmdlets’ reach

AD cmdlets project is moving along with new features being added all the time but what if what you get now (and the current version is 1.0.2) does not give you what you want yet?

Similar to how we used QADObject to manage OUs in the absence of QADOrganizationalUnit cmdlets you can get access to individual attributes as well.

Checkout this thread at PowerGUI.org to see how you can retrieve the attributes not  yet exposed in cmdlets. For example, to get the LastName attribute missing in 1.0.2 you can use the following command:

Get-QADUser | select Name, FirstName, @{Name=”Last Name”; Expression={$_.DirectoryEntry.sn}}

Provision Exchange Mailboxes from CSV

Wouldn’t it be great to pick a few mailboxes, export their properties to Excel, make a few changes, and use that changed file to provision a bunch of new user accounts and mailboxes? PowerGUI comes with commands to do that!

PowerGUI gives you user interface for a lot of actions which used to require scripting. While I am striving to find time at DEC to finish editing my webcast, so I thought I’ll do a few blogcasts (is there such a word already?) now instead.

Here we go:

1. Download and install PowerGUI on a computer which has either Exchange 2007 or its management tools.

2. Click Mailboxes, make sure that the following columns are displayed (right-click the header to add the columns): UserPrincipalName, Name, Database, OrganizationalUnit – these are mandatory for new Exchange mailboxes.

3. Select the mailboxes you want to export and click Report as CSV:

Select sample mailboxes for provisioning

4. Specify the filename for the output (e.g. c:\test.csv) and click OK. The file will open in whatever is your CSV edit. Normally it should be Excel- in my case the machine didn’t have Office so I had to use Notepad:

Change propeties

5. Change the properties as you wish for the new mailboxes (in my case I just did Replace All), add new rows, add a column Password and set passwords for the new accounts (otherwise we’ll just use UPN for that).

6. Save the file.

7. In PowerGUI click Create new from CSV action.

Create from CSV

8. Type in the file path and click OK.

Select CSV file

9. That’s it – the new accounts and mailboxes got provisioned!

New mailboxes are there!

If you want to schedule provisioning to happen on regular basis (e.g. nightly) just go to the PowerShell Code tab and use the code there for your script.

PowerShell and PowerGUI rock! ūüėČ

Tags: , , , , , ,


My Recent Tweets

Legal

The posts on this blog are provided ‚Äúas is‚ÄĚ with no warranties and confer no rights. The opinions expressed on this site are mine and mine alone, and do not necessarily represent those of my employer - WSO2 or anyone else for that matter. All trademarks acknowledged.

© 2007-2014 Dmitry Sotnikov

December 2019
M T W T F S S
« Oct    
 1
2345678
9101112131415
16171819202122
23242526272829
3031  

%d bloggers like this: