Merging Visual Studio Code Coverage fails with ImageNotFoundException - visual-studio-2010

I'm trying to export visual studio code coverage files (data.coverage) into xml as described in this blog post from the code analysis team. I've moved the code example in that post into a custom MSBuild task. My custom task references the Microsoft.VisualStudio.Coverage.Analysis.dll located in the PrivateAssemblies folder of Visual Studio.
Right off the bat, trying to load the code coverage file throws an code analysis typed exception ImageNotFoundException, stating that the "Image file fully-qualified-file-path-to-dll could not be found."
// the following line throws an exception
CoverageInfo current =
CoverageInfo.CreateFromFile( "c:\path\testresults\x\y\z\data.coverage");
The path is fully qualified and the DLL it refers to does exist. My testsettings has this file listed as the assembly to instrument and the "Instrument in place" checkbox is set. I can view code coverage within Visual Studio, so I know coverage is working.
I'm running my MSBuild script from the Visual Studio command line. It looks like this:
<Project ToolsVersion="4.0" DefaultTargets="Default;"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask TaskName="CustomTasks.MergeCoverageTask"
AssemblyFile="CustomTasks.dll"
/>
<Target Name="Default">
<ItemGroup>
<CoverageFiles Include="**\data.coverage" />
</ItemGroup>
<MergeCoverageTask
CoverageFiles="#(CoverageFiles)"
OutputFile="output.xml"
/>
</Target>
</Project>
Can anyone suggest what I need to do to get this working correctly?

5 hours later and this is a tumbleweed. I found some additional detail here, which helped get me further down the path.
In order for this to work, you need to include a few additional files alongside the custom task and supply folder locations for the pdb's and instrumented dll's.
Regarding additional files, you need the following:
The custom build task must reference Microsoft.VisualStudio.Coverage.Analysis.dll
Your bin folder must contain the following additional files:
Microsoft.VisualStudio.Coverage.Symbols.dll
dbghelp.dll
(If you don't have visual studio installed, you must perform regsvr32.exe on msdia100.dll)
Regarding paths to assemblies and symbols, the CreateFromFile method takes a collection of folders to search. What seems really strange is that error complains about not being able to locate missing instrumented assemblies, and it specifies the full path..
Image file c:\project\output\Assembly.dll could not be found.
...but if you specify that path, it doesn't work.
CoverageInfo current =
CoverageInfo.CreateFromFile( "c:\project\testresults\x\In\data.coverage",
new string[] { "c:\project\output" },
new string[] { "c:\project\output" });
However, changing the path to be the folder of the TestResults output works fine:
CoverageInfo current =
CoverageInfo.CreateFromFile( "c:\project\testresults\x\In\data.coverage",
new string[] { "c:\project\testresults\x\Out" },
new string[] { "c:\project\testresults\x\Out" });
I question whether "instrument in place" really means in that folder, or instrument and copy to the MS Test run folder.
Well dear SO folk, if you're reading this, you get a cookie.

Related

Visual studio add project reference with lib file

It looks like there has been some work done to add support for visual studio c++ project to project references.
https://developercommunity.visualstudio.com/t/MsBuild-to-resolve-and-copy-ProjectRefer/668834?space=62
If I setup a reference from GoogleTestSample to oqkern I am able to get a bunch of files copied locally.
oqkern.net.dll
oqkern.net.runtimeconfig.json
and also a bunch of other dlls
Is there a way I can get the oqkern.net.lib file to be copied locally as well?
I seem to need that to be able to compile without getting linker errors.
I think the property below takes care of being able to include source files from the referenced project:
I have tried to use the "content file" approach but it didn't seem to work.
<ItemGroup>
<Library Include="..\..\src\oqkern\bin\$(Platform)\$(Configuration)\oqkern.net.lib">
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</DeploymentContent>
<DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</DeploymentContent>
</Library>
</ItemGroup>
I'm not sure if the content file approach happens soon enough, I need the file copied before the build so things compile.
A pre-build event works:
xcopy /y /d "$(SolutionDir)src\oqkern\bin\$(Platform)\$(Configuration)\oqkern.net.lib" "$(OutDir)"

Using a ** wildcard in an F# project causes Visual Studio to refuse to load the project

I've got an F# project with several additional files stored in many nested folders, creating a complex folder structure. The compiler doesn't need to know about them: all I need to do is to have them copied into the output directory at the end of the build process.
I tried adding my files using the ** wildcard:
<ItemGroup>
    <FilesToCopyToOutput Include="additionalData\**\*.*"/>
</ItemGroup>
It works fine when running MSBuild manually from PowerShell. However, when I attempt to open my project in Visual Studio (v. 2015), I get the following error message:
Cannot open F# project . This project uses
wildcards in the item specification. Wildcards in F# projects are not
currently supported.
Similarly, a C# project with the wildcards works just fine. I guess this has something to do with the fact that the order of files in an F# project matters and using the wildcards causes a problem if a user wants to reorder the files.
However, I'm wondering if there's anything that can be done in my particular case: I don't care if the files are available in VS or not: I just want them to be copied to the output folder.
Using a ** wildcard in an F# project causes Visual Studio to refuse to load the project
Indeed, Visual Studio 2017 is a good choose. I have test the ** wildcard in the Visual Studio 2015 and 2017, it works fine in the Visual Studio 2017 but not in the Visual Studio 2015, got the same error as you.
Since you could not change the tech stack to use Visual Studio 2017, I would like provide a workaround for this issue, you can check if it works for you.
Since you do not care if the files are available in VS or not, you just want them to be copied to the output folder, you can use a power shell script to copy the additionalData folder to the output folder, like:
Copy-Item -Path "ThePathForAdditionalData\additionalData" -Destination "ThePathForProject\bin\Debug" -recurse -Force
Then execute this power shell script with MSBuild task after build:
<Target Name="CopyMyFiles" AfterTargets="Build">
<Message Text="Copying files..."/>
<Exec Command="C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NonInteractive -executionpolicy Unrestricted -command "& { .\YourCopyFiles.ps1 } "" ></Exec>
</Target>
Hope this helps.
I assume FilesToCopyToOutput is the name you gave to an item collection, and the question is how to stop the old F# compiler from thinking it should handle it?
I suspect what you want to do though is to treat an entire folder as content items and copy them to the output folder :
<Content Include="additionalData\**\*.*">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
Copy Task
If you want to copy items with an MSBuild task you can use Copy. You should be able to write :
<ItemGroup>
<MyAdditionalData Include="additionalData\**\*.*" />
</ItemGroup>
<Target Name="CopyFiles">
<Copy
SourceFiles="#(MyAdditionalData)"
DestinationFolder="$(OutputPath)"
/>
</Target>
The Include attribute allows selecting multiple files that can be used as arguments to a task. Exclude is used to exclude files. You can specify a Condition attribute too, eg to run the task only for Release or Debug configuration. $(OutputPath) is one of the MSBuild properties that can be used in paths.
How to: Exclude Files from the Build shows how you can combine all those attributes to process specific items in a directory, eg:
<JPGFile
Include="Images\**\*.jpg"
Exclude = "Images\**\Version2\*.jpg"/>
This will include all files in the Images directory except those in Version2
Using Post-build events
Most people though didn't use MSBuild until the latest simplified format.
The most common way to copy files after build is to use a post-build event from the project's property pages, eg :
xcopy $(ProjectDir)additionalData\*.* $(TargetDir) /s /e
$(ProjectDir) and $(TargetDir) are replacement macros that point to the projects' folder and output folder. The list of all macros is available in Pre-build Event/Post-build Event Command Line Dialog Box.

The following projects do not have a valid ProjectGuid and were not built using a valid solution (.sln) thus will be skipped from analysis

When you are building a dotnet core project with SonarQube you may be facing the error in the log:
WARNING: The following projects do not have a valid ProjectGuid and were not built using a valid solution (.sln) thus will be skipped from analysis...
What should you do?
As dotnet core projects (.csproj) will not have <ProjectGuid>...</ProjectGuid> tag specified in the default template this needs to be manually added.
So you need to edit the .csproj file like this:
<PropertyGroup>
<!-- other properties here -->
<!-- SonarQube needs this -->
<ProjectGuid>{E2CEBBAF-6DF7-41E9-815D-9AD4CF90C844}</ProjectGuid>
Make sure to place your own GUID inside the <ProjectGuid>...</ProjectGuid> Tag
Here's a solution to adding the missing xml elements in powershell.
$paths = Get-ChildItem -include *.csproj -Recurse
foreach($pathobject in $paths)
{
$path = $pathobject.fullname
$doc = New-Object System.Xml.XmlDocument
$doc.Load($path)
$child = $doc.CreateElement("ProjectGuid")
$child.InnerText = "{"+[guid]::NewGuid().ToString().ToUpper()+"}"
$node = $doc.SelectSingleNode("//Project/PropertyGroup")
$node.AppendChild($child)
$doc.Save($path)
}
The solution I came up with is to build the solution, not the project files. If using Azure DevOps, use **/*.sln instead of **/*.csproj in your DotNetCoreCLI build step.
Note that the ProjectGuid can be found in the .sln file if you use such a file.
The .sln file has a long line similar to:
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Project1",
"path\Project1.csproj", "{307CB8DB-DC9C-4830-AA92-D842D89E17E0}"
In it, the first Guid (inside Project(...)) specifies the type of the project, and you can find a "dictionary" on the web that translates each Guid there to a human-readable type. For example, {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} means "C#" project type.
But the last Guid (given after the filename) in the .sln entry is the ProjectGuid.
So if you use an .sln file always, also from the SonarQube runs, there should be no need to insert a Guid in the .csproj file.
The other place the ProjectGuid can be specified is in the .csproj. Like other answers say, it looks like this:
<PropertyGroup>
<!-- possibly other properties -->
<ProjectGuid>{307CB8DB-DC9C-4830-AA92-D842D89E17E0}</ProjectGuid>
</PropertyGroup>
So if you never use .sln file in any context, you can just create any new Guid. In Visual Studio, you can use "Tools" - "Create GUID" - "Registry Format" to create a fresh Guid and and have it formatted correctly for this purpose.
However, from the above, it is clear that if you do use an .sln file in some contexts (like from Visual Studio during development/maintenance), but do not use that .sln file from the SonarQube run, then the ProjectGuid you put in the .csproj should match the one present in the .sln. One way you could achieve it, when creating new projects, is to first add the new project to the .sln, then do a diff ("Compare with Unmodified" or similar) on your .sln file using your version control software (like Git) to obtain the ProjectGuid, and copy/paste that Guid, including braces {...} into the new .csproj file.

web deployment package (.zip file) not created in Visual Studio 2013

I am trying to create a deployment package in Visual Studio 2013. I have specified that the package should be placed at C:\Deployment\bin\WebSite.zip - the absolutely simplest location. All the project files build but the publish fails with this error:
Transformed Web.config using C:\Services\IdentityServer\Thinktecture.IdentityServer.v2\src\OnPremise\WebSite\Web.Siloed.config into obj\Siloed\TransformWebConfig\transformed\Web.config.
Auto ConnectionString Transformed Areas\Admin\Views\Web.config into obj\Siloed\CSAutoParameterize\transformed\Areas\Admin\Views\Web.config.
Auto ConnectionString Transformed Views\Web.config into obj\Siloed\CSAutoParameterize\transformed\Views\Web.config.
Auto ConnectionString Transformed obj\Siloed\TransformWebConfig\transformed\Web.config into obj\Siloed\CSAutoParameterize\transformed\Web.config.
Copying all files to temporary location below for package/publish:
obj\Siloed\Package\PackageTmp.
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\Web\Microsoft.Web.Publishing.targets(2584,5): Error : Copying file ..\..\..\Deployment\bin\um.zip to obj\Siloed\Package\PackageTmp\.ebextensions\um.zip failed. Could not find a part of the path '..\..\..\Deployment\bin\um.zip'.
I have no idea where this path '......\Deployment\bin\um.zip' is coming from. I specified that the deployment package should be created at C:\Deployment\bin\WebSite.zip, not um.zip.
So, I checked out C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\Web\Microsoft.Web.Publishing.targets(2584,5) and the code looks like this:
<!--Force Copy Of all file to the $(WPPAllFilesInSingleFolder) if needed-->
<CopyPipelineFiles PipelineItems="#(FilesForPackagingFromProject)"
SourceDirectory="$(WebPublishPipelineProjectDirectory)"
TargetDirectory="$(WPPAllFilesInSingleFolder)"
SkipMetadataExcludeTrueItems="True"
UpdateItemSpec="True"
DeleteItemsMarkAsExcludeTrue ="True"
Condition="'#(FilesForPackagingFromProject)' != ''">
<Output TaskParameter="ResultPipelineItems" ItemName="_FilesForPackagingFromProjectTempory"/>
</CopyPipelineFile>
I have tried editing the "PipelineItems" and "SourceDirectory" and have even hardcoded them. But the same message, "Could not find part of the path....", is being displayed every time I run the Publishing. The "Could not find part of the path...." points to the new paths I specified in "PipelineItems" and "SourceDirectory. The .zip file never seems to get created anywhere. I have seached my entire computer for um.zip and WebSite.zip with not luck.
Any help would be greatly appreciated as I am completely out of ideas.
Turns out this um.zip is somehow part of build but it is not getting created. Anyway, I was lucky enough to find a previous deployment package that was generated and I just manually built the new deployment package based off the old one. Deployed fine so I guess that is how I will proceed.

Cannot load WiX projects after installing the VS2010 Web Publishing Updates

I installed the VS2010 web publishing updates yesterday, and now whenever I try to load a WiX setup project (all showing as unloaded in solution explorer) I'm getting the error:
The imported project "PROJECTNAME.wpp.targets" was not found. Confirm that the path in the declaration is correct, and that the file exists on disk. C:\Program Files\MSBuild\Microsoft\VisualStudio\v10.5\Web\Microsoft.Web.Publishing.targets
Where PROJECTNAME is the path to my setup wixproj file, without the .wixproj extension. I've checked through the project file and there is no reference to a wpp.targets file anywhere. I decided to try and create a blank targets file in that location and so added one with just this in it:
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
</Project>
But got exactly the same error - a not found exception despite the file being there!
I then dug into the Microsoft.Web.Publishing.targets file and had a look for any ".wpp.targets" text, which gave me this:
<PropertyGroup Condition="'$(EnableWebPublishProfileFile)'=='true' And
'$(WebPublishProfileFile)' != '' And Exists($(WebPublishProfileFile)) ">
<WebPublishProfileCustomizeTargetFile Condition="'$(WebPublishProfileCustomizeTargetFile)'==''">
$([System.IO.Path]::ChangeExtension($(WebPublishProfileFile), '.wpp.targets'))
</WebPublishProfileCustomizeTargetFile>
...
So that looks to be setting up a filename of PROJECTNAME.wpp.targets, but only when the EnableWebPublishProfileFile property is set to true. I added this to my wixproj file's main propertygroup:
<EnableWebPublishProfileFile>False</EnableWebPublishProfileFile>
Again though, it made no difference at all to the error. I'm running out of ideas here now!
Further update
I've been trying to repo this on a blank project (so far without success), and the messing about has narrowed the error down to this line (186) in the Microsoft.Web.Publishing.targets file:
<Import Project="$(WebPublishPipelineCustomizeTargetFile)"
Condition="'$(WebPublishPipelineCustomizeTargetFile)' != ''"/>
This is set at the top of the file:
<WebPublishPipelineCustomizeTargetFile
Condition="'$(WebPublishPipelineCustomizeTargetFile)'==''">
$(WebPublishPipelineProjectDirectory)\*.wpp.targets
</WebPublishPipelineCustomizeTargetFile>
I'm not sure how this is getting changed to PROJECTNAME.wpp.targets though?
I tried overriding this in my project file, but once again, it makes no difference at all.
Next I added an Exists() condition to the line in the targets file, now some projects are working and others are not, instead failing (on build) with the error:
The "DisableEscapeMSBuildVariable" parameter is not supported by the "ImportParametersFile" task. Verify the parameter exists on the task, and it is a settable public instance property.
My journey continues...
I experienced the same issue when trying to open a standard web project.
The proj file was referencing the following import for v10.0 targets but throwing the import error in the question which referred to v10.5 targets.
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.targets" />
The same was true when I referenced a hard coded path - I still got v10.5 error
My solution was to simply back up and remove that version located at:
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\10.5
I'm really not sure what other programs and projects need this version or why import paths were not followed but it go this project open for me seeming falling back to the correct version.

Resources