Monday, December 7, 2009

Hacking the Silverlight Xap file

Every now and then I find I need to pull resources out of a Xap file. One of the issues with this is knowing what’s in the XAP. There have been a number of solutions I’ve used over the years (ok that is like 2.5 ish years) like having an index file either a Csv or Xml etc. A few weeks ago I ran across this little class that some guys were talking about on the Silverlight Insiders/MVP thread called un-zipper found here:

http://www.sharpgis.net/post/2009/04/21/REALLY-small-unzip-utility-for-Silverlight.aspx

What is cool about this class is it makes getting the assets out of a zap even if you don’t know what is in the xap up front easy and straight forward. From a using standpoint you basically need to create a webclient and a call and use the Unzipper to run through the contents. The Unzipper class deals with mucking up what is in the xap so all you need to-do is run through the collection and pull out what you need… Let us take a look at what you need to-do:
Assuming you have the Unzipper class (download here) you need the following libraries:

using System.Collections.ObjectModel;
using System.Net;
using System.Windows.Controls;

From here we need to create a web client

WebClient wc = new WebClient();
wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
wc.OpenReadAsync(new Uri("HackingXaps.xap", UriKind.RelativeOrAbsolute));


In this code we create the WebClient, add a handler and run the call pointed at our xap we want to load.

void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if (e.Error == null)
{
UnZipper unzip = new UnZipper(e.Result);

foreach (string filename in unzip.GetFileNamesInZip())
{
//do something with the file name…?
}
}
}

From here you can pretty much do whatever you want. Look to see this in the up coming version of the HackingSilverlight library.

3 comments:

  1. ok ok here is the source from that UnZipper Class

    public class UnZipper
    {


    private Stream stream;

    public UnZipper(Stream zipFileStream)
    {
    this.stream = zipFileStream;
    }

    public Stream GetFileStream(string filename)
    {
    Uri fileUri = new Uri(filename, UriKind.Relative);
    StreamResourceInfo info = new StreamResourceInfo(this.stream, null);
    StreamResourceInfo stream = System.Windows.Application.GetResourceStream(info, fileUri);

    if (stream != null)
    {
    return stream.Stream;
    }
    return null;
    }

    public IEnumerable<string> GetFileNamesInZip()
    {
    BinaryReader reader = new BinaryReader(stream);
    stream.Seek(0, SeekOrigin.Begin);
    string name = null;

    while (ParseFileHeader(reader, out name))
    {
    yield return name;
    }
    }

    private static bool ParseFileHeader(BinaryReader reader, out string filename)
    {
    filename = null;

    if (reader.BaseStream.Position < reader.BaseStream.Length)
    {
    int headerSignature = reader.ReadInt32();

    if (headerSignature == 67324752)
    {
    reader.BaseStream.Seek(14, SeekOrigin.Current);

    int compressedSize = reader.ReadInt32();
    int unCompressedSize = reader.ReadInt32();
    short fileNameLenght = reader.ReadInt16();
    short extraFieldLenght = reader.ReadInt16();

    filename = new string(reader.ReadChars(fileNameLenght));

    if (string.IsNullOrEmpty(filename))
    {
    return false;
    }



    reader.BaseStream.Seek(extraFieldLenght + compressedSize, SeekOrigin.Current);

    if (unCompressedSize == 0)
    {
    return ParseFileHeader(reader, out filename);
    }
    else
    {
    return true;
    }
    }

    }

    return false;

    }

    }

    ReplyDelete
  2. Hey David.. I was so looking forward to reading your Hacking Silverlight book.

    I guess there must have been some serious reason for leaving it in between.
    Best wishes for your next book.

    You do write great stuff. Keep up the good work.

    Regards and Cheers

    ReplyDelete
  3. So this is a long story... first the manuscxript was almost done and manning decided to have me rip all the learn silverlight part out (6 chapters down the tube) then when it was complete again and ready to post and bereviewed SL2 book sales tanked. Then 3 months into updating for sl3 they decided that they didn't want to really help with editing and with working 12 hours days...

    In any case I found an editor and have new content but he had sceduling problems and we are meeting next week to see what the plan is. may consider giving book out for free with all the sl 4 content. or goign with different publisher that is more willing to help.

    sorry for the rant... :)

    ReplyDelete