I know Since the release of msbuild 15 (vs 2017) that NuGet is now fully integrated into MSBuild.
I have a nuspec file with defining variables of package properties like:
<metadata>
<id>$id$</id>
<version>$version$</version>
<authors>$authors$</authors>
...
</metadata>
The nuspec file is located in the same folder of the project.
When using nuget tool to create the package , it works fine.
nuget pack
When using msbuild v15, it raise an exception.
run the command:
msbuild -version
Microsoft (R) Build Engine version 15.8.168+ga8fba1ebd7 for .NET Framework
15.8.168.64424
msbuild /t:pack /p:configuration=release /p:NuspecFile=mylib.nuspec
raise exception:
C:\Program Files\dotnet\sdk\2.1.402\Sdks\NuGet.Build.Tasks.Pack\build\NuGet.Build.Tasks.Pack.targets(199,5): error : Value cannot be null or an empty string.
The strange is that dotnet sdk version 2.1.402 raises the exception.
I tried msbuild installed with vs2017 with its path and also it raises the same exception.
When i substitute the variables with its values, msbuild is working fine.
The question
Is this a bug in msbuild version 15.8.168.64424 or i missed something ?
In other words, Can msbuild support using the metadata variables of the package?.
As has been mentioned in the comments, you no longer need a Nuspec file as most aspects can be controlled via properties in the csproj file or additional metadata on items (e.g. if you need additional content).
If you do need a nuspec file for some reason, you need to provide the variables for substitution yourself. You can do this in a target inside the csproj file like this:
<Target Name="SetNuspecProperties" BeforeTargets="GenerateNuspec">
<PropertyGroup>
<NuspecProperties>$(NuspecProperties);id=$(AssemblyName)</NuspecProperties>
<NuspecProperties>$(NuspecProperties);config=$(Configuration)</NuspecProperties>
<NuspecProperties>$(NuspecProperties);version=$(PackageVersion)</NuspecProperties>
<NuspecProperties>$(NuspecProperties);description=$(Description)</NuspecProperties>
<NuspecProperties>$(NuspecProperties);authors=$(Authors)</NuspecProperties>
</PropertyGroup>
</Target>
Related
On Ubuntu I'd like to wrap a few C# DLL files into a NuGet package. On Windows one would use the NuGet package explorer or nuget.exe + manually edited *.csproj.nuspec. In summary when manually editing the *.nuspec file one may add DLLs via the <files> section:
<files>
<file src="some\Path\YourDll.dll" target="lib"></file>
</files>
On Ubuntu I'd like to use dotnet pack instead. However it seems like it's not able to operate on a *.csproj.nuspec file:
Usage: dotnet pack [options] <PROJECT | SOLUTION>
Arguments:
<PROJECT | SOLUTION> The project or solution file to operate on. If a file is not specified, the command will search the current directory for one.
Options:
-h, --help Show command line help.
-o, --output <OUTPUT_DIR> The output directory to place built packages in.
--no-build Do not build the project before packing. Implies --no-restore.
--include-symbols Include packages with symbols in addition to regular packages in output directory.
--include-source Include PDBs and source files. Source files go into the 'src' folder in the resulting nuget package.
-c, --configuration <CONFIGURATION> The configuration to use for building the package. The default for most projects is 'Debug'.
--version-suffix <VERSION_SUFFIX> Set the value of the $(VersionSuffix) property to use when building the project.
-s, --serviceable Set the serviceable flag in the package. See https://aka.ms/nupkgservicing for more information.
--nologo Do not display the startup banner or the copyright message.
--interactive Allows the command to stop and wait for user input or action (for example to complete authentication).
--no-restore Do not restore the project before building.
-v, --verbosity <LEVEL> Set the MSBuild verbosity level. Allowed values are q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic].
--runtime <RUNTIME_IDENTIFIER> The target runtime to restore packages for.
--no-dependencies Do not restore project-to-project references and only restore the specified project.
--force Force all dependencies to be resolved even if the last restore was successful.
This is equivalent to deleting project.assets.json.
Can I wrap C# DLLs into a NuGet package on Ubuntu using the dotnet CLI? Or do I have to use the nuget CLI (apt-get install nuget) instead with the approach like on Windows?
I would add this into the .csproj file:
<ItemGroup>
<Content Include="some.dll" PackageCopyToOutput="true">
<pack>true</pack>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
It's not pretty but it works.
I installed nuget package - Selenium.WebDriver.ChromeDriver 2.46.0.. When I publish (through dotnet publish .Net CLI command) .csproject (target framework - netcore2.2) the chromedriver.exe is not being copying on output/publish folder.. Can you please someone assist me?
From the project owner github page:
"chromedriver(.exe)" isn't included in published files on default configuration. This behavior is by design.
If you want to include "chromedriver(.exe)" into published files, please define _PUBLISH_CHROMEDRIVER compilation symbol.
OR
Define PublishChromeDriver property with value to "true" in MSBuild file (.csproj, .vbproj, etc...) to publish the driver file.
<Project ...>
...
<PropertyGroup>
...
<PublishChromeDriver>true</PublishChromeDriver>
...
</PropertyGroup>
...
</Project>
Note: MSBuild property always override the condition of define _PUBLISH_CHROMEDRIVER compilation symbol
There is a known issue with System.Net.Http.
Visual Studio 2017 will take the System.Net.Http.dll from C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\Microsoft\Microsoft.NET.Build.Extensions\net461\lib and put it in the build output. On my machine, this is version 4.3.4 (file version 4.6.26011.1)
If you use a <PackageReference> or even a direct <Reference> to a different version of System.Net.Http.dll, Visual Studio 2017 will disregard your version in favor of its version when creating the build output (in the /bin folder).
This will lead to errors when you try to call the dll externally.
Main Question:
Is there any way to force msbuild/csproj to use the version I reference from NuGet?
Maybe, can I copy and overwrite the existing System.Net.Http.dll in a post-build action?
What I have tried:
I tried using a binding redirect, but that doesn't seem to affect the build output at all (see this comment).
There may be a better way to do this, but this works for me:
Find the correct version of System.Net.Http.dll and then place it
somewhere accessible to your project (like in a /libs folder under
your root project folder)
Using an msbuild/csproj post-build action, copy the correct version to the build output
.csproj snippet for step 2:
<Target Name="CopyFiles" AfterTargets="Build">
<Copy SourceFiles="libs\System.Net.Http.dll" DestinationFolder="$(OutputPath)" />
</Target>
Note:
Supposedly, this will be fixed in net472
We are using VS2013 and .Net 4.5.1(recently migrated, but this error is there from .Net 4.0) . This error occurs only when compiling the project in platform target x64. Is this really a error which will break in runtime? Why MSBUILD does not resolve this mrcorlib.dll properly ? This happens only in projects which were created in VS2010 and does not occur in newly created projects. What am I missing here. All my third party assemblies are in x64bit.
In TeamCity build server, I get following error:
GenerateSatelliteAssemblies
[17:01:18]AL
[17:01:18]C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools\AL.exe /culture:de /keyfile:..\..\MyApp.snk /out:obj\x64\Release\de\MyApp.Hardware.Softing.resources.dll /platform:x64 /template:obj\x64\Release\MyApp.Hardware.Softing.dll /embed:obj\x64\Release\MyApp.Hardware.Softing.Properties.Resources.de.resources
[17:01:18]ALINK warning AL1073: Referenced assembly 'mscorlib.dll' targets a different processor
Here is a workaround:
The issue can be avoided by using the AL.EXE that matches the platform (or bitness) you are attempting to build. That is, you'll see that when you are building x64, that it is trying to use AL.EXE at a path similar to
C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6 Tools
If you can get it to use the x64 version of AL.exe, the issue will go away. That is, use the AL.EXE at a path similar to:
C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6 Tools\x64
Msbuild finds this path by using its TargetFrameworkSDKToolsDirectory. Thus, using the assumption that this directory is the correct directory when building x86, the workaround below essentially appends the x64 sub directory on to the path when building x64 and leaves it as is otherwise:
Create an MsBuildAL1073WarningWorkaround.targets file (name doesn't matter) and add it to the project. It has the following contents:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<TargetFrameworkSDKToolsDirectory Condition=" '$(PlatformTarget)' == 'x64'">$(TargetFrameworkSDKToolsDirectory)$(PlatformTarget)\</TargetFrameworkSDKToolsDirectory>
</PropertyGroup>
</Project>
Edit the .csproj file to import this file near the end of the file (where you'll see the comment that says "To modify your build process...":
<Import Project="MsBuildAL1073WarningWorkaround.targets" />
<!-- To modify your build process... -->
These warnings are shown in the projects that contain localization satellite assemblies(.resx files) in the solution.
This is the bug from Microsoft side and as of Aug 2017, Microsoft still hasn't fixed it.
Here's the quote from the MS feedback page:
It is resulting from a logic bug in the .NET framework binary
alink.dll. But given the limited impact of this issue and the fact
that this tool has a very high bar for servicing we will not be making
a change to address this issue.
Regards,
Ed Maurer Development Lead, VB & C# Compilers
This warning can be safely ignored. Since .Net will load the correct 64bit assemblies on runtime in a 64bit machine. Still microsoft can give a solid answer to this issue. It was unnecessary time wasting warning.
We had the same issue and ended up with Matt Smith's workaround (https://stackoverflow.com/a/41945190/3506760) with one modification that made it work.
Due to feature/bug in MsBuild (https://stackoverflow.com/a/1367309/3506760) we needed to modify targets file described in step 1.
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="MsBuildAL1073WarningWorkaround" BeforeTargets="BeforeBuild" >
<PropertyGroup Condition="'$(Platform)' == 'x64'">
<TargetFrameworkSDKToolsDirectory>$(TargetFrameworkSDKToolsDirectory)$(Platform)\</TargetFrameworkSDKToolsDirectory>
</PropertyGroup>
</Target>
</Project>
While the bug referenced by #jero2rome is closed as Won't Fix, VS2015 RC w/ .NET 4.6 no longer emits this warning:
From VS2013/.NET 4.5.1, I would see the same issue:
GenerateSatelliteAssemblies:
C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools\AL.exe /culture:zh-CHT /out:obj\x64\Debug\zh-CHT\MyComponent.resources.dll /platform:x64 /template:obj\x64\Debug\MyComponent.dll /embed:obj\x64\Debug\MyComponent.Resources.string.zh-CHT.resources
ALINK : warning AL1073: Referenced assembly 'mscorlib.dll' targets a different processor [c:\svn\project\MyComponent.csproj]
With VS2015 RC/.NET 4.6, no warning is emitted:
GenerateSatelliteAssemblies:
C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6 Tools\x64\AL.exe /culture:zh-CHT /out:obj\x64\Debug\zh-CHT\MyComponent.resources.dll /platform:x64 /template:obj\x64\Debug\MyComponent.dll /embed:obj\x64\Debug\MyComponent.Resources.string.zh-CHT.resources
Just some addition to Matt's answer (I don't have enough reputation to add a comment): I believe
near the end of the file
is right after the line:
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
I have tested and if the above line precedes the (re)definition of $TargetFrameworkSDKToolsDirectory then AL1073 warning is gone. Otherwise it persists.
Here is my solution:
<PropertyGroup>
<CreateSatelliteAssembliesDependsOn>
FixWarningAL1073;
$(CreateSatelliteAssembliesDependsOn);
</CreateSatelliteAssembliesDependsOn>
</PropertyGroup>
<Target Name="FixWarningAL1073">
<PropertyGroup>
<TargetFrameworkSDKToolsDirectory Condition=" '$(PlatformTarget)' == 'x64'">$(TargetFrameworkSDKToolsDirectory)$(PlatformTarget)\</TargetFrameworkSDKToolsDirectory>
</PropertyGroup>
</Target>
Add these lines at the end of you .csproj.
In my case removing all attributes from Properties/AssemblyInfo.cs or deleting entire file fixes warning, but this may be not appropriate solution for most of libraries.
Net461, SDK-style project, <GenerateAssemblyInfo> is set to false.
To ignore that warning, you can install .Net Framework 4.5.2 developer pack for all OS_x86_x64, which is compatible with VS2013.
http://www.microsoft.com/en-us/download/details.aspx?id=42637
I have my local nuget library repository separately both for my personal and work releted class libraries.
I have created some of the nuget packages for the libraries which are no longer in development. I did this only for them because I do not know how to update them automatically as soon as my project builds.
I have figured that all the work is being done by nuget command line with Visual Studio Command Prompt. So I can easily do the work I needed (of course I would know commands perfectly and I do not !)
Basically I want the following tasks to execute on the post-build event of my project.
On project build:
copying project dll into a specific folder (lib folder of the nuget package)
updating nuspec file for new file version (my project is increasing the file version on every build)
creating new nupkg file with new file version
Phil Haack shows some of this feature but it is still a prototype as far as I can tell.
So my requirement is the above. Has anyone else accomplished this?
The selected solution looks like it would work but it seems like there is a simpler solution for your requirements.
You can create a nuspec file that will read data from the project's metadata. You only need to do this once with this command:
C:\<Path to project>\nuget spec
This creates 'tokens' in the spec file that will will be replaced by the project's metadata when you create the nuget package. This includes the file version. You will want to replace and because all projects are technically suppose to have them.
More details can be found here: http://docs.nuget.org/docs/creating-packages/Creating-and-Publishing-a-Package#From_a_project
Then...
For .Net Framework (old-school) projects, in you project's Post build events you can do this:
nuget pack "$(ProjectPath)"
xcopy "$(TargetDir)*.nupkg" "<path where you are hosting your local nuget repo>" /C /Y
(assuming nuget.exe is available on your system PATH).
For .Net Core and Standard projects, nuget can't pack them (see https://github.com/NuGet/Home/issues/4491). Instead, use this as your post-build step:
dotnet pack "$(ProjectPath)" --no-build --include-source --include-symbols --output "<path where you are hosting your local nuget repo>"
Of course you can adjust the options to meet your needs. See https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-pack?tabs=netcore2x for dotnet pack command options.
Just in case someone else (like me) come across this ancient question - in the current era (VS2017, SDK/NugetReference format/ .NET Core / .NET Standard / Multi-target projects), where creation of NuGet package is an option in the Project Properties - so, only issue of local repository has to be solved:
If you have single-target project, to copy your .nupkg file to local NuGet repository, add Post-build event (Project properties > Build Events > Post-build event command line):
xcopy $(TargetDir)*.nupkg [path to your local nuget repository] /s
Like:
xcopy $(TargetDir)*.nupkg G:\imbVelesOpenSource\LocalNuGet\imbVelesSecondGeneration\ /s
If you have multi-target project, to copy your .nupkg file to local NuGet repository:
add Post-build event (Project properties > Build Events > Post-build event command line):
xcopy $(TargetDir)..*.nupkg [path to your local nuget repository] /s
Like:
xcopy $(TargetDir)..*.nupkg G:\imbVelesOpenSource\LocalNuGet\imbVelesSecondGeneration\ /s
Update:
Forget post-build events, there is a cleaner way (xcopy approach works strange for multi-target projects), just add this in project XML:
<Target Name="CopyPackage" AfterTargets="Pack">
<Copy SourceFiles="$(OutputPath)$(PackageId).$(PackageVersion).nupkg" DestinationFolder="G:\imbVelesOpenSource\LocalNuGet\imbVelesSecondGeneration\" />
</Target>
Update
For newer NuGet versions, which cut off the last 0 (patch from a 0.0.0.0 version notation), you will need to regex the PackageVersion:
<Target Name="CopyPackage" AfterTargets="Pack">
<Copy SourceFiles="$(OutputPath)$(PackageId).$([System.Text.RegularExpressions.Regex]::Replace("$(PackageVersion)", "^(.+?)(\.0+)$", "$1")).nupkg" DestinationFolder="G:\imbVelesOpenSource\LocalNuGet\imbVelesSecondGeneration\" />
</Target>
Jeremy Skinner has written a blog post on how he performs automated builds of packages and uploads them to the NuGet Gallery. I think that it matches your requirements.
Basically he uses MsBuild to apply the version (with the MsBuild Community Extensions UpdateXml task) to the nuspec file and invoke the nuget.exe to package it up.
I recently published a solution for this that actually creates/updates the nuspec files during the build, so don't have to do so manually, then creates the nupkg files.
All you will have to add is a post-build event for copying the packages to their destination (or add it as an optional stage to my solution).
You can find an article with a walk-through guide here and the source code + binary here.
With the latest nuget package format using "PackageReference" tags you can use the following simple postbuild event in your csproj to update nuspec file with latest dependencies.
<Target Name="AfterBuild">
<WriteLinesToFile File="dependencies.xml" Overwrite="true" Lines=""/>
<WriteLinesToFile File="dependencies.xml" Overwrite="false" Lines="<dependencies>"/>
<WriteLinesToFile File="dependencies.xml" Overwrite="false" Lines="<dependency id="%(PackageReference.Identity)" version="%(PackageReference.Version)" />" />
<WriteLinesToFile File="dependencies.xml" Overwrite="false" Lines="</dependencies >"/>
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted -command "$xml = [xml] (Get-Content Project.nuspec); $xml.package.metadata.RemoveChild($xml.package.metadata.dependencies); $dependencies = [xml](Get-Content dependencies.xml); $xml.Package.Metadata.AppendChild($xml.ImportNode($dependencies.Dependencies, $true)); $xml.Save('Project.nuspec')""/>
<Delete Files="dependencies.xml" />
</Target>
Only premise for this is that you have a nuspec file with rest of the metadata mentioned in the project directory. Here is a sample nuspec file:
<?xml version="1.0"?>
<package>
<metadata>
<id>Package Id</id>
<version>1.0.0</version>
<authors>Author name</authors>
<owners>Owner name</owners>
<description>Description</description>
<contentFiles>
<files include="**/content.zip" buildAction="None" copyToOutput="true" flatten="false" />
</contentFiles>
<dependencies>
</dependencies>
</metadata>
<files>
<file src="bin\Release\Project.dll" target="lib\net462" />
<file src="bin\Release\Project.pdb" target="lib\net462" />
<file src="bin\Release\file.zip" target="Content" />
</files>
</package>
I solved it by using a command line
Let's assume you have added the location of NuGet to your path environment or copies a stable version to a given directory (this is what I did)
I have my NuGet.exe as well as my certificate in a folder named D:\Build, you may need to update this to fit your path.
Then let's assume you have a codesign certificate file named: "CodeSignCertificate.pfx"
with a password: pa$$w0rd
You can get a simple codesign certificate for 17 euro from Ascertia. they also have free trial certificates that are valid for 10 days. the link https://account.ascertia.com/onlineCA/default
then as a one liner I use :
for %f in (X:\Packages\*.nupkg) do D:\Build\nuget sign %f -CertificatePath D:\Build\CodeSignCertificate.pfx -Timestamper http://timestamp.digicert.com -CertificatePassword pa$$w0rd
This sign all my packages in my output directory
if you only want to sign the lastest the NuGet package as this might be the one you just compiled then you can use something like this.
set Path="X:\ASP-WAF\DLL"
for /f "tokens=*" %%a in ('dir /A:-D /B /O:-D /S %Path%') do set NEW=%%a&& goto:n
:n
sign %NEW% -CertificatePath D:\Build\CodeSignCertificate.pfx -Timestamper http://timestamp.digicert.com -CertificatePassword pa$$w0rd
it's not a one-line but you can put it in a bat file and call that in your post build.