Generated AssembyInfo-file causes Multilingual-App-Toolkit to reset translations - c#

When building our .Net application (Target Framework net461), MSBuild generates the AssemblyInfo files like:
[ApplicationName]_[randomHash]_wpftmp.AssemblyInfo.cs.
Additionally we are using MultilingualAppToolkit which references the *.resx file of the project
...original="[ApplicationName]/PROPERTIES/RESOURCES.RESX"
in the translation file (*.de.xlf). But this path is replaced by
...original="[ApplicationName]_[randomHash]_wpftmp/PROPERTIES/RESOURCES.RESX")
and therefore all translations (*.de.resx) are resetted, because they are not existing in the new namespace.
Is there any workaround to avoid replacing the "original"-references in the *.xlf file?

Related

Using Grpc.Tools with Protoc plug-in to generate additional C# files

I am using Grpc.Tools (2.38.1) to generate C# types and gRPC stubs from a Test.proto file containing some service definitions.
To do this I have the following in my project's .csproj file:
<ItemGroup>
<Protobuf Include="**/*.proto" />
</ItemGroup>
This is all working fine: my Test.proto gets compiled to Test.cs and TestGrpc.cs in the obj/Debug folder of my project. The types within them can be referenced from within other types in the project.
But I need to create a WCF interface for the service too, so I thought I could generate this using a custom Protoc plug-in. So I wrote a simple Protoc plug-in that writes out a TestWcf.cs file containing an interface. I then placed this plug-in executable on my path named protoc-gen-blah.exe and updated the entry in the .csproj file to this:
<ItemGroup>
<Protobuf Include="**/*.proto" AdditionalProtocArguments="--blah_out=obj\Debug" />
</ItemGroup>
This correctly creates the C# file, TestWcf.cs, with my interface in: fantastic.
The problem is that my interface within TestWcf.cs cannot be referenced from other types in the project unless I manually include the generated file in the project: something I do not have to do with the other generated files.
Whilst none of the files are included in the project by default―I have to enable 'Show All Files' to see them―Test.cs and TestGrpc.cs have arrows beside them in the Solution Explorer that allow them to be expanded to reveal the types inside. TestWcf.cs does not have this arrow. So Visual Studio is somehow aware that Test.cs and TestGrpc.cs are source code files.
Does anyone know what I need to do for my generated file to be automatically recognised by Visual Studio like the other two files are?
I suspect it has something to do with this part of the Grpc.Tools build target, as I noticed my TestWcf.cs file is not included in the files deleted by the Grpc.Tools clean either, but I can't see why it does not consider my generated file to be C#.
When I build, this is the Protoc call:
D:\...\Src\packages\Grpc.Tools.2.38.1\tools\windows_x86\protoc.exe --csharp_out=obj\Debug ⤶
--plugin=protoc-gen-grpc=D:\...\Src\packages\Grpc.Tools.2.38.1\tools\windows_x86\grpc_csharp_plugin.exe ⤶
--grpc_out=obj\Debug --proto_path=D:\...\Src\packages\Grpc.Tools.2.38.1\build\native\include ⤶
--proto_path=. --dependency_out=obj\Debug\xxxx_Test.protodep --error_format=msvs --blah_out=obj\Debug ⤶
Test.proto
The dependency file looks like this:
obj\Debug/Test.cs \
obj\Debug/TestGrpc.cs \
obj\Debug/TestWcf.cs: Test.proto
Thanks.
I believe the problem is caused some logic in Grpc.Tools that informs MSBuild of the files that have been generated:
public override string[] GetPossibleOutputs(ITaskItem protoItem)
{
...
var outputs = new string[doGrpc ? 2 : 1];
...
outputs[0] = Path.Combine(outdir, filename) + ".cs";
if (doGrpc)
{
...
outputs[1] = Path.Combine(grpcdir, filename) + "Grpc.cs";
}
return outputs;
}
This code only caters for two files being generated from a Protocol Buffer source (name.proto): the Protocol Buffers code generation (name.cs) and the gRPC code generation (nameGrpc.cs). It is not picking up the additional file and informing MSBuild that it exists, hence Visual Studio does not consider it to be code.
There is no away around this short of changing the Grpc.Tools code.

copy App.config when compiling with CodeAnalysis.Compilation.Emit

I am compiling a C# project using the Roslyn CodeAnalysis APIs, as in the following snipet:
...
EmitResult emitResult = null;
using (FileStream outputFileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write))
{
emitResult = compilation.Emit(outputFileStream, null);
}
...
This works perfectly. However, when I want to compile an executable project that contains an App.Config file, this file is not emitted in the output directory (similar to how it is emitted when compiling via Visual Studio), which is problematic if you want to parse some configs from that file at runtime.
I realize that it should not be emitted by default, but I would probably need to enable some option, or to somehow extract the App.Config path from the Project object and emit it myself? I cannot seem to find any information regarding this, and the Project class does not seem to contain any information regarding config files (unless I am missing something).
Is there some specific API that I need to use to achieve the above? Any pointers to existing code that does this available?
Thanks a lot!
Roslyn is not a build system, it's a compiler. It can only transform code into assemblies (and PDBs). When you compile a .csproj in Visual Studio, MSBuild reads all the properties and items in the project file and translates them into a series of steps that, among other things, call the Roslyn compiler, copies App.config files to the output directory, copies references, etc.
While it's true Roslyn can read MSBuild project files, it only uses this information for compilation purposes, such as locating references.
So, if you're dynamically compiling assemblies, you'll have to copy the App.config file yourself (note - VS doesn't emit this file - it just copies and renames it).

How do I coordinate assembly version information in my tree of many C# projects?

What approaches have you taken to coordinating changes to version and Copyright for groups of assemblies?
I have a tree of many csprojs each with its own AssemblyInfo file. As part of my build process I want to set copyright year and version. It looks like the following options be be available but file modification is the only one I've seen thus far:
Modify all files via script
Include resource with date (a macro, a singleton class with public static variables)
Override AssemblyVersion on command line ( -DAssemblyVersion="1.0.0.1" ?)
Reference Environment variable ([assembly: AssemblyFileVersion("${ENV.VERSION")])
I'm used to keeping the source tree clean of generated files in Java/C++ via command line params, defines and centralizing all version specification in a single file.
What approach to do you use to keep the versions in sync and manageable?
Thanks
Peter
In the top folder, I place a CommonAssemblyInfo.cs that contains the ... common stuff, such as copyright and FileVersion. This file is just contains some default attributes and is regenerated by a script(a simple .bat file) on the build server, Hudson in my case. Remove these common attributes in each of the projects AssemblyInfo.cs.
In each project in the solution, I add this file. but use "Add as link" - available in the drop down of the "Add" button when you add an existing file. i.e. all projects just contains a reference to the same file, so there's only one file to update.
Regardless of which route you take to actually update the version number, you can use an individual AssemblyInfo.cs file to specify a shared version.
Create the file at some level above the other projects, in terms of structure, then add it to all projects (from within Visual Studio), but when doing so be sure to select 'Add as link'.
I've used an MSBuild task to handle the updating, too, I just can't think of it - which build engine do you use?
You can theoretically have one single assembly file. Just link the file in all other projects: Add existing file >> link file instead of adding (button dropdown)

Type or namespace cannot be found, when reference does exist

I have a wpf Application in which I am trying to reference a class library i have created.
I have added a reference to the .dll
And i have added the using statement to my file, and the intellisense actually sees the new namespace.
Then in my code I am able to create new objects of classes in my added .dll just fine. the intellisense sees all the methods ect..no problem, no errors.
when I try to build my wpf application, all the sudden I get the type or namespace cannot be found error on my added dll.
Then i get errors whenever i am trying to create objects from that .dll.
I don't get what is happening.. why does it work before I build, but when I build it decides it doesn't know where that .dll is i am referencing?
Also i have gone to that class library i am trying to add, and mades sure it builds with no errors.
The most common cause of this is that your .DLL targets the full .NET Framework, but the WPF Application targets the Client Profile.
For example, if your library targets .NET 3.5, make sure your WPF Application targets the full .NET 3.5 or 4.0 framework, not the client profile.
A few thoughts on this matter that you can try:
Check that a lower version is not calling a higher version assembly (e.g. .NET 3.5 project is not calling a .NET 4.0 assembly).
Clean -> Build (or Rebuild)
Manually delete bin/obj folders of both caller and calling projects. This forces everything to be built - the 'hard ' way. This may sound redundant, but has worked for me a couple of times.
Restart VS - sometimes, there is just no explanation.
Reboot - when nothing else works, give it a break and try again.
You can Copy any .dll files from other project,
two .dll files.
eg: A.dll,A.pdb
and Rename this two files to your project's name.
Then you can rebuild this project.
If you're getting this without a DLL - just a code file check it's set to compile. In Visual Studio 2013 I keep adding code files and it sets the Build Action (found under Advanced section of Properties of the code file to "Content" rather than "Compile". Change this.
Sometimes an explicit naming of the assembly which contains the namespace is required.
xmlns:myns="clr-namespace:MyNamespace;assembly=MyAssembly"
I don't know why it is sometimes required.

How do you get the XML documentation to show for a referenced C# library?

Suppose you have a C# library with several functions, all documented with the usual /// <summary> filled out nicely. Referencing the project will make the function and parameter description appear in the Visual Studio contextual help. But is it possible to have this show if you don't reference the project itself, just a build (and potentially some other file that has the documentation inside)?
Yes there is - the library needs to be built with the "XML Documentation file" tickbox checked (in the project property pages)
With this option ticked the build process will now build an extra XML file in the output directory which contains all of the xml documentation - whenever Visual Studio references an assembly by file it will load and show intellisense documentation from this XML file (if it can be found).
You should distribute this file alongside (in the same directory as) your compiled library.

Categories