Friday, August 12, 2005

I just upgraded our blog engine to dasBlog 1.8. You can learn more here.

Tell me if you see anything strange.

Thank you Scott, Omar, and the rest of the project members.



8/12/2005 3:35:55 PM (Eastern Daylight Time, UTC-04:00)  #   
 Wednesday, August 10, 2005

Found this via Scott Hanselman. Too cool! Please add your location. Simply zoom and move to your location, double-click, then complete your information.


Fun | General

8/10/2005 10:32:22 PM (Eastern Daylight Time, UTC-04:00)  #   
 Wednesday, July 27, 2005

Bob: So, did you have time to check Windows Vista Beta 1?

Max: Yeah, cool!

Bob: Great. What's new?

Max: They changed Notepad's icon!

notepad.jpg

Bob: Oh... Wow...


Fun | General

7/27/2005 1:46:28 PM (Eastern Daylight Time, UTC-04:00)  #   
 Friday, July 15, 2005

My friend and colleague Pascal is selling one of his PDC 2000 souvenirs.

Bottle.jpg

It's an unopened original PDC 2000 bottle of water!!! Who will be the lucky buyer? :-)


Fun

7/15/2005 10:00:10 AM (Eastern Daylight Time, UTC-04:00)  #   
 Thursday, July 14, 2005

I'm currently working hard on the FileSystem support for Xceed FTP for .NET, and I had to share with you a screenshot of one of my tests. My XceedBox.NET sample is now fully supporting FtpFile and FtpFolder mapping.

XceedBoxNET.png

As you can see, my working folder is a zip file located in a folder on an FTP server. The "type" command above has no idea what kind of file it is displaying. It receives an AbstractFile, gets a Stream on it via OpenRead, reads and displays the contents. That AbstractFile is actually a ZippedFile found in a ZippedFolder constructed around an FtpFile found in an FtpFolder.


.NET | FileSystem | FTP

7/14/2005 4:04:21 PM (Eastern Daylight Time, UTC-04:00)  #   
 Monday, July 04, 2005

My friend and colleague Pascal is a big fan of AppRocket. He bought it and is very very satisfied with the software. For those who don't know what is does, let's say it indexes file and folder names of your choice for quick access using a few keyboard letters. For example, by default, it indexes the Start Menu. So typing "PNT" proposes a list of applications or documents to open, starting with Paint.

He convinced me to try it, and I immediately was attracted with the concept. Getting away from the dreadful mouse clicks is a benediction. But ever since installation, I was regularly frustrated with many aspects of the software. So today, I uninstalled it.

First, after installation, my Windows XP Firewall warns me AppRocket wants to listen on a port. What the...? It's a keyboard shortcut program. How come it requires listening? I sent an email to Candy Labs support, and never got any answer.

Second, the application's configuration dialog box does not display correctly when you are using a theme different from the default Windows XP "Luna" (Blue, Silver or Olive). Everytime I want to change something in the configuration, like adding a new path to index, I must switch from my CodeOpus theme to Luna, change stuff, then get back to CodeOpus. I contacted Candy Labs support again... No answer.

As if that wasn't enough, one time I opened the Control Panel's Display Settings by typing "DIS" in AppRocket (yes, it also indexes the Control Panel), then changed the theme to Luna because I wanted to add a path to index. But AppRocket crached with an unhandled exception. Hurray! They are forcing me to switch themes, then crash on me when I do!

The last nail got hit when I monitored the IP connections AppRocket was trying to make, to see why it was listening on a port. It's listening on port 9001, and up to now have no idea why. But I also noticed that what appears to be auto-update-related functionality is trying to connect to http://64.127.102.250/. If you go check the home page, it's really nothing to inspire confidance in the product's seriousness, not to count the lack of any activity on Candy Labs' site.


Fun

7/4/2005 10:31:44 AM (Eastern Daylight Time, UTC-04:00)  #   
 Tuesday, June 28, 2005

Google Earth (aka Keyhole 3) is out, and free! Go check it out!


Fun

6/28/2005 3:28:27 PM (Eastern Daylight Time, UTC-04:00)  #   
 Thursday, June 16, 2005

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.

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.

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 CompressedStream class exposes a GetRemainingStream method for retrieving a Stream reference on the rest of the data in the inner stream.

I've kept the sample real simple, so you get the general idea:

using System;
using System.IO;
using Xceed.Compression;
 
namespace CompressedLogExample
{
  public class CompressedLog
  {
    public CompressedLog( string filename )
    {
      if( filename == null )
        throw new ArgumentNullException( "filename" );
 
      if( filename.Length == 0 )
        throw new ArgumentException( "The filename cannot be empty.", "filename" );
 
      Xceed.Compression.Licenser.LicenseKey = "SAMPLE-APPLICATION-KEY";
      m_filename = filename;
    }
 
    public void AddMessage( string message )
    {
      if( message == null )
        throw new ArgumentNullException( "message" );
 
      lock( m_lock )
      {
        using( Stream fileStream = new FileStream( m_filename, FileMode.Append ) )
        {
          using( CompressedStream compStream = new CompressedStream( fileStream ) )
          {
            byte[] encodedMessage = System.Text.Encoding.Unicode.GetBytes(
              DateTime.Now.ToString() + Environment.NewLine + message );
 
            compStream.Write( encodedMessage, 0, encodedMessage.Length );
          }
        }
      }
    }
 
    public void DisplayMessages( TextWriter writer )
    {
      if( writer == null )
        throw new ArgumentNullException( "writer" );
 
      lock( m_lock )
      {
        try
        {
          using( Stream originalStream = new FileStream( m_filename, FileMode.Open ) )
          {
            Stream workStream = originalStream;
 
            do
            {
              using( CompressedStream compStream = new CompressedStream( workStream ) )
              {
                // We don't want compStream to close sourceStream!
                compStream.Transient = true;
 
                using( StreamReader reader = new StreamReader( 
                         compStream, System.Text.Encoding.Unicode ) )
                {
                  writer.WriteLine( reader.ReadToEnd() );
                  writer.WriteLine( "---" );
 
                  // Before closing the reader (thus compStream), acquire a stream on
                  // the rest of the data if present.
                  workStream = compStream.GetRemainingStream();
 
                  // We must do this AFTER calling GetRemainingStream since compStream
                  // may have read more from its inner stream than necessary.
                  if( workStream.Position == workStream.Length )
                  {
                    workStream = null;
                  }
                }
              }
            }
            while( workStream != null );
          }
        }
        catch( FileNotFoundException )
        {
          writer.WriteLine( "The log is empty." );
        }
      }
    }
 
    private string m_filename = string.Empty;
    private object m_lock = new object();
  }
}

Unfortunately, you can't replace the CompressedStream with a formatted stream like GZipCompressedStream, 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!

Here is some sample code for using this CompressedLog class:

    static void Main(string[] args)
    {
      CompressedLog log = new CompressedLog( @"d:\temp\log.cmp" );
 
      while( true )
      {
        Console.WriteLine( "Write your next message below (empty message to quit):" );
 
        string line = Console.ReadLine();
 
        if( line.Length == 0 )
          break;
 
        log.AddMessage( line );
      }
 
      Console.WriteLine();
      Console.WriteLine( "Your messages were:" );
 
      log.DisplayMessages( Console.Out );
 
      Console.WriteLine( "Press <Enter> to quit." );
      Console.ReadLine();
    }


6/16/2005 3:04:00 PM (Eastern Daylight Time, UTC-04:00)  #