TFS Build Error

Sep 13, 2011 at 8:45 PM

A little new to NuGet and certainly Nugetter.  I am trying with the NuGetterStandardBuildTemplate.xaml and version 1.2.  I get an error during the build:  

TF215097: An error occurred while initializing a build for build definition \Components\SPP.Encryption: The invocation of the constructor on type 'TfsBuild.NuGetter.Activities.PerformNuGetPack' that matches the specified binding constraints threw an exception.

I have NuGet.exe File Path as "$/TFS Custom Activities/NuGet/NuGet.exe" and most of the other settings are like your Simple Project from the documentation.

I can provide more information but unfortunately this is all I get from TFS.  Thanks in advance for your patience.  Do I need NuGet somehow on the TFS server other than command line checked into TFS path above?  NuGetter Assembly is also checked into TFS folder and pointed to in build controller per documentation.  Can't figure out if there is an obvious step I am missing in all of this.

Sep 14, 2011 at 3:28 PM

The following makes me think I have things installed and configured correctly.  If I use the NuGetterStandardBuildTemplate.xaml but remove the line that calls PerformNuGetPack then the build succeeds (but obviously skips that step).  It makes me wonder if there is an issue with one of the parameters so I guess I will start with trial and error unless someone has a better idea of what to try.

Sep 14, 2011 at 6:54 PM

More info.  Can't really debug into the PerformNuGetPack() since it does not seem to get that far before error occurs.  I did change the PerformNuGetPack() call to a SummarizeProperties (changed to pass correct parameters) just to see how that worked and the build succeeded displaying the properties.  I then went back to the PerformNuGetPack() call without passing any parameters and same TF215097 error as first post.  On SummarizeProperties() if I left off a parameter it told me which parameter was left off rather than the crappy generic TF215097 from above.

Sep 14, 2011 at 7:36 PM

Next step - found this link which talked about maybe a reference was missing - http://msmvps.com/blogs/rfennell/archive/2011/01/06/tf215097-error-when-using-a-custom-build-activity.aspx

I ran Reflector and saw System.Management.Automation.dll.  I didn't think this was it but added it to my TFS custom assembly directory just to see if anything changed.  I got farther (an actual run time error trying to create the package.  I have no idea why System.Management.Automation.dll would not be either installed on the TFS server (or maybe permissions?).  What a TERRIBLE message coming back from TFS to tell me I was missing a DLL.

Sep 14, 2011 at 7:46 PM

So my latest error is "Search pattern '$id$*.nupkg' did not find any files at: \\tfs-server\vstfs\builds\Encryption\Encryption_20110914.10\NuGetPackage".  The NuGetPackage directory is empty so I was wondering what should be in here.  The DLL built ended up in another directory at the same level named "Encryption" - the same thing as my solution and the DLL.  Should I change the OutputDirectory or some other parameter within the build process to build to that directory?

Coordinator
Sep 14, 2011 at 11:10 PM

dbock,

Interesting trail of events you've been having.  Thanks for passing on all of the information.

Answer to your first question: No, you don't need NuGet.exe "installed" in TFS more than once and by installed I just mean that it exists in a source control folder and you pass that path in the build definition.  You probably know this but, you don't have to put it in TFS if it is on your build machine.

The reason why System.Management.Automation.dll was not available may be due to the OS on your build machine and what was installed on it.  The assembly is used to allow the calling of PowerShell from .NET.  It is installed on my build machine in the GAC.  I don't have much more info on its origins at this point.

And, that brings us to the NuGetPackage folder.  I came up with that name as a convention, there's nothing special about it at all.  Its purpose is just to be a destination for the packaging step.  If you have a simple project then your assemblies end up in single folder in the "drop" location.  The nuspec file says here's how I want the package and NuGet.exe packages things up and puts the nupkg file where you tell it to.  This is what the NuGetPackage folder (aka, the Output Directory) is meant for.  If NuGet gets all the info it needs and you tell it to put the output in that folder then that's where they will end up.  Likewise, I created the "prepackage" folder, this is where you can organize more complex (multi-framework) projects into a single folder that is the input to NuGet.  And, again, the output would be the NuGetPackage folder (if you follow my convention).

A simple way to look at it is this: In the build definition, the "Base Path" is the source location for the NuGet.exe processing and the "Output Directory" is where NuGet puts the newly generated package.  I used NuGetPrePackage and NuGetPackage as the names of these folders.  I tried to keep the context of the NuGet.exe (parameter names, process, etc.) as close as I could to the command-line calls.

All of this extra "stuff" like the PowerShell script and the prepackage folder is there if you need it - especially when things get more complicated than a single assembly.  Over the years I have tried to create builds that were not done until the output of the build process looked almost identical to what it would look like when it was installed on a production machine.  Then, the packaging process (in this case NuGet but could also be an msi) did not have to do anything special to generate the package.  I just said, here's the files, go package it up.

In your case, the Base Path should be set to the name of the folder where your assembly was created, then NuGet does its thing and outputs into NuGetPackage.

That's a big brain dump.  Let me know how things are going and if you need more help.

MarkNic

Sep 15, 2011 at 4:34 PM

Next issue is the following error that occurs if I don't clear out the build directory the 2nd time around:

CallNuGetPackageCommandLine arguments: pack "C:\Builds\3\Components\Encryption\Sources\Encryption.nuspec" -OutputDirectory "\\tfs-server\vstfs\builds\Encryption\Encryption_20110915.3\Encryption" -BasePath "\\tfs-server\vstfs\builds\Encryption\Encryption_20110915.3\NuGetPrePackage" -version 1.0.0.0

Error reported in the NuGet Process:  Unhandled Exception: System.UnauthorizedAccessException: Access to the path 'C:\Builds\3\Components\Encryption\NuGetExe\NuGet.exe.old' is denied.    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)    at System.IO.File.Delete(String path)    at Bootstrapper.Program.Move(String oldPath, String newPath)    at Bootstrapper.Program.Main(String[] args) 

Is there some option I am missing to clear out directory or to make NuGet.exe.old not read-only?

Coordinator
Sep 15, 2011 at 6:08 PM
Edited Sep 15, 2011 at 7:46 PM

That error is coming from NuGet itself.  Here’s what’s happening.

 

The NuGet.exe file that you download from CodePlex really isn’t the NuGet.exe application (initially). The first time you run it, that NuGet.exe will look online for the most up to date version. After it finds it, it will download that version and then execute - in the process NuGet.exe.old gets created. If there is a NuGet.exe.old in the way and read-only, then NuGet will throw an exception like the one you posted.  This is easy to reproduce and test locally.

So, here’s how you stop that error: Go to a command-line window and the folder that contains the fresh version of NuGet.exe. Run it once by just typing NuGet and hit enter. You will see messages about the bootstrapper starting, then finding the latest version and then downloading. When it’s done, verify by running it again. You should just see “Available commands:” blah, blah. Check THAT version into source control.  

Now, the error you provided should not appear - even if you have a NuGet.exe.old in the same folder. (I verified this) 

MarkNic

Sep 15, 2011 at 8:17 PM

Great information - Thanks.

Sep 15, 2011 at 9:25 PM

Still working on my simple single assembly case and it seems the build process is ignoring the fact that I want my output directory to be "lib\" to satisfy the NuGet requirement that my assembly be in a "lib" subdirectory within the package.  When I build the Release locally it ends up in my "lib" directory so not sure why it doesn't on the build server.

The reason I want it under "lib" is so when I add a package to a solution it is automatically added as a reference in addition to being installed.  Also, NuGet Package Explorer is reporting "Assembly outside lib folder" when I analyze it.

It could be that this is not a TFS NuGetter issue at all but with mine being a very simple case it seems like you have probably solved this.  Do i need to resort to Powershell for this very simple case or am I missing something I can do within the build configuration?

Thank you for your patience

Coordinator
Sep 15, 2011 at 10:23 PM
Edited Sep 15, 2011 at 10:28 PM

You definitely don't need PowerShell on simple projects.  You just need to configure your nuspec file to look for the assembly (source) and put it where you want it (target).  All of this is in the "files" section.

Here is where you can find it in the NuGet documentation:  http://docs.nuget.org/docs/reference/nuspec-reference

Scroll down about a third of the way down the page.

Here's an example that will take all assemblies found in the "Base Path" and put them in the "lib" folder within the package.  You just have to enter the name of the folder that your assemblies are in, into the "Base Path" property of the build definition. 

<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
  <metadata>
    <id>MyCoolPackage</id>
    <version>1.0.0.0</version>
    <authors>MarkNic</authors>
    <owners>MarkNic</owners>
    <licenseUrl>http://www.marknic.net/license</licenseUrl>
    <projectUrl>http://www.marknic.net/projectinfo</projectUrl>
    <iconUrl>http://www.marknic.net/media/icon.png</iconUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>My package description</description>
  </metadata>
  <files>
    <file src="*.dll" target="lib" />
  </files>
</package>


        
    
Jan 19, 2012 at 10:53 PM

Hi, hope you don't mind my bumping this old thread, I just wanted to suggest making mention of the <file src="*.dll" target="lib" /> part of the rpsec in the NuGetter documentation (for the simple case example).

I'm new to nuget, nuspec files and nugetter, and so using the target attribute was not obvious to me either, and I only discovered it when I stumbled on this discussion.

It is available in the nuspec reference, true, but making explicit mention of it in the nugetter doco might save newcomers like me a lot of time.

Cheers, and keep up the good work on nugetter!

Jun 13, 2012 at 11:07 PM
marknic wrote:

That error is coming from NuGet itself.  Here’s what’s happening.

 

The NuGet.exe file that you download from CodePlex really isn’t the NuGet.exe application (initially). The first time you run it, that NuGet.exe will look online for the most up to date version. After it finds it, it will download that version and then execute - in the process NuGet.exe.old gets created. If there is a NuGet.exe.old in the way and read-only, then NuGet will throw an exception like the one you posted.  This is easy to reproduce and test locally.

So, here’s how you stop that error: Go to a command-line window and the folder that contains the fresh version of NuGet.exe. Run it once by just typing NuGet and hit enter. You will see messages about the bootstrapper starting, then finding the latest version and then downloading. When it’s done, verify by running it again. You should just see “Available commands:” blah, blah. Check THAT version into source control.  

Now, the error you provided should not appear - even if you have a NuGet.exe.old in the same folder. (I verified this) 

MarkNic


I ran into that same issue - what's happening is when you get the nuget.exe out of a TFS path, it's marked read-only. Once you reset the flag, it works fine. May be part of the workflow to reset the read-only flag on the exe when you get it from TFS in the first step.