Background
For the past few months we have been working on a strategy to enable a NuGet-y style of dependency lifecycle management for a large-scale enterprise. This entails establishing a system to take care of 7000+ developers distributed geographically all across the planet working across time zones. The environment is heavily regulated with a special interest in compliance with various security, compliance, auditing policies that are in effect across the organization globally and there various regional variations as they might be in different countries/cities etc. Usually in organizations such as this there are various automated software distribution mechanisms (such as System Center) that are employed to distributed software to workstations, servers etc. Further in such organisations there are often very strict controls on the level of access someone has on their work PC.
Problems
As we realized to our peril rather quickly we ran into two main problems which were a direct result of how software is installed when distributed via automated mechanisms and the level of permissions that NuGet needs before it can be installed.
Admin Access
NuGet requires elevated admin level privileges for the logged in user in order to be successfully installed on a given machine. As discussed above in a lot of big organisations such access is heavily regulated and not often granted freely. This elevated access requirement wasn’t always there for NuGet. This link here explains the background and history behind requiring admin rights for NuGet.
Automated Install
The organisation in question uses an automated deployment solution for software that installs a given installer file silently as an elevated user but in “system context”. As it turns out NuGet (or more correctly vsix files) do not like being installed via system context. To see this in action try the following
In the below text please replace {command here} placeholder by cmd. For some reason WordPress engine breaks if I write cmd inline there!
- Get SysInternal tools PSEXEC)
- On a command prompt (run as administrator) and Execute
- A new Command window will open up and execute
psexec.exe -i -s {command here}
- cd C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE
- VSIXInstaller.exe /q NuGet.Tools.vsix
You would notice something like this And the error log would look something like this
Workaround
There are a few options that we evaluated in this situation which included granting admin rights for the developer for a limited period of time and let him/her install via usual VSIX. Following are the two approaches that we ultimately experimented with and then decided on one of them.
VSIX is OPC, Nuke it up!
Basically VSIX is an Open Package Container formatted container file. Which means it is essentially a zipped up file. You can rename it to .zip and unzip using any of your favorite file archiving utilities to peek into the internals of a vsix file. The idea was then simple
- Nuke a VSIX by unzipping it
- Take the remnants and move into a folder in the user profile area from where Visual Studio 2010 can load it up
- If this approach works create an installer that simply copies the files into this folder and use the established tools in the firm that can automate the running of an installer on client desktops and server workstations.
This approach actually worked. We were able to unzip the vsix and move it into a folder in the Program Files area (the same one where nuget vsix actually installs itself into) and Visual Studio 2010 was perfectly happy to load it up as a bona fide extension within VS2010. Job done!
Or so we thought. Until we hit the VS 2012 problem. Yes you guessed right. VS 2012 does not like us doing this. It wags a firm virtual finger at us and tells us off.
Bad developers. Hacking in? No no!
The actual specifics of this problem would make this post rather long winded and boring so I am going to skip these. But suffice it to say that VS 2012 seem to do things differently when it comes to loading extensions via .vsix files. In particular it did not load us the extension properly in different test environments when the vsix was manually unzipped into a folder where it would normally expect.
So then onwards with our final approach which was…..(drum rolls at this point)
Nuke up the VSIX, change the manifest, zip it back!
The approach was to identify what causes NuGet vsix to demand administrative priveleges and be installed in Program Files area when majority of the other extensions are content with installation on a per user profile basis. Searching for some thoughts online I came across this thread which provided the right background on this entire discussion.
Once we knew the reasons behind the admin rights demand for NuGet it was easy to ascertain that the reason as given by the creators of the package is not really valid in our case since within the controlled confines of this organisation all software is centrally distributed and managed and hence we could add a layer of customisations into the MVC installer to “not” install NuGet when it is used internally. With that ironed out here is the basic overview of the steps involved in this idea
- Nuke up the VSIX and examine the remnants of the war torn files.
- Find the manifest file that controls how this VSIX will behave and be used by VS
- Change the “AllUsers” flag to False in the manifest
- Bundle all the original files and this changed manifest into a new vsix file
- Use this new vsix file as the base NuGet installer!
I have highlighted the important bit in the above workflow. It is this AllUsers setting that tells installer engine to elevate the install process and make it a system install as opposed to a user install.
We made these changes and tested within our test environments. It was now possible to install NuGet for only the logged in user without needing elevated rights. Both VS 2010 and 2012’s all editions were content with loading up our modified VSIX as an extension.
Happy days!