<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" version="2.0">
  <channel>
    <title>Martin Plante</title>
    <link>http://blogs.xceedsoft.com/plantem/</link>
    <description>Open window on development at Xceed </description>
    <language>en-us</language>
    <copyright>Xceed Software Inc.</copyright>
    <lastBuildDate>Thu, 16 Jun 2005 19:04:00 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 1.8.5223.0</generator>
    <managingEditor>plantem@xceedsoft.com</managingEditor>
    <webMaster>plantem@xceedsoft.com</webMaster>
    <item>
      <trackback:ping>http://blogs.xceedsoft.com/plantem/Trackback.aspx?guid=4fc3e00e-646e-48bf-8dc2-8e7f1df58fa1</trackback:ping>
      <pingback:server>http://blogs.xceedsoft.com/plantem/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.xceedsoft.com/plantem/PermaLink,guid,4fc3e00e-646e-48bf-8dc2-8e7f1df58fa1.aspx</pingback:target>
      <dc:creator />
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      Customer requests come in waves, as if fashion was driving the development industry.
      Lately, many customers were trying to compress log files. I've deviced it was time
      for a little sample.
   </p>
        <p>
      The idea was to encode each string message in unicode and compress it in a plain
      file, one after the other. I could have used a zip file with each file entry representing
      a message, but for small messages, the zip headers would take too much space for nothing,
      wasting the need for compression in the first place.
   </p>
        <p>
      The deflate compression method has one nice feature: it can detect the end of the
      compressed data while decompressing, without knowing the total compressed size. That's
      why the <a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.compression.compressedstream.html">CompressedStream</a> class
      exposes a <a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.compression.compressedstream.getremainingstream.html">GetRemainingStream</a> method
      for retrieving a Stream reference on the rest of the data in the inner stream.
   </p>
        <p>
      I've kept the sample real simple, so you get the general idea:
   </p>
        <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 0pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 0pt; FONT-SIZE: 8pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: ProggySquareTTSZ">
          <pre style="MARGIN: 0px">
            <span style="COLOR: #0000ff">using</span> System;</pre>
          <pre style="MARGIN: 0px">
            <span style="COLOR: #0000ff">using</span> System.IO;</pre>
          <pre style="MARGIN: 0px">
            <span style="COLOR: #0000ff">using</span> Xceed.Compression;</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">
            <span style="COLOR: #0000ff">namespace</span> CompressedLogExample</pre>
          <pre style="MARGIN: 0px">{</pre>
          <pre style="MARGIN: 0px">  <span style="COLOR: #0000ff">public</span><span style="COLOR: #0000ff">class</span> CompressedLog</pre>
          <pre style="MARGIN: 0px">  {</pre>
          <pre style="MARGIN: 0px">    <span style="COLOR: #0000ff">public</span> CompressedLog( <span style="COLOR: #0000ff">string</span> filename
      )</pre>
          <pre style="MARGIN: 0px">    {</pre>
          <pre style="MARGIN: 0px">      <span style="COLOR: #0000ff">if</span>(
      filename == <span style="COLOR: #0000ff">null</span> )</pre>
          <pre style="MARGIN: 0px">        <span style="COLOR: #0000ff">throw</span><span style="COLOR: #0000ff">new</span> ArgumentNullException(
      "filename" );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">      <span style="COLOR: #0000ff">if</span>(
      filename.Length == 0 )</pre>
          <pre style="MARGIN: 0px">        <span style="COLOR: #0000ff">throw</span><span style="COLOR: #0000ff">new</span> ArgumentException(
      "The filename cannot be empty.", "filename" );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">      Xceed.Compression.Licenser.LicenseKey = "SAMPLE-APPLICATION-KEY";</pre>
          <pre style="MARGIN: 0px">      m_filename = filename;</pre>
          <pre style="MARGIN: 0px">    }</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">    <span style="COLOR: #0000ff">public</span><span style="COLOR: #0000ff">void</span> AddMessage( <span style="COLOR: #0000ff">string</span> message
      )</pre>
          <pre style="MARGIN: 0px">    {</pre>
          <pre style="MARGIN: 0px">      <span style="COLOR: #0000ff">if</span>(
      message == <span style="COLOR: #0000ff">null</span> )</pre>
          <pre style="MARGIN: 0px">        <span style="COLOR: #0000ff">throw</span><span style="COLOR: #0000ff">new</span> ArgumentNullException(
      "message" );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">      <span style="COLOR: #0000ff">lock</span>(
      m_lock )</pre>
          <pre style="MARGIN: 0px">      {</pre>
          <pre style="MARGIN: 0px">        <span style="COLOR: #0000ff">using</span>(
      Stream fileStream = <span style="COLOR: #0000ff">new</span> FileStream( m_filename,
      FileMode.Append ) )</pre>
          <pre style="MARGIN: 0px">        {</pre>
          <pre style="MARGIN: 0px">          <span style="COLOR: #0000ff">using</span>(
      CompressedStream compStream = <span style="COLOR: #0000ff">new</span> CompressedStream(
      fileStream ) )</pre>
          <pre style="MARGIN: 0px">          {</pre>
          <pre style="MARGIN: 0px">            <span style="COLOR: #0000ff">byte</span>[]
      encodedMessage = System.Text.Encoding.Unicode.GetBytes(</pre>
          <pre style="MARGIN: 0px">              DateTime.Now.ToString() + Environment.NewLine + message );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">            compStream.Write( encodedMessage, 0, encodedMessage.Length );</pre>
          <pre style="MARGIN: 0px">          }</pre>
          <pre style="MARGIN: 0px">        }</pre>
          <pre style="MARGIN: 0px">      }</pre>
          <pre style="MARGIN: 0px">    }</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">    <span style="COLOR: #0000ff">public</span><span style="COLOR: #0000ff">void</span> DisplayMessages(
      TextWriter writer )</pre>
          <pre style="MARGIN: 0px">    {</pre>
          <pre style="MARGIN: 0px">      <span style="COLOR: #0000ff">if</span>(
      writer == <span style="COLOR: #0000ff">null</span> )</pre>
          <pre style="MARGIN: 0px">        <span style="COLOR: #0000ff">throw</span><span style="COLOR: #0000ff">new</span> ArgumentNullException(
      "writer" );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">      <span style="COLOR: #0000ff">lock</span>(
      m_lock )</pre>
          <pre style="MARGIN: 0px">      {</pre>
          <pre style="MARGIN: 0px">        <span style="COLOR: #0000ff">try</span></pre>
          <pre style="MARGIN: 0px">        {</pre>
          <pre style="MARGIN: 0px">          <span style="COLOR: #0000ff">using</span>(
      Stream originalStream = <span style="COLOR: #0000ff">new</span> FileStream( m_filename,
      FileMode.Open ) )</pre>
          <pre style="MARGIN: 0px">          {</pre>
          <pre style="MARGIN: 0px">            Stream workStream = originalStream;</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">            <span style="COLOR: #0000ff">do</span></pre>
          <pre style="MARGIN: 0px">            {</pre>
          <pre style="MARGIN: 0px">              <span style="COLOR: #0000ff">using</span>(
      CompressedStream compStream = <span style="COLOR: #0000ff">new</span> CompressedStream(
      workStream ) )</pre>
          <pre style="MARGIN: 0px">              {</pre>
          <pre style="MARGIN: 0px">                <span style="BACKGROUND: #ffffff; COLOR: #008000">//
      We don't want compStream to close sourceStream!</span></pre>
          <pre style="MARGIN: 0px">                compStream.Transient = <span style="COLOR: #0000ff">true</span>;</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">                <span style="COLOR: #0000ff">using</span>(
      StreamReader reader = <span style="COLOR: #0000ff">new</span> StreamReader( </pre>
          <pre style="MARGIN: 0px">                         compStream, System.Text.Encoding.Unicode ) )</pre>
          <pre style="MARGIN: 0px">                {</pre>
          <pre style="MARGIN: 0px">                  writer.WriteLine( reader.ReadToEnd() );</pre>
          <pre style="MARGIN: 0px">                  writer.WriteLine( "---" );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">                  <span style="BACKGROUND: #ffffff; COLOR: #008000">//
      Before closing the reader (thus compStream), acquire a stream on</span></pre>
          <pre style="MARGIN: 0px">                  <span style="BACKGROUND: #ffffff; COLOR: #008000">//
      the rest of the data if present.</span></pre>
          <pre style="MARGIN: 0px">                  workStream = compStream.GetRemainingStream();</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">                  <span style="BACKGROUND: #ffffff; COLOR: #008000">//
      We must do this AFTER calling GetRemainingStream since compStream</span></pre>
          <pre style="MARGIN: 0px">                  <span style="BACKGROUND: #ffffff; COLOR: #008000">//
      may have read more from its inner stream than necessary.</span></pre>
          <pre style="MARGIN: 0px">                  <span style="COLOR: #0000ff">if</span>(
      workStream.Position == workStream.Length )</pre>
          <pre style="MARGIN: 0px">                  {</pre>
          <pre style="MARGIN: 0px">                    workStream = <span style="COLOR: #0000ff">null</span>;</pre>
          <pre style="MARGIN: 0px">                  }</pre>
          <pre style="MARGIN: 0px">                }</pre>
          <pre style="MARGIN: 0px">              }</pre>
          <pre style="MARGIN: 0px">            }</pre>
          <pre style="MARGIN: 0px">            <span style="COLOR: #0000ff">while</span>(
      workStream != <span style="COLOR: #0000ff">null</span> );</pre>
          <pre style="MARGIN: 0px">          }</pre>
          <pre style="MARGIN: 0px">        }</pre>
          <pre style="MARGIN: 0px">        <span style="COLOR: #0000ff">catch</span>(
      FileNotFoundException )</pre>
          <pre style="MARGIN: 0px">        {</pre>
          <pre style="MARGIN: 0px">          writer.WriteLine( "The log is empty." );</pre>
          <pre style="MARGIN: 0px">        }</pre>
          <pre style="MARGIN: 0px">      }</pre>
          <pre style="MARGIN: 0px">    }</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">    <span style="COLOR: #0000ff">private</span><span style="COLOR: #0000ff">string</span> m_filename
      = <span style="COLOR: #0000ff">string</span>.Empty;</pre>
          <pre style="MARGIN: 0px">    <span style="COLOR: #0000ff">private</span><span style="COLOR: #0000ff">object</span> m_lock
      = <span style="COLOR: #0000ff">new</span><span style="COLOR: #0000ff">object</span>();</pre>
          <pre style="MARGIN: 0px">  }</pre>
          <pre style="MARGIN: 0px">}</pre>
        </div>
        <p>
      Unfortunately, you can't replace the CompressedStream with a formatted stream
      like <a href="http://doc.xceedsoft.com/products/streamNet/ref/xceed.compression.formats.gzipcompressedstream.html">GZipCompressedStream</a>,
      because they do not expose a GetRemainingStream method yet. Too bad, since the GZipCompressedStream
      can store a few minimal informations in its header. I'll have to open a feature request
      about that!
   </p>
        <p>
      Here is some sample code for using this CompressedLog class:
   </p>
        <div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 0pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 0pt; FONT-SIZE: 8pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: ProggySquareTTSZ">
          <pre style="MARGIN: 0px">    <span style="COLOR: #0000ff">static</span><span style="COLOR: #0000ff">void</span> Main(<span style="COLOR: #0000ff">string</span>[]
      args)</pre>
          <pre style="MARGIN: 0px">    {</pre>
          <pre style="MARGIN: 0px">      CompressedLog log = <span style="COLOR: #0000ff">new</span> CompressedLog(
      @"d:\temp\log.cmp" );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">      <span style="COLOR: #0000ff">while</span>( <span style="COLOR: #0000ff">true</span> )</pre>
          <pre style="MARGIN: 0px">      {</pre>
          <pre style="MARGIN: 0px">        Console.WriteLine( "Write your next message below (empty message to quit):" );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">        <span style="COLOR: #0000ff">string</span> line
      = Console.ReadLine();</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">        <span style="COLOR: #0000ff">if</span>(
      line.Length == 0 )</pre>
          <pre style="MARGIN: 0px">          <span style="COLOR: #0000ff">break</span>;</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">        log.AddMessage( line );</pre>
          <pre style="MARGIN: 0px">      }</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">      Console.WriteLine();</pre>
          <pre style="MARGIN: 0px">      Console.WriteLine( "Your messages were:" );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">      log.DisplayMessages( Console.Out );</pre>
          <pre style="MARGIN: 0px"> </pre>
          <pre style="MARGIN: 0px">      Console.WriteLine( "Press &lt;Enter&gt; to quit." );</pre>
          <pre style="MARGIN: 0px">      Console.ReadLine();</pre>
          <pre style="MARGIN: 0px">    }</pre>
        </div>
        <!--EndFragment-->
        <img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=4fc3e00e-646e-48bf-8dc2-8e7f1df58fa1" />
      </body>
      <title>Compressed log files</title>
      <guid>http://blogs.xceedsoft.com/plantem/PermaLink,guid,4fc3e00e-646e-48bf-8dc2-8e7f1df58fa1.aspx</guid>
      <link>http://blogs.xceedsoft.com/plantem/PermaLink,guid,4fc3e00e-646e-48bf-8dc2-8e7f1df58fa1.aspx</link>
      <pubDate>Thu, 16 Jun 2005 19:04:00 GMT</pubDate>
      <description>&lt;p&gt;
   Customer requests come in waves, as if fashion was driving the development industry.
   Lately, many customers were trying to compress log files. I've deviced it was time
   for a little sample.
&lt;/p&gt;
&lt;p&gt;
   The idea was to encode each string message in unicode&amp;nbsp;and compress it in a plain
   file, one after the other. I could have used a zip file with each file entry representing
   a message, but for small messages, the zip headers would take too much space for nothing,
   wasting the need for compression in the first place.
&lt;/p&gt;
&lt;p&gt;
   The deflate compression method has one nice feature: it can detect the end of the
   compressed data while decompressing, without knowing the total compressed size. That's
   why the &lt;a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.compression.compressedstream.html"&gt;CompressedStream&lt;/a&gt; class
   exposes a &lt;a href="http://doc.xceedsoft.com/products/zipNet/ref/xceed.compression.compressedstream.getremainingstream.html"&gt;GetRemainingStream&lt;/a&gt; method
   for retrieving a Stream reference on the rest of the data in the inner stream.
&lt;/p&gt;
&lt;p&gt;
   I've kept the sample real simple, so you get the general idea:
&lt;/p&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 0pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 0pt; FONT-SIZE: 8pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: ProggySquareTTSZ"&gt;&lt;pre style="MARGIN: 0px"&gt;&lt;span style="COLOR: #0000ff"&gt;using&lt;/span&gt; System;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&lt;span style="COLOR: #0000ff"&gt;using&lt;/span&gt; System.IO;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&lt;span style="COLOR: #0000ff"&gt;using&lt;/span&gt; Xceed.Compression;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&lt;span style="COLOR: #0000ff"&gt;namespace&lt;/span&gt; CompressedLogExample&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;{&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;class&lt;/span&gt; CompressedLog&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; CompressedLog( &lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt; filename
   )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;if&lt;/span&gt;(
   filename == &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt; )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ArgumentNullException(
   "filename" );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;if&lt;/span&gt;(
   filename.Length == 0 )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ArgumentException(
   "The filename cannot be empty.", "filename" );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; Xceed.Compression.Licenser.LicenseKey = "SAMPLE-APPLICATION-KEY";&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; m_filename = filename;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;void&lt;/span&gt; AddMessage( &lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt; message
   )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;if&lt;/span&gt;(
   message == &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt; )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ArgumentNullException(
   "message" );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;lock&lt;/span&gt;(
   m_lock )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;using&lt;/span&gt;(
   Stream fileStream = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; FileStream( m_filename,
   FileMode.Append ) )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;using&lt;/span&gt;(
   CompressedStream compStream = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; CompressedStream(
   fileStream ) )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;byte&lt;/span&gt;[]
   encodedMessage = System.Text.Encoding.Unicode.GetBytes(&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; DateTime.Now.ToString() + Environment.NewLine + message );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; compStream.Write( encodedMessage, 0, encodedMessage.Length );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;void&lt;/span&gt; DisplayMessages(
   TextWriter writer )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;if&lt;/span&gt;(
   writer == &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt; )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;throw&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; ArgumentNullException(
   "writer" );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;lock&lt;/span&gt;(
   m_lock )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;try&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;using&lt;/span&gt;(
   Stream originalStream = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; FileStream( m_filename,
   FileMode.Open ) )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Stream workStream = originalStream;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;do&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;using&lt;/span&gt;(
   CompressedStream compStream = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; CompressedStream(
   workStream ) )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="BACKGROUND: #ffffff; COLOR: #008000"&gt;//
   We don't want compStream to close sourceStream!&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; compStream.Transient = &lt;span style="COLOR: #0000ff"&gt;true&lt;/span&gt;;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;using&lt;/span&gt;(
   StreamReader reader = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; StreamReader( &lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;  compStream, System.Text.Encoding.Unicode ) )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; writer.WriteLine( reader.ReadToEnd() );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; writer.WriteLine( "---" );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="BACKGROUND: #ffffff; COLOR: #008000"&gt;//
   Before closing the reader (thus compStream), acquire a stream on&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="BACKGROUND: #ffffff; COLOR: #008000"&gt;//
   the rest of the data if present.&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; workStream = compStream.GetRemainingStream();&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="BACKGROUND: #ffffff; COLOR: #008000"&gt;//
   We must do this AFTER calling GetRemainingStream since compStream&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="BACKGROUND: #ffffff; COLOR: #008000"&gt;//
   may have read more from its inner stream than necessary.&lt;/span&gt;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;if&lt;/span&gt;(
   workStream.Position == workStream.Length )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; workStream = &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt;;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;while&lt;/span&gt;(
   workStream != &lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt; );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;catch&lt;/span&gt;(
   FileNotFoundException )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; writer.WriteLine( "The log is empty." );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;private&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt; m_filename
   = &lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt;.Empty;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;private&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;object&lt;/span&gt; m_lock
   = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;object&lt;/span&gt;();&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;
   Unfortunately, you can't replace the CompressedStream&amp;nbsp;with a formatted stream
   like &lt;a href="http://doc.xceedsoft.com/products/streamNet/ref/xceed.compression.formats.gzipcompressedstream.html"&gt;GZipCompressedStream&lt;/a&gt;,
   because they do not expose a GetRemainingStream method yet. Too bad, since the GZipCompressedStream
   can store a few minimal informations in its header. I'll have to open a feature request
   about that!
&lt;/p&gt;
&lt;p&gt;
   Here is some sample code for using this CompressedLog class:
&lt;/p&gt;
&lt;div style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 0pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 0pt; FONT-SIZE: 8pt; BACKGROUND: #ffffff; PADDING-BOTTOM: 0pt; BORDER-LEFT: windowtext 1pt solid; COLOR: #000000; PADDING-TOP: 0pt; BORDER-BOTTOM: windowtext 1pt solid; FONT-FAMILY: ProggySquareTTSZ"&gt;&lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;static&lt;/span&gt; &lt;span style="COLOR: #0000ff"&gt;void&lt;/span&gt; Main(&lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt;[]
   args)&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; CompressedLog log = &lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt; CompressedLog(
   @"d:\temp\log.cmp" );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;while&lt;/span&gt;( &lt;span style="COLOR: #0000ff"&gt;true&lt;/span&gt; )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; {&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; Console.WriteLine( "Write your next message below (empty message to quit):" );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt; line
   = Console.ReadLine();&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;if&lt;/span&gt;(
   line.Length == 0 )&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style="COLOR: #0000ff"&gt;break&lt;/span&gt;;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; log.AddMessage( line );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; Console.WriteLine();&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; Console.WriteLine( "Your messages were:" );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; log.DisplayMessages( Console.Out );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp;&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; Console.WriteLine( "Press &amp;lt;Enter&amp;gt; to quit." );&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; Console.ReadLine();&lt;/pre&gt;
   &lt;pre style="MARGIN: 0px"&gt;&amp;nbsp; &amp;nbsp; }&lt;/pre&gt;
&lt;/div&gt;
&lt;!--EndFragment--&gt;&lt;img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=4fc3e00e-646e-48bf-8dc2-8e7f1df58fa1" /&gt;</description>
      <category>.NET;Samples</category>
    </item>
    <item>
      <trackback:ping>http://blogs.xceedsoft.com/plantem/Trackback.aspx?guid=f5dfed4f-92c5-4f60-b301-b3483c6cabec</trackback:ping>
      <pingback:server>http://blogs.xceedsoft.com/plantem/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.xceedsoft.com/plantem/PermaLink,guid,f5dfed4f-92c5-4f60-b301-b3483c6cabec.aspx</pingback:target>
      <dc:creator />
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      I've been working part time (translation: I should be working on something else) on
      a new sample: my own Command Prompt. I know, I'm reinventing the wheel, not to count
      that Microsoft will launch a new one called msh (codename Monad). But it was more
      a concept or proof around exposing AbstractFolder and AbstractFile within a command
      prompt.
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New" color="#000000">
              <font color="#006400">E:\&gt;</font>
              <strong>dir</strong>
            </font>
          </p>
          <p>
            <font face="Courier New" color="#000000">  Directory of E:\</font>
          </p>
          <p>
            <font face="Courier New" color="#000000">      DATE    
      TIME     SIZE or TYPE NAME<br />
      27/12/2004  4:23 PM         [FOLDER]
      Backup<br />
      03/11/2004 10:33 AM         [FOLDER] Chart30<br />
      24/11/2004 10:09 AM         [FOLDER] CLR Profiler<br />
      11/01/2005  5:24 PM         [FOLDER]
      Config.Msi<br />
      24/11/2004 10:10 AM         [FOLDER] My Music<br />
      12/01/2005  4:13 PM         [FOLDER]
      My Pictures<br />
      10/09/2004  1:52 PM         [FOLDER]
      RECYCLER<br />
      30/09/2004  8:40 PM         [FOLDER]
      System Volume Information<br />
      02/02/2005  2:49 PM         [FOLDER]
      temp<br />
      03/11/2004 10:33 AM         [FOLDER] XceedProjectsNET<br />
      25/01/2005  7:06 AM             
      143 toto.txt</font>
          </p>
          <p>
            <font face="Courier New" color="#000000">  Files: 1  Folders: 14  Total
      file size: 143</font>
          </p>
          <p>
            <font face="Courier New" color="#000000">
              <font color="#006400">E:\&gt;</font>
              <strong>copy
      toto.txt temp</strong>
              <br />
       100%<br /><font color="#006400">E:\&gt;</font><strong>cd temp</strong><br /><font color="#006400">E:\temp\&gt;</font></font>
          </p>
        </blockquote>
        <p>
      As you can see, I can list the contents of folders, copy files, and change the working
      folder. The application simply manages a working "AbstractFolder", and enables commands
      to act on that folder (or an AbstractFolder obtained from an absolute path).
   </p>
        <p>
      The sample quicky evolved into a prototype for upcoming features. Among other things,
      I needed a way to recognize a path like "E:\temp\test.zip\images" as a ZippedFolder
      within a zip file. Let's stop the talking, and show some traces:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <font face="Courier New" color="#000000">
              <font color="#006400">E:\temp\&gt;</font>
              <strong>md
      test.zip<br /></strong>
              <font color="#006400">E:\temp\&gt;</font>
              <strong>md test.zip\images<br /></strong>
              <font color="#006400">E:\temp\&gt;</font>
              <strong>copy "..\My Pictures\Chalet\*"
      test.zip\images<br /></strong> 100%<br /><font color="#006400">E:\temp\&gt;</font></font>
          </p>
        </blockquote>
        <p dir="ltr">
      What have I done here? Create a folder named "test.zip"? Well, the "md" command recognized
      the ".zip" extension as a request to create a new empty zip file. The second "md"
      command actually created a new folder within the zip file. And the paths can freely
      use the zip filename as a folder part for any command, as shown with the copy example.
      If we display the contents of "E:\temp", we see the two expected files:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p dir="ltr">
            <font face="Courier New" color="#000000">
              <font color="#006400">E:\temp\&gt;</font>
              <strong>dir</strong>
            </font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">  Directory of E:\temp\</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">      DATE    
      TIME     SIZE or TYPE NAME<br />
      02/02/2005  3:00 PM         40068736
      test.zip<br />
      25/01/2005  7:06 AM             
      143 toto.txt</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">  Files: 2  Folders: 0  Total
      file size: 40068879</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#006400">E:\temp\&gt;</font>
          </p>
        </blockquote>
        <p dir="ltr">
      As you can see, "test.zip" is really a file (DiskFile) within "E:\temp" (DiskFolder).
      What happens if I try changing the current folder into that zip file?
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p dir="ltr">
            <font face="Courier New" color="#000000">
              <font color="#006400">E:\temp\&gt;</font>
              <strong>cd
      test.zip</strong>
              <br />
              <font color="#006400">E:\temp\test.zip\&gt;</font>
              <strong>dir</strong>
            </font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">  Directory of E:\temp\test.zip\</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">      DATE    
      TIME     SIZE or TYPE NAME<br />
      02/02/2005  3:00 PM         [FOLDER]
      images</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">  Files: 0  Folders: 1  Total
      file size: 0</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">
              <font color="#006400">E:\temp\test.zip\&gt;</font>
              <strong>cd
      images<br /></strong>
              <font color="#006400">E:\temp\test.zip\images\&gt;</font>
              <strong>dir</strong>
            </font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">  Directory of E:\temp\test.zip\images\</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">      DATE    
      TIME     SIZE or TYPE NAME<br />
      06/08/2000  4:40 PM          6400006
      Chaises.bmp<br />
      06/08/2000  4:35 PM          6348550
      Chute.bmp<br />
      06/08/2000  4:29 PM          6337678
      Ciel1.bmp<br />
      06/08/2000  4:30 PM          6396226
      Ciel2.bmp<br />
      06/08/2000  4:33 PM          6414418
      Ciel3.bmp<br />
      06/08/2000  4:38 PM          6524278
      Couple.bmp<br />
      06/08/2000  4:37 PM          6388054
      Martine.bmp<br />
      06/08/2000  4:32 PM          6405478
      Ombre.bmp<br />
      06/08/2000  4:41 PM          6359254
      Rochers.bmp</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">  Files: 9  Folders: 0  Total
      file size: 57573942</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#006400">E:\temp\test.zip\images\&gt;</font>
          </p>
        </blockquote>
        <p dir="ltr" style="MARGIN-RIGHT: 0px">
      The zip file is exposed as a folder, because the path "E:\temp\test.zip" was recognized
      and mapped to a ZippedFolder around a DiskFile. And "images" is nothing more than
      a subfolder within that root ZippedFolder, actually something like:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p dir="ltr" style="MARGIN-RIGHT: 0px">
            <font face="Courier New">new ZippedFolder( new DiskFile( @"E:\temp\test.zip" ), @"\images"
      );</font>
          </p>
        </blockquote>
        <p dir="ltr" style="MARGIN-RIGHT: 0px">
      Ok, let's get into serious things:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p dir="ltr" style="MARGIN-RIGHT: 0px">
            <font face="Courier New" color="#000000">
              <font color="#006400">E:\temp\test.zip\images\&gt;</font>
              <strong>cd
      ..\..<br /></strong>
              <font color="#006400">E:\temp\&gt;</font>
              <strong>copy *.zip RAM:\<br /></strong> 100%<br /><font color="#006400">E:\temp\&gt;</font><strong>cd RAM:\test.zip\images<br /></strong><font color="#006400">RAM:\test.zip\images\&gt;</font><strong>dir m*.bmp</strong></font>
          </p>
          <p dir="ltr" style="MARGIN-RIGHT: 0px">
            <font face="Courier New" color="#000000">  Directory of RAM:\test.zip\images\</font>
          </p>
          <p dir="ltr" style="MARGIN-RIGHT: 0px">
            <font face="Courier New" color="#000000">      DATE    
      TIME     SIZE or TYPE NAME<br />
      06/08/2000  4:37 PM          6388054
      Martine.bmp</font>
          </p>
          <p dir="ltr" style="MARGIN-RIGHT: 0px">
            <font face="Courier New" color="#000000">  Files: 1  Folders: 0  Total
      file size: 6388054</font>
          </p>
          <p dir="ltr" style="MARGIN-RIGHT: 0px">
            <font face="Courier New" color="#006400">RAM:\test.zip\images\&gt;</font>
          </p>
        </blockquote>
        <p dir="ltr">
      My Command Prompt exposes a root MemoryFolder called "RAM:\", which I can freely use.
      The commands act the same, no matter if I'm deeling with a ZippedFolder around a DiskFile
      or a MemoryFile. Want more?
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p dir="ltr">
            <font face="Courier New" color="#000000">
              <font color="#006400">RAM:\test.zip\images\&gt;</font>
              <strong>cd </strong>
            </font>
            <strong>
              <font face="Courier New">ftp://vermouth</font>
              <br />
            </strong>
            <font face="Courier New" color="#000000">
              <font color="#006400">ftp://vermouth\&gt;</font>
              <strong>dir</strong>
            </font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">  Directory of </font>
            <font face="Courier New" color="#000000">ftp://vermouth\</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">      DATE    
      TIME     SIZE or TYPE NAME</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">  Files: 0  Folders: 0  Total
      file size: 0</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">
              <font color="#006400">ftp://vermouth\&gt;</font>
              <strong>md</strong>
            </font>
            <font face="Courier New" color="#000000">
              <strong> foobar.zip<br /></strong>
            </font>
            <font face="Courier New" color="#000000">
              <font color="#006400">ftp://vermouth\&gt;</font>
              <strong>copy</strong>
            </font>
            <font face="Courier New" color="#000000">
              <strong> "E:\My
      Music\WMA\Mes Aieux" foobar.zip<br /></strong> 100%<br /></font>
            <font face="Courier New" color="#000000">
              <font color="#006400">ftp://vermouth\&gt;</font>
              <strong>dir</strong>
            </font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">  Directory of </font>
            <font face="Courier New" color="#000000">ftp://vermouth\</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">      DATE    
      TIME     SIZE or TYPE NAME<br />
      02/02/2005  3:20 PM         62936759
      foobar.zip</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">  Files: 1  Folders: 0  Total
      file size: 62936759</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">
              <font color="#006400">ftp://vermouth\&gt;</font>
              <strong>dir</strong>
            </font>
            <font face="Courier New" color="#000000">
              <strong> c:\inetpub\ftproot</strong>
            </font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">  Directory of c:\inetpub\ftproot\</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">      DATE    
      TIME     SIZE or TYPE NAME<br />
      02/02/2005  3:20 PM         62936759
      foobar.zip</font>
          </p>
          <p dir="ltr">
            <font face="Courier New" color="#000000">  Files: 1  Folders: 0  Total
      file size: 62936759</font>
          </p>
          <p dir="ltr">
            <font color="#006400">
              <font face="Courier New">ftp://vermouth\</font>
              <font face="Courier New">&gt;</font>
            </font>
          </p>
        </blockquote>
        <p dir="ltr">
      FTP servers are threated as any other kind of AbstractFolder. The application simply
      recognize the "FTP:" prefix as a signature for a root FtpFolder, as it did with
      "RAM:" exposed as a MemoryFolder. The command implementations don't care what kind
      of AbstractFolder or AbstractFile they are dealing with.
   </p>
        <p dir="ltr">
      The engine behind this involves FileSystemMapper-derived classes. They mainly
      get asked two kinds of questions:
   </p>
        <blockquote dir="ltr" style="MARGIN-RIGHT: 0px">
          <p>
            <strong>Question 1</strong>: Do you recognize this path as a root?
   </p>
          <p>
      If so, they remove the part of the path they could recognize as a root folder, and
      return the matching AbstractFolder.
   </p>
          <p>
      Examples of mappers and their responsability:
   </p>
          <ul>
            <li>
              <div>
                <strong>DiskMapper</strong> : Drive letters and UNC paths (yes, you can "cd"
            into a UNC path!)
         </div>
            </li>
            <li>
              <div>
                <strong>FtpMapper</strong> : The "FTP:" prefix with server name, and optional
            username and password (e.g. ftp://user:pass@vermouth:9999)
         </div>
            </li>
            <li>
              <div>
                <strong>IsolatedStorageMapper</strong> : A custom prefix name like "STORE:" (that's
            the one my sample app supports).
         </div>
            </li>
            <li>
              <div>
                <strong>MemoryMapper</strong> : A custom prefix used to create the initial root
            MemoryFolder, like "RAM:" (that's the one my app supports). You can create more than
            one MemoryMapper to have more than one ram drive.
         </div>
            </li>
          </ul>
          <p>
            <strong>Question 2</strong>: Can you represent this AbstractFile as an AbstractFolder?
   </p>
          <p>
      If so, they simply return the matching AbstractFolder.
   </p>
          <p>
      An example of such a mapper:
   </p>
          <ul>
            <li>
              <div>
                <strong>ZipFileMapper</strong> : It simply checks if the provided AbstractFile
            exists, then tries to create a ZipArchive around that AbstractFile in a try/catch.
            If it succeeds, it returns this ZipArchive (which derives from ZippedFolder).
         </div>
            </li>
          </ul>
          <p>
      Curiously, today I came across <a href="http://www.xceedsoft.com/Forums/ShowPost.aspx?PostID=2326">a
      post on our forums</a> asking how to detect if a file is really a zip file. I gave
      this man the "new ZipArchive within a try/catch" solution, and he came back, as I
      feared, with concerns with the time wasted catching an exception for all those non-zip
      files. It's actually one of the bottlenecks of my Command Prompt sample. A lot of
      time is wasted throwing an exception for all non-zip files my app comes across. Well,
      I guess I'll have to work sooner than later on a new "ZipArchive.IsZipFile" method!
      :-)
   </p>
        </blockquote>
        <p dir="ltr">
      Now, you have to convince my boss I should put more time on this sample and these
      new FileSystem features! Does mapping absolute paths like shown above to their proper
      AbstractFolder or AbstractFile something that could be usefull for you?
   </p>
        <img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=f5dfed4f-92c5-4f60-b301-b3483c6cabec" />
      </body>
      <title>Mapping absolute paths to an AbstractFolder or AbstractFile</title>
      <guid>http://blogs.xceedsoft.com/plantem/PermaLink,guid,f5dfed4f-92c5-4f60-b301-b3483c6cabec.aspx</guid>
      <link>http://blogs.xceedsoft.com/plantem/PermaLink,guid,f5dfed4f-92c5-4f60-b301-b3483c6cabec.aspx</link>
      <pubDate>Wed, 02 Feb 2005 20:55:51 GMT</pubDate>
      <description>&lt;p&gt;
   I've been working part time (translation: I should be working on something else) on
   a new sample: my own Command Prompt. I know, I'm reinventing the wheel, not to count
   that Microsoft will launch a new one called msh (codename Monad). But it was more
   a concept or proof around exposing AbstractFolder and AbstractFile within a command
   prompt.
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
   &lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;E:\&amp;gt;&lt;/font&gt;&lt;strong&gt;dir&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Directory of E:\&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DATE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   TIME&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SIZE or TYPE NAME&lt;br&gt;
   27/12/2004&amp;nbsp; 4:23 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FOLDER]
   Backup&lt;br&gt;
   03/11/2004 10:33 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FOLDER] Chart30&lt;br&gt;
   24/11/2004 10:09 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FOLDER] CLR Profiler&lt;br&gt;
   11/01/2005&amp;nbsp; 5:24 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FOLDER]
   Config.Msi&lt;br&gt;
   24/11/2004 10:10 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FOLDER] My Music&lt;br&gt;
   12/01/2005&amp;nbsp; 4:13 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FOLDER]
   My Pictures&lt;br&gt;
   10/09/2004&amp;nbsp; 1:52 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FOLDER]
   RECYCLER&lt;br&gt;
   30/09/2004&amp;nbsp; 8:40 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FOLDER]
   System Volume Information&lt;br&gt;
   02/02/2005&amp;nbsp; 2:49 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FOLDER]
   temp&lt;br&gt;
   03/11/2004 10:33 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FOLDER] XceedProjectsNET&lt;br&gt;
   25/01/2005&amp;nbsp; 7:06 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   143 toto.txt&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Files: 1&amp;nbsp; Folders: 14&amp;nbsp; Total
   file size: 143&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
   &lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;E:\&amp;gt;&lt;/font&gt;&lt;strong&gt;copy
   toto.txt temp&lt;/strong&gt;
   &lt;br&gt;
   &amp;nbsp;100%&lt;br&gt;
   &lt;font color=#006400&gt;E:\&amp;gt;&lt;/font&gt;&lt;strong&gt;cd temp&lt;/strong&gt;
   &lt;br&gt;
   &lt;font color=#006400&gt;E:\temp\&amp;gt;&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p&gt;
   As you can see, I can list the contents of folders, copy files, and change the working
   folder. The application simply manages a working "AbstractFolder", and enables commands
   to act on that folder (or an AbstractFolder obtained from an absolute path).
&lt;/p&gt;
&lt;p&gt;
   The sample quicky evolved into a prototype for upcoming features. Among other things,
   I needed a way to recognize a path like "E:\temp\test.zip\images" as a ZippedFolder
   within a zip file. Let's stop the talking, and show some traces:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
   &lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;E:\temp\&amp;gt;&lt;/font&gt;&lt;strong&gt;md
   test.zip&lt;br&gt;
   &lt;/strong&gt;&lt;font color=#006400&gt;E:\temp\&amp;gt;&lt;/font&gt;&lt;strong&gt;md test.zip\images&lt;br&gt;
   &lt;/strong&gt;&lt;font color=#006400&gt;E:\temp\&amp;gt;&lt;/font&gt;&lt;strong&gt;copy "..\My Pictures\Chalet\*"
   test.zip\images&lt;br&gt;
   &lt;/strong&gt;&amp;nbsp;100%&lt;br&gt;
   &lt;font color=#006400&gt;E:\temp\&amp;gt;&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
   What have I done here? Create a folder named "test.zip"? Well, the "md" command recognized
   the ".zip" extension as a request to create a new empty zip file. The second "md"
   command actually created a new folder within the zip file. And the paths can freely
   use the zip filename as a folder part for any command, as shown with the copy example.
   If we display the contents of "E:\temp", we see the two expected files:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;E:\temp\&amp;gt;&lt;/font&gt;&lt;strong&gt;dir&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Directory of E:\temp\&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DATE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   TIME&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SIZE or TYPE NAME&lt;br&gt;
   02/02/2005&amp;nbsp; 3:00 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 40068736
   test.zip&lt;br&gt;
   25/01/2005&amp;nbsp; 7:06 AM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   143 toto.txt&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Files: 2&amp;nbsp; Folders: 0&amp;nbsp; Total
   file size: 40068879&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#006400&gt;E:\temp\&amp;gt;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
   As you can see,&amp;nbsp;"test.zip" is really a file (DiskFile) within "E:\temp" (DiskFolder).
   What happens if I try changing the current folder into that zip file?
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;E:\temp\&amp;gt;&lt;/font&gt;&lt;strong&gt;cd
   test.zip&lt;/strong&gt;
   &lt;br&gt;
   &lt;font color=#006400&gt;E:\temp\test.zip\&amp;gt;&lt;/font&gt;&lt;strong&gt;dir&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Directory of E:\temp\test.zip\&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DATE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   TIME&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SIZE or TYPE NAME&lt;br&gt;
   02/02/2005&amp;nbsp; 3:00 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [FOLDER]
   images&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Files: 0&amp;nbsp; Folders: 1&amp;nbsp; Total
   file size: 0&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;E:\temp\test.zip\&amp;gt;&lt;/font&gt;&lt;strong&gt;cd
   images&lt;br&gt;
   &lt;/strong&gt;&lt;font color=#006400&gt;E:\temp\test.zip\images\&amp;gt;&lt;/font&gt;&lt;strong&gt;dir&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Directory of E:\temp\test.zip\images\&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DATE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   TIME&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SIZE or TYPE NAME&lt;br&gt;
   06/08/2000&amp;nbsp; 4:40 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6400006
   Chaises.bmp&lt;br&gt;
   06/08/2000&amp;nbsp; 4:35 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6348550
   Chute.bmp&lt;br&gt;
   06/08/2000&amp;nbsp; 4:29 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6337678
   Ciel1.bmp&lt;br&gt;
   06/08/2000&amp;nbsp; 4:30 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6396226
   Ciel2.bmp&lt;br&gt;
   06/08/2000&amp;nbsp; 4:33 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6414418
   Ciel3.bmp&lt;br&gt;
   06/08/2000&amp;nbsp; 4:38 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6524278
   Couple.bmp&lt;br&gt;
   06/08/2000&amp;nbsp; 4:37 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6388054
   Martine.bmp&lt;br&gt;
   06/08/2000&amp;nbsp; 4:32 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6405478
   Ombre.bmp&lt;br&gt;
   06/08/2000&amp;nbsp; 4:41 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6359254
   Rochers.bmp&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Files: 9&amp;nbsp; Folders: 0&amp;nbsp; Total
   file size: 57573942&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#006400&gt;E:\temp\test.zip\images\&amp;gt;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr style="MARGIN-RIGHT: 0px"&gt;
   The zip file is exposed as a folder, because the path "E:\temp\test.zip" was recognized
   and mapped to a ZippedFolder around a DiskFile. And "images" is nothing more than
   a subfolder within that root ZippedFolder, actually something like:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p dir=ltr style="MARGIN-RIGHT: 0px"&gt;
   &lt;font face="Courier New"&gt;new ZippedFolder( new DiskFile( @"E:\temp\test.zip" ), @"\images"
   );&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr style="MARGIN-RIGHT: 0px"&gt;
   Ok, let's get into serious things:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p dir=ltr style="MARGIN-RIGHT: 0px"&gt;
   &lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;E:\temp\test.zip\images\&amp;gt;&lt;/font&gt;&lt;strong&gt;cd
   ..\..&lt;br&gt;
   &lt;/strong&gt;&lt;font color=#006400&gt;E:\temp\&amp;gt;&lt;/font&gt;&lt;strong&gt;copy *.zip RAM:\&lt;br&gt;
   &lt;/strong&gt;&amp;nbsp;100%&lt;br&gt;
   &lt;font color=#006400&gt;E:\temp\&amp;gt;&lt;/font&gt;&lt;strong&gt;cd RAM:\test.zip\images&lt;br&gt;
   &lt;/strong&gt;&lt;font color=#006400&gt;RAM:\test.zip\images\&amp;gt;&lt;/font&gt;&lt;strong&gt;dir m*.bmp&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr style="MARGIN-RIGHT: 0px"&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Directory of RAM:\test.zip\images\&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr style="MARGIN-RIGHT: 0px"&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DATE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   TIME&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SIZE or TYPE NAME&lt;br&gt;
   06/08/2000&amp;nbsp; 4:37 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6388054
   Martine.bmp&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr style="MARGIN-RIGHT: 0px"&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Files: 1&amp;nbsp; Folders: 0&amp;nbsp; Total
   file size: 6388054&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr style="MARGIN-RIGHT: 0px"&gt;
   &lt;font face="Courier New" color=#006400&gt;RAM:\test.zip\images\&amp;gt;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
   My Command Prompt exposes a root MemoryFolder called "RAM:\", which I can freely use.
   The commands act the same, no matter if I'm deeling with a ZippedFolder around a DiskFile
   or a MemoryFile. Want more?
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;RAM:\test.zip\images\&amp;gt;&lt;/font&gt;&lt;strong&gt;cd &lt;/strong&gt;&lt;/font&gt;&lt;strong&gt;&lt;font face="Courier New"&gt;ftp://vermouth&lt;/font&gt;
   &lt;br&gt;
   &lt;/strong&gt;&lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;ftp://vermouth\&amp;gt;&lt;/font&gt;&lt;strong&gt;dir&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Directory of &lt;/font&gt;&lt;font face="Courier New" color=#000000&gt;ftp://vermouth\&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DATE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   TIME&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SIZE or TYPE NAME&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Files: 0&amp;nbsp; Folders: 0&amp;nbsp; Total
   file size: 0&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;ftp://vermouth\&amp;gt;&lt;/font&gt;&lt;strong&gt;md&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New" color=#000000&gt;&lt;strong&gt; foobar.zip&lt;br&gt;
   &lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;ftp://vermouth\&amp;gt;&lt;/font&gt;&lt;strong&gt;copy&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New" color=#000000&gt;&lt;strong&gt; "E:\My
   Music\WMA\Mes Aieux" foobar.zip&lt;br&gt;
   &lt;/strong&gt;&amp;nbsp;100%&lt;br&gt;
   &lt;/font&gt;&lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;ftp://vermouth\&amp;gt;&lt;/font&gt;&lt;strong&gt;dir&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Directory of &lt;/font&gt;&lt;font face="Courier New" color=#000000&gt;ftp://vermouth\&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DATE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   TIME&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SIZE or TYPE NAME&lt;br&gt;
   02/02/2005&amp;nbsp; 3:20 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 62936759
   foobar.zip&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Files: 1&amp;nbsp; Folders: 0&amp;nbsp; Total
   file size: 62936759&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&lt;font color=#006400&gt;ftp://vermouth\&amp;gt;&lt;/font&gt;&lt;strong&gt;dir&lt;/strong&gt;&lt;/font&gt;&lt;font face="Courier New" color=#000000&gt;&lt;strong&gt; c:\inetpub\ftproot&lt;/strong&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Directory of c:\inetpub\ftproot\&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DATE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
   TIME&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SIZE or TYPE NAME&lt;br&gt;
   02/02/2005&amp;nbsp; 3:20 PM&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 62936759
   foobar.zip&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font face="Courier New" color=#000000&gt;&amp;nbsp; Files: 1&amp;nbsp; Folders: 0&amp;nbsp; Total
   file size: 62936759&lt;/font&gt;
&lt;/p&gt;
&lt;p dir=ltr&gt;
   &lt;font color=#006400&gt;&lt;font face="Courier New"&gt;ftp://vermouth\&lt;/font&gt;&lt;font face="Courier New"&gt;&amp;gt;&lt;/font&gt;&lt;/font&gt;
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
   FTP servers are threated as any other kind of AbstractFolder. The application simply
   recognize the "FTP:" prefix as a signature for a root&amp;nbsp;FtpFolder, as it did with
   "RAM:" exposed as a MemoryFolder. The command implementations don't care what kind
   of AbstractFolder or AbstractFile they are dealing with.
&lt;/p&gt;
&lt;p dir=ltr&gt;
   The&amp;nbsp;engine behind this involves FileSystemMapper-derived classes. They mainly
   get asked two kinds of questions:
&lt;/p&gt;
&lt;blockquote dir=ltr style="MARGIN-RIGHT: 0px"&gt; 
&lt;p&gt;
   &lt;strong&gt;Question 1&lt;/strong&gt;: Do you recognize this path as a root?
&lt;/p&gt;
&lt;p&gt;
   If so, they remove the part of the path they could recognize as a root folder, and
   return the matching AbstractFolder.
&lt;/p&gt;
&lt;p&gt;
   Examples of mappers and their responsability:
&lt;/p&gt;
&lt;ul&gt;
   &lt;li&gt;
      &lt;div&gt;&lt;strong&gt;DiskMapper&lt;/strong&gt; : Drive letters and UNC paths (yes, you can "cd"
         into a UNC path!)
      &lt;/div&gt;
   &lt;/li&gt;
   &lt;li&gt;
      &lt;div&gt;&lt;strong&gt;FtpMapper&lt;/strong&gt; : The "FTP:" prefix with server name, and optional
         username and password (e.g. ftp://user:pass@vermouth:9999)
      &lt;/div&gt;
   &lt;/li&gt;
   &lt;li&gt;
      &lt;div&gt;&lt;strong&gt;IsolatedStorageMapper&lt;/strong&gt; : A custom prefix name like "STORE:" (that's
         the one my sample app supports).
      &lt;/div&gt;
   &lt;/li&gt;
   &lt;li&gt;
      &lt;div&gt;&lt;strong&gt;MemoryMapper&lt;/strong&gt; : A custom prefix used to create the initial root
         MemoryFolder, like "RAM:" (that's the one my app supports). You can create more than
         one MemoryMapper to have more than one ram drive.
      &lt;/div&gt;
   &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
   &lt;strong&gt;Question 2&lt;/strong&gt;: Can you represent this AbstractFile as an AbstractFolder?
&lt;/p&gt;
&lt;p&gt;
   If so, they simply return the matching AbstractFolder.
&lt;/p&gt;
&lt;p&gt;
   An example of such a mapper:
&lt;/p&gt;
&lt;ul&gt;
   &lt;li&gt;
      &lt;div&gt;&lt;strong&gt;ZipFileMapper&lt;/strong&gt; : It simply checks if the provided AbstractFile
         exists, then tries to create a ZipArchive around that AbstractFile in a try/catch.
         If it succeeds, it returns this ZipArchive (which derives from ZippedFolder).
      &lt;/div&gt;
   &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
   Curiously, today I came across &lt;a href="http://www.xceedsoft.com/Forums/ShowPost.aspx?PostID=2326"&gt;a
   post on our forums&lt;/a&gt; asking how to detect if a file is really a zip file. I gave
   this man the "new ZipArchive within a try/catch" solution, and he came back, as I
   feared, with concerns with the time wasted catching an exception for all those non-zip
   files. It's actually one of the bottlenecks of my Command Prompt sample. A lot of
   time is wasted throwing an exception for all non-zip files my app comes across. Well,
   I guess I'll have to work sooner than later on a new "ZipArchive.IsZipFile" method!
   :-)
&lt;/p&gt;
&lt;/blockquote&gt; 
&lt;p dir=ltr&gt;
   Now, you have to convince my boss I should put more time on this sample and these
   new FileSystem features! Does mapping absolute paths like shown above to their proper
   AbstractFolder or AbstractFile something that could be usefull for you?
&lt;/p&gt;
&lt;img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=f5dfed4f-92c5-4f60-b301-b3483c6cabec" /&gt;</description>
      <category>FileSystem;FTP;Samples;Zip</category>
    </item>
    <item>
      <trackback:ping>http://blogs.xceedsoft.com/plantem/Trackback.aspx?guid=79c0a728-6d72-4b97-9973-74333e4df44d</trackback:ping>
      <pingback:server>http://blogs.xceedsoft.com/plantem/pingback.aspx</pingback:server>
      <pingback:target>http://blogs.xceedsoft.com/plantem/PermaLink,guid,79c0a728-6d72-4b97-9973-74333e4df44d.aspx</pingback:target>
      <dc:creator />
      <body xmlns="http://www.w3.org/1999/xhtml">
        <p>
      I admit, I'm working in zip file compression, and I'm not even using something home
      made for unzipping zip files I run into. I'm using <a href="http://www.winzip.com/">WinZip</a>'s
      context menu.
   </p>
        <p>
      Well, I should talk to the past. I've made a man of myself and implemented my own
      "Unzip Here" context menu, which is using Xceed Zip ActiveX 5.x. Why reinvent the
      wheel when it works fine? Because it didn't work that fine for me.
   </p>
        <p>
      How many times have I right-clicked on a zip file, went to the <strong><em>WinZip</em></strong> menu,
      stared at <strong><em>Extract to here</em></strong> and <strong><em>Extract to d:\someplace\somewhere\zipfilename</em></strong> just
      to find asking myself: <em>"Does that zip file already contain paths?"</em>. If it
      does, I don't need to create a "zipfilename" subfolder, thus I should select the first
      menu item. But if it doesn't, I sure don't want all unzipped files to end up in the
      current folder, thus I want to select the second menu item. I end up opening the zip
      file just to view file paths.
   </p>
        <p>
      That's what I just implemented. You right-click on a zip file, you click on <strong><em>Unzip
      Here</em></strong>, and it will automatically detect if it needs to create a subfolder
      (using the zip filename) or not, then unzip everything.
   </p>
        <p>
      I won't go into the full details of how to create a Windows Shell Extension component,
      the sample is pretty self-explanatory, and the web is filled with tutorials. In short,
      you:
   </p>
        <ul>
          <li>
         Create a new <strong><em>ATL COM AppWizard</em></strong> project (VC++ 6). 
      </li>
          <li>
         Add a new <strong><em>Simple Object</em></strong> with default names and attributes
         (make sure not to select "Free Threaded"). 
      </li>
          <li>
         Remove references to the newly created interface, you don't need it. (I left the IDL
         in there instead of copying the CLSID somewhere else... I'm lazy). 
      </li>
          <li>
         Remove the type library from the resources and RGS file, you don't need it. 
      </li>
          <li>
         Implement <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/ifaces/ishellextinit/ishellextinit.asp">IShellExtInit</a> and <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/ifaces/icontextmenu/icontextmenu.asp">IContextMenu</a> interfaces
         (see UnzipHereExtension.cpp). 
      </li>
          <li>
         Add the required registry keys (see "DllRegisterServer" in UnzipHere.cpp).</li>
        </ul>
        <p>
      The heart of the extension resides in <strong><em>IContextMenu::InvokeCommand</em></strong>.
      Don't forget more than one file can be selected when your context menu gets called.
   </p>
        <p>
      While debugging, you'll often need to restart the <strong><em>explorer.exe</em></strong> in
      order to release usage of your DLL. Use the Task Manager's run menu to reload it.
      If you don't like ending a task via the Task Manager, try this: Start Menu -&gt; Shutdown,
      press Ctrl-Alt-Shift and click Cancel. The explorer.exe process will end.
   </p>
        <p>
      On my TODO list:
   </p>
        <ul>
          <li>
         Support zip files not ending with the ZIP extension (like self-extracting zip files). 
      </li>
          <li>
         Implement a "Zip This" menu. 
      </li>
          <li>
         Add a "File already exists. Do you want to overwrite?" prompt. 
      </li>
          <li>
         Hide the "aborted" error on non-zip files.</li>
        </ul>
        <p>
      Comments welcomed! Have fun!
   </p>
        <a href="http://blogs.xceedsoft.com/plantem/content/binary/UnzipHere.zip">UnzipHere.zip
   (21 KB)</a>
        <img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=79c0a728-6d72-4b97-9973-74333e4df44d" />
      </body>
      <title>Implementing my own "Unzip Here" context menu</title>
      <guid>http://blogs.xceedsoft.com/plantem/PermaLink,guid,79c0a728-6d72-4b97-9973-74333e4df44d.aspx</guid>
      <link>http://blogs.xceedsoft.com/plantem/PermaLink,guid,79c0a728-6d72-4b97-9973-74333e4df44d.aspx</link>
      <pubDate>Mon, 13 Dec 2004 20:57:24 GMT</pubDate>
      <description>&lt;p&gt;
   I admit, I'm working in zip file compression, and I'm not even using something home
   made for unzipping zip files I run into. I'm using &lt;a href="http://www.winzip.com/"&gt;WinZip&lt;/a&gt;'s
   context menu.
&lt;/p&gt;
&lt;p&gt;
   Well, I should talk to the past. I've made a man of myself and implemented my own
   "Unzip Here" context menu, which is using Xceed Zip ActiveX 5.x. Why reinvent the
   wheel when it works fine? Because it didn't work that fine for me.
&lt;/p&gt;
&lt;p&gt;
   How many times have I right-clicked on a zip file, went to the &lt;strong&gt;&lt;em&gt;WinZip&lt;/em&gt;&lt;/strong&gt; menu,
   stared at &lt;strong&gt;&lt;em&gt;Extract to here&lt;/em&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;em&gt;Extract to d:\someplace\somewhere\zipfilename&lt;/em&gt;&lt;/strong&gt; just
   to find asking myself: &lt;em&gt;"Does that zip file already contain paths?"&lt;/em&gt;. If it
   does, I don't need to create a "zipfilename" subfolder, thus I should select the first
   menu item. But if it doesn't, I sure don't want all unzipped files to end up in the
   current folder, thus I want to select the second menu item. I end up opening the zip
   file just to view file paths.
&lt;/p&gt;
&lt;p&gt;
   That's what I just implemented. You right-click on a zip file, you click on &lt;strong&gt;&lt;em&gt;Unzip
   Here&lt;/em&gt;&lt;/strong&gt;, and it will automatically detect if it needs to create a subfolder
   (using the zip filename) or not, then unzip everything.
&lt;/p&gt;
&lt;p&gt;
   I won't go into the full details of how to create a Windows Shell Extension component,
   the sample is pretty self-explanatory, and the web is filled with tutorials. In short,
   you:
&lt;/p&gt;
&lt;ul&gt;
   &lt;li&gt;
      Create a new &lt;strong&gt;&lt;em&gt;ATL COM AppWizard&lt;/em&gt;&lt;/strong&gt; project (VC++ 6). 
   &lt;li&gt;
      Add a new &lt;strong&gt;&lt;em&gt;Simple Object&lt;/em&gt;&lt;/strong&gt; with default names and attributes
      (make sure not to select "Free Threaded"). 
   &lt;li&gt;
      Remove references to the newly created interface, you don't need it. (I left the IDL
      in there instead of copying the CLSID somewhere else... I'm lazy). 
   &lt;li&gt;
      Remove the type library from the resources and RGS file, you don't need it. 
   &lt;li&gt;
      Implement &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/ifaces/ishellextinit/ishellextinit.asp"&gt;IShellExtInit&lt;/a&gt; and &lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/ifaces/icontextmenu/icontextmenu.asp"&gt;IContextMenu&lt;/a&gt; interfaces
      (see UnzipHereExtension.cpp). 
   &lt;li&gt;
      Add the required registry keys (see "DllRegisterServer" in UnzipHere.cpp).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
   The heart of the extension resides in &lt;strong&gt;&lt;em&gt;IContextMenu::InvokeCommand&lt;/em&gt;&lt;/strong&gt;.
   Don't forget more than one file can be selected when your context menu gets called.
&lt;/p&gt;
&lt;p&gt;
   While debugging, you'll often need to restart the &lt;strong&gt;&lt;em&gt;explorer.exe&lt;/em&gt;&lt;/strong&gt; in
   order to release usage of your DLL. Use the Task Manager's run menu to reload it.
   If you don't like ending a task via the Task Manager, try this: Start Menu -&amp;gt; Shutdown,
   press Ctrl-Alt-Shift and click Cancel. The explorer.exe process will end.
&lt;/p&gt;
&lt;p&gt;
   On my TODO list:
&lt;/p&gt;
&lt;ul&gt;
   &lt;li&gt;
      Support zip files not ending with the ZIP extension (like self-extracting zip files). 
   &lt;li&gt;
      Implement a "Zip This" menu. 
   &lt;li&gt;
      Add a "File already exists. Do you want to overwrite?" prompt. 
   &lt;li&gt;
      Hide the "aborted" error on non-zip files.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
   Comments welcomed! Have fun!
&lt;/p&gt;
&lt;a href="http://blogs.xceedsoft.com/plantem/content/binary/UnzipHere.zip"&gt;UnzipHere.zip
(21 KB)&lt;/a&gt;&lt;img width="0" height="0" src="http://blogs.xceedsoft.com/plantem/aggbug.ashx?id=79c0a728-6d72-4b97-9973-74333e4df44d" /&gt;</description>
      <category>Zip;Samples</category>
    </item>
  </channel>
</rss>