How to pre-populate assemblies to the Add References dialog in Visual Studio 2005

This one is good to keep track of when working in a team enviroment where everyone uses their own folder structures.

Here are some options I found that worked for me when I tried them on my machine:

  1. Add a new sub-key under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v2.0.50727\AssemblyFoldersEx (or the same sub-key under HKEY_CURRENT_USER if you want the assemblies to appear only for the current user instead of all users).  The default value of the sub-key should be the folder path that you want Visual Studio to look in for assemblies to include in the Add References dialog.  This registry path is specific to VS 2005 and the .NET Framework 2.0 and will not work for previous versions of VS or the .NET Framework.  It is documented in this MSDN document.
  2. Add a new sub-key under HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\AssemblyFolders (or the same sub-key under HKEY_CURRENT_USER if you want the assemblies to appear only for the current user instead of all users).  The default value of the sub-key should be the folder path that you want Visual Studio to look in for assemblies to include in the Add References dialog.  This registry path is global and any folders listed here will be processed by VS .NET 2002, VS .NET 2003 and VS 2005 as well as the .NET Framework 1.0, 1.1 and 2.0.  It is documented in this KB article.
  3. Place a copy of the file in the folder c:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PublicAssemblies.  This path is dependent on the version of Visual Studio that you have installed and whether or not you installed it to the default path, so you may need to adjust it as needed for your system.  The path that I list is for a default install of VS 2005.

 

[Aaron Stebner’s WebLog]

Installing SQL Server Express

There’s a good article on MSDN for controlling the installation of SQL Server Express. If you are bundling Express with your application, you may want to handle the Express options to make it simpler for the user. There some nice code for determining if Express is already installed.

Counterstrings

I was reading some of the older postings in James Bach’s excellent blog, Training the minds of testers, when I found a little gem called “counterstrings”.

A counterstring is a graduated string of arbitrary length. No matter where you are in the string, you always know the character position. This comes in handy when you are pasting huge strings into fields and they get truncated at a certain point. You want to know how many characters that is.

Here is a 35 character counterstring:

2*4*6*8*11*14*17*20*23*26*29*32*35*

Each asterisk in the string occurs at a position specified by the immediately preceding number. Thus, the asterisk following the 29 is the 29th character in that string. So, you can chop the end of the string anywhere, and you know exactly where it was cut. Without having to count, you know that the string “2*4*6*8*11*14*17*2” has exactly 18 characters in it. This saves some effort when you’re dealing with a half million characters. I pasted a 4000 character counterstring into the address field of Explorer and it was truncated at “2045*20”, meaning that 2047 characters were pasted.

I realize this is may not be a very interesting sort of testing, except perhaps for security purposes or when you’re first getting to know the app. But security is an increasingly important issue in our field, and sometimes when no one tells you the limits and dynamics of text fields, this can come in handy.

[James Bach’s Blog (Testing)]

This is a really cool and simple way to verify the length of an entry field in an application. He also has a small applet, downloadable from that blog entry, that will let you create counterstrings of various patterns. I may code a clone up in Delphi for my own nefarious purposes.

Fun with the MSDE: installing

Dana Epp has posted a request for information about the MSDE on his blog. He wants to install an app that that requires a named instance of the MSDE and wants to include the smallest footprint of the MSDE installer bits. On machines that already have the MSDE, he wants to install an additional named instance and wanted to avoid including the MSDE bits since it was already installed. With SQL Server named instances, you can’t do that. Adding a second instance isn’t a reconfiguration of the existing install of SQL Server/MSDE/Express, it’s a completely separate install. It’s considered to be a separate application by the installer and the OS.

I’m not sure why Microsoft went that way, but it’s tied to how the Windows Installer works. A Windows Installer file (.msi) installs just one install of itself. If you try running it again, the installer locates itself on the machine and brings the installer up in maintenance mode. It’s not designed to let you install multiple copies of a single application. If you want to do that, you have to go down the multiple instance transform route. A multiple instance transform file (.mst) is basicly the difference between two .msi files. You use the .mst file to change some of the values in a .msi file so that it gets considered to be a different installer by the Windows Installer runtime. By that’s a whole ‘nother story in and of itself.

Because each instance is essentially a separate installation, you don’t want to mess around with the source installer bits. Otherwise, you’ll make it difficult to install patches or upgrades. I’m pretty sure that’s why Microsoft prefers that you to use their executable to install SQL Server/MSDE/Express. If you use the .msi files, then the patches have be generated against the .msi files that you used. If you merged the SQL Server .msi into your .msi, then upgrades to SQL Server on that machine will required your .msi file. Ouch.

Each instance has to have a .mst file, it’s a one to one relationship. I’m not sure what MS is doing under the hood in the SQL Server install process, but my guess is that it’s creating .mst files at runtime when you specify an instance name. Otherwise it have to include X number of .mst files in the package, and if they did that some twisted person would try to install X+1 instances and break the installer. Creating a .mst file on the fly is doable, but it’s not something I would want to implement. When the user specifies a new instance you need to take your .msi installer file, copy it to a new .msi file. Then you modify that .msi file with the instance name, increment a property, and generate a new product GUID. You then generate the .mst file from the difference between the original .msi file and the new one. After that, you delete the new .msi file, it’s no longer needed. Then you call msiexec with the .msi file and the .mst with the appropriate parameters. I’m not sure that you could reliably generate installer patches (.msp files) under that scenario.

I’m not a fan of how Microsoft implemented the multiple instances. When I wrote the server end of e-Link, I used the Windows Installer to install the service. If the user wants to install a second instance of e-Link, they can use an administration utility that I wrote that can register additional instances of the service, but using the same executable. It provides the same functionality to the user, but only requires one set of files. This makes updating the service much easier as the patch only has to target one installed instance.

I can see why MS went along the single instance route with Windows Installer. It prevents the user from accidently installing 8 copies of “Hunt the Wumpus”. It makes it easy to allow installers to repair existing installations or modify the original setup. It does makes some tasks extremely difficult for installing. The big thing that I can see what would require multiple installs are web sites. There you could have multiple installations as people usually install a web a couple of times to try different settings, of have “live” and “staging” versions of a site.

If you want to install a web site with Windows Installer multiple times on the same machine, you have a few choices.

  • You could limit the install to a single instance. If the user wants multiple copies of the web site files, they have to do that part manually. We do that with the web gui end of e-Link and we document how to do it. Another way (which I have not tried) would be to rename the web site or virtual directory and it the physical name of the folder that it was installed into. Then run the installer again. It will come up in maintenance mode and you would select repair and it should install another set of files into the previously selected location. The draw to both methods is that the installer will repair or uninstall only the files it knows about. If you add anything manually, then you must remove it manually.
  • You could supply a fixed number of instance transforms. If you do this, you’ll need an intelligent front end application to your installer so that you can prompt the user for the instance name. Then you have to check to see if that instance is already installed. If not, then you get the next available instance number and see if you have enough transfoms to use one for this install. Lots of error checking required here, it’s not something I would want to do.
  • You could generate instance transforms at run time. Much of the same logic as the previous option, plus the additional work of creating the transform. I definitely don’t want to ever have to do this.

This is why you don’t see many .msi files for installing web sites.
Trackback to Dana’s post

RE:How to determine if the current user is an administrator

This is pretty cool. A lot of the stuff that I write is low level admin type of utilities. As my coding meter moves further away from the Win32 Delphi to C#, I’ll need stuff like this more often.

Following, is the method that I use to determine if a user is an Administrator. Note that in .NET 1.0/1.1 the using construct wrapped around the creation of the WindowsIdentity won’t compile as its implementation of IDisposable is new for .NET 2.0. Previously you had to rely on the finalizer of the object to run so that the handle of the user token could be freed.

        using System;
        using System.Security.Principal;
        using System.Windows.Forms;

        public static bool IsAdministrator
        {
            get
            {
                if (SystemInformation.Secure)
                {
                    using (WindowsIdentity identity = WindowsIdentity.GetCurrent())
                    {
                        WindowsPrincipal wp = new WindowsPrincipal(identity);

                        return wp.IsInRole(WindowsBuiltInRole.Administrator);
                    }                   
                }

                return false;
            }
        }

There is also a check to determine if the operating system is secure (ie Windows NT platform) – the documentation states that the IsInRole method returns no results on Windows 98 and Windows Millennium Edition. I’m not entirely sure how a method that returns a boolean value can return no results, so it is wrapped in the Secure check just in case an exception is thrown when using it on Windows 9x/ME.

from [Managed from down under]

Why you wont find C# example code for writing Shell Extension handlers

Jesse Kaplan posted the following (thanks to Junfeng Zhang)

Writing in-process \shell extensions in managed code is actually a very dangerous thing to do because it has the effect of injecting your managed code (and the .NET Framework) into every application on the machine that has a file open dialog.

The problems occur because only one version of the .NET Framework can be loaded in a process at any given time (other shared components such as java and msxml have the same property and thus the same restriction).

If you write your shell extension using the 2.0 .NET Framework and an application built with the 1.1 .NET Framework uses a file open dialog, your shell extension will fail because it can not run on an earlier version. Things can get even worse if your shell-extension manages to get loaded in a process before another applications managed code does: your extension may force an existing application onto a different runtime version than the one it was expecting and cause it to fail.

Because of these problems we strongly recomend against using any single-instance-per-process runtime or library (such as the .NET Framework, java, or msxml) in an in-process shell extension.

Interesting scientific study about font usage on web pages.

Jeff Atwood posted a cool article from Wichita State about font legibility. Serif mono-spaced fonts were the worst (sorry Courier) and Tahoma did the best.

The study is worth reading, the testing methodology was objective and at pretty much validates what fonts you think should be used for a given type of web site. The other good tip in Jeff’s post was that Software Usability Research Laboratory (SURL) at Wichita State has an excellent newsletter that documents their usability studies.

Client vs Developer

Client vs Developer wars.
This is stuff isn’t directly applicable to our development patterns, but it has some useful information.

“Grayscreen” prototyping (building a simple HTML model of a website) provides an extremely effective way of communicating a website’s content, structure, and functionality before design and programming begin. Prototyping overcomes many other difficulties commonly associated with web development, such as managing expectations, communicating effectively, working through the design process, and creating and delivering content.

It’s another example of how design up front methods save time and money.

Good article plus a free book in PDF format.

Grimmy weighs in on blogs

It’s subtle, but I like it. If I was ever to write a blog posting tool, the icon for posting the entry would look like the first panel in that strip. If you like that strip, you can access at the archives at Grimmy.com.

That pesky SQL Server Express. I’m going to have to support it, it’s time to start collecting tips from the veterans….

These problems left me stranded for days, then today, on another machine, I hit a different set of problems I kept getting the following “Failed to generate user instance of SQL Server due to a failure in starting the process for the user instance. The connection will be closed.” and if I set “User Instance” to false the following “An attempt to attach an auto-named database for file C:\[app_path]\ASPNetDB.mdf failed. A database with the same name exists, or specified file cannot be opened, or it is located on UNC share.”

..

If you don’t want to follow the link, the short answer is that SQLExpress creates a directory per user in “c:\Documents and Settings\[user]\Local Settings\Application Data\Microsoft\Microsoft SQL Server Data\SQLEXPRESS” that it uses to store information. Deleting this directory has fixed both of my problems.
[from Enjoy Every Sandwich]