VS2019 extension using IDebugEventCallback2 - c#

I created a new VS extension using VS2019 16.1.6.
and I added this using statement
using Microsoft.VisualStudio.Debugger.Interop;
and added the interface IDebugEventCallback2 to my class
public sealed class VSIXProject1Package : AsyncPackage, IDebugEventCallback2
Not I get the error:
error CS0433: The type 'IDebugEventCallback2' exists in both 'Microsoft.VisualStudio.Debugger.Interop, Version=8.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' and 'Microsoft.VisualStudio.Debugger.InteropA, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
How can I get rid of this error? Or is there an other way to react to debugger events than using IDebugEventCallback2?
edit:
Problem reported to Microsoft:
https://developercommunity.visualstudio.com/content/problem/651199/vs2019-extension-using-idebugeventcallback2.html

VS2019 uses PackageReference format to manage nuget packages for VSIX project.
And by default it will reference Microsoft.VisualStudio.SDK and Microsoft.VSSDK.BuildTools package.Also, since Microsoft.VisualStudio.SDK package have dependencies on many other packages, this project will also reference those packages.
See this simple structure:
Microsoft.VisualStudio.SDK
......(other dependencies)
--Microsoft.VisualStudio.Debugger.Interop
--Microsoft.VisualStudio.OLE.Interop
--Microsoft.VisualStudio.Debugger.Interop.10.0
--Microsoft.VisualStudio.Debugger.InteropA
......(11.0,12.0,14.0,15.0)
--Microsoft.VisualStudio.Debugger.Interop.16.0
--Microsoft.VisualStudio.Debugger.InteropA
So it's clear this issue results from the VSIX project adds reference to both Microsoft.VisualStudio.Debugger.Interop and Microsoft.VisualStudio.Debugger.InteropA.
These two assemblies have the same namespace Microsoft.VisualStudio.Debugger.Interop, and all have IDebugEventCallback2 Interface. I think it's why causes this issue.
As a workaround:
Normal we can use extern alias for this situation. But it hasn't supported for PackageReference format yet. Fortunately I found a good hint from gertjvr. So all we need is:
Unload the project=>Edit the xxx.csproj=>Add the content below into the project file:
<Target Name="ChangeAliasesOfStrongNameAssemblies" BeforeTargets="FindReferenceAssembliesForReferences;ResolveReferences">
<ItemGroup>
<ReferencePath Condition="'%(FileName)' == 'Microsoft.VisualStudio.Debugger.Interop'">
<Aliases>signed</Aliases>
</ReferencePath>
</ItemGroup>
</Target>
You can change the ReferencePath to Microsoft.VisualStudio.Debugger.InteropA if you want to use the Interface from this assembly. It depends on your need.

Related

Polly.Caching.Memory.MemoryCacheProvider throws System.TypeLoadException : method not implemented for one application

I'm using these pacakges:
PackageReference Include="Polly" Version="7.2.2"
PackageReference Include="Polly.Caching.Memory" Version="3.0.2"
I have a testproject that uses these packages and the code works.
When I try to integrate my code in an existing application with lots of other nuget packages, suddenly I get a TypeLoadException.
The method TryGet in the type Polly.Caching.Memory.MemoryCacheProvider from the assembly Polly.Caching.Memory, Version=3.0.0.0, Culture=neutral, PublicKeyToken=c8a3ffc3f8f825cc doesn't have an implementation.
I have been checking everything, but I can't find the cause of this.
The versions of Polly and Polly.Caching.Memory are aligned across all projects involved.
In the bin folder the correct version appears.
I looked at the code of the assembly and the code has an implementation for TryGet
Any suggestion on what I can do to further investigate this?
The packages were all correctly configured.
I got on the right track when I saw that the method was returning a tuple.
I figured that perhaps this second application was not using the correct versions of the same packages.
I changed :
<HintPath>..\Solutions\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll</HintPath>
To
<HintPath>..\Solutions\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll</HintPath>
Bingo!

PrivateFontCollection not found Error in c# (linux)

I'm using command dotnet build in order to build a game in the MonoGame framework in Ubuntu 20.04 using .NET 5.0.
It was fine in Windows, but now that I'm using it here, it gives me this error:
error CS1069: The type name 'PrivateFontCollection' could not be found in the namespace 'System.Drawing.Text'. This type has been forwarded to assembly 'System.Drawing.Common, Version=0.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' Consider adding a reference to that assembly. [/home/mrwoto/Ali/Programming/csharp/SAO/SAO/SAO.csproj]
So, is there anyway to resolve it? How can I add a reference to it in .csproj file?
One option is to add it from the terminal with
dotnet add package System.Drawing.Common
After this, you should be able to see something like the following in the .csproj file.
<PackageReference Include="System.Drawing.Common" Version="5.0.2" />
Please note that dotnet add is more than just adding some text to csproj.
From dotnet add package:
The dotnet add package command provides a convenient option to add a package reference to a project file. After running the command, there's a compatibility check to ensure the package is compatible with the frameworks in the project. If the check passes, a <PackageReference> element is added to the project file and dotnet restore is run.

CS1069: The type name 'RegistryKey' could not be found in the namespace

I use VS 2019 .NET Core app and getting this type of error
CS1069: The type name 'RegistryKey' could not be found in the namespace "Microsoft.Win32". This type has been forwarded to assembly 'Microsoft.Win32.Registry, version=4.1.3.0, Culture="neutral, PublicKeyToken=b03f5f711d50a3a' Consider adding a reference to that assembly.
What causing it?
Did you install the NuGet Package Microsoft.Win32.Registry?
The "Registry" has not be part of .NET Core. For more info, you can refer to Use the Windows Compatibility Pack to port code to .NET Core.
Well, as the message itself puts it, it´s just a matter of adding a reference to that assembly. Add this to your .csproj:
<ItemGroup>
<PackageReference Include="Microsoft.Win32.Registry" Version="4.4.0" />
</ItemGroup>

Fixing "They type 'X' exists in both 'Y' and 'Z'" C# error for System.ServiceModel in LINQPad

If I:
Create a new C# query in LINQPad 6.
Add the System.ServiceModel.Http NuGet package or another package that references it.
Try to instantiate a class from the System.ServiceModel namespace, for example System.ServiceModel.BasicHttpBinding.
Leading to the following .linq file:
<Query Kind="Expression">
<NuGetReference>System.ServiceModel.Http</NuGetReference>
</Query>
new System.ServiceModel.BasicHttpBinding()
Then I get a compile error:
CS0433 The type 'BasicHttpBinding' exists in both 'System.Private.ServiceModel, Version=4.7.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' and 'System.ServiceModel.Http, Version=4.7.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
If I create a project in Visual Studio and add the same NuGet package and code, I do not get this error.
According to the C# Language reference for the error, it should be possible to resolve by using the -reference compiler option or by not referencing one of the assemblies. However, I can't seem to find a way to use this compiler option in LINQPad, nor can I find any way to remove the assembly reference to System.Private.ServiceModel.
How can I fix the error?
This is a bug in LINQPad, triggered by an obscure scenario. The System.Private.ServiceModel package contains a lib folder with an assembly which is required at runtime, and a ref folder with a underscore.underscore file which indicates that no assemblies should be referenced by the compiler. Because LINQPad finds no reference assemblies, it feeds the compiler the assembly in the lib folder, which causes the error.
I've got a fix ready and regression tests are currently running. The fix will likely make it into the 6.11.2 beta build, which should be released in a day or two.

Error: Could not load file or assembly 'Microsoft.Win32Registry' from .NET Standard Library Consumed by .NET Framework Console App

The Problem
The Microsoft.Win32.Registry nuget package is giving me a lot of issues . We had .NET Framework 4.7.2 library that had a helper class that used that package and worked fine from a .NET Framework 4.7.2 unit test project. We recently converted the library to target .NET Standard 2.0, and now this class breaks when used with the following error:
ERROR: System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Win32.Registry, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
File name: 'Microsoft.Win32.Registry, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
at NetStandardRegistryLib.RegistryUtil..ctor(String remoteMachineName)
at NetStandardRegistryLib.Program.Main(String[] args) in C:\src\Microsoft.Win32.Registry-IssueRepro\FrameworkRegistry\RegistryEditor\Program.cs:line 21
When I look at output of the Console project, I don't see the Microsoft.Win32.Registry.dll in the output.
Using ILSpy and loading my .exe - it seems it would try to resolve the .dll from my dotnet core installation, which wouldn't work since it's a .NET Framework app.
To Reproduce
I've created a repo that reproduces for me on my Windows 2010 machine. You can find it here: https://github.com/TylerNielsen/Microsoft.Win32.Registry-IssueRepro
Clone the repo, then open and build the RegistryEditor project.
Using Powershell or your favorite editor - call the tool with three required arguments [remoteMachineName] [Environment variable name to set] [Value to set on the environment variable] **
** Note, this actually requires a remote machine you can reference by IP address. For some reason using 127.0.0.1 doesn't work for me, but I'm unsure why. The use case for this utility is for accessing remote machine environment variables.
Other Notes
When I create a .NET Framework Class Library to use for unit tests and reference the same .NET Standard Library - the Microsoft.Win32.Registry package is included and the utility runs just fine.
In your repo, if you look into both csproj files you'll see they are quite different. The NetStandardRegistryLib.csproj is the new format, the RegistryEditor.csproj is the old one.
Your problem is that old style projects do not resolve dependencies transitively. RegistryEditor will not copy dependencies of its own dependency NetStandardRegistryLib.
There are at least two ways to solve your problem:
Just add Microsoft.Win32.Registry Nuget package to RegistryEditor project explicitly. That'll make the Microsoft.Win32.Registry.dll to appear in the RegistryEditor build folder.
Convert the RegistryEditor.csproj to new format. It's not limited to netstandard builds, you can use it for builds targeting .Net Framework versions as well. And it does resolve dependencies transitively!
Here's a long guide for how to do the conversion in general https://natemcmaster.com/blog/2017/03/09/vs2015-to-vs2017-upgrade/
Since your project is quite simple, I've converted it for you. Just replace the content of RegistryEditor.csproj with the code below. It's still targeting net472.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
<AssemblyName>RegistryEditor</AssemblyName>
<RootNamespace>RegistryEditor</RootNamespace>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\NetStandardRegistryLib\NetStandardRegistryLib.csproj" />
</ItemGroup>
</Project>
Note that several properties that used to be in AssemblyInfo.cs file are provided by csproj file properties now, so you need to remove them from AssemblyInfo.cs to fix compilation errors:
[assembly: AssemblyTitle("RegistryEditor")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("RegistryEditor")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

Categories