📜 ⬆️ ⬇️

Visual Studio 2019 support in PVS-Studio


The support of Visual Studio 2019 in PVS-Studio affected several different components at once: the plug-in for the IDE itself, the command line analysis application, the C ++ core and the C # analyzers, as well as several utilities. About what problems we encountered during the support of the new version of the IDE and how they were solved, I will briefly describe in this article.

Before you start, you want to look back a little to trace the history of support for past versions of Visual Studio, which will give a better understanding of our vision of the problem and the decisions made in certain situations.

Starting from the first version of the PVS-Studio analyzer, in which the plug-in for Visual Studio appeared (then it was Visual Studio 2005), support for new versions of Visual Studio was quite a simple task for us - basically it was about updating the plug-in project file and dependencies of various Visual Studio extensions APIs. Sometimes it was required to additionally support new features of the C ++ language, which the Visual C ++ compiler gradually learned, but this also usually did not cause problems immediately before the release of the next edition of Visual Studio. And then there was only one analyzer in PVS-Studio - for C and C ++ languages.

Everything changed for the release of Visual Studio 2017. In addition to the fact that many APIs for expanding this IDE were very significantly changed in this version, after the upgrade we faced problems ensuring the backward compatibility of the new C # analyzer that appeared at that time (as well as our new C ++ layer). analyzer for MSBuild projects) with older versions of MSBuild \ Visual Studio.
')
Therefore, before reading this article, I strongly recommend that you read the related article about Visual Studio 2017 support: " Support for Visual Studio 2017 and Roslyn 2.0 in PVS-Studio: sometimes using ready-made solutions is not as easy as it seems at first glance ." The article mentioned above describes the problems that we encountered last time, as well as the interaction patterns of various components (for example, PVS-Studio, MSBuild, Roslyn). Understanding this interaction will be useful when reading this article.

Ultimately, the solution of these problems introduced significant changes to our analyzer, and, as we hoped, new approaches that we applied then will make it possible in the future to support updated versions of Visual Studio \ MSBuild much easier and faster. In part, this assumption has already been confirmed when numerous Visual Studio 2017 updates were released. Did this new approach help us with the support of Visual Studio 2019? About this below.

PVS-Studio plugin for Visual Studio 2019


It all started, it would seem, not bad. It was quite easy to port the plugin to Visual Studio 2019, where it started and worked fine. Despite this, 2 problems were immediately revealed, which promised trouble in the future.

The first is the IVsSolutionWorkspaceService interface used to support the Lightweight Solution Load mode, which, by the way, was disabled in one of the previous updates in Visual Studio 2017, was decorated with the Deprecated attribute, which was only a warning when building, but in the future promised more Problems. Quickly, Microsoft introduced this mode and abandoned it ... They figured out this problem quite simply - they refused to use the corresponding interface.

The second is that when loading Visual Studio with the plugin, the following message appears:

Viewing the launch logs of Visual Studio (ActivityLog file) finally dot the 'i':

Warning: Extension 'PVS-Studio' uses the 'synchronous auto-load' feature of Visual Studio. This feature will not be supported. Please contact the extension vendor to get an update.

For us, this meant one thing - changing the way the plugin was loaded into asynchronous mode. I hope you will not be upset if I do not overload you with details on the interaction with COM interfaces of Visual Studio, and I’ll go over the changes briefly.

Microsoft has an article on how to create asynchronously loaded plugins: " How to: Use AsyncPackage to load VSPackages in the background ". At the same time it was obvious to everyone that the matter would not be limited to these changes.

One of the main changes is the method of loading, or rather, initialization. Previously, the necessary initialization took place in two methods - the overrided Initialize method of our class-descendant Package, and the OnShellPropertyChange method. The need to remove part of the logic into the OnShellPropertyChange method is due to the fact that during synchronous loading of the plug-in, Visual Studio may not be fully loaded and initialized, and as a result, not all the necessary actions could be performed at the initialization stage of the plug-in. The solution to this problem is to wait for Visual Studio to exit the 'zombie' state and defer the execution of these actions. This is the logic that was rendered in OnShellPropertyChange with the status 'zombie' checked.

In the abstract class AsyncPackage , from which asynchronously loaded plugins inherit, the Initialize method has the sealed modifier, so initialization needs to be done in the redefined InitializeAsync method, which was done. The logic with the zombie tracking of the state of Visual Studio also had to be changed, since we stopped receiving this information in the plugin. However, a number of actions that had to be performed after initializing the plug-in did not go anywhere. The solution was to use the OnsPackageLoaded method of the IVsPackageLoadEvents interface, where actions that require pending execution were performed.

Another problem logically stemming from the fact of asynchronous loading of the plug-in is the absence of the PVS-Studio plug-in commands when Visual Studio starts. When you open the analyzer's double-click log from the file manager (if you need to open it through Visual Studio), the required version of devenv.exe was launched with the command to open the analyzer report. The startup team looked like this:

"C:\Program Files (x86)\Microsoft Visual Studio\ 2017\Community\Common7\IDE\devenv.exe" /command "PVSStudio.OpenAnalysisReport C:\Users\vasiliev\source\repos\ConsoleApp\ConsoleApp.plog" 

The "/ command" flag here is used to invoke a command registered in Visual Studio. Now this approach did not work, since the commands were not available until the plug-in was loaded. As a result, I had to stop at the “crutch” with parsing the devenv.exe launch line after loading the plug-in, and if there is a string representation of the command for opening the log, the log download itself. Thus, having refused in this case to use the “correct” interface for working with commands, we managed to preserve the necessary functionality, postponing the loading of the log until the full load of the plug-in.

Fuh, it seems to have figured out and everything works - everything loads and opens correctly, there are no warnings at last.

And here comes the unexpected - Paul (hello!) Installs a plugin for himself, and then asks why we didn’t do asynchronous loading?

To say that we were surprised - to say nothing - like that? No, really - here is a new version of the plug-in installed, here's a message stating that the package is synchronously downloadable. We install the same version of the plug-in on our cars with Alexander (and you, too, hello) - all is well. Nothing is clear - we decided to see which versions of the PVS-Studio libraries are loaded into Visual Studio. And suddenly it turns out that the versions of the PVS-Studio libraries for Visual Studio 2017 are being used, despite the fact that the VSIX package contains the correct versions of the libraries - for Visual Studio 2019.

Fumbling with VSIXInstaller, we managed to find the cause of the problem - the package cache. The theory was also confirmed by the fact that when the access rights to the package in the cache were restricted (C: \ ProgramData \ Microsoft \ VisualStudio \ Packages), VSIXInstaller wrote error information to the log. What is surprising, if there is no error, no information about the fact that the package is installed from the cache is not written to the log.

Note Studying the behavior of VSIXInstaller and related libraries, I noted to myself that it is very great that Roslyn and MSBuild have open source code that makes it convenient to read, debug, and track the logic of work.

As a result, the following happened - when installing the VSIXInstaller plug-in, I saw that the corresponding package was already in the cache (there was a .vsix package for Visual Studio 2017), and during installation it used it, rather than the package being actually installed. Why it does not take into account the restrictions / requirements described in .vsixmanifest (for example, the version of Visual Studio for which the extension can be installed) is an open question. Because of this, it turned out that, although .vsixmanifest contained the necessary restrictions, the plug-in designed for Visual Studio 2017 was installed on Visual Studio 2019.

The worst thing is that such a setup broke the dependency graph of Visual Studio, and although outwardly it might even seem that the development environment was working fine, in fact, everything was very bad. It was impossible to install and remove extensions, make updates, and so on. The process of 'recovery' was also quite unpleasant, because it was necessary to manually remove the extension (the corresponding files), as well as manually edit the configuration files that store information about the installed package. In general - pleasant enough.

To solve this problem and avoid similar situations in the future, it was decided to create a GUID for the new package in order to completely separate the Visual Studio 2017 and Visual Studio 2019 packages (with older packages there is no such problem, and they always used a common GUID).

And since it was about unpleasant surprises, I’ll mention one more - after updating to Preview 2, the 'moved' menu item under the 'Extensions' tab. It would seem - nothing terrible, but access to the functions of the plugin has become less convenient. On subsequent versions of Visual Studio 2019, including the release version, this behavior is preserved. I did not find any mention of this 'feature' at the time of its release in the documentation or blog.

Now, it would seem, everything works, and with the support of the plugin for Visual Studio 2019 is over. The next day after the release of PVS-Studio 7.02 with Visual Studio 2019 support, it turned out that this was not the case - another problem with an asynchronous plugin was found. For a user, this could look like this: when opening a window with analysis results (or launching an analysis), our window was sometimes displayed “empty” - there was no content in it: buttons, a table with analyzer warnings, etc.

In fact, this problem was sometimes repeated in the course of work. However, it was repeated only on one machine, and began to appear only after updating Visual Studio in one of the first versions of 'Preview' - there were suspicions that something broke during installation / upgrade. Over time, the problem, however, ceased to repeat even on this machine, and we decided that it “fixed itself”. It turned out that no - just so lucky. More precisely, no luck.

The case turned out to be in the order of initialization of the environment window itself (the successor of the ToolWindowPane class) and its contents (in fact, our control with a grid and buttons). Under certain conditions, the initialization of the control occurred before the initialization of the pane, and, despite the fact that everything worked without errors, the FindToolWindowAsync method (creating the window during the first access) correctly worked, but the control remained invisible. We fixed this by adding lazy initialization for our control to the pane fill code.

C # 8.0 support


Using Roslyn as a basis for the analyzer has a significant advantage - there is no need to manually support new language constructs. All this is supported and implemented in the framework of the Microsoft.CodeAnalysis libraries - we use the already-made results. Thus, support for new syntax is implemented by updating the libraries.

Of course, with regard to static analysis directly, here you have to do everything yourself, in particular, to process new language constructs. Yes, we get the new syntactic tree automatically by using a more recent version of Roslyn, but we need to teach the analyzer how to perceive and process new / modified tree nodes.

I think the most discussed innovation of C # 8 are nullable reference types. I will not write about them here - this is a big enough topic worthy of a separate article (which is already in the process of writing). In general, we have so far stopped at ignoring nullable annotations in our dataflow mechanism (that is, we understand them, parse and skip them). The fact is that despite the non-nullable reference type of a variable, you can still quite simply (or by mistake) write the value null , which can lead to NRE when dereferencing the corresponding reference. In this case, our analyzer may see a similar error and issue a warning to use a potentially null reference (of course, if it sees such an assignment in the code) despite the non-nullable reference type of the variable.

I want to note that the use of nullable reference types and the accompanying syntax opens up the possibility of writing very interesting code. For ourselves, we called it 'emotional syntax'. The code below compiles itself quite well:

 obj.Calculate(); obj?.Calculate(); obj.Calculate(); obj!?.Calculate(); obj!!!.Calculate(); 

By the way, in the course of the work, I found a couple of ways to 'fill up' with Visual Studio using the new syntax. The fact is that you can not limit the number of characters to one when you put '!'. That is, you can write not only the code of the form:

 object temp = null! 

but also:

 object temp = null!!!; 

You can pervert, go ahead and write like this:

 object temp = null!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!; 

This code is successfully compiled. But if you request information about the syntax tree using the Syntax Visualizer from the .NET Compiler Platform SDK, Visual Studio will crash.

From the Event Viewer, you can pull information about the problem:

 Faulting application name: devenv.exe, version: 16.0.28803.352, time stamp: 0x5cc37012 Faulting module name: WindowsBase.ni.dll, version: 4.8.3745.0, time stamp: 0x5c5bab63 Exception code: 0xc00000fd Fault offset: 0x000c9af4 Faulting process id: 0x3274 Faulting application start time: 0x01d5095e7259362e Faulting application path: C:\Program Files (x86)\ Microsoft Visual Studio\2019\Community\Common7\IDE\devenv.exe Faulting module path: C:\WINDOWS\assembly\NativeImages_v4.0.30319_32\ WindowsBase\4480dfedf0d7b4329838f4bbf953027d\WindowsBase.ni.dll Report Id: 66d41eb2-c658-486d-b417-02961d9c3e4f Faulting package full name: Faulting package-relative application ID: 

If you go further and increase the number of exclamation marks several times, Visual Studio will fall by itself - the help of Syntax Visualizer will not be needed for this. The Microsoft.CodeAnalysis libraries and the csc.exe compiler also do not digest this code.

Of course, these are synthetic examples, but still this fact seemed funny to me.

Toolset


Note Again I face the problem of translating the word 'evaluation' in the context of a conversation about MSBuild projects. The translation, which seemed to be the closest in meaning and at the same time sounding normal - “building a model of the project”. If you have alternative translation options - you can write to me, it will be interesting to read.

It was obvious that updating the toolset would be the most time consuming task. More precisely, it seemed so initially, but now I am inclined to think that the plug-in support was the most problematic. In particular, this was related to the already existing toolset and the mechanism for building the model of MSBuild projects, which was still working successfully now, although it required expansion. The lack of need to write algorithms from scratch greatly simplified the task. Our bet on “our” toolset, made at the stage of support for Visual Studio 2017, has once again been justified.

Traditionally, it all starts with updating NuGet packages. On the management tab of the NuGet packages, there is an 'Update' button for the solution ... which does not work. When updating all packages, multiple version conflicts arose, and resolving them all didn’t seem to be the right way. A more painful, but, it seems, more reliable way is the 'piecewise' update of target Microsoft.Build / Microsoft.CodeAnalysis packages.

One of the differences was immediately revealed by tests of diagnostic rules - the structure of the syntactic tree for an already existing node has changed. It's okay, corrected quickly.

Let me remind you that during the work we test analyzers (C #, C ++, Java) on open source projects. This allows a good test of diagnostic rules — to find, for example, false positives, or to get an idea of ​​which other cases have not been considered (reduce the number of false negatives). These tests also help to track possible regression in the initial update of the toolset libraries. And this time was no exception, since a number of problems surfaced.

One of the problems was the deterioration of behavior within CodeAnalysis libraries. More specifically, on a number of projects in the code of libraries, exceptions began to arise during various operations - obtaining semantic information, opening projects, etc.

Attentive readers of the article about support for Visual Studio 2017 will remember that our distribution contains a stub - the MSBuild.exe file, 0 bytes in size.

This time I had to go further - now the distribution kit also contains empty compiler stubs - csc.exe, vbc.exe, VBCSCompiler.exe. What for? The path to this began with the analysis of one of the projects in the test database, on which the "diffs" of reports appeared - a number of warnings were absent when using the new version of the analyzer.

The problem turned out to be in conditional compilation symbols - when analyzing a project using the new version of the analyzer, some of the characters were extracted incorrectly. In order to better understand why this problem arose, we had to plunge into the Roslyn libraries.

To parse conditional compilation characters, use the GetDefineConstantsSwitch method of the Csc class from the Microsoft.Build.Tasks.CodeAnalysis library. Parsing is performed using the String.Split method on a number of delimiters:

 string[] allIdentifiers = originalDefineConstants.Split(new char[] { ',', ';', ' ' }); 

This parsing method works fine, all the necessary conditional compilation characters are retrieved successfully. We dig further.

The next key point is calling the ToolTask class's ComputePathToTool method . This method builds the path to the executable file ( csc.exe ) and checks its presence. If the file exists, the path to it is returned, otherwise null is returned.

Calling code:

 .... string pathToTool = ComputePathToTool(); if (pathToTool == null) { // An appropriate error should have been logged already. return false; } .... 

Since there is no csc.exe file (it would seem, why do we need it?), PathToTool is null at this stage, and the current method ( ToolTask.Execute ) completes its execution with a false result. As a consequence, the results of the task, including the resulting conditional compilation characters, are ignored.

Well, let's see what happens if you put the csc.exe file in the expected place.

In this case, pathToTool indicates the actual location of the existing file, and execution of the ToolTask.Execute method continues. The next key point is the call to the ManagedCompiler.ExecuteTool method. And it begins as follows:

 protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands) { if (ProvideCommandLineArgs) { CommandLineArgs = GetArguments(commandLineCommands, responseFileCommands) .Select(arg => new TaskItem(arg)).ToArray(); } if (SkipCompilerExecution) { return 0; } .... } 

The SkipCompilerExecution property is true (logically, we are not performing the actual compilation). As a result, the calling method (already mentioned ToolTask.Execute ) checks that the return code of the ExecuteTool method is 0, and, if so, ends its execution with the value true . What you have there for csc.exe lay - a real compiler or Leo Tolstoy's 'War and Peace' in textual presentation - it does not matter.

As a result, the main problem stems from the fact that the sequence of steps is determined in the following order:


and not vice versa. Compiler stubs successfully solve this problem.

Well, how did you get successful compilation symbols, if the csc.exe file was not detected (and the result of the task was ignored)?

There is a method in such a case - CSharpCommandLineParser.ParseConditionalCompilationSymbols from the library Microsoft.CodeAnalysis.CSharp . Parsing is also performed by the String.Split method with a number of delimiters:

 string[] values = value.Split(new char[] { ';', ',' } /*, StringSplitOptions.RemoveEmptyEntries*/); 

Notice the difference with the delimiter set from the Csc.GetDefineConstantsSwitch method? In this case, the whitespace character is not a separator. Thus, if the conditional compilation characters were space-separated, this method will parse them incorrectly.

Such a situation arose on problematic projects - in them, conditional compilation characters were spaced apart, and successfully parsed with the GetDefineConstantsSwitch method, but not with ParseConditionalCompilationSymbols .

Another problem that found itself after updating the libraries was the deterioration of behavior in some cases, in particular - on projects that were not going to. Problems arose in the Microsoft.CodeAnalysis libraries and were returned to us in the form of various exceptions - ArgumentNullException (some internal logger was not initialized), NullReferenceException, and others.

I want to tell about one of these problems below - it seemed to me quite interesting.

We encountered this problem when checking the latest version of the Roslyn project - a NullReferenceException was thrown from the code of one of the libraries. Due to the sufficiently detailed information about the location of the problem, we quickly found the problem code and, for the sake of interest, decided to try whether the problem recurs when working from Visual Studio.

Well - it was possible to reproduce it in Visual Studio (the experiment was conducted on Visual Studio 16.0.3). To do this, we need a class definition of the following form:

 class C1<T1, T2> { void foo() { T1 val = default; if (val is null) { } } } 

We also need the Syntax Visualizer (included in the .NET Compiler Platform SDK component). You must request a TypeSymbol (menu item “View TypeSymbol (if any)”) from the node of the syntax tree of the ConstantPatternSyntax type ( null ). After this, Visual Studio will restart, and in the Event Viewer you can view information about the problem, in particular, find the stack trace:

 Application: devenv.exe Framework Version: v4.0.30319 Description: The process was terminated due to an unhandled exception. Exception Info: System.NullReferenceException at Microsoft.CodeAnalysis.CSharp.ConversionsBase. ClassifyImplicitBuiltInConversionSlow( Microsoft.CodeAnalysis.CSharp.Symbols.TypeSymbol, Microsoft.CodeAnalysis.CSharp.Symbols.TypeSymbol, System.Collections.Generic.HashSet'1 <Microsoft.CodeAnalysis.DiagnosticInfo> ByRef) at Microsoft.CodeAnalysis.CSharp.ConversionsBase.ClassifyBuiltInConversion( Microsoft.CodeAnalysis.CSharp.Symbols.TypeSymbol, Microsoft.CodeAnalysis.CSharp.Symbols.TypeSymbol, System.Collections.Generic.HashSet'1 <Microsoft.CodeAnalysis.DiagnosticInfo> ByRef) at Microsoft.CodeAnalysis.CSharp.CSharpSemanticModel.GetTypeInfoForNode( Microsoft.CodeAnalysis.CSharp.BoundNode, Microsoft.CodeAnalysis.CSharp.BoundNode, Microsoft.CodeAnalysis.CSharp.BoundNode) at Microsoft.CodeAnalysis.CSharp.MemberSemanticModel.GetTypeInfoWorker( Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode, System.Threading.CancellationToken) at Microsoft.CodeAnalysis.CSharp.SyntaxTreeSemanticModel.GetTypeInfoWorker( Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode, System.Threading.CancellationToken) at Microsoft.CodeAnalysis.CSharp.CSharpSemanticModel.GetTypeInfo( Microsoft.CodeAnalysis.CSharp.Syntax.PatternSyntax, System.Threading.CancellationToken) at Microsoft.CodeAnalysis.CSharp.CSharpSemanticModel.GetTypeInfoFromNode( Microsoft.CodeAnalysis.SyntaxNode, System.Threading.CancellationToken) at Microsoft.CodeAnalysis.CSharp.CSharpSemanticModel.GetTypeInfoCore( Microsoft.CodeAnalysis.SyntaxNode, System.Threading.CancellationToken) .... 

As you can see, the cause of the problem is dereference of the zero reference.

As I mentioned earlier, we encountered the same problem during the testing of the analyzer. If you use the Microsoft.CodeAnalysis debugging libraries to build the analyzer, you can come to the exact problem location by debugging, by requesting TypeSymbol from the necessary syntax tree node.

As a result, we arrive at the ClassifyImplicitBuiltInConversionSlow method mentioned in the above trace trace method:

 private Conversion ClassifyImplicitBuiltInConversionSlow( TypeSymbol source, TypeSymbol destination, ref HashSet<DiagnosticInfo> useSiteDiagnostics) { Debug.Assert((object)source != null); Debug.Assert((object)destination != null); if (source.SpecialType == SpecialType.System_Void || destination.SpecialType == SpecialType.System_Void) { return Conversion.NoConversion; } Conversion conversion = ClassifyStandardImplicitConversion(source, destination, ref useSiteDiagnostics); if (conversion.Exists) { return conversion; } return Conversion.NoConversion; } 

The problem is that the destination parameter in this case is null . Accordingly, when accessing destination.SpecialType, a NullReferenceException is thrown . , Debug.Assert , , — . .

C++


— - , . , , , .

— , , ToolsVersion . — , toolset' , , . , , . , ToolsVersion, MSBuild / Visual Studio, 16.0. … , Visual Studio:
Visual Studio product name
Visual Studio version number
Tools Version
PlatformToolset version
Visual Studio 2010
10.0
4.0
100
Visual Studio 2012
11.0
4.0
110
Visual Studio 2013
12.0
12.0
120
Visual Studio 2015
14.0
14.0
140
Visual Studio 2017
15.0
15.0
141
Visual Studio 2019
16.0
Current
142

, , , Windows Xbox, , (, — , ), Microsoft — . :)

— toolset' ( ).

— Visual Studio 2017 (, VisualStudioVersion ). , , C++ — , .NET . .NET toolset ToolsVersion. C++ , toolset'. Build Tools Visual Studio 2017 toolset' MSBuild.exe.config , . , toolset' (, Microsoft.Build.Evaluation.ProjectCollection.GlobalProjectCollection.Toolsets ), toolset', ( <= Visual Studio 2015).

— , ToolsVersion 15.0 , toolset'a. toolset — Current — , toolset, , Visual Studio 2019 . , – toolset' Current — 15.0 .

C# .NET Core


2 , :


— .targets / .props . , toolset'.

Visual Studio ( toolset'a – 15.0 ):

 The imported project "C:\Windows\Microsoft.NET\Framework64\ 15.0\Microsoft.Common.props" was not found. 

C# .NET Core Visual Studio 2017 ( toolset' — Current ):

 The imported project "C:\Program Files (x86)\Microsoft Visual Studio\ 2017\Community\MSBuild\Current\Microsoft.Common.props" was not found. .... 

( ), .

, , . ( C# .NET Core , toolset'e) . , , , . :)

, ? toolset'a .targets / .props .NET Core SDK ( Sdk.props , Sdk.targets ). , , .NET Core . , toolset , .NET Core , , .

.NET Core : , MSBuild.

, , :


From the steps described above, it is obvious that setting the necessary environment has two main objectives:
.targets / .props , .NET Core , — Microsoft.DotNet.MSBuildSdkResolver. toolset'a , — , ( toolset'). , , , .

Sdk toolset', , . , , . Microsoft.Common.props. toolset' .

, , .NET Core SDK, .

Conclusion


Visual Studio 2019 , Visual Studio 2017, , , . — Microsoft , Visual Studio 2015 Visual Studio 2017. , toolset'a, Visual Studio , . — toolset' — , . .NET Core ( , Visual Studio) , , .

, , — , .



, : Sergey Vasiliev. Support of Visual Studio 2019 in PVS-Studio

Source: https://habr.com/ru/post/454738/


All Articles