I'm trying to import a targets file from a relative path. The targets file is containing version information. The goal is not to have to modify all the thousands of projects files that we have when we create a new branch and have a new assembly version. We need the assembly versions because 2 version of the system can be installed at the same time and we have dlls in the global assembly cache.
Here's what it looks like in the project file:
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\..\..\..\Versions.targets" />
...
<ItemGroup>
<Reference Include="MyDll, Version=$(VersionAssemblies), Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\..\..\..\..\..\..\..\..\Apps\$(CodeVersion)\DEVP\appl\BinApps\MyDll.dll</HintPath>
</Reference>
</ItemGroup>
...
</Project>
This is working fine if I'm working with a .vbproj. But the issue is that we have a lot of old .cobproj Cobol project files. For some reason, it seems like Visual Studio 2010 don't set the working directory when opening a cobproj, so it's unable to reach Versions.targets...
If I rename my cobproj to use vbproj as extension, it's working fine. So it's definitively something that Visual Studio is doing when a project of a known extension is opened, but I've searched a lot and I didn't find where I could add cobproj to tell Visual Studio that it's a known extension.
Another interesting fact, it that if I double click on my cobproj, it's working, because the working directory is already set to the directory in which the cobproj is... If I open Visual Studio and then do a File/Open and select my cobproj, then it's not working.
I'm wondering if someone may know how I could fix my issue without changing the extention of all my cobproj. I'd like a cleaner solution.
Thanks!
I've found a workaround, if I modify the Project Type Guid in the .sln, I can make Visual Studio act with my .cobproj like it would with a .vbproj, at least regarding the working directory setting.
From the .sln file:
Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "appsEXCI.Donnees.Containers.Cobol", "appsEXCI.Donnees.Containers.Cobol.cobproj", "{54E1DEC4-8919-40F6-B7BB-C936921B221F}"
EndProject
Related
I am aware there are multiple questions on this topic already, but they all seem outdated. To clarify, I am using the "new" VSIX manifest format, and trying to follow the official instructions here: https://learn.microsoft.com/en-us/nuget/visual-studio-extensibility/visual-studio-templates
I have one project template and a couple of item templates that go with it. They all depend on deploying a NuGet package that should come bundled locally with the VSIX. I have examined the resulting VSIX file and all the files seem to be in the right place:
The project template has the required XML for declaring which packages to install:
<WizardExtension>
<Assembly>NuGet.VisualStudio.Interop, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</Assembly>
<FullClassName>NuGet.VisualStudio.TemplateWizard</FullClassName>
</WizardExtension>
<WizardData>
<packages repository="extension" repositoryId="VsixID.etc.etc">
<package id="Rx-Linq" version="2.2.5" />
</packages>
</WizardData>
The repositoryID matches the ID attribute in the .vsixmanifest file.
There is an individual Asset entry for each package, with the form:
<Asset Type="Rx-Linq.2.2.5.nupkg" d:Source="File" Path="Packages\Rx-Linq.2.2.5.nupkg" d:VsixSubPath="Packages" />
I have removed all packages.config and all the package references from the .csproj file installed by the VSIX (and even from the VSIX project itself just for good measure).
I have inspected the output VSIX and there is indeed a Packages folder in the VSIX containing all the .nupkg files. This folder is indeed unpacked and copied into the Visual Studio Extensions folder.
Despite all this, when I create a new project with the template, VS displays an error message saying: Failed to restore package from C:\users\<pathtoextensions>\Packages.
The thing is, the .nupkg files are actually present in the exact folder that the error message refers to.
I have been searching this for days and I can't seem to find any reference to best practices that actually work. It seems like these VSIX manifests are geared towards the legacy packages.config way of doing things, and there are discussions about how to extend them to use PackageReference instead.
Can anyone give any advice at all at how we are supposed to proceed going forward? Are packages not supposed to be deployed with the VSIX anymore? Are we supposed to just fill in the project with PackageReference entries and just let the user resolve them manually?
I feel like I am missing something fundamental here and any insight would be extremely valuable.
Update: I have also opened an issue on the NuGet github repository, as this is clearly a problem with the PackageRestore feature when restoring packages stored in a VSIX installer. Everything else mentioned in this question is working as intended and expected, except the package restore.
How do you actually include NuGet packages in Visual Studio Project
Templates VSIX targeting Visual Studio 2019?
Actually, there is no way to specify in a VS project template project that nuget packages can be used both using packages.config and PackageReference. Only two project templates of nuget management types can be created separately.
I have an easy way and since you have some issues with PackageReference format, you can try this funtion:
PackageReference
1) add these reference node in projecttemplate.csporj file:
<ItemGroup>
<PackageReference Include="Rx-Linq">
<Version>2.2.5</Version>
</PackageReference>
</ItemGroup>
2) When you create a project by this project template, please check these two options and VS will automatically read xxx.csproj and then recover the corresponding nuget package based on the information in it during build process.
Note: also make sure that the nuget url is checked and can be access under Package Source.
packages.config
In additon, for packages.config, you can just create a file named packages.config and then add your nuget info into it:
1)
2) add these into projecttemplate.csproj file:
<ItemGroup>
<Content Include="packages.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Reference Include="Rx-Linq, Version=2.2.5, Culture=neutral, PublicKeyToken=eb42632606e9261f, processorArchitecture=MSIL">
<HintPath>..\packages\Rx-Linq.2.2.5\lib\net472\xxxxxxx.dll</HintPath>
</Reference>
</ItemGroup>
Note: if this nuget package has dependencies, you should also add them(above steps) into packages.config and xxxx.csproj file. This funcution is a little more complicated than yours but it works. So, I recommend that you use PackageReference format.
More info you can refer to this similar issue.
I'm using VS2019 Pro v16.3.5. I have installed the .Net Core 3.0 SDK.
I have an Azure Durable Functions C# project that makes use of Microsoft.Extensions.Logging.Abstractions v3.0.0.0
This assembly is contained within the shared framework Microsoft.AspNetCore.App. So, I've added a reference to this from my csproj file, as seen below:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<AzureFunctionsVersion>v3-preview</AzureFunctionsVersion>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
Trouble is VS seems to have difficulty resolving this. In Solution Explorer, for my project, I get a yellow triangle over Dependencies\Frameworks\Microsoft.AspNetCore.App:
I also get the following compilation error:
Could not load file or assembly
'Microsoft.Extensions.Logging.Abstractions, Version=3.0.0.0,
Culture=neutral, PublicKeyToken=adb9793829ddae60'. The system cannot
find the file specified.
I also had this issue after migrating to VS2019/netcore3.0
During migration I had to add a FrameworkReference to Microsoft.AspNetCore.App, just like Ruard pointed out.
In my case the solution was to :
close the solution
delete all bin/obj folder
(most important) delete the .vs folder.
Hope this will solve your problem as well.
I have a web app that generates some configuration files that I need to include into my VS-project. I know this can be done manually and also that there is a wildcard-solution (Auto include new files created outside Visual Studio) but I'm not really pleased with this.
I need the files to be included without having to reload the project, and also VS sometimes changes the wildcard configuration and reference the individual files.
I'm thinking that there might be some plugin etc that could to this? Something with a file system watcher that includes the files?
Or does anyone know how to prevent VS from changing the wildcard-config?
Edit: I think that the changed in the csproj are triggered when you ie add a new file to the project. Then VS removes the folder** and adds a direct reference to all the files included and to the new file.
Edit 2: Seems like this works until you remove a file from the solution explorer, that's when VS creates all these "hard" references to a file.
I came up with a solution that seems to work, that is importing an external project, in my YadaYada.Web.csproj:
<Import Project="..\CustomBuild.targets" />
And then in CustomBuild.targets
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Content Include="$(MSBuildProjectDirectory)\MyConfigurationFolder\**" />
</ItemGroup>
</Project>
This will included the files in my builds but not in the VS-ui which is probably fine for me.
Thanks!
Background: I have several solutions with roughly 300 C++ projects across them, most of them shared. We are using Visual Studio 2013 and have a build script that compiles all of the projects in the correct order, ensuring dependencies are resolved ahead of time. Our development/engineering team builds all of the code through the build script and then attempts to debug using Visual Studio 2013.
Issue: The "build then debug" process results in Visual Studio telling us that the Projects are out of date. This stems from the ProjectEvaluationFingerprint property (in Line 39 Microsoft.CppBuild.targets) including a $(SolutionDir) in the output file. The recommended fix from Microsoft suggests removing the $(SolutionDir) from the file. As our developers tends to transition back and forth between projects, I do not want to manually change this .targets file on every developer's machine (and remember to change it back when they leave the project). I would like to override the property in the .vcxproj by using a .targets file explicitly for this.
The property in Microsoft.CppBuild.targets looks like:
<!-- Global up-to-date check support -->
<PropertyGroup>
<ProjectEvaluationFingerprint>$(Configuration)|$(Platform)|$(SolutionDir)|$(ProjectEvaluationFingerprint)</ProjectEvaluationFingerprint>
</PropertyGroup>
Generally, I have been following Microsoft's How to: Use the Same Target in Multiple Project Files. I have created a .targets file (test.targets) that contains the following code (note the TEST text was to test evaluation of the property in both the build script and building the project in Visual Studio):
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectEvaluationFingerprint>$(Configuration)|$(Platform)|TEST|$(ProjectEvaluationFingerprint)</ProjectEvaluationFingerprint>
</PropertyGroup>
I then import it using the following line in the .vcxproj
<Import Project="..\..\Config\VSPropertySheets\test.targets" />
The project.lastbuildstate file now reads:
#TargetFrameworkVersion=v4.0:PlatformToolSet=v120_xp:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit
Debug|Win32|D:\views\devbranch\Products\SLN\|Debug|Win32|TEST|
It is appending the new ProjectEvaluationFingerprint to the existing one, so it is not overriding (I can understand this to a degree, but I'm no MSBuild expert).
Question: How can I override this one property using a .targets file? Do I need to use a replaceregexp task or do I have an easier option?
You can override this property, but you have to be careful about two things:
the new setting you want is this:
<ProjectEvaluationFingerprint>$(Configuration)|$(Platform)|TEST/ProjectEvaluationFingerprint>
Note the removal of $(ProjectEvaluationFingerprint), which would contain the previous value of this tag
the location where you put the import is important: you will want to put it at the very end of your project (i.e. after the Microsoft.CppBuild.targets import).
Concretely:
use_custom_fingerprint.targets
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectEvaluationFingerprint>$(Configuration)|$(Platform)</ProjectEvaluationFingerprint>
</PropertyGroup>
</Project>
project.vcxproj
<Project ...>
...
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<Import Project="use_custom_fingerprint.targets" />
</Project>
Note that I also tried the extension .props and this worked just the same.
Note: The new import after importing Microsoft.CppBuild.targets.$(Platform).user.props is not sufficient, it must be after Microsoft.CppBuild.targets.
Disclaimer: tried in Visual Studio 2015
I have the same problem. I was able to progress a step further than you, but I still haven't a full solution.
The reason why you have now the old fingerprint appended to the new one without solution dir is your line
<ProjectEvaluationFingerprint>$(Configuration)|$(Platform)|TEST|$(ProjectEvaluationFingerprint)</ProjectEvaluationFingerprint>
The
$(ProjectEvaluationFingerprint)
Holds the old fingerprint, so just remove this part from the value for ProjectEvaluationFingerprint and your lastbuildstate will have the desired value.
Sadly now (at least for me) Visual Studio always thinks the fingerprint is wrong and will re-link the project with every compile, not only when switching sln file.
I removed the line from the props sheet and the up-to-date check works again as expected as long as solution directory doesn't change. I then modified the Microsoft.CppBuild.targets directly and this works: No more "not up-to-date" projects, even when switching solution directory.
I have a Visual Studio project that relies on several DLL references. Here is a sample of those references in my csproj:
<ItemGroup>
<Reference Include="Class1.Project1">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\bin\Class1.Project1.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Class1.Project2">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\bin\Class1.Project2.dll</HintPath>
<Private>False</Private>
</Reference>
</ItemGroup>
However, when I include this class as a project dependency in a web site project, Visual Studio is finding dependencies of the dependencies shown above. During build Visual Studio is then defaulting the "Copy Local" property to "True" and copying these dependencies into my web site's ~/bin directory.
This, in turn, is overwriting the versions of the DLL files that already exist in this directory. This causes the following error:
Could not load file or assembly
'Class5.Project5, Version=3.6.1861.2,
Culture=neutral,
PublicKeyToken=dfeaee0e3978ac79' or
one of its dependencies. The located
assembly's manifest definition does
not match the assembly reference.
(Exception from HRESULT: 0x80131040)
How do I make Visual Studio default the "Copy Local" setting to "False" for everything? I do not want Visual Studio to copy DLL files automatically during build. Nor do I want to tie my build to very specific versions of a DLL.
It sounds to me as though you have multiple projects configured to output into the same directory - is this true?
If so, you'll need to review your configuration as Visual Studio assumes (nay, requires) that each project has a unique output directory.
Also, you wrote:
This, in turn, is overwriting the versions of the DLL files that already exist in this directory.
Where did these existing files come from?
Visual Studio assumes that it has full rights to make whatever changes it sees fit in the build output directories - trying to argue with it is a fine route to a whole new world of pain.
(Unfortunately, I speak from experience. Sigh.)
I had this problem once,
On Publish: The easiest way to prevent writing over the existing dll files is to set them as ReadOnly. You will get a warning on publish for each file that could not be replaced but it will do the job.
On Build: To set the CopyLocal automatically off you need to place the dll files on the GAC.
Why were there other versions already in the bin directory?
In any case, I wonder if you would get the same problem using a Web Application Project. Since it's a project, it has a single file listing the direct references, and if these are project references (references to the output of other assemblies in the same solution), then MSBUILD can ensure that the correct version is used.
See if you can reproduce this by starting with a new web application project and just adding the references.
You could try the following in your project file.
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
And then, in your code try this.
<ItemGroup>
<Reference Include="Class1.Project1">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\bin\Class1.Project1.dll</HintPath>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</Reference>
<Reference Include="Class1.Project2">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\bin\Class1.Project2.dll</HintPath>
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
</Reference>
</ItemGroup>