Visual Studio pré build event delete reference - visual-studio

I'm going to spare you the trouble of explaining why I want to do this, but I'm looking for a way to remove a reference to a dll when a project is build. I'm not talking about an unused reference, but a reference that might contain the same namespaces and the same classes which my project is using. I was thinking of a pré build event command line, but I don't know what the command will look like.
PS: For those of you who do care why I want this. I have a template project A that contains classes that use base classes defined in another project B. This template project (A) its only function is to be packed up in a Nuget package to then be deployed in multiple other projects, for simplicity sake imagine 3 projects C, D and E. Using the Nuget in projects C, D & E will generate all the classes and put a reference to the dll of project B, because we need the Base classes. At the moment I also get a reference to the DLL of template project (A). This is what should not happen because all classes with the same namespaces will exist in project A and in projects C, D & E. This is why I want to automatically remove the reference to the template project (A).
Thanks in advance.
Kind regards,
Yannick

Visual Studio pré build event delete reference
Do you want to delete the reference project A in the build event command line when you build the project? If yes, I am afraid there is no directly build event command line to do this, you can create a power shell script to delete the reference, then execute this power shell script in the build event.
However, just as imp said "Why do you need a reference to the Package A, if it's not going to be used at all?". So as a workaround, you can not add reference project A to the project C, D and E, To accomplish this, you can target the dll files to the tools folder instead of lib folder in the .nupsec file:
<files>
<file src="bin\Debug\ProjectA.dll" target="Tools\ProjectA.dll" />
</files>
The .nuspec of Project A should be:
<?xml version="1.0"?>
<package >
<metadata>
<id>MyModels</id>
<version>1.0.0</version>
<authors>Tester</authors>
<owners>Tester</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Package description</description>
<releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
<copyright>Copyright 2018</copyright>
<tags>Tag1 Tag2</tags>
</metadata>
<files>
<file src="bin\Debug\ProjectB.dll" target="lib\Net45\ProjectB.dll" />
<file src="bin\Debug\ProjectA.dll" target="Tools\ProjectA.dll" />
</files>
</package>
Then pack this .nuspec file, generate the nuget package, install this package to the project, the reference Project A will not be added to the project.
Hope this helps.

Related

Cannot copy folder with nuget package in .net core

I Create a NuGet package and install into another project. but don't copy a file into the location project. only my file reference to NuGet package and I change the code, The package also changes! I want to copy the package to the target project.
<?xml version="1.0"?>
<package>
<metadata minClientVersion="3.3.0">
<id>MyPackage</id>
<version>1.0.0</version>
<authors>Meysam</authors>
<owners>Meysam</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Package description</description>
<releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
<copyright>Copyright 2018</copyright>
<tags>Tag1 Tag2</tags>
<contentFiles>
<files include="cs/*.*/**" buildAction="Compile" />
</contentFiles>
</metadata>
<files>
<file src="ConsoleApp1\CustomClass\CustomClass.cs" target="contentFiles\cs\any\CustomClass" />
</files>
</package>
Copying files into the project that uses a nuget package is only supported when using packages.config, which isn't supported by SDK-style projects, which are required for .NET Core projects. As your screenshots show, contentFiles in PackageReferences projects are included at build time. The little arrow icon in the bottom right corner of the C# and folder icons you pointed to in your screenshot are visual indicators that the file and folder are different to the other files and folders in your project. In fact, that little icon overlay is similar to what Windows adds for shortcuts, so if you understand a shortcut is a file that "points to" another file, it should make sense that these are shortcuts to files outside your project, but are included as part of your project.
Anyway, it's working as designed.
You'll need to find another way to do whatever you want, but you didn't describe why you're trying to include a file in the project that references your package, so I can't give direct advice. My best advice, if you are experienced with ASP.NET and ASP.NET Core is think about how ASP.NET used to read a lot of settings directly from web.config, but ASP.NET Core instead uses a builder pattern, so that users are not forced to store settings in web.config and can store settings anywhere they want. If what you're doing is similar, your package users will have a better experience if you provide them with a configuration builder that they can override, rather than having a file in their project that they must edit and gets overwritten every time they upgrade to a new version of your package.
Cannot copy folder with nuget package in .net core
Yes, just like zivkan said:
Copying files into the project that uses a nuget package is only
supported when using packages.config
But, we could use a workaround to resolve this issue. We could add a copy task in the xx.targets file, and set this file in the \build folder in the .nuspec file.
The content of mypackage.targets file:
<Target Name="CopyFile" AfterTargets="AfterBuild">
<ItemGroup>
<CopyFiles Include="$(NuGetPackageRoot)\mypackage\4.0.0\cs\*.*\**" />
</ItemGroup>
<Copy
SourceFiles="#(CopyFiles)"
DestinationFolder="$(ProjectDir)"
/>
</Target>
And the .nuspec file:
<file src="xxx\xxx\mypackage.targets" target="build" />
Hope this helps.

Unable to step into Nuget package

I have a common project that I build and create a nuget package from, for consumption in my other applications.
The build process for the common project both creates a nuget package, deploys it to our private nuget repo and pushes the symbols to our internal symbol server.
In my "other applications", in this specific case an ASP.NET website, I pull in the nuget package from our repo but when I try to step into code in that assembly it just skips over it. I cleared my local symbol cache and as soon as I start debugging VS pulls in all the symbols from the symbol server so I know that bit is working.
Can anyone help me?
You need to publish Nuget package with symbols and refer to them using the Symbols under Tools->Options->Debugging->Symbols.
See HOW TO DEBUG A .NET CORE NUGET PACKAGE?
Other members also asked the similar issue before:
How to debug code in a nuget package created by me
Update:
Since you want to step into code in the assembly, you still need to provide the source code file in the NuGet package alongside the dll.
As we know:
A symbol is a file containing metadata that represent the link between
your original source code and the machine code that has been
translated by a compiler.
In the Microsoft world, a symbol is represented by a .PDB (Program DataBase) file. It is the heart of the debugging process because thanks to these metadata, the debugging tools are able to correlate the instructions executing in the application to the original source code and providing features like breakpoint or variable watchers.
So if you only provide the dll and .pdb file, you still not step into the code, you also need provide the source code, then add the source code to the Debug Source Files for the solution that references the package:
More detail on providing the source code:
If you're currently packaging without a Nuspec, you'll need to create a Nuspec, then add the pdb to the list of files in the lib folder and source file in the src folder. "NuGet spec" may be a useful command for generating the initial spec as defined in NuGet docs. Below is my .nuspec file, you can check it:
<?xml version="1.0"?>
<package >
<metadata>
<id>MyTestPackage</id>
<version>1.0.3</version>
<authors>Admin</authors>
<owners>Admin</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Package description</description>
<releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
<copyright>Copyright 2017</copyright>
<tags>Tag1 Tag2</tags>
</metadata>
<files>
<file src="bin\Debug\MyTestPackage.dll" target="lib\Net46" />
<file src="bin\Debug\MyTestPackage.pdb" target="lib\Net46" />
<file src="Class1.cs" target="src" />
</files>
</package>
More detail on add the source code to the Debug Source Files:
When you have a solution open, right click on Solution, select Properties...Common Properties...Debug Source Files, and add the root source directory for the relevant binary reference:

Is there a way to add an 'Import' to a project in a VS extension?

I want to add a new <Import> to a project when I detect that a particular type of file has been added to the project. (the <Import> adds a task to the build process that takes the file and performs work during a build).
(Detection of a file having been added to the project is done using IVsSolutionEvents.HandleItemAdded).
I currently have code that uses Microsoft.Build.Evaluation.Project to add an Import element to the project. However this is an edit to a project file on disk. If I use this code to add an Import after detecting the addition of a new item to the project I create a conflict between a change on disk (the new Import) and an in-memory change (the addition of the new file). The user is then presented with a dialog where they must choose which change to throw away.
My question is this:
Is there a way to add a new <Import> to a project via the visual studio extensibility API in such a way that the modification to the project would be "in-memory", avoiding a conflict between the addition of the new project item, and the addition of the Import?
For existing project types, I've found the easiest way is leveraging NuGet. You can define a NuGet package which contains the .targets file in a special build/ folder, and NuGet will automatically add the <Import> when it is added to a project within Visual Studio. It will also update the references if you upgrade the package in the future. A full example is the packaging of the Antlr4BuildTasks package, which currently uses the following .nuspec file to create the package. The key here is the section following the <!-- Build Configuration --> comment.
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata minClientVersion="2.7">
<id>Antlr4</id>
<version>0.0.0</version>
<authors>Sam Harwell, Terence Parr</authors>
<owners>Sam Harwell</owners>
<description>The C# target of the ANTLR 4 parser generator for Visual Studio 2010+ projects. This package supports projects targeting .NET 2.0 or newer, and built using Visual Studio 2010 or newer.</description>
<language>en-us</language>
<projectUrl>https://github.com/sharwell/antlr4cs</projectUrl>
<licenseUrl>https://raw.github.com/sharwell/antlr4cs/master/LICENSE.txt</licenseUrl>
<iconUrl>https://raw.github.com/antlr/website-antlr4/master/images/icons/antlr.png</iconUrl>
<copyright>Copyright © Sam Harwell 2014</copyright>
<releaseNotes>https://github.com/sharwell/antlr4cs/releases/v$version$</releaseNotes>
<requireLicenseAcceptance>true</requireLicenseAcceptance>
<developmentDependency>true</developmentDependency>
<tags>antlr antlr4 parsing</tags>
<title>ANTLR 4</title>
<summary>The C# target of the ANTLR 4 parser generator for Visual Studio 2010+ projects.</summary>
<dependencies>
<dependency id="Antlr4.Runtime" version="$version$" />
</dependencies>
</metadata>
<files>
<!-- Tools -->
<file src="..\tool\target\antlr4-csharp-$CSharpToolVersion$-complete.jar" target="tools"/>
<!-- Build Configuration -->
<file src="..\runtime\CSharp\Antlr4BuildTasks\bin\net40\$Configuration$\Antlr4.net40.props" target="build\Antlr4.props"/>
<file src="..\runtime\CSharp\Antlr4BuildTasks\bin\net40\$Configuration$\Antlr4.net40.targets" target="build\Antlr4.targets"/>
<file src="..\runtime\CSharp\Antlr4BuildTasks\bin\net40\$Configuration$\Antlr4BuildTasks.net40.dll" target="build"/>
</files>
</package>

Is it possible to get NuGet.exe running disconnected from Visual Studio?

I've been wrestling with NuGet for a few days now and I'm turning to StackOverflow in frustration - hopefully someone here can be kind enough to point me in the right direction.
I've used NuGet several times for simple one-man pet projects, but this is the first time I've used it for something I really care about and want to have fully continuous builds, etc. I'm trying to create a simple NAnt build script to get the source for Git, ensure the external dependencies have been brought down, compile, and run tests - vanilla CI.
I originally went down the path of trying to get solution restore working, but it just didn't work or I didn't how it worked. Visual Studio is not on the build server and will not be installed there - that is not an option. As an aside, I couldn't get solution restore to work just with two developers (one trying to bring down the source fresh and build cleanly). I'm assuming it's because "allow solution restore" must be turned on everywhere (and is not by default). I punted on that approach before I got to the bottom of it - frankly, having my package manager so tightly coupled to the IDE makes me uncomfortable and was hoping I could do it another way. The package managers I'm used to using are simple command line tools - the CI build script invokes it on build, and developers do it on demand. I've spent the last two hours trying to get this working with the last 30 minutes in the NuGet source code. I feel like I'm fighting the tool and need to reboot.
Does anyone have any examples of the best to use NuGet in a multi-developer + CI scenario? This is what I want:
Any and all developers can get the source and run the tests in 3 or
less clicks (preferably 1). If the binaries are not present locally, that will be JIT fetched. If they are there, they will be updated if necessary, etc. This would ideally not even require NuGet to be installed (i.e. NuGet.exe would need to be in my repo).
Do #1 via a CI server like Jenkins, TeamCity, etc. (preferably using the same script)
If its not overly fighting the tool, I would like to have all this disconnected from Visual Studio with a single packages.config file and all binaries dumped into a single Lib folder in the root of the repo.
Any pointers would be very much appreciated.
Below, how I think you can achieve each your requisites:
You need to "Enable NuGet Package Restore" in your solution: http://docs.nuget.org/docs/workflows/using-nuget-without-committing-packages
As #alexander-doroshenko mentioned for TeamCity you can use Nuget Installer: http://confluence.jetbrains.com/display/TCD7/NuGet+Installer, but if you want a script to run in Jenkins, try this (works at TC too, as a command line step) for each project:
nuget.exe install "[Project folder]/packages.config" -source "" -solutionDir "" -OutputDirectory "packages"
This requisite will be done by item 1 and 2.
TeamCity has a build step for that, called "NuGet Installer", it fetch required packages from .sln file and download the locally. It does not require Visual Studio to run.
Read more about it here: http://confluence.jetbrains.com/display/TCD7/NuGet+Installer
There are several different solutions for integrating NuGet into your build process depending on how much integration you require. In our case we wanted to use NuGet as package manager and allow developers to build their solutions even if they haven't got NuGet installed on their machine. For that to work we enabled package restore which adds the NuGet binaries to your solution folder and updates the project files. Note that NuGet doesn't always do the update of the project files correctly. In our case we found that some project files got updated but others didn't. To verify that the project was updated you will need to open the project file as XML file. To achieve this load the solution and right click the project in question and select unload project. Then right click the project again and select edit [PROJECT_NAME]. In the project file you should see
A RestorePackages property in the first propertygroup. This property should have the value true
An import statement at the very end of the project file. This import statement should point to the 'NuGet.targets file that accompanies the NuGet binary.
Below is an example of one of our project files (heavily edited)
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<SolutionDir Condition="'$(SolutionDir)' == '' or '$(SolutionDir)' == '*undefined*'">$(MSBuildProjectDirectory)\..</SolutionDir>
<ProjectGuid>{8B467882-7574-41B2-B3A8-2F34DA84BE82}</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>MyCompany.MyNamespace</RootNamespace>
<AssemblyName>MyCompany.MyNamespace</AssemblyName>
<!-- Allow NuGet to restore the packages if they are missing -->
<RestorePackages>true</RestorePackages>
</PropertyGroup>
<Import Project="$(SolutionDir)\BaseConfiguration.targets" />
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="MyClass.cs" />
<!--
.... MANY MORE FILES HERE
-->
</ItemGroup>
<!-- Import the Nuget.targets file which integrates NuGet in the build process -->
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
The next step you'll need to take is to provide a solution level NuGet configuration file in which you'll indicate where the packages need to be 'installed' and what the URL of the package repository is. In our case the solution directory structure looks like:
(D) root
(D) build
(D) packages
(D) source
(D) .nuget
NuGet.config
NuGet.exe
NuGet.targets
(D) MyCoolProject
MyCoolProject.csproj
MyCoolProject.sln
(D) templates
NuGet.Config
Where (D) indicates a directory.
The NuGet.config file contains the following configuration settings.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageRestore>
<add key="enabled" value="True" />
</packageRestore>
<config>
<add key="repositorypath" value="packages" />
</config>
<packageSources>
<add key="OurPackageServer" value="PACKAGE_SERVER_ADDRESS" />
</packageSources>
<activePackageSource>
<add key="All" value="(Aggregate source)" />
</activePackageSource>
</configuration>
This configuration file indicates that package restore is enabled, that the repository path (where the packages are placed) is the packages directory and which package sources are active.
By placing a NuGet.config file in the root directory we can use the hierarchical configuration option with NuGet. This allows the individual solutions to override computer specific configurations. The other benefit is that this way we don't need to have NuGet installed on the build server (because the executable and the configurations are in the repository).
With this setup developers can build the solution from Visual Studio. The build should work fine on developers machines even if they don't have NuGet installed. Note however that they won't be able to add packages to a project without having NuGet installed in visual studio.
On the build server you can simply use MsBuild to build the solution which will automatically download the packages from your package repository. Visual Studio is not required to be installed on the build machine for that (just the .NET framework of your choice).

MSBuild: changing project references to file binary references

I have a few .net / C# projects that I'm building with MSBuild.
In the project I'm building, there are some project references to other C# projects.
I'm only building individual projects, so I'd like to repoint the project references to actual binaries in a folder during the build.
I'm already setting "BuildProjectReferences" to False for my MSBuild step.
So essentially I want to have MSBuild ignore the project refs and look for those binaries in a new directory.
Is this possible to do? Is this possible without having to dynamically modify the project file prior to build?
** Update 1 **
More info might help...I'm actually building each binary via Ant/AntDotNet/MSBuild and uploading to Artifactory. I'm basically using Ivy's dependency management with .Net binaries.
Right now I have the uploads and downloads of dependencies working fine.
The only part I'm missing is getting MSBuild to look for the binaries as file dependencies instead of the project references that it has in the project file.
** Update 2 **
It looks like MSBuild supports editing the csproj file using XMLPoke and XMLPeek.
So in my case I'd need to change the following in my project file:
<ProjectReference Include="..\MyReferencedProject\MyReferencedProject.csproj">
<Project>{MyReferencedProjectGUID}</Project>
<Name>MyReferencedProject</Name>
<Private>False</Private>
</ProjectReference>
to this
<Reference Include="MyReferencedProject">
</Reference>
Can anyone give me any pointers on that?
Answer on Update2:
Your question is related/duplicate to this question. There is no easy way to convert it. You should write MSBuild custom task for it to update MSBuild project files before build.
I ended up using Ant combined with the xmltask addon.
<target name="convert" description="convert project references to file references">
<echo>Converting the following Project references :: ${Project.ItemGroup.ProjectReference.Name}</echo>
<xmltask source="MyParentProject.csproj" dest="MyParentProject.csproj">
<rename path="/:Project/:ItemGroup/:ProjectReference/:Name" to="BinaryName"/>
</xmltask>
<replace file="MyParentProject.csproj" token="<BinaryName>" value="<Reference Include=""/>
<replace file="MyParentProject.csproj" token="</BinaryName>" value=""></Reference>"/>
<xmltask source="MyParentProject.csproj" dest="MyParentProject.csproj">
<copy path="/:Project/:ItemGroup/:ProjectReference/:Reference" buffer="refbuffer" append="true"/>
<paste path="/:Project/:ItemGroup[1]" buffer="refbuffer"/>
<remove path="/:Project/:ItemGroup/:ProjectReference" />
</xmltask>
<echo>Conversion complete.</echo>
</target>
In the first xmltask we are setting the "Name" element to "BinaryName" so we can find it.
Next we have two Ant Replace tasks that change something like
"<BinaryName>MyReferencedProject</BinaryName>"
to
"<Reference Include="MyReferencedProject"></Reference>"
And in the last xmltask moves our project references we converted into file references into the upper ItemGroup that normally has the file references.
Then finally we delete the ProjectReferences section.

Resources