Get resource file as IO.Stream

dxmedia

Member
Joined
Jul 2, 2010
Messages
16
Programming Experience
1-3
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'.


Another way would be:

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

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.


I currently use and it works:

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

but I want it to be called by name.


Thank you.
 
There should be a few clues here. First, look at this:
VB.NET:
Return New System.IO.Memory[B][U]Stream[/U][/B](My.Resources.MyFileName)
Now, look at this:
VB.NET:
System.IO.UnamnagedMemory[B][U]Stream[/U][/B]
Now, look at this:
VB.NET:
Return My.Resources.ResourceManager.Get[B][U]Stream[/U][/B]("resource name goes here")
Check out the documentation for the UnmanagedMemoryStream class and see what it's base class is.
 
Here is a review of my question.

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

I am having trouble with 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.


-----------------------------------------------------
I will try to explain the whole process step by step.

For example, I put 3 resource files in the DLL. To do that I do the following steps, in the Visual Studio 2008:

- I double click on 'My Project' in the 'Solution Explorer'
- I click on 'Resources' tab
- From 'Add Resource' top menu, I click on 'Add Existing File...'
- Then an 'Open Dialog' opens
- I select 3 files that I want to incorporate in the DLL
- Then my files get added in the 'Resources' screen, and a 'Resources' folder with my files appears in the 'Solution Explorer'


Now, if I click on each file in the 'Resources' folder from the 'Solution Explorer', in the property grid, the properties of the file appear.


In the documentation it is suggested to set the 'Build Action' property to 'Embedded Resource'. This makes it easy to read and enumerate the resources, but this property set to 'Embedded Resource' also doubles the file size (the DLL size is double the size of all the files added)


To keep the file size normal, I set the 'Build Action' property to 'None'.
The 'None' property also incorporates the files into the DLL, but the DLL now has the correct size (meaning the sum of all added files)


Now I am trying to make 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.


I suggest to do all these steps before you answer, so you understand my request.
-----------------------------------------------------


When the 'Build Action' property was set to 'Embedded Resource', there were some ways to enumerate resource files by name, using 'GetMAnifestResourceStream'.

When the 'Build Action' property is set to 'None' the 'GetMAnifestResourceStream' doesn't work anymore.

Also, When the 'Build Action' property is set to 'None', I can only use:
Return New System.IO.MemoryStream(My.Resources.MyFileName) to get a file from the resources, but I have to write manually 'My.Resources.MyFileName' at design time, for each file added in resources. Also I can not enumerate the resources.


Could you please give me some suggestions on enumerating and retrieving the files by name at runtime.

Please, don't ask questions like 'why do you need this', or suggest that I set 'Build Action' to 'Embedded Resource' as a solution.


Thank you in advance.
 
OK, I can see what you've done wrong now. You went to the Resources page of the project properties and added the files there, right? You then went into the Solution Explorer and change the Build Action of the files to Embedded Resource, right? That's why you were doubling the file size: you were adding each file twice.

There are two different ways to add resources: on the Resources page of the project properties and in the Solution Explorer. You do NOT do both. If you want to use GetManifestResourcestream then you do NOT use the Resources page. You add the files to the project in the Solution Explorer manually, then you set the Build Action to Embedded Resource.

In future, do one or the other, not both.

1. Add a file to the Resources page of the project properties and then access it via My.Resources. This will automatically add the file to the project in the Solution Explorer but the Build Action will be None and it should be left that way.

2. Add the file to the project in the Solution Explorer by using Add New Item or Add Existing Item. Set the Build Action of the file to Embedded Resource and then access the resource using GetManifestResourceStream.
 
Please, don't ask questions like 'why do you need this', or suggest that I set 'Build Action' to 'Embedded Resource' as a solution.
I think it's up to us what we suggest and what we ask. If we ask "why" it's usually because we think you're trying to solve the wrong problem. If the best answer to your question is to ask a different question, that's what we're going to suggest. As you can see from my previous post, the solution, or at least part of it, was in fact to do exactly what you ask me not to suggest.
 
Thank you very much jmcilhinney,

Indeed that was the problem I was adding the files two times. You are absolutely wright.

Regarding the "don't ask questions like why do you need this", I write this because I posted a lot of different questions on forums and ended up with suggestions that required me to change my whole application.
For example, I was looking for a way to call a function on the main application thread from another thread WITHOUT using forms which support Me.Invoke. I got a lot of suggestions of using hidden forms or other things that I did not need, and finally someone suggested using SynchronizationContext. Indeed this was the real solution to my trouble.

Sorry about this, but you are right on this one.
 
Noone is saying that you have to take the advice provided if it isn't appropriate for your situation but that doesn't mean that someone shouldn't suggest it. If you start telling people what they can and can't suggest then you might miss out on something worthwhile, and you might end up with nothing at all.
 
Return New System.IO.MemoryStream(My.Resources.MyFileName) to get a file from the resources, but I have to write manually 'My.Resources.MyFileName' at design time, for each file added in resources. Also I can not enumerate the resources.

I'd suggest you look at the generated code for this (search the entire solution, including hidden text, for MyFileName) as, if it's anything like the settings, you may well find that it is just a named property that calls an indexed collection

e.g. My.Settings.ConnectionString is just a Property inside the Settings.Designer.vb file:

VB.NET:
Property ConnectionString
  Get
    Return DirectCast(blah.someCollection("ConnectionString"), String)
  End Get
...
End Property

Hence, what you see as typed code might jsut be a thin wrapper for an untyped/collected object indexed by string; the very thing youre looking to do
 
Back
Top