Is there a signed version of LinqPad that I could use in order to access internals of signed assemblies?
Yes. In LINQPad, go to: Edit, Preferences... and then the Advanced tab, and change the following setting:
And then (as it says in the screenshot) add the following to your project's AssemblyInfo.cs:
[assembly: InternalsVisibleTo("LINQPadQuery")]
Extra information for those puzzled how to insert assembly attributes into AssemblyInfo.cs;
Visual Studio (tested 2022) generates MyProject.AssemblyInfo.cs from your MyProject.csproj file.
Add this to your MyProject.csproj:
<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
<_Parameter1>LINQPadQuery</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
After a rebuild, the MyProject.AssemblyInfo.cs, found in the obj directory, now contains below line:
...
[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("LINQPadQuery")]
...
Related
Since dotnet core moved back to the .csproj format, there is a new autogenerated MyProject.AssemblyInfo.cs which contains, among others:
[assembly: AssemblyCompany("MyProject")]
[assembly: AssemblyVersion("1.0.0.0")]
Note that this is automatically regenerated every build.
Previously, the file was found in the /obj/ directory, now it appears to be only in memory as the file can't be found on disk and clicking the error message does not open any file.
This is the error message:
Since they are defined there, I can't define them myself in the classical AssemblyInfo.cs.
Where/how can I define the Company and Version of a project?
As you've already noticed, you can control most of these settings in .csproj.
If you'd rather keep these in AssemblyInfo.cs, you can turn off auto-generated assembly attributes.
<PropertyGroup>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
If you want to see what's going on under the hood, checkout Microsoft.NET.GenerateAssemblyInfo.targets inside of Microsoft.NET.Sdk.
Those settings have moved into the .csproj file.
By default, they don't show up but you can discover them from Visual Studio 2017 in the project properties Package tab.
Once saved those values can be found in MyProject.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net461</TargetFramework>
<Version>1.2.3.4</Version>
<Authors>Author 1</Authors>
<Company>Company XYZ</Company>
<Product>Product 2</Product>
<PackageId>MyApp</PackageId>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion>
<NeutralLanguage>en</NeutralLanguage>
<Description>Description here</Description>
<Copyright>Copyright</Copyright>
<PackageLicenseUrl>License URL</PackageLicenseUrl>
<PackageProjectUrl>Project URL</PackageProjectUrl>
<PackageIconUrl>Icon URL</PackageIconUrl>
<RepositoryUrl>Repo URL</RepositoryUrl>
<RepositoryType>Repo type</RepositoryType>
<PackageTags>Tags</PackageTags>
<PackageReleaseNotes>Release</PackageReleaseNotes>
</PropertyGroup>
In the file explorer properties information tab, FileVersion is shown as "File Version" and Version is shown as "Product version"
I do the following for my .NET Standard 2.0 projects.
Create a Directory.Build.props file (e.g. in the root of your repo)
and move the properties to be shared from the .csproj file to this file.
This also enables central management of these shared properties in a multi project solution, allowing for example to set the copyright and/or version numbers only once for all projects.
MSBuild will pick it up automatically and apply them to the autogenerated AssemblyInfo.cs.
They also get applied to the nuget package when building one with dotnet pack or via the UI in Visual Studio 2017.
See https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-your-build
Example:
<Project>
<PropertyGroup>
<Company>Some company</Company>
<Copyright>Copyright © 2020</Copyright>
<AssemblyVersion>1.0.0.1</AssemblyVersion>
<FileVersion>1.0.0.1</FileVersion>
<Version>1.0.0.1</Version>
<!-- ... -->
</PropertyGroup>
</Project>
You can always add your own AssemblyInfo.cs, which comes in handy for InternalsVisibleToAttribute, CLSCompliantAttribute and others that are not automatically generated.
Adding AssemblyInfo.cs to a Project
In Solution Explorer, right click on <project name> > Add > New Folder.
Name the folder "Properties".
Right click on the "Properties" folder, and click Add > New Item....
Select "Class" and name it "AssemblyInfo.cs".
Suppressing Auto-Generated Attributes
If you want to move your attributes back to AssemblyInfo.cs instead of having them auto-generated, you can suppress them in MSBuild as natemcmaster pointed out in his answer.
Adding to NightOwl888's answer, you can go one step further and add an AssemblyInfo class rather than just a plain class:
I want to extend this topic/answers with the following. As someone mentioned, this auto-generated AssemblyInfo can be an obstacle for the external tools. In my case, using FinalBuilder, I had an issue that AssemblyInfo wasn't getting updated by build action. Apparently, FinalBuilder relies on ~proj file to find location of the AssemblyInfo. I thought, it was looking anywhere under project folder. No. So, changing this
<PropertyGroup>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
did only half the job, it allowed custom assembly info if built by VS IDE/MS Build. But I needed FinalBuilder do it too without manual manipulations to assembly info file. I needed to satisfy all programs, MSBuild/VS and FinalBuilder.
I solved this by adding an entry to the existing ItemGroup
<ItemGroup>
<Compile Remove="Common\**" />
<Content Remove="Common\**" />
<EmbeddedResource Remove="Common\**" />
<None Remove="Common\**" />
<!-- new added item -->
<None Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
Now, having this item, FinalBuilder finds location of AssemblyInfo and modifies the file. While action None allows MSBuild/DevEnv ignore this entry and no longer report an error based on Compile action that usually comes with Assembly Info entry in proj files.
C:\Program Files\dotnet\sdk\2.0.2\Sdks\Microsoft.NET.Sdk\build\Microsoft.NET.Sdk.DefaultItems.targets(263,5):
error : Duplicate 'Compile' items were included. The .NET SDK includes 'Compile' items from your project directory by default.
You can either remove these items from your project file, or set the 'EnableDefaultCompileItems' property to 'false' if you want to explicitly include them in your project file.
For more information, see https://aka.ms/sdkimplicititems. The duplicate items were: 'AssemblyInfo.cs'
Thanks, this helped me a lot.
In my case, building the project Blazor Server Side Website was successful both on Release and Debug, but publishing the website still failed with the Duplicate Attribute error, which confused me a bit.
The solution was to add <GenerateAssemblyInfo>false</GenerateAssemblyInfo> both to the .csproj and .pubxml file:
Path: <Project>/Properties/PublishProfiles/<ProfileName>.pubxml:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
...
<!-- Add the line below -->
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
</Project>
With .NET 5+, you can use AssemblyMetadata:
<AssemblyMetadata Include="Bar" Value="Baz" />
I've a problem with a build with TFS 2015.
I've a simple project that reference B.dll . B.dll use A.dll . The project don't reference A.dll as it don't use it itself.
A.dll & B.dll bothe are company Framework dll stored in the GAC.
[error]LogistiqueTest\Index.aspx.vb(7,14): Error BC30009: Reference required to assembly 'A.DII.Technique.Interfaces, Version=3.5.0.0, Culture=neutral, PublicKeyToken=e60618ca32d203a8' containing the implemented interface 'A.DII.Technique.Interfaces.IGestionException'. Add one to your project.
This is not a big deal, just a reference that's missing. But we don't want to add unecessary references in our projects
Moreover, this problem don't occurs with visual studio (2013 pro)
So I tracked the problem and I saw that :
-> Visual studio retrieve quickly the reference (A.dll) after the "call" of this line
Target "CoreBuild: (TargetId:61)" in file "C:\Program Files (x86)\MSBuild\12.0\bin\Microsoft.Common.CurrentVersion.targets" from project "D:\AgentTFS_02_work\3\s\LogistiqueTest\LogistiqueTest.vbproj" (target "Build" depends on it):
But TFS don't use the same file; it use
"C:\Program Files
(x86)\MSBuild\Microsoft\VisualStudio\v12.0\Web\Microsoft.Web.Publishing.targets"
The difference between those files is in Microsoft.Common.CurrentVersion.targets, there is some code for resolving assemblies.
So my questions are, is there a way to make TFS build my solution visual studio like ? Force the other target file to be used? Is there another trick to be able to resolve this assembly ?
I tried to add, like i saw in many post around the web, a folder that contains every .dll required, but TFS don't event try to resolve path for A.dll
More information : The exception occurs at the execution of Vbc.exe
because with VS execution the command line has A.dll in the /import section when with TFS it's not added. No problems with MSBuild.exe.
I finally found an anwser :
http://www.nsilverbullet.net/2012/02/17/automatically-resolving-secondary-assembly-references-with-msbuild-and-tfs-build/
I need to add this to the proj file that has problems.
<Target Name="AfterResolveReferences">
<!-- Redefine referencepath to add dependencies-->
<ItemGroup>
<ReferencePath Include="#(ReferenceDependencyPaths)"></ReferencePath>
</ItemGroup>
</Target>
Where do I put InternalsVisibleTo from AssemblyInfo in the new Visual Studio 2017 .csproj project file?
Just in case anyone would like to put InternalsVisibleTo within a .csproj file instead of AssemblyInfo.cs (a possible scenario is to have a naming convention between a project under test and a test project), you can do it like this:
<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>$(MSBuildProjectName).Test</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
Having this the following code will be generated
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("MyProject.Test")]
inside auto-generated AssemblyInfo.cs (e.g. for Debug configuration and .NET Standard 2.0 target)
/obj/Debug/netstandard2.0/MyProject.AssemblyInfo.cs
Additional Info
In case you're on .NET Core 3.1 and this approach isn't working, you may have to explicitly generate assembly info by adding the following to your .csproj file:
<PropertyGroup>
<!-- Explicitly generate Assembly Info -->
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
</PropertyGroup>
As of .NET 5 (and newer .NET versions) this actually works once added to your csproj:
<ItemGroup>
<InternalsVisibleTo Include="YourProject.Tests.Unit" />
</ItemGroup>
Work and discussion around this feature can be seen on this PR on dotnet's GitHub repo.
To clarify Hans Passant's comment above, you simply have to add InternalsVisibleTo to any cs file in your project. For example, I created an AssemblyInfo.cs file in the root of the project and then added the following content (only):
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=<ADD_KEY_HERE>")]
On my Developer PC i have registered the according dll´s and referenced them. (Add reference -> COM)
On the TFS build server this of course causes errors since the references are not registered there and wont be in the future.
What is the best way to circumvent this?
Using tlbimp.exe directly is not necessary. Try replacing any <COMReference> items in the project file with <COMFileReference>. An example would look like this:
<ItemGroup>
<COMFileReference Include="MyComLibrary.dll">
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMFileReference>
</ItemGroup>
The COM dll doesn't need to be registered on the machine for this to work.
Each COMFileReference item can also have a WrapperTool attribute but the default seems to work fine. The EmbedInteropTypes attribute is not documented as being applicable to COMFileReference, but it seems to work as intended.
See https://learn.microsoft.com/en-ca/visualstudio/msbuild/common-msbuild-project-items#comfilereference for a little more detail. This MSBuild item has been available since .NET 3.5.
OK, the answer was more easy than one might think.
Just use "tlbimp.exe" to create an according intrerop.dll which you include in your project and reference to this dll instead to the COM objects.
You may save the time using tlbimp.exe because Visual Studio creates this dll automatically when you reference a COM object.
But it does not upload it to TFS. So finally I just used the automatically created dll and the TFS build Server was happy.
One may find the automatically created Interop dll in: "ProjectFolder\obj\x86\Development"
For anyone who's having trouble with namespace:
tl;dr: use tlbImp /namespace: YOUR_NAMESPACE to give your dll a namespace
This solution worked for Azure Pipeline too. But at first I was having trouble with COMFileReference. When I replaced COMReference with COMFileReference my VS build was failing saying "Namespace can't be found". Finally found the solution here.
I used tlbImp to generate a dll of the COM file using /namespace attribute following this article. Only then you can use the dll in COMFileReference. Here's a bit elaborate example:
<ItemGroup>
<COMFileReference Include="My/Folder/MyComLibrary.dll">
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMFileReference>
</ItemGroup>
or
<ItemGroup>
<COMFileReference Include="..\My\parent\folder\MyComLibrary.dll">
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMFileReference>
</ItemGroup>
I bumped into a strange situation with MSBuild just now. There's a solution which has three projects: LibX, LibY and Exe. Exe references LibX. LibX in its turn references LibY, has some content files, and also references to a third-party library (several pre-built assemblies installed in both GAC and local lib folder). The third-party library is marked as "Copy Local" ("private") and appears in the output of the LibX project, as the LibY's output and LibX's content files do. Now, Exe project's output has LibX project output, content files of the LibX project, LibY project output (coming from LibX), but NO third-party library's assemblies.
Now I worked this around by referencing the third-party library directly in Exe project, but I don't feel this is a "right" solution.
Anyone had this problem before?
There is a difference in behavior when building with MSBuild (i.e. command line, TFS Build and other tools) compared to building with Visual Studio. The secondary references are not included in the references variable sent into MSBuild compile tasks.
There are several extension points provided by MSBuild to change how references are to be resolved. I have successfully used AfterResolveReference to fix this issue for some of my projects - I have posted more info about the background on my blog.
The workaround is to add the following code into you vbproj or csproj files
<Target Name="AfterResolveReferences">
<!-- Redefine referencepath to add dependencyies-->
<ItemGroup>
<ReferencePath Include="#(ReferenceDependencyPaths)">
</ReferencePath>
</ItemGroup>
</Target>
Microsoft has stated that this is a won't fix on Connect
You can actually go into the Microsoft.CSharp.targets or Microsoft.VisualBasic.targets file (located in the framework directory, usually C:\Windows\Microsoft.NET\Framework\v3.5) and modify the csc or vbc task parameters to include additional reference dependencies. In the file (VB targets, line 166; C# targets, line 164) change:\
References="#(ReferencePath)"
to
References="#(ReferencePath);#(ReferenceDependencyPaths)"
This might cause other issues depending on how complicated things are and it may play tricks with the Visual Studio inproc compiler, but it's the only way to do it in MSBuild that I've found.
josant's answer almost worked for me; I kept getting an error in Visual Studio when I tried that:
A problem occurred while trying to set the "References" parameter for the IDE's in-process compiler. Error HRESULT E_FAIL has been returned from a call to a COM component
The solution to my problem was to put a condition on the ItemGroup, like this:
<Target Name="AfterResolveReferences">
<!-- Redefine referencepath to add dependencies-->
<ItemGroup Condition=" '$(BuildingInsideVisualStudio)' != 'true' ">
<ReferencePath Include="#(ReferenceDependencyPaths)"></ReferencePath>
</ItemGroup>
</Target>
That caused Visual Studio to ignore the reference change completely, and the build works fine locally and on the build server.
Yes, I've had that problem, too. Though I'd love to say otherwise, I believe you must include all transitive dependencies as references in your build file.
I've combined Alex Yakunin's solution with one that will also copy native dll's.
The AfterResolveReferences method fails if you've got a directed graph not a tree with a "trying to deploy different copies of the dll" error. (cf. How to configure msbuild/MSVC to deploy dependent files of dependent assemblies)