Using and Discovering StreamInsight Instances

Embedding a StreamInsight server instance in your application is easy:

 using (var server = Server.Create("Default"))
{
   …
}

But there’s a hitch. What does“Default” mean? If you’ve spent time with the StreamInsight samples, you might imagine the “Default” incantation has a special meaning. The verification tests we run on the StreamInsight team require that you install a server instance named “Default”, and – not coincidentally – this tends to be the choice of instance name in StreamInsight samples as well. Let’s look at how to work with, discover, and understand server instances. First, some general notes:

  • A SQL Server 2008 R2 license is required to run StreamInsight, either as a dedicated service or an embedded server. The instance name passed to the Server.Create method associates the embedded server with a particular license.
  • A free evaluation edition is available as well. See the StreamInsight team blog for details.
  • A SQL Server 2008 R2 installation is not required. StreamInsight uses standalone installers.
  • There are two installers. One includes only the client libraries that can be used to connect to an existing StreamInsight service. The other installs the same libraries but additionally registers a server instance and (optionally) a service. The stand-alone service is optional because some users may want to just embed StreamInsight.
  • A StreamInsight server instance carefully controls resource allocation – memory, cores – for the stream queries it hosts. As a result, it is best to embed a single server instance in your application. Otherwise, the instances will compete with each other for resources, and no one wins.

If you write an application that embeds StreamInsight, you need to know the name of the corresponding instance. But what if your application is running on a strange machine? The usual official advice applies: use app/web config files to store the instance name for Server.Create. You can configure the management service URI used by Server.Connect in the same way.

Now the unofficial advice.

Server instance information is stored in the registry. Launch regedit and take a look under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft StreamInsight to see examples. Looking up values in the registry can be hazardous, particularly if you want to be robust to permutations of 32/64-bit operating system, StreamInsight install, and .NET application. Shahar Prish’s advice on the topic gives an idea of the challenges, but fortunately there is an easier alternative in .NET 4.0. The new OpenBaseKey method allows you to explicitly select a 64-bit registry view (I was pretty excited to find this – as far as I can tell, there were no announcements of this extension to the .NET registry key APIs). Here’s a utility you can use to reliably retrieve StreamInsight instance data:

 public struct InstanceInfo
{
    const string InstanceKeyPrefix = "MSSI.";

    public readonly string Name;
    public readonly Version Version;
    public readonly string Edition;

    InstanceInfo(string name, RegistryKey instanceKey)
    {
        Name = name;
        System.Version.TryParse((string)instanceKey.GetValue("Version", string.Empty), out Version);
        Edition = (string)instanceKey.GetValue("Edition");
    }

    public override string ToString()
    {
        return new { Version, Name, Edition }.ToString();
    }

    public static IEnumerable GetInstalledInstances()
    {
        // On a 64-bit machine, StreamInsight always registers instances in the 64-bit registry hive
        // even for 32-bit installations. In addition, we need to ensure that we access the correct
        // hive even if we're running a 32-bit .NET application on a 64-bit machine.
        using (var baseKey =
            RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)
            ?? RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32))
        {
            using (var siKey = baseKey.OpenSubKey(@"SOFTWARE\Microsoft\Microsoft StreamInsight"))
            {
                if (null == siKey) yield break;

                foreach (var subKeyName in siKey.GetSubKeyNames())
                {
                    if (subKeyName.StartsWith(InstanceKeyPrefix, StringComparison.Ordinal))
                    {
                        using (var instanceKey = siKey.OpenSubKey(subKeyName))
                        {
                            yield return new InstanceInfo(subKeyName.Substring(InstanceKeyPrefix.Length), instanceKey);
                        }
                    }
                }
            }
        }
    }
}

I’ll call out one trick in the implementation: the ToString() override uses an anonymous type to format output. The compiler auto-generates a ToString() implementation for anonymous types, so we can write:

 new { Version, Name, Edition }.ToString()

instead of the more familiar but error-prone:

 string.Format(System.Globalization.CultureInfo.InvariantCulture,
    "Name = {0}, Version = {1}, Edition = {2}",
    Name, Version, Edition)

Let me know if you have any questions on StreamInsight instances! If I can’t answer them I can hopefully find someone who can.