May 2006 - Posts

Soon the happy family of Visual Studio 2005 Team products will be enlarged with "Visual Studio 2005 Team Edition for Database Professionals":

Visual Studio Team Edition for Database Professionals delivers a market-shifting database development product designed to manage database change, improve software quality through database testing and bring the benefits of Visual Studio Team System and life cycle development to the database professional.

One of the fathers of this tool is Gert Drapers, who has been with the SQL Server group for many years (going back to the dark Sybase ages) and has moved on to Visual Studio some time ago. (Note: Visual Studio seems to be a popular "move on" target for SQL Server folks; Euan Garden has moved to Visual Studio too recently).

The first CTP of the new baby will arrive on June 11th. More information is available on http://msdn.microsoft.com/vstudio/teamsystem/products/dbpro.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Just tried it, but unfortunately I didn't work out very well. Guess that's why it's being called a "beta" :-). Nevertheless, I wanted to shared this with you guys:

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Finally it's there, the betas of three amazing products we've been waiting for so long:

  • Windows Vista (build 5384.4)
  • Longhorn Server
  • 2007 Microsoft Office

all went into the beta 2 stage a couple of days ago and are now available through MSDN Subscriptions and will become available through the Beta Experience programs. I'l start downloading next weekend and most likely I'll move to a Windows Vista Beta 2 + 2007 Microsoft Office Beta 2 setup for my day-to-day work.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

A first CTP build of Microsoft Expression Web Designer (Quartz) can be downloaded here. I'm not so much into web development anymore, except for the ASP.NET 1.x and 2.0 basics, but I've been working with tools like FrontPage quite a bit in the past. If I have some spare free time left, I'll install and explore this build shortly.

Other Expression products include the Microsoft Expression Graphic Designer (Acrylic - vector and bitmap graphics) and Microsoft Expression Interactive Designer (Sparkle - WPF/XAML development).

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Posted Monday, May 15, 2006 8:48 PM by bart | with no comments
Filed under:

It's there: a new build of the LINQ (Language INtegrated Query) technology, released on May 10th. You can grab the bits over here: http://www.microsoft.com/downloads/details.aspx?FamilyId=1E902C21-340C-4D13-9F04-70EB5E3DCEEA&displaylang=en.

LINQ is a codename for a set of extensions to the .NET Framework that encompass language-integrated data query, set, and transform operations. It includes extensions to the C# and Visual Basic languages with native language syntax for queries and provides class libraries to take advantage of these capabilities.

This package is a combined update of both the VB and C# LINQ Community Technology Previews released in January 2006 and December 2005. It includes samples, whitepapers, hands-on labs and compiler/IDE support for creating LINQ-enabled applications. Major component additions in this release are the DLinq Designer, LINQ over Dataset, Data Binding, and ASP.NET LINQ project templates.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Yesterday I claimed my blog through Technorati. However, this required me to add a little JavaScript to my blog's homepage, more specifically:

<script type="text/javascript" src="http://embed.technorati.com/embed/c2mjgt7ag5.js"></script>

However, when entering this in the News-section of my blog, Community Server decided to do a bit of encoding for the script-tag alone (not for img tags etc); look like XSS-protection isn't it? So, the script tag was displayed in plain text on my homepage, not exactly what I had in mind ;-).

The solution is to change the communityserver.config file of your Community Server installation and to add the following

<script src="true" type="true" language="true" />

to the <markup><html>...</html></markup> section.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Posted Monday, May 08, 2006 11:43 AM by bart | with no comments
Filed under:

Oh my god, what a painful experience this was. Today, I was playing around with the Virtual Server 2005 R2 API to create a virtual networks visualizer which should be pretty straightforward to do thanks to the COM API that comes with the product. And yes indeed, it's fairly simple as I expected. However, debugging this stuff in VS2005 is rather difficult.

Let's start with the Ole32.dll's CoInitializeSecurity call that's required to get the Virtual Server 2005 COM interop to work. Simply stated, this call has to happen in the process before any other call to the function otherwise you end up with a RPC_E_ TOO_LATE error code (a.k.a. 0x80010119). Basically, one just needs to turn impersonation on in order to talk to Virtual Server 2005 (on the same machine or in the domain) and to gain access to the functions inside. The required call looks as follows:

CoInitializeSecurity(IntPtr.Zero, -1, IntPtr.Zero, IntPtr.Zero, (uint)RpcAuthnLevel.PktPrivacy, (uint)RpcImpLevel.Impersonate, IntPtr.Zero, (uint)EoAuthnCap.DynamicCloaking, IntPtr.Zero);

However, the trouble is the vshost.exe process in Visual Studio 2005 that's used for debugging purposes (when you press F5, it's the *.vshost.exe executable that get's launched). As the matter in fact, this process does the following:

  IL_0000:  call       class [mscorlib]System.Threading.EventWaitHandle [Microsoft.VisualStudio.HostingProcess.Utilities.Sync]Microsoft.VisualStudio.HostingProcess.Synchronize::get_HostingProcessInitialized()
  IL_0005:  brfalse.s  IL_0024
  IL_0007:  call       class [mscorlib]System.Threading.EventWaitHandle [Microsoft.VisualStudio.HostingProcess.Utilities.Sync]Microsoft.VisualStudio.HostingProcess.Synchronize::get_HostingProcessInitialized()
  IL_000c:  callvirt   instance bool [mscorlib]System.Threading.EventWaitHandle::Set()
  IL_0011:  pop
  IL_0012:  call       class [mscorlib]System.Threading.ManualResetEvent [Microsoft.VisualStudio.HostingProcess.Utilities.Sync]Microsoft.VisualStudio.HostingProcess.Synchronize::get_StartRunningUsersAssembly()
  IL_0017:  brfalse.s  IL_0024
  IL_0019:  call       class [mscorlib]System.Threading.ManualResetEvent [Microsoft.VisualStudio.HostingProcess.Utilities.Sync]Microsoft.VisualStudio.HostingProcess.Synchronize::get_StartRunningUsersAssembly()
  IL_001e:  callvirt   instance bool [mscorlib]System.Threading.WaitHandle::WaitOne()
  IL_0023:  pop
  IL_0024:  ret

The solution is fairly straightforward and is to disable the Visual Studio hosting process using the project's properties, tab Debug. Finally I can start debugging my new 'invention'.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Windows Vista's coming closer day by day. I can feel the heat :-). Last week, I was at Hasselt to present some stuff around Windows Vista, IE7 and Office 2007. And quite honestly, it was one of the first presentations where I was pretty confident of the build quality of the software I was showing the audience. IE7 reached the beta 2 stage and Windows Vista is approaching this stadium pretty fast as well. As David said on his blog, build 5365 is the best Vista build ever seen and I have to agree with him for the full 100%. Everything just seems to work: my audio stack is alive-n-kicking again, the ALT-TAB-includes-Windows-logo-problem has been solved and the system just runs so much smoother, all graphical effects included.

And just a week after downloading the 3 GB ISO file (which took me half a day due to the speed limits on the MS Connect servers to give every one a fair amount of bandwidth) a new build has been published online, i.e. build 5381 which happens to be a beta 2 preview. I guess I'll skip this one (no promises - bet I'm downloading it anyway next week :-)). According to the plan beta 2 is expected to arrive on May 22 later this month.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Introduction

I hope lots of you have been investigating Windows PowerShell (formerly known as Monad or MSH) already and have been downloading RC1 lately. In the past I've been blogging about Monad (my apologies for still using the codename, I'm hearing myself talking about things such a Whidbey, Yukon, Longhorn and Office 12 quite a bit as well) from the end-user's (that's the IT pro's) perspective. In today's post, I'm going to focus on the developer's side of the story.

PowerShell programmability

Programmability of Windows PowerShell is an absolute must. In the end, the idea of Monad is to close the gap between GUI administration tools and their much beloved command-line brothers that play a central role in IT admins' nightly dreams :-). And of course those IT folks are right: in order to be productive, things need to be scriptable and have a big need for automation. Historically, there have been many technologies that aided in doing those kind of jobs, including ADSI, WMI and WSH but none of those were delivering the complete story. And you, as a developer, are responsible to make your application manageable by leveraging the power of those (boring?) technologies. That's where things such as WMI events, System.Management and other API's such as EIF (Enterprise Instrumentation Framework) enter the scene.

Monad's primary role is to deliver a great shell that provides access to virtually anything (don't forget the father of WMI is also Monad's father, i.e. Jeffrey Snover) by means of providers and cmdlets. By building cmdlets that capture some kind of atomic tasks (e.g. create a mailbox, stop a process, delete an item, etc) and taking advantage of an object-oriented pipeline, Monad gives IT folks a lot of flexibility compared to the things that exist today (toolboxes full of .exe files spitting out nasty-to-parse text and with the lack of proper fault - not to mention the OO 'exception' word yet - handling).

So, what are providers and what are those cmdlets? An overview:

  • Providers are the abstraction over hierarchical data stores such as a file system. Monad ships with a couple of those (of which the instances are called "PS drives", see get-psdrive) to mount your file drives but also the registry, the certificate store, etc in the shell. So, you can do things like:

    PS C:\> cd HKLM:\SOFTWARE\Microsoft
    PS HKLM:\SOFTWARE\Microsoft> dir
  • Cmdlets are little pieces of functionality that's callable using the PS shell, just like normal commands in a classic shell. The main difference is that those cmdlets are 100 percent managed code and don't live inside executable files. Furthermore, cmdlets work with objects instead of accepting text as input and spitting out text as output. For example, performing a dir operation (which is an alias for get-childitem) results in System.IO.FileInfo instances if you're calling it in the context of a "file drive". The idea is that standalone cmdlets perform a little piece of work and become great automation mechanisms when working together with other cmdlets in a pipeline structure:

    get-process | where { _$.ProcessName -eq "notepad" } | stop-process

Cmdlets form the groundwork for manageability in the future. The idea is pretty simple: encapsulate your manageability "tasks" in cmdlets that might just be little façades over more complex structures inside your application (which can consist of portions of unmanaged code - cf. Exchange 12 manageability through (managed code) cmdlets). GUI-based administration tools then call into those cmdlets by hosting the Monad engine that has the full pipelining support in it, the extended type system and much more to aid in parsing, error handling, etc. And of course, those GUI-based administration tools can be writting using the MMC 3.0 technology which is the graphical cornerstone of the manageability story. By layering the GUI administration tools on top of the cmdlets, one creates also the opportunity for reproducibility by means of recording scripts. In the end, all you do in the GUI tools can be done using cmdlets as well. The cmdlets play the role of the interface to the rest of the system if you want to put it that way. And so, running GUI tools in a kind of script recording mode (somewhat equivalent to the SQL Management Studio's capabilities to record SQL scripts while working inside the GUI admin tools) is the best script generator ever seen (you'll be able to create scripts just like you record Word macros).

As a developer, you'll take care of creating those cmdlets (and maybe providers as well) to help your IT brothers to do a better job by playing with an application you can now call manageable (okay, you shouldn't forget about performance counters and event logging as well :-)). In this post, we'll take a look at the creation process of cmdlets.

Your first cmdlet

Let's take a look at the steps you have to go through in creating your first cmdlet. In order to show the richness of the processing pipeline etc we can't afford to play around with a "hello world" like sample, so we'll have to look a little further. Instead, we'll build a cmdlet (btw, that's pronounced as "command-let") that looks for regular expression matches in a (set of) given file(s).

Step 1 - Create a Visual Studio project

Cmdlets are .NET classes as I mentioned before. So to kick off, we'll create a new class library project (e.g. in C#) and give it a meaningful name, for example FindString. Next, add a reference to the System.Management.Automation.dll assembly which you can find in %programfiles%\Windows PowerShell\v1.0.

Step 2 - Declare the cmdlet class

Next, it's time to declare our cmdlet-acting class as follows:

using System.Management.Automation;

[
Cmdlet("Get", "Matches"
)]
public class FindString :
PSCmdlet
{
}

Note: Using the CmdletAttribute (you know you can omit the -Attribute suffix in C#) you indicate the verb and noun of the cmdlet. Every cmdlet in Monad follows this pattern for clarity. For the verbs, it's recommended to take one from the list in the Windows SDK. The comment in the get-row over there mentions, so let's follow this guidance:

Get

This verb retrieves data. Use with Set.

Do not use verbs such as read, open, cat, type, dir, obtain, dump, acquire, examine, find, or search.

The class has to inherit from PSCmdlet and has to be annotated with the CmdletAttribute attribute as you can see.

Step 3 - Parameterize the cmdlet

Now it's time to take a look at the functionality itself. This consists of two steps: add parameters to the cmdlet and write the real functionality. We'll start by defining the parameters by declaring a couple of public properties and decorating those with the ParameterAttribute attribute and a couple of named parameters, as shown below (defined using the prop codesnippet in C#):

private string pattern;

[
Parameter(Mandatory=true
, Position=0)]
public string
Pattern
{
   get { return
pattern; }
   set { pattern = value
; }
}

private string
[] fullName;

[
Parameter(Mandatory=true, Position=1, ValueFromPipelineByPropertyName=true
)]
public string
[] FullName
{
   get { return
fullName; }
   set { fullName = value
; }
}

The first parameter is called Pattern and will contain the regular expression pattern we'll look for. It's a mandatory parameter and has to appear in the first position of the cmdlet's syntax (you'll see it's possible to specify those parameters in a bunch of different ways). The second one is called FullName and is also mandatory but appears in the second (and following) position(s). It's of type string[] so that it can contain more than one filename, and it can be fed in through the pipeline by the property name. That means that cmdlets that return objects with a public property called FullName can be linked to this cmdlet by means of piping (|).

Take a look at the following:

PS C:\> $a = get-childitem *.txt
PS C:\> $a | get-member F*


   TypeName: System.IO.FileInfo

Name     MemberType Definition
----     ---------- ----------
FullName Property   System.String FullName {get;}

Get-childitem (abbreviated as dir or ls) returns instances of type System.IO.FileInfo which contains a property called FullName. That enables us to pipe this data in and use it in our cmdlet as a parameter. So, you'll be able to write things like:

dir | get-match [a-z]*

Step 4 - Implement the core functionality

The core of the cmdlet's implementation goes in the ProcessRecord method (note: asynchronous variants of this method also exist, we're not going to focus on those for now). The following is a pretty short implementation of our matching logic relying on System.Text.RegularExpressions and System.IO to read files:

protected override void ProcessRecord()
{
   List<Match> matches = new List<Match>();

   ProviderInfo
info;
   foreach (string item in FullName)
      foreach (string file in GetResolvedProviderPathFromPSPath(item, out info))
         using (StreamReader sr = File.OpenText(file))
            matches.Add(
new Match(file, Regex.Matches(sr.ReadToEnd(), pattern)));

   WriteObject(matches);
}

The call to WriteObject returns the result to the pipeline for further processing; other cmdlets could use our output as their input, or the user can just feed this in to cmdlets like format-list (or work with variables, etc). To aid our implementation, we've created a simple Match class:

public class Match
{
  
public Match(string file, MatchCollection
matches)
   {
     
this
.file = file;
     
this
.matches = matches;
   }

  
private MatchCollection
matches;

  
public MatchCollection
Matches
   {
     
get { return
matches; }
     
set { matches = value
; }
   }

   private string
file;

   public string
File
   {
     
get { return
file; }
     
set { file = value
; }
   } 
}

Step 5 - Create a custom shell

Time to compile the cmdlet and create a custom shell. To do this, follow each of those:

  1. Compile the cmdlet and copy the FindString.dll file to the Windows PowerShell\v1.0 installation folder (for ease of testing right now).
  2. Open Windows PowerShell and execute the following commands to build a new shell using the Make Kit:

    PS C:\Program Files\Windows PowerShell\v1.0> make-shell -out test -ns Demo -ref findstring.dll
    Windows(R) PowerShell MakeKit
    Copyright (C) 2005 Microsoft Corporation. All rights reserved.

    Shell test.exe is created successfully.

  3. If you try to start the shell now, you'll get the following error because the shell is not registered yet:

    PS C:\Program Files\Windows PowerShell\v1.0> test
    Error loading the extended type data file:
    Cannot find the registry key: "SOFTWARE\Microsoft\PowerShell\1\ShellIds\Demo.test\Path", using "C:\Program Files\Windows PowerShell\v1.0" to load the configuration files.

    There were errors in loading the format data file:
    Cannot find the registry key: "SOFTWARE\Microsoft\PowerShell\1\ShellIds\Demo.test\Path", using "C:\Program Files\Windows PowerShell\v1.0" to load the configuration files.


    To solve this issue, register the shell as follows:

    PS C:\Program Files\Windows PowerShell\v1.0> cd HKLM:\SOFTWARE\Microsoft\PowerShell\1\ShellIds
    PS HKLM:\SOFTWARE\Microsoft\PowerShell\1\ShellIds> mkdir Demo.test

       Hive: Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds

    SKC  VC Name                           Property
    ---  -- ----                           --------
      0   0 Demo.test                      {}

    PS HKLM:\SOFTWARE\Microsoft\PowerShell\1\ShellIds> cd Demo.test
    PS HKLM:\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Demo.test> new-itemproperty -path . -name Path -value "C:\Program Files\Windows PowerShell\v1.0\test.exe"

    PSPath       : Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\She
                   llIds\Demo.test
    PSParentPath : Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\She
                   llIds
    PSChildName  : Demo.test
    PSDrive      : HKLM
    PSProvider   : Registry
    Path         : C:\Program Files\Windows PowerShell\v1.0\test.exe

Step 6 - Testing time

Launch the shell and test whether it provides access to the newly written cmdlet (it should!):

PS C:\Program Files\Windows PowerShell\v1.0> get-command -noun matches
PS C:\Program Files\Windows PowerShell\v1.0> test
PS C:\Program Files\Windows PowerShell\v1.0> get-command -noun matches

CommandType     Name                            Definition
-----------     ----                            ----------
Cmdlet          Get-Matches                     Get-Matches [-Pattern] <Stri...


PS C:\Program Files\Windows PowerShell\v1.0>

A now, the big test:

PS C:\Program Files\Windows PowerShell\v1.0> get-matches Wmi about_Alias.help.txt

Matches                                 File
-------                                 ----
{Wmi, Wmi, Wmi}                         C:\Program Files\Windows PowerShell\...

Seems to be okay, isn't it? The system tells me the file about_Alias.help.txt contains 3 times the word Wmi somewhere, but where? Let's use a variable:

PS C:\Program Files\Windows PowerShell\v1.0> $a = Get-Matches Wmi about_Alias.help.txt
PS C:\Program Files\Windows PowerShell\v1.0> $b = $a[0]
PS C:\Program Files\Windows PowerShell\v1.0> $b

Matches                                 File
-------                                 ----
{Wmi, Wmi, Wmi}                         C:\Program Files\Windows PowerShell\...

Remember Get-Matches returns a List<Match> object, so we'll have to select an item from this list to get the rest of the properties. Or to speak with variables, $a is from type List<Match> and $b contains a Match instance. Now, we can ask for the matches as follows:

PS C:\Program Files\Windows PowerShell\v1.0> $b.Matches


Groups   : {Wmi}
Success  : True
Captures : {Wmi}
Index    : 5780
Length   : 3
Value    : Wmi

Groups   : {Wmi}
Success  : True
Captures : {Wmi}
Index    : 6008
Length   : 3
Value    : Wmi

Groups   : {Wmi}
Success  : True
Captures : {Wmi}
Index    : 6241
Length   : 3
Value    : Wmi

Or, to print the indices directly, we can use the foreach construct (which is an alias for ForEach-Object):

PS C:\Program Files\Windows PowerShell\v1.0> $b.Matches | foreach { $_.Index }
5780
6008
6241

Or what about this?

PS C:\Program Files\Windows PowerShell\v1.0> dir *.txt | get-matches PowerShell | foreach { $total = 0 } { $total += $_[0].Matches.Count }
PS C:\Program Files\Windows PowerShell\v1.0> $total
450

<Quiz>

What's the difference between dir *.txt | get-matches PowerShell and get-matches PowerShell *.txt? Tip: how many List<Match> instances does each return?

</Quiz>

Learn more

In the future, I'll cover providers and more advanced cmdlets over here as well. So, stay tuned on my blog! For the Dutch-speaking readers, the next .NET Magazine (#13) will cover Windows PowerShell cmdlets, so make sure to get your hands on it! You can subscribe to get a copy of .NET Magazine on MSDN Netherlands.

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

A couple of days ago, the TechEd Europe 2006 websites were released to the web, enabling you to register today for TechEd Developers (formerly called TechEd) and TechEd IT Forum (formerly called "IT Forum") which will take place in November 2006 in sunny Barcelona.

From the Microsoft EMEA TechEd website:

   
Microsoft Tech·Ed: Developers
7 – 10* November 2006
Barcelona, Spain

*6 November for Pre-Conference Seminars

Tech·Ed: Developers is Microsoft’s premier EMEA conference designed to provide developers with deep dive technical training, information and community resources focusing on building software solutions with Microsoft development tools for current and soon-to-be-released products and technologies.

Microsoft Tech·Ed: IT Forum
14 – 17* November 2006
Barcelona, Spain

*13 November for Pre-Conference Seminars

Tech·Ed: IT Forum is Microsoft’s premier EMEA conference designed to provide IT professionals with technical training, information and community resources to build, plan, deploy and manage the secure connected enterprise.

 
I'll post more information on this event later over here on my blog. Stay tuned!Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

More Posts