Troubleshooting pkgdef Files

Troubleshooting pkgdef Files

  • Comments 6

For those using the Visual Studio 2010 SDK to create extensions for Visual Studio, you should find the creation and use of .pkgdef files to be mostly automatic (see What's a PkgDef and Why?). However, like anything involving computers and software, there are occasions that require manual intervention because they aren’t covered by the automatic settings or things can go wrong. This article illustrates some possible issues with .pkgdef files and provides techniques for discovering what’s wrong and correcting them.

Please note that these techniques apply not only to the Visual Studio 2010 IDE, but also to applications built using the Visual Studio 2010 Shell (Isolated) (or Integrated). All of the examples assume the case of VS 2010 running on 32-bit Windows 7. For other cases, substitute the appropriate file locations and names and registry root key.

What Could Go Wrong?

First of all, how do you know if something goes wrong? A problem with a .pkgdef file usually manifests itself in one of two ways:

  1. All or part of a Visual Studio extension, such as a VS Package, simply fails to load or an error message is displayed about needing to reinstall Visual Studio.
  2. Your Visual Studio extension tries to retrieve a registry value it expected to be included in the install and does not find it. The result can be anything from using an appropriate default to displaying a message about an exception.

Either of these symptoms can be caused by one or more of the issues listed below. The list is by no means intended to be exhaustive.

Issue: Per-user Extension Is Not Enabled

Pkgdef files that are installed as part of a user extension deployed using the new VSIX format are copied to a sub-folder of %LocalAppData%\Microsoft\VisualStudio\10.0\Extensions. The pkgdef loader does not automatically search for pkgdef files here. Rather, it loads pkgdef files for user extensions that have been enabled, which the Extension Manager and the stand-alone VSIX installer both do automatically. If you choose to unpack a VSIX file yourself, or otherwise do a manual xcopy-style deployment, it’s easy to forget the step that enables the extension. This is easily fixed.

Remedy: Use the Extension Manager to enable per-user extensions

It’s entirely possible that if you manually deployed the contents of a VSIX file, you simply need to enable it in the Extension Manager dialog and restart Visual Studio before the pkgdef loader will pick it up.

Remedy: Enable per-user extensions when running as administrator

On a related note, there is an option to disable loading of all per-user extensions when running ‘as administrator’ (elevated), regardless of being enabled or not. This is controlled under Tools-Options-Extension Manager as Load per user extensions when running as administrator. Make sure this checkbox is checked (when appropriate).

Issue: pkgdef File Is Not Found

For all other extensions (those that are not per user), the pkgdef loader searches the locations listed in the PkgDefSearchPath of the master pkgdef file. The value of PkgDefSearchPath has three elements:

  1. $RootFolder$\Common7\IDE\Extensions
  2. $RootFolder$\Common7\IDE\CommonExtensions
  3. $RootFolder$\Common7\IDE\devenv.admin.pkgdef

$RootFolder$ is the location where Visual Studio is installed (C:\Program Files\Microsoft Visual Studio 10.0). The first two search elements are folders, which are recursively scanned looking for pkgdef files. The third element is a specific pkgdef file (which does not typically exist, but is kept in the list as a placeholder for system administrators).

An easy mistake to make is to drop a pkgdef file into either $RootFolder$ or $RootFolder$\Common7\IDE or some other sub-folder and expect the pkgdef loader to just find it. However, these locations are not in the search path.

Remedy: Use /log to discover which pkgdef files are loaded

You can find out exactly which pkgdef files the loader is finding, using the /log command line option for Visual Studio. Among the items the pkgdef loader logs are the full expanded value for the PkgDefSearchPath, a list of all of the pkgdef files found on the search path, and a list of the pkgdef files found for enabled extensions.

Trick
Since the pkgdef loader will not rebuild the cache if it does not think it is out of date, there is a bit of a trick to using /log to debug pkgdef load issues when you are not sure which files it is finding (and thus which ones to touch). Use Notepad to create a file called “log.pkgdef” that contains a single comment line (“// comment”) and copy it to C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\Extensions. This ensures that the pkgdef loader has a new file to process. If you need to run /log more than once with this file in place, be sure that it gets saved with a new timestamp before each run.

Run: devenv.exe /log

When Visual Studio is finished loading (status bar reads “Ready”), File - Exit, start Windows Explorer, browse to C:\Users\User\AppData\Roaming\Microsoft\VisualStudio\10.0, and open the file ActivityLog.xml. It should open in Internet Explorer using the associated XSL to format it in an table.

Near the top of the file, Visual Studio will list the PkgDefSearchPath:

LogPkgDefSearchPath

This is followed by the number of files found and then the list of those files, for example:

LogFileScanLoad

Armed with the knowledge of which folders are being scanned and which pkgdef files were discovered, you should now be able to make sure your pkgdef file is deployed to an appropriate location.

Remedy: Install System-wide extensions under the PkgDefSearchPath

Any extension that is not installed per-user should be installed in a sub-folder of $RootFolder$\Common7\IDE\Extensions or $RootFolder$\Common7\IDE\CommonExtensions.

Issue: Invalid Syntax

This issue is most likely to crop up if you run into a situation where you must create or edit a pkgdef file manually. Like any language, it’s easy to forget a closing quote or insert an extra one.

The syntax of a pkgdef file is actually quite simple. Each line can be one of:

  • comment – starts with a semi-colon (‘;’') or double-slash (‘//’)
  • registry key – starts with a square bracket (‘[‘) and ends with a square bracket (‘]’) that defines a section of values
  • registry value – starts with a name in double quotes or the at sign (‘@’ not in quotes) for a ‘default’ value of a key, followed by an equals sign, and then a string or numeric value

Common syntax mistakes include:

  • Not enclosing a registry value name in double quotes:
    incorrect: name=”value”
    correct: “name”=”value”
  • Enclosing the symbol for the default value of a registry key in double quotes:
    incorrect: “@”=”value”
    correct: @=”value”
  • Omitting an opening or closing double quote for a name or string value
  • Adding comments at the end of a line defining a key or value. Comments must be on their own line.

The pkgdef loader is not very tolerant of syntax errors and will simply refuse to load a pkgdef file that contains even a single error, rather than risk corruption of the pkgdef cache. When it does reject a pkgdef, this information is written to the activity log.

Remedy: Use /log to discover pkgdef file syntax errors

Use /log to generate ActivityLog.xml. Any syntax errors will be highlighted in red, along with a warning showing the name of the offending file (which is not loaded).

LogSyntaxErr

In this example, the value of “foo” is missing the closing quote expected for strings and the value of bar is given as word, rather than dword or qword. The name for “bax” is not put in quotes. Once you edit the file to make these corrections (and save it and deploy it to the correct location), the pkgdef loader will see that the file has been updated and rebuild the cache automatically (you do not have to force this rebuild by deleting the registry value from the cache again).

Remedy: Use the PkgDef Editor extension for Visual Studio

Another way to find and fix syntax errors is to download and install the new editor extension we’ve created to give syntax coloring and error output for pkgdef files. It can be found in the Visual Studio gallery, either through the Extension Manager or directly in the gallery. Just search for “pkgdef” under the Tools category and download the PkgDef Editor extension.

EditSyntaxErr

In this example, the same errors as above are flagged, along with the pop-up message describing the problem with the value of “foo”.

Issue: Unrecognized Substitution String

pkgdef files are made portable by tokenizing system-specific and user-specific information. These are known as substitution strings. Examples are $RootKey$, which defines the root of the Visual Studio configuration registry, the starting point for all key values, and $PackageFolder$, which is the full path in the file system to the location from where the current pkgdef file is being loaded.

Substitution strings are case-sensitive and must be enclosed between two dollar-signs (‘$’). Common mistakes related to tokens are:

  • Omitting the closing dollar-sign" on a substitution string name:
    incorrect: [$RootKey\subkey]
    correct: [$RootKey$\subkey]
  • Using incorrect case or spelling:
    incorrect: “pathtomyfile”=”$packagefolder$\myfile.dll” or “$pkgfolder$\myfile.dll”
    correct: “pathtomyfile”=”$PackageFolder$\myfile.dll”

When the pkgdef loader cannot recognize a substitution string, it simply does nothing and uses it ‘as is’. When this happens in a registry key or value name, it means the key or value will not be put in the correct location or get the correct name.

Remedy: Search the registry

This can be very difficult to debug, except by knowing what to look for. When this happens for a string value, it is a little easier to detect, simply by looking in the registry using regedit.exe:

RegToken

In this example, the value for “bax” was specified with “$PkgFolder$”, rather than “$PackageFolder$”.

Remedy: Use PkgDef Language Integration for Visual Studio

As seen above, the PkgDef Editor extension can make it much easier to see problems with pkgdef files. In particular, it knows the valid tokens for string substitution and can flag the ones it does not recognized:

EditTokenErr

In this example, all of the string substitution tokens (anything starting and ending with the dollar-sign) are highlighted (in blue) and the unrecognized tokens are flagged as errors. One string contains a value that was intended to be a string substitution, but is missing the closing dollar-sign, so it is not highlighted. Also in this example, it is easy to see that $RegRoot$ is not a recognized string substitution, but using regedit it was simply missing-in-action.

Issue: Invalid Registry Key

The pkgdef loader will not write to arbitrary registry locations. It only writes registry entries within the configuration hive of Visual Studio (or an Visual Studio Shell (Isolated) application). This rule is easily followed by starting all key/section names with $RootKey$.

Remedy: Use /log to discover invalid registry keys

The pkgdef loader will log attempts to write to locations outside of the application’s configuration hive:

LogSection

In this example, using the file from the previous example, $RegRoot$ was not recognized as a substitution string, so it did not get replaced with the appropriate root key for the application. And the result is not a valid location for a registry key for the application.

Issue: Registry Value Collisions

Sometimes the same registry value is being set by more than one pkgdef file. In other cases, a registry value is being set, but it’s not clear which pkgdef file is doing it. You can either scan all of the pkgdef files and discover where the value is being set. Or use /log again.

Remedy: Use /log to discover which pkgdef(s) set a value

To discover all pkgdef files that are setting a value, use a simple trick: explicitly set that same value by temporarily changing the master pkgdef (C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\devenv.pkgdef) to explicitly set the value before all of the other pkgdef files are processed. This will require Administrator rights to edit the file, but is otherwise straightforward. Make a backup copy of devenv.pkgdef, then bring it up in an editor. Below the [$Initialization$] section, add a new section for the parent key of the value. Then add the key value below it, save it, and run devenv.exe with /log. The pkgdef loader will log all of the additional writes to that value, along with the path to the offending pkgdef.

LogCollision

In this example, we caught the blog.pkgdef file writing to the value “foo” under “$RootKey$\MyExtension”. The next step is to determine why and whether this needs to change (be sure to put devenv.pkgdef back the way you found when you’re done).

Summary

This post has described several tactics for troubleshooting pkgdef issues. The most basic of these is to use /log, along with a trick for forcing PkgDef Management to rebuild the pkgdef cache. You may also find that the PkgDef Editor extension is helpful when editing pkgdef files.

BillWeinberger Bill Weinberger: Developer, Visual Studio Platform

Bill has been with the VS Platform team for about two years, and has more than a few previous years of software industry experience working on IDEs and vertical applications. For Visual Studio 2010, he was a key contributor to PkgDef Management.

Leave a Comment
  • Please add 6 and 4 and type the answer here:
  • Post
  • Bill:

    Am upgrading from Visual Studio 2008 to Visual Studio 2010 Professional.

    What causes log warning:

     Current pkgdef cache timestap not valid

    With the log warning:

      PkgDef encountered data collision in section 'HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0_Config\ShellFileAssociations\.dbproj' for value ''

    Drive C does not persist across reboots - need to copy/restore

    the appropriate files. Am already copying and restoring visualstudio.reg, vscommon.reg,

    and .vssettings files.

    This is part of a college lab upgrade - been doing it since VC98.

    We make a few changes to visualstudio.reg that cannot be made thru

    the IDE (default directories and 2 paths in vsmacros that do not use

    %userprofile%).

    I suspect the more are more files to copy/restore.

    Thanks

    Rich Connelly (rconnell@providence.edu)

    Providence College

  • $ProgramFiles$ is supposed to point to %ProgramFiles% as per MSDN documentation. But on my 64 bit machine, $ProgramFiles$ points to %ProgramFiles(x86)%. What is the substitution string i need to use to make it point to %ProgramFiles%?

  • @Shyam On 64-bit systems, 32-bit processes (like Visual Studio's devenv.exe) run under in WOW64 emulation mode. This sets the environment variable %ProgramFiles% to %ProgramFiles(x86)% when the process starts. Given this, what you're asking for is not possible with pkgdef. See this MSDN topic for more detail on WOW64: msdn.microsoft.com/.../aa384274(v=VS.85).aspx

  • In 2012, the behavior seems to be slightly changed.

    For common extensions (installed in the Common7\IDE\Extensions folder), it seems necessary to 'touch' (change last write time) the file named "extensions.configurationchanged" to trigger the pkfdef parsing, otherwise nothing shows up in the log.

    Another 'touch' after removing the pkgdef file unregisters the extension.

    I searched a couple of hours before discovering that! :)

  • @James Dingle: You don't need to manually touch the cache files or the registry values with the cache timestamps.

    Instead, in VS2012 run "devenv.exe /updateconfiguration" after making a configuration change (e.g. modifying or deleting pkgdef files) to force devenv to re-scan the pkgdef files on next restart.

  • Could I see an example of the entry in the devenv.pkgdef so I can do this with my errors? BTW Im using VS2012

Page 1 of 1 (6 items)