2009/03/15

Permanently Get Rid of "Unblock" Button on Downloaded Files

I'm really surprised at myself for waiting so long before I removed this friction point from my daily environment.  Like almost all developers, we look for the path of least resistance when we're trying to get work done.  And I'm going to be generous and say that we're all smart enough to know that we take some level of risk with downloading and executing files from the Internet.  So why should we be bothered by Windows telling us that a file we just downloaded (especially intentionally just downloaded) may be unsafe and tries to protect us?  I don't care, I want to execute it without all the extra safety precautions.  I don't want to have to go into every file I download and click on the "Unblock" button so it will function as expected.  I've read some posts that this is unique to Internet Explorer only, but that's not so.  My browser of choice is Firefox (haven't had the desire to switch to Chrome yet) and it does the same thing.  This is especially true when downloading CHM help files as nothing loads because the content is blocked.  Even more so when you unzip a file that is still "blocked" and all the expanded files are now also "blocked."  You end up with a bunch of file properties that look similar to this with that not so attractive "Unblock" button at the bottom:

image

So how can you permanently get rid of it? Well Windows is applying an NTFS stream to the file that keeps what zone the file is originally from.  The easiest way is to edit your Group Policy settings (normally handled by your domain settings if you're in a corporate network, but also exists on a personal machine).  Since this isn't normally something configured for home use, I'm not entirely sure which versions of Vista it can be found in.  The disclaimer on the setting says at least XP Professional SP2.  Anyway, you will need to run %windir%\System32\gpedit.msc as an administrator.  Next, navigate to Local Computer Policy -> User Configuration -> Administrative Templates -> Windows Components -> Attachment Manager.  The setting "Do not preserve zone information in file attachments" is most likely at a status of "Not configured".  You will want to go into the properties of it and change it to Enabled.  No restarts necessary to apply it.

image

From that point on, any file you download will no longer have to be "Unblocked." 

2009/03/12

The difference in random number generation in .NET

The next project I plan on working on is going to rely heavily on a Monte Carlo method of populating the initial state. Knowing this, I started digging into the different ways of generating random numbers in .NET. Everybody immediately goes with System.Random when they're starting out since it's readily visible in a new class file. This is all well and good, but you run into the issue that what it gives you is a pseudo-random number. It's actually pretty interesting to pop open Reflector and look at what it's doing under the hood. Granted it uses the system's ticks to seed the random number if you don't provide one yourself, but it does mean that processes (or even threads) creating an instance in the same tick will have the same random numbers. Well that can be a problem...

So how do we get a more *random* random number? That's where System.Security.Cryptography.RNGCryptoServiceProvider comes into the picture. Digging into this class it's making an external call, so not quite as easy to figure out how it's getting it's randomness. It really doesn't matter too much because it does come up with a better randomness. The drawbacks of using it though are that the way to work with it is quite a bit different than the System.Random class, and it is quite a bit slower. With the RNGCryptoServiceProvider you have to work with a byte array and do the conversions to whatever random type you want to work with. So if you build out your classes to use System.Random and later want to switch to RNGCryptoServiceProvider you have your work cut out for you. Or what about using RNGCryptoServiceProvider in production for "better" randomness, but use System.Random when you're unit/integration testing because you can control it? There isn't a common interface to use in that case, but I've been tinkering around getting such an interface set most of the day. Once I have it fleshed out more I'll post it up here.

Now back to the slowness of RNGCryptoServiceProvider vs. Random. Finding a few useful answers on Stack Overflow there was mention of it being slower, but never really gave any indication of how much worse it was. I've seen too many statements like this and the difference really only came down to maybe a few hundred milliseconds (so not a noticeable problem in the applications I've worked on). So I decided to toss together a test and find out just how much slower it is. Here's what I did to test it:

   1:  namespace ConsoleApplication1 
   2:  {  
   3:      using System; 
   4:      using System.Diagnostics; 
   5:      using System.Security.Cryptography; 
   6:    
   7:      class Program 
   8:      { 
   9:          static void Main(string[] args) 
  10:          { 
  11:              Stopwatch stopwatch = new Stopwatch(); 
  12:              RNGCryptoServiceProvider gen = new RNGCryptoServiceProvider(); 
  13:              Random generator = new Random(); 
  14:              //Since I'm only working with int for both randomizers... 
  15:              byte[] randomValues = new byte[ sizeof(Int32) ];  
  16:    
  17:              //step up the iterations by from 1 to 100,000,000; advancing by power of 10 
  18:              for (int iterations = 1; iterations <= Math.Pow(10,8); iterations *= 10)
  19:              { 
  20:                  Console.WriteLine(String.Format("Iterations: {0}", iterations));
  21:    
  22:                  //Start the RNGCryptoServiceProvider timing 
  23:                  stopwatch.Reset(); 
  24:                  stopwatch.Start(); 
  25:                  for (int i = 0; i < iterations; i++) 
  26:                  { 
  27:                      gen.GetBytes(randomValues); 
  28:                      BitConverter.ToInt32(randomValues, 0); 
  29:                  } 
  30:                  stopwatch.Stop(); 
  31:                  TimeSpan rngRandom = stopwatch.Elapsed; 
  32:                  Console.WriteLine( 
  33:                      String.Format("\tRNGCryptoServiceProvider:\t{0}", stopwatch.Elapsed)); 
  34:    
  35:                  //Start the System.Random timing 
  36:                  stopwatch.Reset(); 
  37:                  stopwatch.Start(); 
  38:                  for (int i = 0; i < iterations; i++) 
  39:                  { 
  40:                      generator.Next(); 
  41:                  } 
  42:                  stopwatch.Stop(); 
  43:                  TimeSpan sysRandom = stopwatch.Elapsed;
  44:                  Double speedFactor = Convert.ToDouble(rngRandom.Ticks) / Convert.ToDouble(sysRandom.Ticks); 
  45:                  Console.WriteLine( 
  46:                      String.Format("\tSystem.Random:           \t{0}\t~{1:0.00}x faster", 
  47:                                      stopwatch.Elapsed,
  48:                                      speedFactor));  
  49:                  Console.WriteLine(); 
  50:              } 
  51:              Console.ReadLine(); 
  52:          }  
  53:      }  
  54:  }

And here's the results:

image



The times varied a bit on my Core 2 Duo 2.50 GHz, 32-bit Vista laptop, but this isn't too far from the norm. It wasn't until 100,000 iterations that it took more that 1/10 of a second to finish, but at that point System.Random was ~279.2 times faster! The big thing is that even though the number of iterations are was growing by a factor of 10, RNGCryptoServiceProvider seemed to increase the time by more than a factor of 10.



So I guess the bottom line in the System.Random vs. RNGCryptoServiceProvider argument over slowness is in small numbers it doesn't greatly matter. Now if you're going to be generating more than 100,000 numbers in a very tight loop, it might be worth sacrificing "true" randomness with speed.