|
|
|
|
Open window on development at Xceed
|
|
|
 Friday, April 08, 2005
Don pointed us to the Computerworld Development Survey, where we learn that developers use .NET and C# more than other frameworks and languages.
In the survey, you can read this:
| What is your current position/job function? |
| IT manager |
38% |
| Developer |
36% |
| Non-developer IT staff |
8% |
| Non-IT manager |
5% |
| Other |
13% |
There are more IT managers than developers? What gives? Another table I had problems with is this one:
| What is your current employment status? |
| Employed in organization with more than 100 employees |
86% |
| Employed in organization with 100 or fewer employees |
7% |
| Self-employed |
6% |
| Not employed* |
1% |
Hmmm, that looks strange. I felt there were more smaller companies around. Then I read the end of the article:
Methodology This study was conducted among subscribers to Computerworld.
Ok, now I understand. Surveys are biased by definition. You need the definition to understand them! My understanding is:
-
Computerworld is read by IT managers, not developers.
-
Big companies subscribe to Computerworld for their IT department. Small companies put their money elsewhere first.
|
|
 Thursday, April 07, 2005
Did you notice that when maps.google.com cannot find your location, it always displays the same map? It's somewhere in Kansas, close to the Oklahoma border:

It made me think of The Wizard of Oz, so I searched where Dorothy Gale was from. She's from Liberal, Kansas, which is way to the West of what's displayed.
The first thing you notice is the Coffeyville Country Club. So I've googled for "Coffeyville Country Club Google", and realized this was simply the default location when you open maps.google.com, and zoom in... Google Maps' center of the United-States... Dah! So much trouble for a so simple solution.
|
|
 Tuesday, April 05, 2005
Just learned through Neowin.net that maps.google.com now supports switching between the drawn view of the map and a satellite view. Switching views is as simple as clicking on either "Map" or "Satellite". And guess what? Zooming and moving works as well in "Satellite" view. They were quite fast integrating their new Keyhole acquisition!
If you compare the "Link to this page" of the same area for both views, you can see that the only difference is the "t=k" extra parameter for the satellite view ("k" as in Keyhole).
Bravo Google, you did it again!
|
|
 Friday, April 01, 2005
This one is my favorite news of this "fishy" day!
As a long time Win32/COM developer with several books containing many sample programmers [sic], I am just appalled that Microsoft would consider dropping support for classic IDL. This would cause trouble for developers who are still using the samples that I created 10+ years ago! -- Geoffrey Rickder
That was funny!
|
|
 Monday, March 28, 2005
 Wednesday, March 23, 2005
I've just finished a meeting about an issue we're having with our .NET components. Though I fully agree with our decision, it's very frustrating, and I thought I'd share this with you.
A few years ago, before .NET was officially released, we decided to embrace the idea of digitally signing our ActiveX DLLs. The idea was to garantee our clients those DLLs were really from us. It was an added value that had no (visible) impact on the products themselves.
When .NET came in, though one could argue the strong name was sufficient, we decided to stick with digitally signing and do both. Actually, the strong name isn't offering CRL verification, nor detailed information about the "signer". It's not actual identity, it's only integrity.
Somewhere in time (we're still not sure when... maybe since .NET 1.0 SP3/.NET 1.1 SP1?), clients started complaining about our assemblies causing a network access. For most of them, the only impact was their sudden suspicion that our products were spywares, while in reality it was Windows' WinVerifyTrust API accessing crl.verisign.com or crl.thawte.com to check if the certificate used to sign the DLL was revoked.
But others got bigger problems. Some people behind a very strick firewall, ignoring outgoing connections instead of rejecting them, had a timeout while loading our assemblies. That timeout (at least 15 seconds) is hardcoded in WinVerifyTrust! We can't do anything about it.
And finally, those using a dial-up connection were seeing their Dial-Up dialog box appearing when our assemblies were loaded. Nothing to put confidence in our products. How come using Xceed Grid for .NET causes a network access?
There are solutions for those clients, but ugly solutions that either involve disabling CRL checking in the first place (yeah, right, let's sign our DLLs, then ask our clients to turn off its use!), or regularly install our certificate in the list of trusted certificates, which is only good for a certain period, and must be repeated again and again.
We've just decided to stop signing our .NET assemblies. Most of our competitors don't anyway. And those that do are having the same problem. But it's so damn frustrating to see that security is again loosing a battle. Sure, the impact is quite minor, but I'm left with a mixed feeling of failure and blames against the current implementation of WinVerifyTrust.
|
|
 Friday, March 11, 2005
Found this through ComputerZen. The whole Richard Grimes incident is getting out of hands. Come on, people! Managed applications are the future. The .NET framework is awesome! I gave COM/ATL/ActiveX courses in the past. I could see those VB6 developers in front of me staring at the immensity of exceptions and rules and gotchas behind the COM scene. For the user, COM is great. But for the creator, it's an infinite loop of pitfalls.
"1199 signatories including 202 Microsoft MVPs since March 8th, 2005."
202? I can't beleive it.
|
|
 Tuesday, March 08, 2005
Warning: Do not try this at home!
A few days ago, Pierre-Luc at support asked me if Xceed Zip for .NET was thread safe. I knew from his look that he was expecting a "yes" or a "no". At least, that's what the client who asked him the same question expected.
My first answer was more in nuances: Though the library was made to be safely accessible from multiple threads at the same time, by the nature of the sequential format of the zip file, it is not possible to work on the same zip file from multiple threads.
He nodded with approbation, confirming me his client wasn't trying such crazy action, but simply dealing with a multi-threaded application where each thread may be zipping in its own private file. I gave him my benediction: In that case, yes, Xceed Zip for .NET is thread safe.
Pierre-Luc wasn't two feet away when I was illuminated by an idea. It wouldn't be that crazy to try zipping into the same zip file from multiple threads. How neat would it be to benefit from multi processor or hyperthreading machines for zipping a single file? Guess what... you can! You shouldn't... but you can! Don't ask us to support this scenario... but you can!
Here's the deal. Any ZipArchive you modify gets updated when the last modify operation occurs. If you know you're about to make more than one modification to a single zip file, you should first call BeginUpdate, do all modifications, and finally call EndUpdate. The zip file will only get rebuilt on that final call. The files you copy into the zip file before EndUpdate will be compressed and stored in temp files within the ZipArchive's TempFolder.
That means any copy operation you perform within a BeginUpdate/EndUpdate block are atomic, and only involve compressing the sources into independant temp files. You see where I'm heading? How about spawning threads within that block, each thread copying its own source, and waiting for all threads to finish before calling EndUpdate?
I had to try it. I started with a class implementing IAsyncResult, which would be managing the copy operation on a separate thread:
internal class AsyncCopyResult : IAsyncResult
{
public AsyncCopyResult(
AbstractFolder source,
AbstractFolder dest,
AsyncCallback callback,
object state )
{
m_source = source;
m_dest = dest;
m_callback = callback;
m_state = state;
m_thread = new Thread( new ThreadStart( this.ThreadProc ) );
m_completed = new ManualResetEvent( false );
}
public void Begin()
{
m_completed.Reset();
m_thread.Start();
}
public void End()
{
// We must not join thread since we may get called by callback, itself
// within thread.
m_completed.WaitOne();
if( m_result != null )
throw m_result;
}
#region IAsyncResult IMPLEMENTATION
public object AsyncState
{
get { return m_state; }
}
public bool CompletedSynchronously
{
get { return false; }
}
public WaitHandle AsyncWaitHandle
{
get { return m_completed; }
}
public bool IsCompleted
{
get { return m_completed.WaitOne( 1, false ); }
}
#endregion
private void ThreadProc()
{
try
{
m_result = null;
if( m_source == null )
throw new ArgumentNullException( "source" );
if( m_dest == null )
throw new ArgumentNullException( "dest" );
if( m_source.IsRoot )
{
m_source.CopyFilesTo( m_dest, true, true );
}
else
{
m_source.CopyTo( m_dest, true );
}
}
catch( Exception except )
{
m_result = except;
}
m_completed.Set();
if( m_callback != null )
{
try
{
// Important note: This callback may be calling End.
// Thus End's implementation should not wait for thread,
// but for handle.
m_callback( this );
}
catch
{
System.Diagnostics.Debug.WriteLine( "Unhandled exception within callback." );
}
}
}
private Thread m_thread = null;
private ManualResetEvent m_completed = null;
private AbstractFolder m_source = null;
private AbstractFolder m_dest = null;
private AsyncCallback m_callback = null;
private object m_state = null;
private Exception m_result = null;
}
The ThreadProc method is simply copying the source folder into the destination folder. The rest is plumbing for implementing IAsyncResult. In my main class, I created a static method that uses the AsyncCopyResult class like this:
private static void CopyMultipleFolders(
AbstractFolder[] sources,
AbstractFolder dest )
{
// I'm using AutoBatchUpdate with the using directive, an easy way
// to call BeginUpdate and EndUpdate only if the folder implements
// IBatchUpdateable.
using( AutoBatchUpdate auto = new AutoBatchUpdate( dest ) )
{
AsyncCopyResult[] results = new AsyncCopyResult[ sources.Length ];
// First create the threads and state objects.
for( int i=0; i<sources.Length; i++ )
{
results[ i ] = new AsyncCopyResult( sources[ i ], dest, null, null );
}
// Then launch each thread
foreach( AsyncCopyResult result in results )
{
result.Begin();
}
// We can't call WaitAll on an STA thread, but it doesn't matter.
// We wait for each one separately.
foreach( AsyncCopyResult result in results )
{
result.AsyncWaitHandle.WaitOne();
try
{
result.End();
}
catch( Exception except )
{
Console.WriteLine( except.Message );
}
}
}
}
Once each thread is done copying its own source folder into the destination folder, the AutoBatchUpdate class calls EndUpdate on the destination folder (if it implements IBatchUpdateable). In the case of a zip file destination, the final zip file is built by reassembling already compressed temp files. Here's an example of how to call CopyMultipleFolders:
AbstractFile target = new DiskFile( @"d:\temp\multi.zip" );
if( target.Exists )
target.Delete();
ZipArchive zip = new ZipArchive( target );
AbstractFolder firstSource = new DiskFolder( @"d:\Downloads" );
AbstractFolder secondSource = new DiskFolder( @"d:\Music" );
CopyMultipleFolders( new AbstractFolder[] { firstSource, secondSource }, zip );
The best thing is that this method works for any kind of AbstractFolder, source or destination. If you're confident the size of the zip file isn't too large, you can improve performance by setting the ZipArchive's TempFolder to a new MemoryFolder.
But remember: Don't try this! I didn't tell you it was possible.
|
|
|
|
|
|
|
|
Copyright © 2010 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 | | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 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) |
|