Array or no array in Powershell? Why using @(…) is a good idea.

Here’s a funny thing in Powershell:

PS C:\> cd C:\WINDOWS\system32
PS C:\WINDOWS\system32> (dir *.dll).GetType()

IsPublic IsSerial Name                           BaseType
-------- -------- ----                           --------
True     True     Object[]                       System.Array

PS C:\WINDOWS\system32> (dir kernel32.dll).GetType()

IsPublic IsSerial Name                           BaseType
-------- -------- ----                           --------
True     True     FileInfo                       System.IO.FileSystemInfo

PS C:\WINDOWS\system32>

See what’s happening? If dir (or actually Get-ChildItem) finds several items matching our criteria then it returns an array, which is what you’d expect. But if the cmdlet finds just a single item then that item is returned directly instead of being encapsulated into an array. If you’re unexperienced with Powershell then that’s probably not what you’re expecting.

For example, this script will not always work as expected:

if ((dir *.dll).Length -gt 1) { 'many items' }

If there is more than 1 matching item then all will be fine, but if exactly one item is found then that script will break. And worse, it will break without the user noticing since no exception is thrown. It will simply print out ‘many items’ in this case, even though there is just one item. To understand why, try this:

PS C:\WINDOWS\system32> (dir kernel32.dll).Length
989696

What happens is that dir returns one item, of type FileInfo, which happens to have a property called Length which contains the size of the file. Thus we’re calling System.IO.FileInfo.Length instead of System.Array.Length… Very confusing!

Fortunately, there’s an easy way to make sure that you always get an array, namely the @(…) construct which does nothing if its expression evaluates to an array and if it doesn’t, encapsulates it into one.

Examples:

PS C:\WINDOWS\system32> @(dir kernel32.dll).Length
1
PS C:\WINDOWS\system32> if (@(dir *.dll).Length -gt 1) { 'many items' }

To sum it up: Always use @(…) if you want to work with arrays! Note that this applies to all cmdlets, not just Get-Childitem!

/Emil

Deciding whether an NHibernate object reference is a proxy

Have you ever had a need to decide whether an object reference to an NHibernate-mapped object is the real instantiated object or an NHibernate-generated proxy used for lazy loading? Here’s how to do it:

if (entityObject is NHibernate.Proxy.INHibernateProxy)
{
  ...
}

You don’t often need to make a distinction between proxies and the real objects but it may be useful when traversing object structures without triggering lazy-loading.

A related method is NHibernateUtil.IsInitialized which may come in handy in similar use cases as the above. It tells whether a proxy or persistent collection is initialized (i.e. loaded from the database) or not.

if (NHibernateUtil.IsInitialized(entityObject))
{
  ...
}

/Emil

Listing and resuming workflow instances

We recently had a need to list suspended Workflow Foundation 4 instances hosted in Windows Server AppFabric from code, and here’s how to do it:

SqlInstanceQueryProvider provider = new SqlInstanceQueryProvider();
var providerArgs = new NameValueCollection { { "connectionString", _instanceStoreConnectionString } };
provider.Initialize("WfInstanceProviderA", providerArgs);

InstanceQuery query = provider.CreateInstanceQuery();
var args = new InstanceQueryExecuteArgs { InstanceStatus = InstanceStatus.Suspended };

IAsyncResult asyncResult = query.BeginExecuteQuery(args, new TimeSpan(0, 0, 0, 30), null, null);
IEnumerable instances = query.EndExecuteQuery(asyncResult);

By the way, this requires a reference to Microsoft.ApplicationServer.StoreManagement.dll which is installed with AppFabric.

Resuming the workflow instances can be done like this:

SqlInstanceControlProvider provider = new SqlInstanceControlProvider();
var providerArgs = new NameValueCollection { { "connectionString", _instanceStoreConnectionString } };
provider.Initialize("WfInstanceProviderA", providerArgs);

InstanceControl control = provider.CreateInstanceControl();

foreach (InstanceInfo instanceInfo in instances)
{
    InstanceCommand cmd = new InstanceCommand
    {
        CommandType = CommandType.Resume,
        InstanceId = instanceInfo.InstanceId,
        ServiceIdentifier = instanceInfo.HostInfo.HostMetadata
    };

    // Not included in instanceInfo.HostInfo.HostMetadata...
    cmd.ServiceIdentifier["VirtualPath"] = 
         "/EducationWorkflowServices/AktivitetService.xamlx";

    IAsyncResult asyncResult = control.CommandSend.BeginSend(cmd,
        new TimeSpan(0, 0, 0, 30), null, null);
    control.CommandSend.EndSend(asyncResult);
}

AppFabric also has some great PowerShell cmdlets for administration that can be used for the same thing. Here are a few examples:

Import-Module ApplicationServer
Get-ASAppServiceInstance -status 'suspended'
Get-ASAppServiceInstance -status 'suspended' | Resume-ASAppServiceInstance
Get-ASAppServiceInstance -status 'suspended' | Stop-ASAppServiceInstance -Terminate
Get-ASAppServiceInstance -status 'suspended' | Remove-ASAppServiceInstance
Get-ASAppServiceInstance -InstanceId 95a25419-0d71-42c4-ab70-aa523ba603fc
Get-ASAppServiceInstance -InstanceId 95a25419-0d71-42c4-ab70-aa523ba603fc | Suspend-ASAppServiceInstance

Yet another alternative is to query the AppFabric persistance store database directly using SQL:

SELECT *
FROM [AppFabric_Application_Extensions].[System.Activities.DurableInstancing].[InstancesTable]
WHERE IsSuspended=1

Choose the alternative most to your liking 🙂

/Emil

The case of the slow for-loop

We recently had a problem with a page in an MVC application that was very slow, it took minutes before the server finished creating it. It turned out that it was this for-loop that caused the problem:

for (int i = 0; i < Model.Deltagare.Count(); i++)
{
  var deltagare = Model.Deltagare.ElementAt(i);
  ...
}

where Model.Deltagare is an IEnumerable. This is a common construct when you need to track the loop index for some reason but it turns out that its use really should be discouraged. The problem is that ElementAt(i) can take a really long time depending on the underlying list type of the enumerable. If it’s an array, it’s really quick, but in our case it was a System.Linq.Enumerable.WhereSelectListIterator and apparently ElementAt(i) had to traverse the enumerator from the start each time it was called. That’s not what you want to use an iterator for…

We changed the above loop to a foreach-loop instead, so that the iterator can be used more naturally:

int i;
foreach (var deltagare in Model.Deltagare)
{
  ...
  i++;
}

The duration of our loop went from about 10 minutes to 1 second for a list of about 6000 items.

Lesson learned.

/Emil

NDepend 3

In case you missed it, there’s a very powerful tool called NDepend that helps you analyze your code structure and detect potential problems very easily. A new version, NDepend 3, was released earlier this year and the biggest new feature is probably Visual Studio integration:

It still has all the code metrics you’ll probably ever need, a custom made code query language, diagrams (some of which are still a little difficult to read) and graphs to help with analysis. See my post about the previous version for some examples.

Here are a few live examples of using NDepend: http://www.ndepend.com/Features.aspx#Tour

If you’re into code analysis you should give NDepend a try. With this new version it’s more usable than before and it still has the same very powerful analysis engine under the hood. Check out http://www.ndepend.com for more info.

/Emil

Authentication for IIS-hosted WCF services

WCF is very powerful and very, very complicated to configure in many cases. Seemingly simple requirements can get really difficult to get right and security definitely falls in that category. I recently had the following need:

  • WCF-services hosted in IIS 7.5
  • Windows authentication should be used for the services
  • The client must not be required to be in the same domain as the service application

Simple enough, right? Not for me it wasn’t…

My first idea was to set the authentication settings in IIS to Windows Authentication and configure the client to use credentials from a config file, this was the method I’m used to when calling ASMX services, but it didn’t work. It was really frustrating as well as it’s so difficult to understand what’s going on.

No matter what changes I did in the configuration files, I kept getting errors such as

The HTTP request is unauthorized with client authentication scheme 'Anonymous'.
The authentication header received from the server was 'Negotiate,NTLM'.

I was finally able to come up with a solution which I thought I’d share with you. I don’t know if it’s optimal, but if you think it’s not then please leave a comment.

What I did was this:

  • Disable IIS authentication by setting it to Anonymous in the IIS Manager
  • In the binding configuration for the services, set security mode to Message and to use Windows Authentication:
    <security mode="Message">
     <message clientCredentialType="Windows" />
    </security>
    
  • On the client side we now have the option to pass on the currently logged in user’s credentials (requires no extra handling, just call the service) or to explicitly give the credentials to use. The latter is done like this for a ClientBase<T> proxy:

    client.ClientCredentials.Windows.ClientCredential.Domain = "xxx";
    client.ClientCredentials.Windows.ClientCredential.UserName = "yyy";
    client.ClientCredentials.Windows.ClientCredential.Password = "zzz";
    client.MyMethod();
    
  • This solved the problem for me. I think the major difficulty I had was that IIS and WCF security settings collided, so I believe the lesson learned is to do security on only one place and that place should probably be WCF.

    On a related note, I have also had problems with service discovery, WSDL, etc if the web application is not set to Anonymous authentication in IIS, so it seems to be a good idea to do it like that for that reason as well.

    Also, I’m not the only one to have problems with WCF security, here are a few others:
    Post 1, Post 2.

    /Emil

Templates for SQL Server Management Studio

Templates for SQL Server Management Studio 2008 are stored in this folder on WIndows XP:

C:\Documents and Settings\[user]\Application Data\Microsoft\Microsoft SQL Server\100\Tools\Shell\Templates\Sql

On my new WIndows 7 machine, the location is:

C:\Users\[user]\AppData\Roaming\Microsoft\Microsoft SQL Server\100\Tools\Shell\Templates\Sql

Create sub-folders and SQL files there and they show up in the Template Explorer. Really useful…

/Emil

NUnit with SQLite and .Net 4.0 Beta 2

SQLite and unit testing is a great combination for testing database operations without having to manage database files. You can simply create an in-memory database in your setup code and work with that instance. Perfect in combination with NHibernate, for example.

If you want to do this in the current .Net 4.0 beta you’re out of luck though, you’ll get an exception:

System.IO.FileLoadException: Mixed mode assembly is built against version 'v2.0.50727' of the runtime
and cannot be loaded in the 4.0 runtime without additional configuration information.

The solution is pointed out by Jomo Fisher. What you do is to include this snippet in the application config file:

<startup useLegacyV2RuntimeActivationPolicy="true">
  <supportedRuntime version="v4.0"/>
</startup>

When unit testing assemblies that references System.Data.SQLite.DLL then you have to put that snippet in NUnit’s config file (C:\Program Files\NUnit 2.5.2\bin\net-2.0\nunit.exe.config).

If you combine this with the tip in my post NUnit with Visual Studio 2010 Beta 2, you should insert the following

<startup useLegacyV2RuntimeActivationPolicy="true">
  <supportedRuntime version="v4.0"/>
  <requiredRuntime version="v4.0.20506" />
</startup>

plus

<loadFromRemoteSources enabled="true" />

under the runtime tag.

This works for me, hopefully it will for you as well.

/Emil