Is it possible to have vs project that is backwards compatible with vs2013 and vs2017? - msbuild

So my team uses VS2013 right now and I just recently proved that I can run our project with VS2017. So I was wondering if there is a way I can push my changes to our master branch without my team noticing anything. This means if they open up their VS2013 they run the project just fine and, when I run it with VS2017 it runs fine too. (It won't do that right now because the 3rdParty libraries were compiled with msvc 1800 and with my project running at msvc 1900 it gives me linking errors)
Can I take advantage of MSBuild conditionals to do this?
<Choose>
<When Condition=" '$(Configuration)'=='Debug' ">
<PropertyGroup>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>.\bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Include="UnitTesting\*.cs" />
<Reference Include="NUnit.dll" />
</ItemGroup>
</When>
<When Condition=" '$(Configuration)'=='retail' ">
<PropertyGroup>
<DebugSymbols>false</DebugSymbols>
<Optimize>true</Optimize>
<OutputPath>.\bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
</PropertyGroup>
</When>
</Choose>

You should can use VS17 and your Team VS13. If you opening the project in VS17, don't upgrade your Windows SDK version and platform toolset and the team and you can build as usual, but you cannot use new C++ features, because the older VS13 compiler cannot compile them

Related

Standalone project shows empty after initialization

Well, this is not a question and I don't know if this is against the rules. But I found no topic on this point and I figured out one potential method.
Yesterday, I try to create a standalone vue project with .net6. I read the official guideline and installed node.js,npm,vue,vue#cli and so on. I was pretty sure all the prerequisites were met.
But the project turned out to be empty after initialization by vs2022 with a command window that runs successfully. I tried to reinstall node.js because the project file shows information below:
sampleproject
<Project Sdk="Microsoft.VisualStudio.JavaScript.Sdk/0.4.0-alpha">
<PropertyGroup Label="Globals">
<ProjectGuid>...</ProjectGuid>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<StartupCommand>npm run serve</StartupCommand>
<JavaScriptTestRoot>.\</JavaScriptTestRoot>
<JavaScriptTestFramework>Jest</JavaScriptTestFramework>
</PropertyGroup>
<ItemGroup>
<Script Include="**" Exclude="*.esproj;**\node_modules\**" />
</ItemGroup>
<!-- This target is copied from the ASP.NET SPA template in order to ensure node_modules are in place. -->
<Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">
<!-- Ensure Node.js is installed -->
<Exec Command="node --version" ContinueOnError="true">
<Output TaskParameter="ExitCode" PropertyName="ErrorCode" />
</Exec>
<Error Condition="'$(ErrorCode)' != '0'" Text="Node.js is required to build and run this project. To continue, please install Node.js from https://nodejs.org/, and then restart your command prompt or IDE." />
<Message Importance="high" Text="Restoring dependencies using 'npm'. This may take several minutes..." />
<Exec WorkingDirectory="$(SpaRoot)" Command="npm install" />
</Target>
</Project>
Then I found that all needed files were ready in the target filesfiles
Anyway, the point is vs2022 language. I changed back my vs2022 language to English by uninstall other languages pack in vs installer. And all files comes out in the project.
before
after
Everything works well now.

Failure to build dll when adding a dll with nuget in the Library outtype in .netcore3.1

I have a plugin application(.net web site link). In the solution, there is a console application and projects of more than one library type. The selected plugins are being loaded and the application starts a listening.
The problem is; If I add nugetten dll to a library type project, the compiled version of these dlls should be created when there is build in the folder I specified.
.csproj;
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<OutputType>Library</OutputType>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
<AssemblyInfoFilePath>Properties\AssemblyInfo.cs</AssemblyInfoFilePath>
<UpdateAssemblyVersion>True</UpdateAssemblyVersion>
<UpdateAssemblyFileVersion>True</UpdateAssemblyFileVersion>
<UpdateAssemblyInfoVersion>True</UpdateAssemblyInfoVersion>
<AssemblyVersionSettings>None.None.Increment.DateStamp</AssemblyVersionSettings>
<AssemblyFileVersionSettings>None.None.Increment.DateStamp</AssemblyFileVersionSettings>
<AssemblyInfoVersionSettings>None.None.Increment.DateStamp</AssemblyInfoVersionSettings>
<PrimaryVersionType>AssemblyVersionAttribute</PrimaryVersionType>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<OutputPath>..\Nemesis.Agent\bin\Debug\Plugins\PrinterPlugin\</OutputPath>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="itext7" Version="7.1.13" />
<PackageReference Include="PdfiumViewer.Core" Version="1.0.4" />
<PackageReference Include="PuppeteerSharp" Version="2.0.4" />
</ItemGroup>
<ItemGroup>
...
</ItemGroup>
</Project>
packages;
folder
I used this code In PrintPdfDocument;
var pdfDocument = PdfiumViewer.PdfDocument.Load(new MemoryStream(bytes));
error during runtime;
I could not find the source of the error.I've tried other namespaces. The problem is solved if I manually move the compiled dll to the relevant folder. .net framework wasn't having this problem.
I overcame this problem by adding the following code to csproj.
<CopyLocalLockFileAssemblies>True<CopyLocalLockFileAssemblies>

Using FsLex/Yacc in Vs2013

I'm trying to resurrect an old f# parser project I had working in vs 2008 to work with vs 2013. It uses FsLexYacc.
I got it building ok by using a prebuild step as thus:
fslex --unicode "$(ProjectDir)XpathLexer.fsl"
fsyacc --module XpathParser "$(ProjectDir)XpathParser.fsy"
But this is less than ideal, as it always executes whether or not the inputs have changed.
I then tried just using the old MsBuild actions:
<FsYacc Include="XpathParser.fsy">
<FsLex Include="XpathLexer.fsl">
but these appeared to be completely ignored during the build process. Is that right? Have these build tasks been removed somehow?
I then found some stuff documented under vs C++ that I thought might work:
<CustomBuild Include="XpathParser.fsy">
<Message>Calling FsYacc</Message>
<Command>fsyacc --module XpathParser "$(ProjectDir)XpathParser.fsy"</Command>
<Outputs>$(ProjectDir)XpathParser.fs</Outputs>
</CustomBuild>
and
<PropertyGroup>
<CustomBuildBeforeTargets>CoreCompile</CustomBuildBeforeTargets>
</PropertyGroup>
(I inspected the Microsoft.Fsharp.Targets file to come up with the "CoreCompile" target.)
Alas, still no cigar.
Is anyone able to shine a light on whether it is indeed possible to properly integrate fslex/yacc into a vs 2013 solution, and if so, how?
I don't think the those tools are included by default with the F# compiler that is installed with Visual Studio and so the tasks don't exist. I did the following with a Visual Studio 2012 project, but I expect it would be similar in VS 2013. Here were the steps I had to follow:
Install FSharp.Powerpack from nuget. This has the fslex and fsyacc tools as well as build tasks and targets.
Unload the project and edit the .fsproj file.
Add an import statement for the FSharp.Powerpack.target file. This will add the CallFsLex and CallFsYacc build targets. I added this after the import for Microsoft.FSharp.targets:
<Import Project="$(ProjectDir)\..\packages\FSPowerPack.Community.3.0.0.0\Tools\FSharp.PowerPack.targets" />
Add these three properties to main PropertyGroup at the top of the file:
<FsYaccToolPath>..\packages\FSPowerPack.Community.3.0.0.0\Tools</FsYaccToolPath>
<FsLexToolPath>..\packages\FSPowerPack.Community.3.0.0.0\Tools</FsLexToolPath>
<FsLexUnicode>true</FsLexUnicode> This tells the build tasks where to find the necessary tools and sets the unicode option for fslex.
To use the targets we've imported, you need to define the FsLex and FsYacc item groups with the input files to use. You also need to add Compile items for the output .fs files. You end up with something like this in an ItemGroup section:
<Compile Include="Sql.fs" />
<FsYacc Include="SqlParser.fsp">
<Module>SqlParser</Module>
</FsYacc>
<Compile Include="SqlParser.fsi" />
<Compile Include="SqlParser.fs" />
<FsLex Include="SqlLexer.fsl" />
<Compile Include="SqlLexer.fs" />
You might be able to use the FsLex and FsYacc build tasks directly by referencing the FSharp.Powerpack.Build.Tasks.dll, but for me this was easier to get going.
This is what works for me (Windows 7 x64, Visual Studio 2013 Ultimate RTM):
Get and install "PowerPack for FSharp 3.0 + .NET 4.x + VS2012" from CodePlex (https://fsharppowerpack.codeplex.com/downloads/get/625449)
Create the following Registry key: HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\AssemblyFolders\FSharp.PowerPack-1.9.9.9 (for x64 versions of Windows, omit the Wow6432Node for 32bit versions) and set its (Default) value to the installation directory of the F# PowerPack (e.g. "C:\Program Files (x86)\FSharpPowerPack-4.0.0.0\bin"). [This is related to a long standing/regression bug in src/FSharp.PowerPack/CompilerLocationUtils.fs which basically breaks tool discovery.]
Import the PowerPack targets (AFTER importing the F# targets) in your *.fsproj file: <Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\FSharp.PowerPack.targets" />
Update your ItemGroup node to something like this (use FsYacc accordingly):
<ItemGroup>
<None Include="App.config" />
<FsLex Include="Lexer.fsl" />
<Compile Include="Lexer.fs">
<Visible>False</Visible>
</Compile>
<Compile Include="Program.fs" />
</ItemGroup>
Include a reference to FSharp.PowerPack.dll and build.
You should end up with a *.fsproj file similar to this:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>8c565f99-d6bc-43a9-ace9-eadfe429c0f7</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>FsYaccTest</RootNamespace>
<AssemblyName>FsYaccTest</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFSharpCoreVersion>4.3.1.0</TargetFSharpCoreVersion>
<Name>FsYaccTest</Name>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<!-- Snip -->
</PropertyGroup>
<ItemGroup>
<Reference Include="FSharp.PowerPack">
<HintPath>C:\Program Files (x86)\FSharpPowerPack-4.0.0.0\bin\FSharp.PowerPack.dll</HintPath>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="FSharp.Core, Version=$(TargetFSharpCoreVersion), Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Numerics" />
</ItemGroup>
<PropertyGroup>
<MinimumVisualStudioVersion Condition="'$(MinimumVisualStudioVersion)' == ''">11</MinimumVisualStudioVersion>
</PropertyGroup>
<Choose>
<When Condition="'$(VisualStudioVersion)' == '11.0'">
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</When>
<Otherwise>
<PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets')">
<FSharpTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
</PropertyGroup>
</Otherwise>
</Choose>
<Import Project="$(FSharpTargetsPath)" />
<Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\FSharp.PowerPack.targets" />
<PropertyGroup>
<FsLexUnicode>true</FsLexUnicode>
</PropertyGroup>
<ItemGroup>
<None Include="App.config" />
<FsLex Include="Lexer.fsl" />
<Compile Include="Lexer.fs">
<Visible>False</Visible>
</Compile>
<Compile Include="Program.fs" />
</ItemGroup>
</Project>
Note: You can probably omit creating the Registry key if you provide a proper FsYaccToolPath as described in mike z's answer.
This looks like it works - at least, in my experience, if you use the separate FsLexYacc nuget package as detailed here, and then put the following in your fsproj file (extracted from the github example):
Next to all the other imports:
<Import Project="..\packages\FsLexYacc.6.0.4\bin\FsLexYacc.targets" />
etc, etc
and then for the source files:
<FsYacc Include="Parser.fsp">
<OtherFlags>--module SqlParser</OtherFlags>
</FsYacc>
<FsLex Include="Lexer.fsl">
<OtherFlags>--unicode</OtherFlags>
</FsLex>
No need to do anything apart from edit the fsproj file, and install the nuget packages.

Mulitargeting C# project files with Mono and MonoDevelop

I have a collection of csproj files that all refer to the same set of source files, but have slightly different target data making it so I need to keep the project files separate. E.g. there are WinPhone, XBox, Desktop, MonoTouch variants of the same project.
For things that really are duplicated, like the list of .cs files to compile, I'd like to consolidate the list into a single file so I don't keep having to make sure that all variations are kept in sync. I originally tried doing this by removing the sources from the .csprojs and putting them into a .targets file that got imported by all the csprojs, but that made the source files disappear from both VS and MonoDevelop.
My second attempt was by making the Desktop csproj file the primary one, and letting all the variations import that csproj with some conditional logic. This keeps the source files editable from the main csproj and they build into all flavors. Now Visual Studio understands what I was trying to do but MonoDevelop can't build it. In the MonoDevelop solution the iOS version of the core DLL is grayed out and says "(not built in active configuration)"
I've also tried xbuilding the csproj and solution, which seems to get past the problems that MonoDevelop has but hiccups on other things related to resolving monotouch assemblies. I had thought MonoDevelop used xbuild, but maybe not?
Since this works in the Windows msbuild it seems like it's either a bug or a not supported feature in Mono. Or maybe there's a better way to tackle the whole scenario... Thought I'd ask here.
For specifics,
My Core.iOS.csproj file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<Project
xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
DefaultTargets="Build"
ToolsVersion="4.0" >
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>10.0.0</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{AE37B15F-F4BE-48DE-9F20-F00A601EC89E}</ProjectGuid>
<ProjectTypeGuids>{6BC8ED88-2882-458C-8E55-DFD12B67127B};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<AssemblyName>Core.iOS</AssemblyName>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="monotouch" />
</ItemGroup>
<Import Project=".\Core.csproj" />
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>
And my Core.csproj file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<Project
xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
DefaultTargets="Build"
ToolsVersion="4.0">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Core</RootNamespace>
</PropertyGroup>
<!-- Using AssemblyName's presence to check for whether this is imported. -->
<PropertyGroup Condition=" '$(AssemblyName)' == '' ">
<ProductVersion>8.0.50727</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{FC495BD8-11B1-46B0-A9DE-F245A0CBEE94}</ProjectGuid>
<AssemblyName>Core</AssemblyName>
<SignManifests>false</SignManifests>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<!-- properties similar to Debug -->
</PropertyGroup>
<ItemGroup Condition=" '$(Platform)' == 'AnyCPU' ">
<Reference Include="System" />
<Reference Include="System.Core" />
</ItemGroup>
<Import Condition=" '$(AssemblyName)' == 'Core' " Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<Compile Include="[...]" />
<Compile Include="[...]" />
</Project>
And, like I said, a variation of this seems to be working correctly when using VS Express for WinPhone and XBox360 projects. Is this something that should work? Is there a better way to do this?
Thanks,
Short answer:
This won't work because although MonoDevelop uses the MSBuild file format, it doesn't use the real MSBuild/xbuild engine for all project types yet. I'd suggest using links instead of an include.
Full background:
MonoDevelop has an old internal build engine that's derived from the SharpDevelop 1.0 build engine, i.e it predates the existence of MSBuild. We're in the process of migrating to MSBuild, but this has taken several stages, and is not yet complete.
A few years ago, MonoDevelop switched its project file format to a Visual Studio compatible subset of MSBuild. This was done by serializing/deserializing known MSBuild properties and items into MD's internal project model, but doing the build using the old build engine. This meant that any MSBuild projects that only used features accessible from the Visual Studio UI worked fine. However, it did not support the more advanced MSBuild features that are only accessible by hand-editing the MSBuild XML.
Later MD gained experimental support for using the xbuild/MSBuild build engine, but at the time xbuild was not mature, and it did not have MSBuild targets for all project types. It remained experimental, and build code for new project types (MonoTouch, etc) was written using the MD internal build engine.
Mono for Android needed to be supported in Visual Studio, so had to have MSBuild targets. Instead of writing and maintaining build code for two build engines, we finished up xbuild and MonoDevelop's MSBuild engine integration so it could be used for Mono for Android projects. However, we could not enable the xbuild build engine by default in MD, since many other project types did not yet have xbuild targets. Instead, we allowed project addins to force the use of the xbuild engine on a per-project-type basis.
This is essentially the current state - the xbuild engine is used for Mono for Android projects, and newer project types such as iPhone Binding projects and PLP projects, and is recommended for new project types. But older project types such as MonoTouch, MonoMac, ASP.NET etc have not yet been migrated at the time of writing.

Is there any MSBuild property that shows we are in publish?

I want to conditionally undefine DEBUG if it's a publish build.
is there a property I can check to see if we're currently publishing?
You can wire in your own target to set a property that you can then key behavior off of, or do whatever you want. The project modification below shows how to wire into the existing Publish target dependencies with your own before and after target. The before target sets a property. Then, in the existing part of your project where DEBUG is defined within the $(DefineConstants) property, you conditionally decide on whether or not to add DEBUG into the constant list, based on the property you set when the build is being performed because of a Publish.
<PropertyGroup>
<PublishDependsOn>MyBeforePublish;$(PublishDependsOn);MyAfterPublish</PublishDependsOn>
</PropertyGroup>
<Target Name="MyBeforePublish">
<PropertyGroup>
<DetectPublishBuild>true</DetectPublishBuild>
</PropertyGroup>
</Target>
<Target Name="MyAfterPublish">
<PropertyGroup>
<DetectPublishBuild>false</DetectPublishBuild>
</PropertyGroup>
</Target>
...
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<DefineConstants
Condition="'$(DetectPublishBuild)' != 'true'"
>DEBUG;$(DefineConstants)</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
Tested in VS2019 16.10.1.
<Target Name="XXX" Condition="'$(PublishProtocol)'!=''">
<Copy SourceFiles="Web.Base.config" DestinationFiles="Web.config" OverwriteReadOnlyFiles="True" Condition="!('$(PublishProfileName)' == '' And '$(WebPublishProfileFile)' == '')" />
This will perform the "Copy" only when the build is using the PublishProfile flag.
http://sedodream.com/2013/01/06/commandlinewebprojectpublishing.aspx
<Choose>
<When Condition="'$(BuildType)' == 'publish'">
<PropertyGroup>
<DefineConstants>Release</DefineConstants>
</PropertyGroup>
</When>
</Choose>
You may need other values in there besides release. But, this should work.
What we do at our place though is to actually have a publish, debug, and release. We created publish by having it copy from release so it has all the settings in it.