Extracting a Resource

3xodus

Freshman
Joined
Dec 26, 2004
Messages
47
Location
Derbyshire, UK
Using this thread by Plausibly Damp (http://www.xtremedotnettalk.com/showthread.php?t=83574), and various other threads, I've pretty much got the hang of how to use icons / images and such from resources. One thing I can't figure out is how to save the file - pretty much extracting the file from my apps resource, to the HD.

Is there a way to do this, without 'cheating' by setting the image in a picturebox and saving it from there... A method that can work on all filetypes maybe - I'm thinking it would be possible to make a (very basic) installer this way, by adding a compressed archive to the project, then extracting it to a temporary location, then decompressing it (RARLabs, the makers of WinRAR have a RAR decompression control on their site) and then deleting the compressed archive. Registry entries could also be made either in code from the 'installer', or by executing a .reg - I suppose you could make a fairly good installer with some work.

Sorry for the long-whinded explanation - and tia for any help ;)
 
IngisKahn said:
Just create a FileStream and write the contents of the resource stream to it.

Hi - thanks for the advice. I've never used FileStream before, but from various forum posts, I've put this together -
Visual Basic:
        Dim ASM As [Assembly]
        Dim fStream As New FileStream(InputBox("Extract to (w/ .rar ext)", "Extract to *.rar"), FileMode.Create, FileAccess.Write)
        Dim sw As System.IO.FileStream
        ASM = [Assembly].GetExecutingAssembly()
        sw = ASM.GetManifestResourceStream("ResExtract.Test.rar")
        fStream.Write(array() as byte, offset as integer, count as integer) ' 
        sw.Close()
Am I going in the right direction here? If so, what is my "array as byte"? I don't really know much about this, so sorry if this is totally wrong or if I use the wrong terms :p - I think I have to convert the .rar resource so a byte array, and said byte array would be the array for fStream.Write() :-\

Also, I'm assuming for the offset, that would simply be 0, and for count, it would be the length of the byte array?

Again, sorry if I'm talking crap here, I'm only just starting to look into System.IO :)
 
IngisKahn said:
You dim a byte array to use as a buffer. Then read in from sw and write out to fstream.
Thanks for that - I get how this should work, but I'm missing something. I used MSDN and this forum, but this is the best I have got so far:
Visual Basic:
        Dim myAssem As [Assembly]
        Dim fStream As New FileStream(Application.StartupPath & "extracted.zip", FileMode.Create, FileAccess.Write)
        Dim sw As System.IO.FileStream
        Dim bBuffer() As Byte 'buffer
        myAssem = [Assembly].GetExecutingAssembly()
        [u]sw = myAssem.GetManifestResourceStream("ResExtraction.Test.zip")[/u]
        sw.Read(bBuffer, 0, 100)   'read 100 bytes
        fStream.Write(bBuffer, 0, 100) 'write an array of 100 bytes
The line of code that I've underlined is throwing up the error "An unhandled exception of type 'System.NullReferenceException' occurred in ResExtraction.exe.
Additional information: Object reference not set to an instance of an object."

Any idea what I've done wrong here? Thanks for the help :)
 
2 things.
First, GetManifestResourceStream doesn't return a FileStream, it returns a Stream so you need to change your dim of sw (Another example of the benefits of Option Strict).
Second, you never create your byte buffer, throw an = new Byte(100) in there.
 
IngisKahn said:
2 things.
First, GetManifestResourceStream doesn't return a FileStream, it returns a Stream so you need to change your dim of sw (Another example of the benefits of Option Strict).
Second, you never create your byte buffer, throw an = new Byte(100) in there.

Thanks for all your help IngisKahn, it now works perfectly :) Though the biggest file I tested was 2MB, it seems really fast - though my code could be much better.

Anyway, thanks a lot for helping me with this :D
 
Hi, sorry to bring this thread up again - but I have a problem somewhere :(

I was working on the routine - getting a progress bar and labels to follow the progress of the extraction etc... And though I've finally got that working properly, it takes *ages* to extract anything.

The file that is embedded into my test app is 315kb, and used to extract almost instantly. It now takes around a minute or more.

If anyone can spot what my problem is or offer any advice to speed it up, that'd be great.. Also I ought to mention that this routine is running in it's own thread (so my app isn't frozen during the extraction), I don't suppose that could cause a problem?

Thanks ! Here's the code - (Edit: I have had to use code ... /code tags, since VB tags put all of the code on one line, making the page unreadable :()
Code:
                Try
        Dim myAssem As [Assembly]
  Dim fStream As New FileStream(Application.StartupPath & "\nfo.rar", FileMode.Create, FileAccess.Write) 'InputBox("Dir to extract to", "Extract to-"), FileMode.Create, FileAccess.Write)
        Dim sw As System.IO.Stream
        Dim resSize As Long = 0 'The size of the resource
        Dim resDone As Long = 0 'Amount extracted
        myAssem = [Assembly].GetExecutingAssembly()
        sw = myAssem.GetManifestResourceStream("ResExtraction.Test.rar")
                     Dim bbuffer(sw.Length / 1024) As Byte 'Stream buffer
                     resSize = sw.Length
                     lblFilesize.Text = resSize
                     PB.Maximum = resSize
                     PB.Minimum = 0
                     PB.Step = PB.Maximum / sw.Length
                     '-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
                     Do
                         sw.Read(bbuffer, 0, 1)
                         fStream.Write(bbuffer, 0, 1)
                         'Update labels, progress bar etc... ***********************
                         resDone = resDone + 1
                         lblExtracted.Text = resDone
                         PB.PerformStep()
                         PB.Text = PB.Value & "%"
                         '/Updates ***************************************************
                     Loop Until PB.Value = PB.Maximum 'resDone = sw.Length
                     '-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
                     MsgBox("Extracted!", MsgBoxStyle.Information, "Extraction is complete")
                     cmdExtract.Enabled = True
                     Exit Sub
                 Catch ex As Exception
                     MsgBox(ex.ToString, MsgBoxStyle.Critical, "ResExtraction Error")
                     Exit Sub
                 End Try
 
Last edited:
I can't explain the sudden slow down, but going thru the file one byte at a time is generally very slow. Pick a buffer size (1024 is ok), open the file stream specifing that buffer size, and read and write that many bytes each time. Of course you have to test and handle the case when the number of bytes left is less than the buffer size.
 
IngisKahn said:
I can't explain the sudden slow down, but going thru the file one byte at a time is generally very slow. Pick a buffer size (1024 is ok), open the file stream specifing that buffer size, and read and write that many bytes each time. Of course you have to test and handle the case when the number of bytes left is less than the buffer size.
Thanks again for the replies IngisKahn :)

That's the reason I tried to make the buffer size based on the resource filesize (Dim bbuffer(sw.length / 1024)), but when I tried to read and write 1024 bits at a time, the resulting .rar file was around 97MB (although interestingly, when I extract it using WinRAR, it works fine and extracts to the normal filesize.. The 97MB file functioned just the same as the proper 315kB original file :s)

However thanks for the comment - I'll try to work out a better way to decide the biffer size, based on the resource filesize, and maybe the # of bytes read and written at a time should be based on that same formula?

Thanks again, I'll see what I can do with this :)
 
RAR files prolly look like this:

Start marker
Data
End Marker


Your RAR file prolly looks like this

Start marker
Data
End Marker
00000000000000 <- Its filed with 90 MB of zeros :P
 
Back
Top