SonarLint Connected mode for multiple projects - c#

So,
The company has a SonarQube key for each individual project. So, we got a Common.dll project, and a Network.dll project, and a MyProject.exe project all maintained in SonarQube as individual projects.
However, in my Visual Studio i have one solution with all three projects. How can I "bind" each project to SonarQube for all of them, so that the binding is between Common.dll and Common.dll, not MyProject.Exe for all three.
(if that makes sense). I want the connected mode binding to be individual to project, not one project for the entire solution.
Thanks
Jaeden "Sifo Dyas" al'Raec Ruiner

This is not supported by SonarLint and there is no plan for short-term on this.

You may exclude common projects from analysis. A PropertyGroup that I shared below, conditionally excludes the library from the analysis scope based on a solution's name (.NET csproj file):
<PropertyGroup>
<SonarQubeExclude Condition=" $(SolutionName) == 'Solution1' ">true</SonarQubeExclude>
</PropertyGroup>

Related

How can you condition based on if a Nuget package is installed, whether directly or transitively?

I want all projects in my solution to have a certain attribute if a certain Nuget package is pulled into it. I've tried in a Directory.Build.targets:
<ItemGroup>
<PackageReference Update="MyNugetPackage" GeneratePathProperty="true" />
</ItemGroup>
<PropertyGroup Condition="'$(PkgMyNugetPackage)' != ''">
<MyProperty>true</MyProperty>
</PropertyGroup>
but it seems the generated property from GeneratePathProperty doesn't flow up to referencing projects, so this only sets MyProperty in projects which have a PackageReference directly in them, not also those that reference projects with a PackageReference.
Is there any way to do this or in general to pass information from a child project to a parent project? So projects can set variables visible to referencing projects, which could be accessed something like $(ProjectReferences.MyChildProject.Property1)?
MSBuild doesn't have a first-class concept of parent and child projects. A project can invoke the running of another project and a project can 'reference' another project. But that doesn't create a relationship that has a representation. There is no syntax for addressing 'parent' or 'child' projects because there is no representation that the syntax would apply to.
A ProjectReference doesn't create a relationship between two projects. It indicates that a project needs the outputs of another project. A project that has one or more ProjectReference items will perform its compile step after the referenced projects have been built or have been verified to be up to date.
What version of MSBuild are you using? Recent versions of MSBuild have added enhancements that may help.

Assembly Version of [MyMvcProject].Views.dll

When compiling a .net core Web MVC project VS / Compiler creates an assembly called [MyMvcProject].Views.dll with an AssemblyFileVersion of 0.0.0.0.
Is it possible to change the Version for this generated file (and maybe also change other Assembly properties?
UPDATE
I've added Manually AssemblyInfo.cs and edited my csproj with <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
With this constellation it seems that the data is not propagated to [MyMvcProject].Views.dll
I would like to stick with AssemblyInfo.cs because I share the this file over several projects. (Unless there's another solution to have consistent Assembly Versions over many projects).
Still would like to give [MyMvcProject].Views.dll a specific version.
Any idea?
I would like to stick with AssemblyInfo.cs because I share the this file over several projects. (Unless there's another solution to have consistent Assembly Versions over many projects).
You can use a Directory.Build.props file to achieve this. This file is recognised automatically by the dotnet build system (it's part of MSBuild) and will apply to all projects within the same directory or lower. If you want to apply a Version property for an entire solution, for example, you can drop a Directory.Build.props file next to the .sln file, with the following contents:
<Project>
<PropertyGroup>
<FileVersion>1.0.0.404</FileVersion>
</PropertyGroup>
</Project>
As you might expect, this AssemblyFileVersion property will also apply to your [MyMvcProject].Views.dll assembly.
Here's a detailed list of the AssemblyInfo properties you can specify when using this approach: AssemblyInfo properties.
Addition by #gsharp:
If there's also a version set in the project properties, then the project version will "win" over the Directory.Build.props version.
Go to your project "Properties" and on "Package" tab you have most of the properties that are in AssemblyInfo in classic .Net Framework projects like "Assembly version" and "Assembly file version".
Also you could try to use this command to build your project: dotnet publish /p:Version=1.2.3

MSBuild .NET project that will output existing assembly as it's result

I need to create csproj file that will be usable as project reference in VS2013 and will output prebuilt binary as it's "Build" result.
We use referenced projects for build, however company policy doesn't allow access to some of that projects for everyone. As a result projects need to be updated manually to make them build. This is really a major inconvenience when switching branches and when making edits to project files, so I want to create dummy project that will be bound to pre-built binaries as their "output" and will be placed instead of real projects.
EDIT: Moving that assembly to Nuget package is not an option for now since Nuget has some issues with dev flow (when you need to debug/test/develop package). I saw some VS extension that implements switching between Nuget package and local project which might solve this issue, but I'm not sure if it will be accepted and want to explore other options.
To be clear - the thing I want to avoid is editing project in any way, so that project can be built cleanly after pulling it from Git, and I don't have to clean it every time before commit.
I haven't properly tested it, but the solution seems really simple (if I understand the question properly).
Just add this to the existing .csproj, overriding the Build target to just give the path to the pre-built assembly.
<Target
Name="Build"
Returns="$(TargetPath)" />
This assumes the TargetPath property already defined, and it should automatically be if you're modifying the original .csproj. Otherwise just define it yourself in a <PropertyGroup> before the Build task.
Note that having TargetPath defined is important for the ProjectReferences in your own project to resolve.
How about having those restricted (binary only) projects reside in an internal Nuget package feed, so that Nuget can install the packages as needed, on build?

Copy External Configurations to Local Projects in Visual Studio?

What is the easiest way to create a build configuration in approximately 50-100 projects (same solution) IF Visual Studio has already detected the build configuration from another project?
Our team uses a set of common projects (namespace is simply "Common") within several solutions. The Common namespace has it's own master solution with its own set of build configurations. Common's solution contains five build configurations ("Debug-QA", "Debug-Dev", etc.).
Whenever these projects are used within a NEW solution (ie "MyNewSolution"), Visual Studio shows the build configurations from Common's master solution. Unfortunately, these configurations have not yet been created in MyNewSolution or any of MyNewSolution's projects. This creates a problem for ADDING the build configurations to the other projects, or including the projects in these build configurations, since there is no way to CREATE a build configuration if the name already exists (which Visual Studio thinks it does, thanks to the Common projects being included).
My goal is to add the same configurations (ie "Debug-QA", "Debug-Dev", etc.) into MyNewSolution, and its projects, so that all of the projects and solutions match. The only way I can see to do this is to manually create the build configuration on each new project... which is torture since MyNewSolution has approximately 50-100 projects.
FYI: I'm using Visual Studio 2012
This is more of a hack than a proper solution, but you could always:
Create a a copy of the configuration you want for the entire solution with a GUID as its name.
Remove the copy from the projects which already have the original configuration (undo changes).
Rename the GUID to the original configuration's name using the "Find/Replace in Files" tool.
Even if it isn't a very viable option, it is a pretty good quick fix.
EDIT:
How to manually remove configurations from solutions:
With the solution file opened in a text editor, you will see a block called Global which contains sections. The SolutionConfigurationPlatforms section contains the configuration's definitions. There is also an other section called ProjectConfigurationPlatforms where the configurations are assigned. Simply remove the references to the configuration from both groups and that should do it. If you have more complex solutions, there might be other references to remove. This is just a base case.
How to manually remove configurations from projects:
Again, with the project file opened in a text editor, you will see many references to the configuration you want to remove. C# projects have a PropertyGroup with the configuration as a condition. You can simply remove the group entirely. There might be other references to the configuration around the file so make sure to clean everything properly.
Make sure that you have a backup of your files if something goes wrong.
If there is very little project-level customization of the target configurations, this would probably be simplest to manage via an externalized configuration imported into your individual projects via the MSBuild Import element.
In order to allow project-specific overrides, this Import should be placed near the top of the project files. e.g.:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\CommonConfig.targets" Condition="Exists('..\..\CommonConfig.targets')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
...
This would, unfortunately, require you to edit all the project files once to add the Import. However, once this is done, you would be able to add a configuration to the imported .targets file and have it automatically propagate to all the projects.
I can't tell you what will work best for you, but I can say from experience that it becomes very easy to create new solution spaces with 50+ projects from old solution spaces when you don't let Visual Studio write the project files. Instead, you can take off-the-shelf third-party software that will read some configuration files you give it and in a few seconds will spit out a solution and all the projects you need, all configured the way you need them to be.
The same software would also generate the standalone "Common" solution when you just want to compile the common projects.
The right software will give you the flexibility and power that makefiles provide when you're setting up your projects, but you still get to do your work in Visual Studio.
I've used CMake extensively in that role, but for C++ rather than C#. I'm very happy with CMake; I have used it in environments with 50+ projects whose source code is scattered so far and wide that I use scripts to find it all, with some third-party libraries that are brought in as precompiled DLLs or LIBs. Also, from experience I know there's nothing stopping someone from concurrently maintaining their own hand-crafted set of VS project files for the same source code if they really want to. But of course you may want to do your own shopping around for the best software for your environment.
It is a significant investment of time to convert several dozen projects from hand-crafted project files to a more makefile-like system, but in an environment that requires reconfiguring or recombining the projects many times, I felt the investment paid back rather quickly.

How do I deploy two ClickOnce versions simultaneously?

I would like the ability to have a test ClickOnce server for my applications where users can run both the production version and the test version in parallel. Is this possible?
I first tried using the following in AssemblyInfo.cs and also changing the name in the ClickOnce deployment though all this achieved was overwriting the users' production version with the test version. Likewise, it did the same when they went back to the production server.
#if DEBUG
[assembly: AssemblyTitle("Product Name - Test")]
#else
[assembly: AssemblyTitle("Product Name")]
#endif
I thought I should also clarify that the two deployment locations are different from one another and on different servers.
UPDATE
I've also tried setting the GUID for the manifest depending on the debug mode, but again it does not work (dummy GUID's used below).
#if DEBUG
[assembly: Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")]
#else
[assembly: Guid("BBBBBBBB-BBBB-BBBB-BBBB-BBBBBBBBBBBB")]
#endif
How are the two distinguished? It seems that the installer sees them as two separate programs as I get a confirmation of installation for each. Though, when I install the second one, "Add/Remove Programs" only sees the latter, though the former is still on disk, as when I go to reinstall it later, it just simply runs, but then the add/remove programs switches back to the former name.
It might sound kind of lame, but the easiest way to do this is to have two EXE projects in your solution. The Main method of each of these will just call the Main method in your original EXE project (which you'll have just switched over to being a DLL file).
This means that each EXE project can have its own ClickOnce publishing settings, as well as its own app.config file. This means you have different connection strings for the production and the test version.
Your other option (the one that might seem to make the most sense) is to use MageUI.exe to manually build the ClickOnce files, which would let you choose a different configuration file and publish location each time you ran the tool. There's also a command line version (Mage.exe) so you could in theory automate this.
However, we found that the solution with two "runner" projects was far far simpler. I'd recommend you try that first.
ClickOnce: Concurrent versions explains how to do this.
I manually edited the .csproj to specify a different ProductName for debug/release.
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
...
<PublishUrl>publishbeta\</PublishUrl>
<InstallUrl>http://www.softwareabc.com/download/beta/</InstallUrl>
<ProductName>Software ABC Test</ProductName>
<AssemblyName>SoftABCTest</AssemblyName>
<ApplicationIcon>Resources\Test.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
...
<PublishUrl>publish\</PublishUrl>
<InstallUrl>http://www.softwareabc.com/download/</InstallUrl>
<ProductName>Software ABC</ProductName>
<AssemblyName>SoftABC</AssemblyName>
<ApplicationIcon>Resources\Application.ico</ApplicationIcon>
</PropertyGroup>
One caveat is that Visual Studio 2010 doesn't update this if you switch between debug/release. It only takes effect when it loads the solution so make sure to switch debug/release then close and reopen the solution.
See the succinct video on concurrent versioning: ClickOnce: Concurrent versions.
Try changing the Assembly Name in the Application tab in the properties window.
I do that all the time. I even have a screen in my application that changes which version a specific user will get. And I'm not doing anything tricky on the app side, all the magic is on the web server hosting the ClickOnce files.
Take a look at the article my buddy wrote, Fine Grained Versioning with ClickOnce . It explains how we did it.
A variation on Peter Mortensen's two project scenario. I wanted dev, customer test, and customer release. In my case I wanted the customer test providing some visual clues that it was test, not live (e.g. 'TEST' in the title and a different visual theme).
I found it simplest to have two solutions as well as two stub projects. Each project in its own directory, with its own stub program.cs, app.config and assemblyinfo.cs.
In the dev/test solution, the debug configuration was for dev, the release config was for customer test. I used SlowCheetah to transform the app.config for the latter.
In the customer release solution I needed only a release config.
You have to edit your csproj manually, after having at least once configured your project to publish a Click Once application.
Move some of Click Once related properties from the <PropertyGroup> to the <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> property group and duplicate them under the <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> property group.
The properties to duplicate are ApplicationRevision (only if you want separate revision counters), PublishUrl, ProductName and SuiteName (the last two are required to be able to differentiate the configurations on the target machines). You also will have to override the AssemblyName property (without removing it from the first group).
If you want to be able to debug your project under any configuration, you also will have to add the StartAction and StartProgram properties in each group where you overrode the AssemblyName property.
After having given these properties adequate (i.e. different) values, you will be able to publish both configurations, without having to modify your project, just by selecting the desired configuration. Note however you will have to unload your project between publishes for different configurations, or Visual Studio will mess up your parameters.
After that, you also will be able to install both versions on the same target machine.
It is possible to deploy 2 versions of the same application without changing the AssemblyName, here is how it's done...
Create a clickonce deployment
Open the .application file and make the following edit:
3. Run the setup and MyApp will be installed. Depending on previous attempts you may need to clear the application cache with mage -cc
Edit the .application file again replacing MyApp with MyApp2
Run setup and MyApp2 will be installed

Categories