VS 2010 Setup Project: Error updating dependencies

April 28, 2011

I successfully created my Web Setup Project, but a couple of days later the setup project stopped compiling and raised errors instead:

ERROR: Unable to update the dependencies of the project. The dependencies for the object ‘MyAssembly.DLL’ cannot be determined.

Clicking the Refresh Dependencies command in the context menu of the setup project’s Dependencies raised the error

The operation could not be completed.

These errors occur in VS 2010, and seem to be around for several years now (connect, connect, connect).

Workaround

From the workarounds section of this Connect entry, this solution worked for me:

1. Open .VDPROJ file (in a text editor)
2. Find the "Hierarchy" section.
   Delete everything so the section looks like this:

    "Hierarchy"
    {
        
    }

3. Find the "File" section.
   Delete everything so the section looks like this:

        "File"
        {
            
        }

4. Reload the project
5. Rebuild the project.

I removed the whole sections “Hierarchy” and “File”, which also worked.

However, the whole procedure seems cumbersome considering you may have more than one setup project in a solution, and probably more than one solution you are developing or maintaining.

Fix

The error still seems to be present in VS 2010 SP 1. Fortunately, MS in the meantime provides the hotfix KB2286556 which solved the problem for now.


Pitfalls installing Web Setup .msi on IIS 7

April 26, 2011

I created a Web Setup project in Visual Studio 2010 for a .Net 4 web application to install on a Windows 2008 Server running IIS 7. The prerequisite knowledge is described in my previous posts.

Upon starting the .msi file (or the accompanying setup.exe), I received the error message

“The installer was interrupted before Application could be installed. You need to restart the installer to try again.

Click “Close” to exit.”

This Social MSDN entry brought the first step to the solution: activate logging using the command line

msiexec /i <path to msi file> /l*vx C:\SomeDirectory\SomeFilename.log

I needed to register the .Net 4 framework in IIS using the commands

cd C:\Windows\Microsoft.NET\Framework\v4.0.30319
aspnet_regiis.exe -i
aspnet_regiis.exe -ga MyDomain\MyUserName

After registering the framework version, the next error showed in these lines in the log file:

INFO   : [SetTARGETSITE]: Custom Action is starting...
INFO   : [SetTARGETSITE]: CoInitializeEx - COM initialization Apartment Threaded...
ERROR  : [SetTARGETSITE]: FAILED: -2147221164
ERROR  : [SetTARGETSITE]: Custom Action failed with code: '340'
INFO   : [SetTARGETSITE]: Custom Action completed with return code: '340'

The cause for these errors was that the IIS 6 Management Compatibility feature was not installed on the server.

Installation of this feature is easy: go to Control Panel\Programs and Features\”Turn Windows features on or off” and check the IIS 6 Management Compatibility checkbox. (on Server 2008, this can be done in the Server Manager, under Roles, Webserver (IIS)).

Visual Studio requires IIS 6 Management Compatibility to be installed on the developer machine:

To enable Visual Studio to create and use local IIS Web sites, you must enable metabase compatibility. This lets Visual Studio interact with the IIS metabase and with the IIS 7.0 configuration store.

I also found a similar statement in the IIS forum:

Visual Studio 2010 web setup project still only targets older IIS versions. This is why the compatibility features are required.

So how can a developer detect if the IIS 6 Compatibility feature is installed?

The registry path HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\InetStp contains the IIS version in the keys MajorVersion and MinorVersion.

This page contains the list of IIS components that can be detected under the registry path HKEY_LOCAL_MACHINE\Software\Microsoft\InetStp\Components. (see also SO, CodeProject), and the relevant keys seem to be Metabase and ADSICompatibility (both 1 of the compatibility feature is installed).

This page on Metabase compatibility explains the architecture of this feature:

It supports the Admin Base Objects (ABO) interface, also known as IMSAdminBase, as well as the ADSI and WMI providers that were built on top of ABO in IIS 6.0.

This component is not installed by default because IIS 7.0 itself is not using it.

My understanding is that the DirectoryEntry class which queries ADSI can only work if ABO is installed. ABO itself is a COM library, so the required classes and interfaces must be stored in the registry.

The file Iadmw.h of the IIS SDK contains the definition

DEFINE_GUID(IID_IMSAdminBase_W, 0x70b51430, 0xb6ca, 0x11d0, 0xb9, 0xb9, 0x0, 0xa0, 0xc9, 0x22, 0xe7, 0x50);

and indeed, the key HKEY_CLASSES_ROOT\Interface\{70B51430-B6CA-11D0-B9B9-00A0C922E750} has the default value IADMCOM if the Metabase compatibility is installed.


Installing additional Virtual Directories in a Web Setup Project

April 21, 2011

A Visual Studio Web Setup Project (or Deployment Project) lets you define the contents of a Web Application Folder by adding Content Files and Primary Output of a Web project in the File System view.

Additionally, using the menu command Add Special Folder/Web Custom Folder, one can add more web directories to the setup project, which will end up in the file system under c:\inetpub\wwwroot and will define a separate IIS application for each folder.

In one of my projects I needed to add additional Virtual Directories located at web root and pointing to subdirectories of the web app located in the Web Application Folder. (some URLs generated by the app were root-based, and will be cleaned up, so please don’t ask)

This can accomplished by creating an installer class derived from System.Configuration.Install.Installer, and using one of the many APIs available to administrate IIS (MSDN on IIS 6, MSDN on IIS 7). The project containing the installer class must be added to the setup project’s File System view.

I chose to use the MSDN sample to create Virtual Directories using System.DirectoryServices.DirectoryEntry as described in my previous post. The installer class is called by the web installer using the Custom Actions mechanism.

The find the physical location of the installed directories, you can either derive the path information from Assembly.GetExecutingAssembly().FullName or by passing the installation directory as a parameter to the Custom Action.

  • Custom Actions
  • Install
  • Primary output from MyWebInstaller
  • CustomActionData /targetdir=[TARGETDIR]

You can name the parameter as you like, but the [TARGETDIR] is a pre-defined web installer property.

The parameter is accessed via the Context.Parameters collection in the installer:

var targetdir = Context.Parameters["targetdir"];

This value is used to create the virtual directory in web root:

const string WebRoot = "IIS://127.0.0.1/W3SVC/1/Root";
CreateVDir(WebRoot, "MyRootDir", targetdir.Replace(@"\\", @"\") + "MyDir");

Notes:

  • This post has a complete walk-through on web setup projects and custom actions.

Exploring IIS with PowerShell

April 19, 2011

I need to write a Web Installer with a bit more complex logic than the standard setup provides, and came across pages like Creating Sites and Virtual Directories Using System.DirectoryServices that deal with .Net classes I have never seen before. (Note: while the page deals with IIS 6, the classes also work on IIS 7 if the IIS 6 Management Compatibility feature is installed)

Trying to figure out what System.DirectoryServices can accomplish, I chose PowerShell to poke around in IIS.

PowerShell needs to be run as administrator, otherwise you will get an “access denied” error (unless you provide login information in the DirectoryEntry constructor)

First, we load the DirectoryServices.dll:

> [system.reflection.assembly]::loadwithpartialname(
    "System.DirectoryServices.dll")

Next, we can retrieve the IIS service entry using a DirectoryEntry

> $service = new-object system.directoryservices.directoryentry(
    "IIS://127.0.0.1/W3SVC")
> $service.SchemaClassName
IIsWebService

See this chart for the IIS Admin Object Hierarchy.

The children of the IIsWebService are

> $service.Children | select-object  SchemaClassName, Path, AppRoot
SchemaClassName       Path                                    AppRoot
---------------       ----                                    -------
IIsFilters            IIS://127.0.0.1/W3SVC/FILTERS
IIsApplicationPools   IIS://127.0.0.1/W3SVC/APPPOOLS
IIsWebInfo            IIS://127.0.0.1/W3SVC/INFO
IIsWebServer          IIS://127.0.0.1/W3SVC/1                 {}

Let’s get the web server root

> $root = new-object system.directoryservices.directoryentry(
    "IIS://127.0.0.1/W3SVC/1/Root")
> $root.Children | select-object  SchemaClassName, Path, AppRoot

SchemaClassName   Path                                    AppRoot
---------------   ----                                    -------
IIsWebVirtualDir  {D:\MyVirtDir}                          {}
IIsWebDirectory   IIS://127.0.0.1/W3SVC/1/Root/MyWebApp   {/LM/W3SVC/1/ROOT/MyWebApp}

An IIsWebDirectory has a defined AppRoot property, whereas an IIsWebVirtualDir has a file system directory as Path, but no AppRoot.

You can instantiate a DirectoryEntry for both IIsWebDirectory and IIsWebVirtualDir using the value of the ADsPath property:

> $root.Children | select-object  SchemaClassName,  ADsPath, Path
SchemaClassName   ADsPath                                  Path
---------------   -------                                  ----
IIsWebVirtualDir  IIS://127.0.0.1/W3SVC/1/Root/MyVirtDir   {D:\MyVirtDir}
IIsWebDirectory   IIS://127.0.0.1/W3SVC/1/Root/MyWebApp    IIS://127.0.0.1/W3SVC/1/Root/MyWebApp

Add VS Solution Dependency Visualizer to Visual Studio Tools Menu

April 18, 2011

After installing VS Solution Dependency Visualizer, open Visual Studio and navigate to Tools, External Tools. This opens the External Tools dialog.

Click the Add button, and enter

Title VS Solution Dependency Visualizer
Command C:\Program Files\devio IT Services\VS Solution Dependency Visualizer\vsslndepvis.exe
Arguments $(SolutionDir)$(SolutionFileName)

Press OK.

The Tools menu will now show a command VS Solution Dependency Visualizer which opens the program with the current solution.

The latest release (version 0.50) of VS Solution Dependency Viewer is available for download here.


cmd.net: tee, xslt

April 18, 2011

The tee command of the cmd.net collection is a .Net implementation of the tee command available on other platforms.

As usual, the -in and -out switches define the encodings of stdin and stdout.

The filename parameter is given directly (without a leading switch), and the file’s encoding can be defined using the -enc switch.

The -a switch appends to an existing file instead of creating a new file.

The xslt command is a translation of the PowerShell xslt script I posted some time ago.

The xml file is provided on stdin, and the xslt file is defined via the -xslt switch (along with -xsltenc for the encoding).

Again, the -in and -out switches define the encodings of stdin and stdout.

The current version of cmd.net is available for download here.


Series: ASP.Net User Control Libraries

April 15, 2011

How to create User Control Libraries in Visual Studio and why this is a bad idea.

Creating ASP.Net User Control Libraries in Visual Studio 2010

getting started

Migrating ASP.Net User Controls to a DLL in Visual Studio 2010

migrating existing code

Handling tilde (~) paths in ASCX correctly using ParseControl

an issue and a fix

Wiring Events of ASCX Controls after ParseControl

another issue fixed

ASP.Net UserControl Life Cycle in DesignMode

an insight


cmd.net: df, enc, guid

April 15, 2011

The df command of the cmd.net collection lists all available drives and their total space, used and free space in GB.

Drive Total  Used  Free Used% FS     Label
C:\      97    57    39   59% NTFS
D:\     833   443   389   53% NTFS
E:\       0     0     0     %

(e: being a removable disk drive in this case)

The guid command writes a new GUID to stdout

D:\projects\cmdnet\net40>guid
d9999ffd-659d-4f56-a38e-698005ed3a9b

The enc command converts an encoded stdin to a different encoding on stdout using the -in [encoding] and -out [encoding] command-line switches.

enc -in [CP number or encoding name]
    -out [CP number or encoding name]
    < [input filename]
    > [output filename]
some-batch-command
    | enc -out [CP number or encoding name]
    > [output filename]

The current version of cmd.net is available for download here.


cmd.net: datetime

April 14, 2011

The datetime command of the cmd.net collection outputs the current date and time.

Using the -f (format) switch to select a .Net date format string (standard, custom), you can adjust the output format:

D:\projects\cmdnet\net40>datetime
14.04.2011 16:11

D:\projects\cmdnet\net40>datetime -f D
Donnerstag, 14. April 2011

D:\projects\cmdnet\net40>datetime -f T
16:15:24

D:\projects\cmdnet\net40>datetime -f o
2011-04-14T16:15:02.9943652+02:00

D:\projects\cmdnet\net40>datetime -f u
2011-04-14 16:15:15Z

Use the -utc switch to retrieve the UTC timestamp:

D:\projects\cmdnet\net40>datetime -f o -utc
2011-04-14T14:16:13.3573897Z

The -ci switch selects a CultureInfo to display the date in a different language:

D:\projects\cmdnet\net40>datetime -ci fr -f D
jeudi 14 avril 2011

D:\projects\cmdnet\net40>datetime -ci fr-fr -f D
jeudi 14 avril 2011

(I noticed that the language-only culture info only works in .Net 4)

If you want to display the date string in a language that is not supported in the DOS code page, you need to first switch the code page using the chcp command:

D:\projects\cmdnet\net40>chcp
Aktive Codepage: 850.

D:\projects\cmdnet\net40>netenv
input code page: 850
input Windows code page: 1252
input encoding: Western European (DOS)
output code page: 850
output Windows code page: 1252
output encoding: Western European (DOS)
culture: de-AT
LCID: 3079
culture display name: German (Austria)

D:\projects\cmdnet\net40>chcp 1251
Aktive Codepage: 1251.

D:\projects\cmdnet\net40>datetime -ci ru -f D
14 апреля 2011 г.

D:\projects\cmdnet\net40>chcp 850
Aktive Codepage: 850.

The current version of cmd.net is available for download here.


The Unicode Video

April 14, 2011

I just came across this video on YouTube showing every displayable (with some restrictions) character in the Unicode BMP. (1 character per frame)

Next, the Unicode code point of the day with Wikipedia links to corresponding alphabet or language, which of course reminds me of the series Every character has a story.

Update 11/04/18:

BabelStone comments on the video and hosts a page called Unicode 6.0 Slide Show implemented in JavaScript. Warning: Since the browser displays the Unicode characters, you need to have the required fonts installed on your machine.


Follow

Get every new post delivered to your Inbox.