Search code examples
.netvb.netwinformsresourcesresx

ResXResourceWriter method replaces the entire ResX file


I'm trying to write a method that should add a resource to an ResX file, the resource is added but the other resources contained in the ResX file are lost, I think that the file is replaced by a new one with only the resource that I added.

PS: I've taken the example from HERE.

What I'm doing wrong and What changes I need to do in my method to fix this?

''' <summary>
''' Adds a resource inside a ResX resource table.
''' </summary>
''' <param name="ResXFile">Indicates the ResX file to add the resource.</param>
''' <exception cref="System.Exception"></exception>
Private Sub AddResXResource(ByVal ResXFile As String,
                            ByVal ResourceName As String,
                            ByVal Resource As Object,
                            Optional ByVal Comment As String = Nothing)

    If Not IO.File.Exists(ResXFile) Then
        Throw New Exception(String.Format("Resource file: '{0}' not found.", ResXFile))

    Else

        ' Open the existent ResX file.
        Using ResXWritter As New Resources.ResXResourceWriter(ResXFile)

            ResXWritter.AddResource(New Resources.ResXDataNode(ResourceName, Resource) _
                                        With {.Name = ResourceName, .Comment = Comment})
            ResXWritter.Generate()

        End Using ' ResXWritter As New Resources.ResXResourceWriter(ResXFile)

    End If ' Not IO.File.Exists(ResXFile)

End Sub

This is how I'm using the method:

Dim MyResource As Bitmap = SystemIcons.Information.ToBitmap
AddResXResource(".\Resources.resx", "SysIcon_Info", MyResource, "Resource comment")

Solution

  • Finally this is what I'm doing (retrieve the existent resources to copy them again in the specified file together with the new one resource), but I don't consider this a consistent solution so I would like to mark as accepted a solution that avoids the copying of the original resources, I really suppose that one of the provided ResX Classes/methods should do that task.

    The code:

    ' Add ResX Resource
    ' ( By Elektro )
    '
    ' Usage Examples:
    ' AddResXResource(".\Resources.resx", "Bitmap Resource", SystemIcons.Information.ToBitmap, "Resource Comment")
    '
    ''' <summary>
    ''' Adds a resource inside a ResX resource table.
    ''' </summary>
    ''' <param name="ResXFile">Indicates the ResX file to add the resource.</param>
    ''' <exception cref="System.Exception"></exception>
    Private Sub AddResXResource(ByVal ResXFile As String,
                                ByVal ResourceName As String,
                                ByVal Resource As Object,
                                Optional ByVal Comment As String = Nothing)
    
        Dim [Resources] As New Dictionary(Of String, Object)
    
        If Not IO.File.Exists(ResXFile) Then
            Throw New Exception(String.Format("Resource file: '{0}' not found.", ResXFile))
    
        Else
    
            ' Open the existent ResX file.
            Dim ResX = New Resources.ResXResourceSet(ResXFile)
    
            ' Get the resource enumerator.
            Dim ResXDictionay As IDictionaryEnumerator = ResX.GetEnumerator()
    
            ' Loop through the existing resources to copy them in the collection.
            Do While ResXDictionay.MoveNext()
                Resources.Add(CStr(ResXDictionay.Key), ResXDictionay.Value)
            Loop ' ResXDictionay.MoveNext()
    
            ' Add the resource(s) in the ResX file.
            ' Note: This will replace the existent file.
            Using ResXWritter As New Resources.ResXResourceWriter(ResXFile)
    
                ' Add the retrieved resources into the ResX file.
                If [Resources] IsNot Nothing Then
                    For Each ResourceItem In [Resources]
                        ResXWritter.AddResource(ResourceItem.Key, ResourceItem.Value)
                    Next ResourceItem
                End If
    
                ' Add the specified resource into the ResX file.
                ResXWritter.AddResource(New Resources.ResXDataNode(ResourceName, Resource) _
                                            With {.Name = ResourceName, .Comment = Comment})
                ResXWritter.Generate()
    
            End Using ' ResXWritter As New Resources.ResXResourceWriter(ResXFile)
    
        End If ' Not IO.File.Exists(ResXFile)
    
        [Resources] = Nothing
    
    End Sub