VB.NET 2008 Get resource file as IO.Stream

mediasoftware
mediasoftware used Ask the Experts™
on
Hi,

I am developing a VB.NET 2008 application, consisting of a main EXE application and several resource DLLs.

I need two functions for the DLL:

1) one function to get a list of all files in the resources of the DLL.
2) one function to return 'by name' a resource file as a System.IO.Stream type.

NOTE: The files will not be "Embedded Resource" (this doubles the size of the DLL), so I think cannot use 'GetManifestResourceStream'.

I currently use:

Return New System.IO.MemoryStream(My.Resources.MyFileName)

but I want it to be called by name.


Thank you.
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Most Valuable Expert 2012
Top Expert 2008

Commented:
You should be able to use this:

Return My.Resources.ResourceManager.GetStream("resource name goes here")

Author

Commented:
Hi,

Thank you for your suggestion. I tried it and it does not seem to work. I also took a look at the documentation for this, and it seems it returns a System.IO.UnamnagedMemoryStream, which may not be compatible with my System.IO.Stream requirement.

Thank you.
Most Valuable Expert 2012
Top Expert 2008

Commented:
Tell me what you mean by "does not seem to work"?  All streams in .NET inherit from System.IO.Stream, including UnmanagedMemoryStream.

Author

Commented:
I am using this resources to pass them to a third-party .NET component, that requires them in this format.
(System.IO.Stream)

Could you also tell me ho exactly do I have to write the "resource name goes here" ? With/without namespace ? Just the filename ?

Thank you.
Most Valuable Expert 2012
Top Expert 2008

Commented:
Since UnmanagedMemoryStream implements System.IO.Stream, the component should be able to use it as a stream.  Are you getting errors?  When you add resources to the Resources.resx, they are given a name.  You just need the name of the resource that you used when you added the resource.  This is not an embedded resource, so you don't need to use the namespace for the name.

Author

Commented:
Here if a part of the error I am getting:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: Resource 'my_file' was not a Stream - call GetObject instead.

I tried GetObject but it did not work either.
Most Valuable Expert 2012
Top Expert 2008

Commented:
How was the resource added to Resources.resx file?  

Author

Commented:
I add the resources using the VS 2008 "Resources" tab, from the My Project screen, I'm not manually editing Resources.resx

As I said before, it works with:

Return New System.IO.MemoryStream(My.Resources.MyFileName)

but I need to get the resources by name, which also works by using

GetMAnifestResourceStream

but this requires to set the resources Build Action to "Embedded Resource", which doubles the size of my DLL file.

I currently use "None" as Build Action, but I can use any Build Action that does not increase the file size more than the actual resources size.

Most Valuable Expert 2012
Top Expert 2008

Commented:
That would suggest that you could do something like this, too:

Return My.Resources.ResourceManager.GetStream("MyFileName")

Author

Commented:
This certainly should work, but it doesn't.

It will be useful if I send you the project with source code to see if you find an workaround ?

Thank you in advance.
Most Valuable Expert 2012
Top Expert 2008

Commented:
If I look at the Resources.Designer.vb file that gets generated for the resources, with a resource string (My.Resources.String1), I see the code below.

What does the resource designer code look like for MyFileName?


  
        '''<summary>
        '''  Looks up a localized string similar to Test.
        '''</summary>
        Friend ReadOnly Property String1() As String
            Get
                Return ResourceManager.GetString("String1", resourceCulture)
            End Get
        End Property

Open in new window

Author

Commented:
I have 3 resource files, named: autumn, summer, winter.
This is what 'Resources.Designer.vb' contains:

'------------------------------------------------------------------------------
' <auto-generated>
'     This code was generated by a tool.
'     Runtime Version:2.0.50727.4927
'
'     Changes to this file may cause incorrect behavior and will be lost if
'     the code is regenerated.
' </auto-generated>
'------------------------------------------------------------------------------

Option Strict On
Option Explicit On

Imports System

Namespace My.Resources
   
    'This class was auto-generated by the StronglyTypedResourceBuilder
    'class via a tool like ResGen or Visual Studio.
    'To add or remove a member, edit your .ResX file then rerun ResGen
    'with the /str option, or rebuild your VS project.
    '''<summary>
    '''  A strongly-typed resource class, for looking up localized strings, etc.
    '''</summary>
    <Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0"),  _
     Global.System.Diagnostics.DebuggerNonUserCodeAttribute(),  _
     Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(),  _
     Global.Microsoft.VisualBasic.HideModuleNameAttribute()>  _
    Friend Module Resources
       
        Private resourceMan As Global.System.Resources.ResourceManager
       
        Private resourceCulture As Global.System.Globalization.CultureInfo
       
        '''<summary>
        '''  Returns the cached ResourceManager instance used by this class.
        '''</summary>
        <Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)>  _
        Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager
            Get
                If Object.ReferenceEquals(resourceMan, Nothing) Then
                    Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("Resource_File.Resources", GetType(Resources).Assembly)
                    resourceMan = temp
                End If
                Return resourceMan
            End Get
        End Property
       
        '''<summary>
        '''  Overrides the current thread's CurrentUICulture property for all
        '''  resource lookups using this strongly typed resource class.
        '''</summary>
        <Global.System.ComponentModel.EditorBrowsableAttribute(Global.System.ComponentModel.EditorBrowsableState.Advanced)>  _
        Friend Property Culture() As Global.System.Globalization.CultureInfo
            Get
                Return resourceCulture
            End Get
            Set
                resourceCulture = value
            End Set
        End Property
       
        Friend ReadOnly Property autumn() As Byte()
            Get
                Dim obj As Object = ResourceManager.GetObject("autumn", resourceCulture)
                Return CType(obj,Byte())
            End Get
        End Property
       
        Friend ReadOnly Property summer() As Byte()
            Get
                Dim obj As Object = ResourceManager.GetObject("summer", resourceCulture)
                Return CType(obj,Byte())
            End Get
        End Property
       
        Friend ReadOnly Property winter() As Byte()
            Get
                Dim obj As Object = ResourceManager.GetObject("winter", resourceCulture)
                Return CType(obj,Byte())
            End Get
        End Property
    End Module
End Namespace

Author

Commented:
I found the solution, I was actually adding the files two times.

http://www.vbdotnetforums.com/vb-net-general-discussion/42670-visual-basic-net-2008-get-resource-file-io-stream.html#post121927

Now I can use, GetMAnifestResourceStream.

Thank you very much for your support.
Most Valuable Expert 2012
Top Expert 2008
Commented:
The values are byte arrays, so you would need something like this:


Imports System.IO

Public Shared Function GetResourceStream(ByVal resourceName As String) As MemoryStream
   Dim buffer As Byte() = CType(My.Resources.ResourceManager.GetObject(resourceName), Byte())
   Return New MemoryStream(buffer)
End Function

Open in new window

Author

Commented:
Thank you for your support.

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial