Unraveling the confusion about Embedded Resources - vb.net

EDIT: Read answer number 1 from Tim Schmelter and then use this question for examples of how to embed resources and access them at runtime.
The subject of embedded resources comes up a lot, especially with people asking how to access the embedded files at runtime. Things get more confusing because Visual Studio gives you 2 different ways of embedding a resource, and different ways of accessing those resources at runtime. The problem is that depending on which method you used to embed the resource, the method you’re trying to use to access the file at runtime might not work. This post is an attempt to clear up all the confusion that I see out there, but I also have a question that nobody can seem to answer factually: Why is the size of my compiled program TWICE the size of the embedded resource (sometimes)? For example if I embed a 20MB file into my project, why does my program compile to 40MB? I haves asked this question in the past and nobody was able to reproduce my results. I found that the reason they were not able to reproduce was because they were embedding the file in a different way. See here:
Method 1:
Double-click on My Project to open the property pages and go to the Resources Tab. Now click Add Resource > Add Existing File. Browse to the file you want to embed. For this example I’m using an executable. You will now see your file on the Resources Tab:
You will also see that a folder named Resources was created under your project and the embedded file has been placed in this folder:
EDIT: THIS NEXT STEP WAS THE PROBLEM. TURNS OUT THAT WHEN YOU ADD A FILE VIA THE RESOURCES TAB YOU SHOULD NOT SET THE BUILD ACTION TO EMBEDDED RESOURCE. Counter intuitive to say the least!
Now with the file selected, look down at the properties window for the file and change the build action to Embedded Resource: (this step should ONLY be performed when you add a file via method 2).
Now compile your program. You will see that the size of your compiled program is at least double the size of your embedded resource. This does not happen with method 2. See here:
Method 2:
Right-click on your project name and choose Add > Existing Item. Browse to your file, and this time you will notice that while it was indeed placed under your project, there was no Resources folder created:
Now once again select the file and change the Build Action to Embedded Resource and compile. This time the size of the compiled program will be as you expected - about the size of the embedded file and not double the size as with method 1.
Which method you use to embed your file will determine which method you can use to access the file at runtime. For method 1 this is very simple, all you have to do is:
My.Computer.FileSystem.WriteAllBytes(Path, My.Resources.ResourceName, Append)
Where Path is the location and name for the file you want to save on the harddrive, ResourceName is the name of the embedded resource that you see in the project window (minus any extension), and Append is whether or not you want to create a new file or overwrite an existing file. So for example, using test.exe from the above images, I could save that file to the C drive like this:
My.Computer.FileSystem.WriteAllBytes(“C:\test.exe”, My.Resources.test, False)
Couldn’t be easier.
Method 2 however doesn’t appear to give you access to My.Resources so it gets a little more complicated. You have to create a Stream to hold the resource, put the stream into a byte array, then write the bytes out to the file system. The simplest way I have found to do this is like this:
Using s As Stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(Project.ResourceName)
Dim bytes(s.Length) As Byte
s.Read(bytes, 0, bytes.Length)
File.WriteAllBytes(OutputFile, bytes)
End Using
With this method ResourceName must contain the file extension AND project name so using our example from above we can just do:
Using s As Stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(WindowsApplication1.test.exe)
Dim bytes(s.Length) As Byte
s.Read(bytes, 0, bytes.Length)
File.WriteAllBytes(“C:\test.exe”, bytes)
End Using
Text-based files are a little different:
Dim output As String
Using sr As StreamReader = New StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream(WindowsApplication1.test.txt))
output = sr.ReadToEnd()
End Using
Using sw As StreamWriter = New StreamWriter(“C:\test.txt”)
sw.Write(output)
End Using
Having struggled with this in the past I hope this will help someone. And if you think you can explain factually why method 1 of embedding a resource bloats my compiled program to double its size, I would really appreciate it.

I assume that Method 1 is adding the files twice.
http://www.vbdotnetforums.com/vb-net-general-discussion/42670-visual-basic-net-2008-get-resource-file-io-stream.html#post121923
At least that is the conclusion of the thread above.
Quote:
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.
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.
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.

Just an update for anyone who wants to use this code. The code actually writes one additional byte to the file due to zero-based declaration of the byte array.
To get an exact copy of the original file change the code to:
Using s As Stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(WindowsApplication1.test.exe)
Dim bytes(s.Length-1) As Byte
s.Read(bytes, 0, bytes.Length)
File.WriteAllBytes(“C:\test.exe”, bytes)
End Using

Related

Can JSFL be used to set a Global Include script?

We are converting several thousand .FLA files from SWF (Flash CS6) to HTML5 Canvas (Animate CC format). I have already written a JSFL script that automates the process:
Converts Compiled Clips to HTML5-friendly objects
Converts document to HTML5 Canvas format
Associates a new Publish Profile and HTML template with the document
Changes the publish filenames
So, the hard part is done! But I want to optimize it a bit more.
The current HTML template has some shared utility functions. The utility functions add 5-10kb to the file size of each animation, which themselves are probably in the 20-50kb range.
I would rather include these utility functions by setting a Global Include script, going to the top-left of the Actions panel, selecting Include, and adding a script with the + key. (When I'm done, it will show the URI underneath Global Script)
This produces the output I want, and it's perfect! The only downside is, I have to do this manually -- I'd like a way to associate the .JS file as a Global Include when running my JSFL conversion script.
Does anyone know of a JSAPI method to retrieve or set a Global Include script in HTML5 Canvas documents?
I haven't been able to find any documentation on such a function in JSFL/JSAPI. It doesn't seem like setting the scripts leaves a trace in the History pane, so I'm at a loss here.

How to build with a custom eglfs cursor atlas?

I'm trying to change the eglfs mouse cursor graphics for my embedded linux QT application (QT5.5). I have the new cursor atlas PNG and the new JSON descriptor file, but the documentation is rather vague:
".. a custom cursor atlas can be provided by setting the QT_QPA_EGLFS_CURSOR environment variable to the name of a JSON file. The file can also be embedded into the application via Qt's resource system."
I'd prefer to keep everything within the resource system if possible but I can't work out how to do it.. do I need a specific qrc file containing the path to the JSON file? I assume that the PNG file would also need to be added as a resource so that it gets built into the application?
If adding it via the resource system is a bad idea where's the correct place to set the QT_QPA_EGLFS_CURSOR environment variable? I'm currently specifying the platform on the command line via "-platform eglfs"; will this be ok or will I need to set the platform to eglfs in the build?
After much trial, error and digging around I have found the solution that I was looking for within the resource system.
Create a new resource file called "cursor.qrc", the contents of which needs to be two lines:
path/to/your/custom-cursor-atlas.png
cursor.json
The first line (path to your cursor atlas) must be relative to your resource directory.
You then need to put the JSON file (contents as described in the documentation) in the root of your resource directory. It must be called "cursor.json", and its image location line must must match the location in your new resource file and be of the format:
"image": ":/path/to/your/custom-cursor-atlas.png",
This will then include your cursor atlas in resources, and Qt will find it when your application starts.
Run time solution example:
export XDG_RUNTIME_DIR=~
export QT_QPA_EGLFS_CURSOR=~/cursor.json
In the cursor.json:
"image": "cursor.png",
Put your custom cursor.png atlas into your home dir (~) then run the Qt app from there.

Compile image in .exe vb.net

I want to make a simple .exe application in vb.net. The application wont have an installation just pure run on .exe file .
Application has one form and two pictures. When i set the option on image to build action - compile
Unable to open module file 'C:\Users\t3cho\documents\visual studio 2013\Projects\Apps\Apps\Resources\power.png': System Error &H80041feb&
Is there any other way to make an .exe file with images without installation or additional folders.
The easiest way to include images (and other types of resources) into the application is to right-click the project, go to the "Resources"-Tab and add the image there. You can change its name to e.g. MyEmbeddedImage and access it like this
Dim img As Image = Properties.Resources.MyEmbeddedImage
or
Dim img As Image = My.Resources.MyEmbeddedImage
This automatically sets the Build Action to None.
Note: This approach is type-safe and you will get errors at compile time, if the image is missing.
See: My.Resources Object and How to: Add or Remove Resources
If you still want to embed the image "manually", you must set the Build Action to Embedded Resource and access it as #Icemanind describes.
Yes. It's called embedded resources. Set your image's Build Action to Embedded Resource. You can then get the image at runtime like so:
Try
_assembly = [Assembly].GetExecutingAssembly()
_imageStream = _assembly.GetManifestResourceStream("MyNameSpace.MyImage.png")
' Do something with _imageStream
Catch ex As Exception
' Resource not found or something went wrong
End Try

Monogame and .fx files?

I'm currently following this tutorial but using MonoGame :
http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series1/Terrain_from_file.php
As said in the tutorial, my main goal is to render a terrain from an image file.
There is a .fx provided with the tutorial which I included in my project.
I had some issues using MonoGame to load the bmp file for example and now I managed to load it. The problem comes now from the fx file. MonoDevelop tells this : The MGX File is Corrupt !
Here is the original code from the writer of the article :
effect = Content.Load<Effect> ("effects");
And here is how I used it with MonoGame :
effect = Content.Load<Effect> ("effects.fx");
I am really lost about the usage of the effects file in MonoGame. Is there any good tutorial about this ? Anyway I'm really lost with MonoGame. How come there is no clear tutorials for MonoGame has it is widely used ?
You need to convert your shader .fx to appropriate file format for monogame using 2MGFX tool. You can find the tool inside installed monogame directory C:\Program Files (x86)\MSBuild\MonoGame\v3.0
How to use:
Create a .bat file and write code as shown below:
2MGFX.exe effects.fx effects.mgfxo
pause
Execute the .bat file
Note that the shader file, .bat file and 2MGFX.exe must be in same directory.
Here is how to use compiled .mgfxo file as effect:
Put the effects.mgfxo into Assets\Content folder of your project
Load a file as shown below
Stream s = Assembly.GetExecutingAssembly().GetManifestResourceStream("ProjectNameSpace.Assets.Content.effects.mgfxo");
BinaryReader Reader = new BinaryReader(s);
Effect effect = new Effect(graphics, Reader.ReadBytes((int)Reader.BaseStream.Length));
If you have problems converting a shader .fx to .mgfxo please leave comments.
I've been trying to follow Riemers tutorial myself, like you, I struggled with the effects.
I had to make a couple changes to the original effects file before I successfully managed to compile and use it without any exceptions.
Renamed the following:
vs_2_0 to vs_4_0
ps_2_0 to ps_4_0
POSITION to SV_POSITION
Once these changes were made I used the compile tool like following:
2MGFX.exe effects.fx effects.mgfxo /Profile:DirectX_11
Once compiled I moved the mgfxo file into my contents folder and assigned following parameters:
Build action: Embedded resource
Copy to output directory: Copy always
It took me a couple of attempts until I managed to use the shader without MonoGame throwing any exceptions at me.
byte[] bytes = File.ReadAllBytes("Content/effects.mgfxo");
effect = new Effect(GraphicsDevice, bytes);
Using the 2MGFX tool is optional, you can either use the tool or the Content pipeline, personally I prefer the Content pipeline because it will automatically process the shader file everytime I (re)build the Content project.
How to do this?
First: add a MonoGame Content project,
Then add the .FX file in this project
Set the Content processor to: "MonoGame effect content processor" in properties
Then, in your game project Add a Reference to this Content project.
And use the shader like so:
var myEffect = Content.Load<Effect>("shaderFileNameWithoutExtension");
or if you have folders in your content project:
var myEffect = Content.Load<Effect>("FolderName\\shaderFileNameWithoutExtension");
I'm seeing you're working on Linux. Compiling shaders on Linux is a little difficult. In my own projects, I find the following resource especially helpful.
http://www.infinitespace-studios.co.uk/general/monogame-building-fx-shaders-on-a-mac-and-linux/
Following this, you're able to build shaders using the MonoGame Pipeline as normal (provided you have added the pipeline reference).
Hope this helps!

ActionScript 2 load another SWF that loads other files - relative path/url problem

Few facts first:
1. I can only use ActionScript 2.
2. All files are within the same domain (i.e "http://www.example.com").
I have a loader SWF which acts as a selection tool ("auto_magic.swf") located at "/" in the website (the root folder).
A User selects the tool he needs (it's a mechanical diagnostic system) and the main movie loads it (currently I use loadMovie() - suggest else if needed).
That tool is located at "/tools/[tools_name]/tool_main.swf".
Now, the "tool_main.swf" is loading just fine.
The problem is that "tool_main.swf" needs to load other files located in its folder, so for example it tries to load "config.xml", BUT Flash isn't looking for "config.xml" in the tool's dedicated folder - instead it's looking for this file at the root folder "/" where "auto_magic.swf" is located, probably because the movie's main swf is coming from there.
To make it even worst I cannot modify the tool's SWF ("tool_main.swf") because it's coming from a third party.
Is there any solution? As far as I see this I need one of these solutions;
1. Be able to set the base url of the loaded swf.
2. *Change* the whole movie's base url at run-time because it needs to load several tools from different folders.
Trying to solve this for several good hours. Help will be highly appriciated!
relative paths are always relative to where the main swf exists. so as your load chain expands, '/' always refers to the location of the Main.swf.
in AS2, you can inspect a swfs _url property to determine its fully qualified url location, and determine its parent folder.
In the AS2 child swf, you can use this:
var myfolder = this._url.slice(0, this._url.lastIndexOf('/') + 1);
and then use that to load in further assets relative to itself.
hope that helps.