|
|
|
|
Open window on development at Xceed
|
|
|
 Thursday, September 30, 2004
One of the gotchas of the Xceed FileSystem is its behaviour when it can't process a file a folder: it throws an exception right away. Call it lazy by default! Take this code for example: AbstractFolder folder = new DiskFolder( @"c:\" );
AbstractFile[] gdiFiles = folder.GetFiles( true, "gdiplus.dll" );
foreach( AbstractFile file in gdiFiles )
{
Console.WriteLine( "{0}: {1}",
file.LastWriteDateTime.ToShortDateString(), file.FullName );
}
You would expect this to list all gdiplus.dll files found on your C: drive. On most computers, it will throw an UnauthorizedAccessException, because the currently logged in user probably does not have read access to all folders, like "System Volume Information" or other users' profiles under "Documents and Settings".
Does that mean you're doomed? No. Every time a method that processes many items encounters a problem with an item, it will raise the ItemException event. If you handle this event, you have access to the current and target item (if applies) and the exception that is about to be thrown. More important, you can instruct the sender to try again on the same item, skip the faulty item and continue with the next one, or abort the current operation and throw the exception (default).
Before we take a closer look, you must understand how events work with the FileSystem. Since all files and folders are represented by their own instance, it would be unthinkable to advise for events on each and every one, or have delegates propagated on every child instance a folder creates for its processing.
Instead, every method that can raise events exposes pairs of overloads, one taking a FileSystemEvents and object as its first two parameters. You create yourself a single FileSystemEvents instance (or ZipEvents), advise for events you wish to handle on it, then pass it to every method which can accept one. The second object parameter can be anything you wish, and is passed back to the event handler. In French, we call this a "fourre-tout" parameter. Babelfish translates this to "hold-all". The library calls it "user data".
The above code would now look like this: FileSystemEvents events = new FileSystemEvents();
events.ItemException += new ItemExceptionEventHandler( FileSystemEvents_ItemException );
AbstractFolder folder = new DiskFolder( @"c:\" );
AbstractFile[] gdiFiles = folder.GetFiles( events, null, true, "gdiplus.dll" );
foreach( AbstractFile file in gdiFiles )
{
Console.WriteLine( "{0}: {1}",
file.LastWriteDateTime.ToShortDateString(), file.FullName );
}
With the event handler doing the simplest thing: private static void FileSystemEvents_ItemException( object sender, ItemExceptionEventArgs e )
{
System.Diagnostics.Debug.WriteLine( e.Exception.Message );
e.Action = ItemExceptionAction.Ignore;
}
Good. This should work. You run it. You see a blank screen. Nothing seems to be running. Sure, you ear your hard drive rumbling, but your application looks dead. That's bad. The ScanningFolder, ItemProgression and ByteProgression events come to the rescue. The first one is fired everytime the contents of a folder is retrieved. The second one is fired when an item is about to be copied or moved. The last one is fired every 64k of copied or moved data between files. In our case, we will advise for the ScanningFolder event, by adding this line: events.ScanningFolder += new ScanningFolderEventHandler( FileSystemEvents_ScanningFolder );
And implementing this event handler: private static char[] mg_animationChars = new char[] { '|', '/', '-', '\\' };
private static int mg_animationIndex = 0;
private static void FileSystemEvents_ScanningFolder( object sender, ScanningFolderEventArgs e )
{
Console.Write( mg_animationChars[ mg_animationIndex++ ] );
Console.Write( '\b' );
mg_animationIndex %= mg_animationChars.Length;
}
Wow! DOS-style animation, my favourites! (Hey, it was my school). For the remaining events, it's yours to discover. Feel free to post your questions on our forums. Though we do not guarantee a fast answer, I personally try to monitor my own products' groups as often as possible.
|
|
Mitch Denny created a nice little tool called Shrinklet, which monitors your clipboard for URLs, and lets you replace them with a shorter shrinkster.com URL, via a simple balloon notification.

Cool! Now, I need the sources! 
|
|
 Thursday, September 23, 2004
 Saturday, September 18, 2004
Before I dive into the Xceed FileSystem (the heart of Xceed Zip for .NET), a quick tour of the object model is required. At the heart of the Xceed FileSystem are three abstract classes: the base FileSystemItem class and the two derived AbstractFile and AbstractFolder classes. They expose the basic operations we can do on files and folders, like copy, move, create, delete, read from or write to, browse contents, get or change attributes and dates. You're already familiar with all this, either using Windows Explorer, a third party shell explorer, or the good old command prompt.
Files and folders are not only found on disk drives, they can be located in memory, on an FTP or HTTP server, on your Windows CE device, in the isolated storage, in your favorite source control system, in an email as an attachment, name it. Sometimes, the device is smart enough to expose itself as a real drive. For example, ram drives are usually accessible through normal file paths. They acquire a drive letter and trick the OS in thinking they are a legitimate disk drive. Another good example is Daemon Tools, which lets you expose a CD ISO image located on your hard disk as if it was a CD drive. In both cases, normal IO APIs can access them with the proper file paths.
But most often, integration stops at the shell or application level. For example, ActiveSync will let you access files and folders on your Windows CE device through Windows Explorer, as if they were normal files and folders. But don't try using classes under System.IO to access them. It won't work. You have to revert to RAPI, and manage the bridge between "worlds" yourself.
Another example is the zip file support in Windows XP (and originally in Windows 98 with the Plus! pack). From Windows Explorer, it lets you see zip files as if they were folders. What is a folder? A "place" where files are stored. What is a zip file? A "place" where files are stored. Makes sense! Neet. But again, something like this won't work: System.IO.Directory.GetFiles( @"d:\data.zip", "*.bmp" );
For classes under System.IO, "d:\data.zip" is an unknown binary file, it's not a folder. You need third party libraries to read from that zip file, using a proprietary API which makes sense only for zip files. And most often, those libraries will support files accessible with a path or streams. Beyond that, you'll need to code it yourself.
The Xceed FileSystem removes those barriers between devices, virtual file systems, remote data, etc. A file is a file. A folder is a folder. Who cares how it works underneath. Let's says I want to get image files located in a particular folder of a zip file located on an FTP server, and copy them into a project folder located in a VSS database located on a server accessible through a UNC path. AbstractFile ftpFile = new FtpFile( "ftp.xceedsoft.com", @"\pub\resources.zip" );
AbstractFolder zipFolder = new ZippedFolder( ftpFile, @"\Images" );
AbstractFile vssIniFile = new DiskFile( @"\\Repository\WebDepot\srcsafe.ini" );
AbstractFolder vssFolder = new VssFolder( vssIniFile, @"$\Intro\Logos" );
foreach( AbstractFile imageFile in zipFolder.GetFiles( false, "*.bmp" ) )
{
imageFile.CopyTo( vssFolder, true );
}
An FtpFile is a file. A ZippedFolder is a folder. A DiskFile is a file. A VssFolder is a folder. Once you have the instances, working with them hides their implementation. You can copy files. You can browse folder contents.
Another example. We can read from files. We can write to files. Something like this makes perfect sense: AbstractFile logFile = new DiskFile( @"d:\myapp.log" );
if( !logFile.Exists )
logFile.Create();
string line = string.Empty;
using( StreamWriter writer = new StreamWriter( logFile.OpenWrite( false ) ) )
{
while( ( line = Console.ReadLine() ).Length > 0 )
{
writer.WriteLine( line );
}
}
using( StreamReader reader = new StreamReader( logFile.OpenRead() ) )
{
while( ( line = reader.ReadLine() ) != null )
{
Console.WriteLine( line );
}
}
A file is a file, right? Then changing the first line with this should not surprise you: AbstractFile zipFile = new DiskFile( @"d:\myappdata.zip" ); AbstractFile logFile = new ZippedFile( zipFile, @"\logs\today.log" );
It still works. A zip file named "myappdata.zip" is created in the "D:\" folder, and contains a file named "logs\today.log" which contains what you typed.
Xceed Zip for .NET comes with the following classes:

DiskFile and DiskFolder are your regular disk file and folder accessible with a file path (drive letter or UNC path). MemoryFile and MemoryFolder virtually let you create ram drives for your process. IsolatedFile and IsolatedFolder give you access to the user isolated storage (System.IO.IsolatedStorage). Finally, StreamFile is a special implementation of an AbstractFile that lets you expose any stream as if it was a file.
You wont find the FtpFile and FtpFolder classes (yet). Though they are "feature complete", they will be available in Xceed FTP for .NET 2.1 (hopefully this year, or early next year). As for VssFile and VssFolder they are incomplete academic implementations someone here did for a project. Because that's the fun part: nothing's sealed. AbstractFile and AbstractFolder are waiting for you to derive from them. As a matter of fact, MemoryFile and MemoryFolder were first exposed as a sample on how to derive from AbstractFile and AbstractFolder. But they are so usefull that they are now first class citizens. Do you have other ideas of file and folder implementations that should be available in the Xceed FileSystem?
|
|
 Thursday, September 09, 2004
I have to say that is one of the worst messages I've seen:

|
|
 Friday, September 03, 2004
One of the software pieces I’ve made in my career which I’m the most proud of is the Xceed FileSystem. Ever since I’ve started programming in object oriented languages, I was convinced that files and folders were a base representation and starting implementation, no matter where they resided, how they were encoded, or how they could be accessed.
Back in my COM days, I’ve tried to accommodate my object-oriented vision of files and folders to the feature-oriented paradigm of COM. I remember a design meeting for Xceed FTP ActiveX where I was pushing for IFile and IFolder interfaces, with coclasses like “FtpFile”, “FtpFolder”, “DiskFile” or “DiskFolder”. But COM wasn’t ready for this… and moreover, neither were our customers.
I will always remember my first encounter with System.IO.FileInfo and System.IO.DirectoryInfo. It was Xceed’s early contact with that new .NET Framework platform Microsoft was planning to launch a year later; a fully object-oriented API! At last! Oh what a joy it was to see them displayed in front of me, waiting for me to derive from them and implement numerous new worlds. Sure, I was a little disappointed to see the base classes implementing disk I/O, as opposed to having derived classes do the job, but it was an early beta, and I convinced myself I could influence Microsoft to correct this minor mistake. Right?
Well… Those were my first impressions. I was dreaming of an object-oriented API, and the .NET Framework would slowly drift away from this idealist goal. I was dreaming of a Microsoft able to change stuff in 15 minutes just because they were suddenly more accessible.
A few weeks later, a colleague and I were at Redmond to get a peek at the next beta version of the .NET Framework, ready to convince whom it may concern that System.IO.FileSystemEntry et al were not quite perfect… and kaboom! It hit us: they had sealed FileInfo and DirectoryInfo in this most recent build. How could they not see the obvious? How could they not see “my” object-oriented file system?
That week, we did meet the System.IO guys, and they listened. They agreed the idea was cool. But the conclusion was just more evident: the .NET Framework’s goal was not to provide purely object-oriented framework. It was to provide a language-neutral, easy to understand framework. Being well-suited for object-oriented languages was not enough. And Kit George gave us the shoulder tap we needed. He told us our object-oriented file system sounded pretty cool. Why wait for the base classes coming from MS?
And that week, in building 20, Pascal Bourque and I designed the major part of Xceed Zip for .NET, with its object-oriented file system. It was a very special week. The kind you miss…
|
|
 Thursday, September 02, 2004
This is my first post as a new blogger. Now that most software developers are exposing themselves, it was inevitable that I do the same one day. And this day has come.
I am Martin Plante, and I've been working at Xceed Software for 7 years now. Though I was not part of the beginning of the company, founded by Daniel Côté and Odi Kosmatos, two Université de Montréal buddies, I'm responsible for one thing; the name. We were supposed to start the adventure the three of us, but I backed out at the last minute, not before convincing them "Xceed" was a cool name. I joined three years later.
I'm proud of that name. I'm damn proud of what it represents. I believe we succeeded in establishing a name that means well designed and supported libraries. But they would probably not choose this name again. It's too far in the alphabet, and our customers regularly misspell it.
Officially, I’m a Lead Developer here. Obviously, for a relatively small ISV like us, I end-up doing much more than this. I’m an architect, developer, tester, writer, and support agent. We do have people dedicated to documentation, testing and support, but I need to get involved from time to time, especially with technical support, since I know my products more than anybody else.
Those products are mostly the non-visual libraries you can find at Xceed:
Don’t be surprised if this blog is not as much active as some other developer blogs out there. My goal is not to talk about my social life, or computer stuff not related to my job, or comment the latest news the minute it comes out. I want that blog to be an open window on what I’m working on at Xceed. Sure, I’ll sometimes digress from that pious wish (it’s too easy when blogging), but I want you to get direct dev-to-dev information. You probably won’t see more than a post a week, my initial goal being to post every two weeks at the minimum.
See ya later, with my real first port.
Martin.
|
|
|
|
|
|
|
|
Copyright © 2008 Xceed Software Inc.
|
|
|
|
Calendar
| | Sun | Mon | Tue | Wed | Thu | Fri | Sat | | 27 | 28 | 29 | 30 | 31 | 1 | 2 | | 3 | 4 | 5 | 6 | 7 | 8 | 9 | | 10 | 11 | 12 | 13 | 14 | 15 | 16 | | 17 | 18 | 19 | 20 | 21 | 22 | 23 | | 24 | 25 | 26 | 27 | 28 | 29 | 30 | | 31 | 1 | 2 | 3 | 4 | 5 | 6 |
| June, 2006 (1) |
| April, 2006 (2) |
| March, 2006 (2) |
| February, 2006 (2) |
| January, 2006 (4) |
| November, 2005 (3) |
| October, 2005 (3) |
| September, 2005 (6) |
| August, 2005 (2) |
| July, 2005 (4) |
| June, 2005 (4) |
| May, 2005 (3) |
| April, 2005 (10) |
| March, 2005 (4) |
| February, 2005 (4) |
| January, 2005 (3) |
| December, 2004 (4) |
| November, 2004 (5) |
| October, 2004 (4) |
| September, 2004 (7) |
|