7

I'm generating/constructing from code a custom .Net managed resource file (a .resx file)

In C# or VB.Net, how I could design a method capable to merge, join or embbed my custom .resx file into a .net assembly (more or less in the same way that VS compiler does by default)?

So, in one hand I have a Application.exe (already compiled), and in the other hand I have a resources.resx, my intention is to "merge" the resx into the compiled assembly.

Any sort of info will be gratefull, because I didn't found nothing about it.

PS: The only requisite is not use 3rd party tools such as ILMerge.

ElektroStudios
  • 19,105
  • 33
  • 200
  • 417
  • 1
    Couldn't you use a DLL to for the resources? Its not compiled into the EXE but would allow updates independent of the EXE – Ňɏssa Pøngjǣrdenlarp Mar 18 '15 at 12:46
  • @Plutonix what you mean? I didn't understood right, If you are asking me whether I can add a dll into the resx table? then yes, If you are asking me whether I can use a dll instead of a .resx?: then no because I will not discard all the work that I spent writting +1.000 lines of code to manage a .ResX file in various ways (an helper class to add/read/delete resources and that kind of things). thanks for comment – ElektroStudios Mar 18 '15 at 13:23
  • Here is the source if helps you to see an approach on this issue: http://pastebin.com/qYccnJVh – ElektroStudios Mar 18 '15 at 13:27
  • So you have an EXE with or without some resources already. At some point you want to add more resource items to it using a resx as the repository for the new items? Presumably this takes place on a deployed app? – Ňɏssa Pøngjǣrdenlarp Mar 18 '15 at 13:29
  • Instead of embedding the .resx into the exe, why not load the .resx file at runtime, using like ResourceManager.CreateFileBasedResourceManager https://msdn.microsoft.com/en-us/library/system.resources.resourcemanager.createfilebasedresourcemanager(v=vs.110).aspx – cchdev Mar 23 '15 at 13:12

2 Answers2

6

You won't be able to merge resources into an already compiled file without external tools (either hand-rolled or already existing). That may be why you didn't find any info about it. It is possible to merge the file by hand but I'd recommend another approach.

If possible you could try generating your resource file before the compilation occurs, for example by using a text template in Visual Studio. Then when compiling the usual behavior would be applied to the generated resx file which would be lifted in the assembly.

If generating the resource file before compilation is not possible, you will have to use an external tool

Community
  • 1
  • 1
samy
  • 14,832
  • 2
  • 54
  • 82
  • Thanks for answer, you talk about external tools but I've tried IlMerge, ILMergeGUI, .Net Shrink and SmartAssembly, none of them works to merge a resx (they didn't recognize that kind of .resx file, and changing the extension to .dll will not work), then you say merging is not possible, welll, and what happens about joining or embedding? – ElektroStudios Mar 18 '15 at 13:20
  • 1
    Merging implies two compiled elements (eg: code.dll and resources.dll). If you take a look at the link in my answer you should see examples of joining / embedding that may help you – samy Mar 18 '15 at 13:48
  • thanks but I didn't found how to do it through the link that you've provided – ElektroStudios Mar 21 '15 at 21:15
4

I finally solved through a little different approach, after I created the ResX file what I do is compile a .net assembly at runtime and asigning that ResX file as an embeded resource of the assembly to be compiled, so, the result is a compiled .net dll that can be merged or whatever I want and I can extract the ResX file at any moment from that dll, nice!.

If someone knows a simpler/easier alternative than this, feel free to post an answer (for help or just for the remaining bounty)

Here is the example code:

Imports System.CodeDom.Compiler
Imports System.IO
Imports System.Reflection

Public Class Form1

Private Sub Test() Handles MyBase.Shown

    ' Create the ResX file.
    Dim resX As New ResXManager(Path.Combine(Application.StartupPath, "C:\MyResources.resx"))
    With resX
        .Create(replace:=True)
        .AddResource(Of String)("String Resource", "Hello World!", "String Comment")
    End With

    ' Compile an assembly.dll that contains the ResX file as an embedded resource.
    Dim codeProvider As CodeDomProvider = CodeDomProvider.CreateProvider("VB") ' or New VBCodeProvider()
    Dim parameters As CompilerParameters = New CompilerParameters()
    With parameters
        .GenerateExecutable = False
        .OutputAssembly = "C:\Assembly.dll"
        .EmbeddedResources.Add("C:\MyResources.resx")
    End With
    Dim results As CompilerResults = codeProvider.CompileAssemblyFromSource(parameters, "Public class ResourceClass : End Class")

    ' Read the assembly.
    Dim assembly As Assembly = assembly.LoadFile("c:\Assembly.dll")

    ' Extract/read the ResX file from assembly.
    Dim embeddedFileName As String = "MyResources.resx"
    Dim targetFilePath As String = "C:\NewMyResources.resx"
    Using s As Stream = assembly.GetManifestResourceStream(embeddedFileName)
        Dim buffer As Byte() = New Byte(CInt(s.Length - 1)) {}
        Dim read As Integer = s.Read(buffer, 0, CInt(s.Length))
        Using fs As New FileStream(targetFilePath, FileMode.Create)
            fs.Write(buffer, 0, buffer.Length)
        End Using
    End Using

End Sub

End Class

I've taken some help to do this from here:

Generating DLL assembly dynamically at run time

Read embedded file from assembly

Community
  • 1
  • 1
ElektroStudios
  • 19,105
  • 33
  • 200
  • 417