Search code examples
c#vb.netwinformsvisual-studioresx

Merge ResX file at runtime?


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.


Solution

  • 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