Monday, March 20, 2006

.Net Framework Applications Writing to the Windows Root Directory (Part II)

As I expected, Microsoft had the answer for this one right away. In fact it was so simple I can't believe it didn't occur to me. I suppose it's an aspect of .Net that you take for granted these days: The temp directory in question is created by the JIT compiler while it's compiling the native image from the MSIL executable. It can't assume that the codebase directory is available for that since you could be running off of a CD or a read only network share. Although, I think %TEMP% would have been a better choice of location. In any case, they recommended that we try using NGen.exe to pre-compile the Winform apps we're deploying to Citrix.

That worked at first. Until I started playing around. I tried the debug switch, and I tried precompiling release and debug versions side-by-side. At some point I seem to have broken something on my machine. I am still seeing NGen store files under Assembly/NativeImages, and it appears from Fusion Viewer that they're loading from there, but FileMon is showing the temporary folder being used again. I've tried NGen /delete, and messed around with renaming/relocating the files, but no luck. Looks like we're going to have to find a solution that involves moving that temporary compilation folder.

Here's the Fusion Log Output when the native image is found. If you don't NGen the Exe, Fusion Log shows nothing.

*** Assembly Binder Log Entry (3/20/2006 @ 3:07:00 PM) ***

The operation was successful.
Bind result: hr = 0x0. The operation completed successfully.

Assembly manager loaded from: C:\WINNT\Microsoft.NET\Framework\v1.1.4322\fusion.dll
Running under executable C:\Data\Experiments\ConsoleTest\bin\Release\ConsoleTest.exe
--- A detailed error log follows.

=== Pre-bind state information ===
LOG: DisplayName = ConsoleTest, Version=1.0.2270.26987, Culture=neutral, PublicKeyToken=null
LOG: Appbase = C:\Data\Experiments\ConsoleTest\bin\ReleaseLOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = NULL
Calling assembly : (Unknown).

LOG: Not processing DEVPATH because this is a pre-jit assembly bind.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Post-policy reference: ConsoleTest, Version=1.0.2270.26987, Culture=neutral, PublicKeyToken=null
LOG: Found assembly by looking in the cache.

File Under: Technology,

Thursday, March 16, 2006

.Net Framework Applications Writing to the Windows Root Directory

After deploying a Winform app to Citrix yesterday, we could not get it to run. It would throw a hard exception and die before it ever displayed anything. After a little poking around, we discovered that the fault was an "Access Denied" message while trying to create a randomly named folder in the Windows root directory.

I used .Net Reflector to look into the application code a bit, but quickly became irritated by the complexity of the startup routine and decided to write a simple repro. After making my repro as simple a .Net app as you can run, it seems that every .Net application writes some sort of randomly named test folder to the windows root directory at startup.

Here's the repro code:

class Class1
static void Main(string[] args)

And here's what FileMon says it's doing:

This wouldn't be too big a deal on a regular desktop, but it is really not acceptable to have to give every Citrix user the rights to delete arbitrary files from the Windows root directory!

Anybody know of a good place to read up on the behavior of the framework as it loads up a process? I think we'll be opening a PSS case on this one.

File Under: Technology,

Going-Away Present from Minnesota

Breaking Trail at Hyland
Ever since the snowless Afton race I've been driving around with my skis and a bag of ski clothes in my car. In all that time we've had barely a flake of snow. So last week I gave up on winter an hauled all the stuff upstairs. Sure enough, this week we've had two big storms dropping 6 inches or more on the Twin Cities. Fantastic!

I made it over to Hyland for a big loop around the park on Tuesday. The conditions were as nice as I've skied there. Amazingly, I was the first person to ski in from across the street.

I think I'll head over again after work today.

Hyland Trails

File Under: Adventure,

Monday, March 13, 2006

March Blizzard

We got hit with a good 6-8 inches of snow last night. A perfect going-away present from Minnesota. Time to dig out the ski wax!

In case you've ever wondered why reports of heavy snowfall are always followed by the number of people without power, I just happened to have my camera with me this morning to catch some snowy branches in action:

Snowy Branches Hit the Power Line

Wednesday, March 08, 2006

New Zealand Birds

I've never been much of a birder in Minnesota. Part of it is the old thing that you never do the "tourist" stuff in your own town. Then there's the fact that there are about 300 species of bird to be found in Minnesota, plus another hundred or so that pass through occasionally. Skimming through the Minnesota list, I've probably seen over 100 of them, but I've never bothered to keep track of which particular duck or warbler species I have or haven't seen.

Minnesota Ornithologists Union - Minnesota Bird Checklist

On the other hand, once I hit New Zealand, pretty much everything I see will be new (aside from the ubiquitous English Sparrow and Ring-Necked Pheasant). It should be good fun to see how many birds I can check off the list. Even better, how many can I catch in halfway decent pictures.

2 down 200 to go!

New Zealand Fantail
New Zealand Fantail (Rhipidura fuliginosa)

Routeburn Flats Robin
Robin (Petroica australis)

File Under: New Zealand,

Friday, March 03, 2006

GAC 2.0

A colleague stopped by today with a simple question that derailed my whole afternoon. We're just getting started with deploying .Net Framework 2.0 to servers, and he was wondering: "Do we need a new version of the Oracle Data Provider for Oracle?".

I hadn't thought about that yet. My first questions were "What happened to the old one, and what's going on with the GAC in 2.0?"

The GAC was easy enough to figure out. The %windir%\assembly shell view now shows both 1.x assemblies and 2.x assemblies. Behind the scenes in the file system, there's a new GAC_MSIL folder and a GAC_32 (or GAC_64 if you're on a 64-bit machine).

This series of posts describes it all in more detail, including the behavior of the loaders:
Wonders of the Whidby GAC

Short version: 2.x assemblies are invisible to Framework 1.x, but the other permutations should work.

With that mystery solved, the next question was "What have they done with ADO.Net?".

I created a simple VS 2005 project with the Microsoft System.Data.OracleClient 1.1 version. Tested that, no problem. Next I tried to add a reference to the System.Data.OracleClient 2.0 version. Wouldn't let me. The namespaces are the same, so no surprise. I deleted the 1.1 reference, added the 2.0 reference, recompiled, tested. It worked just fine with zero changes. So for a simple test case, they seem to be completely backwards compatible. For the fun of it, I pulled the assemblies out of the GAC, ran ILDasm on them, and compared the dumps. All the core classes the same. It looks like a couple things have been dropped, and the 2.0 version has some new connection pooling stuff. Which pretty much matches what Microsoft has to say here:

What's New in ADO.Net

As for the original question regarding the Oracle Data Provider for Oracle, Oracle says that an ADO.Net 2.0 compliant assembly will ship with ODP.Net 10.2 in early 2006:

Oracle ODP.Net FAQ

In the meantime, I don't see anything that would prevent the 1.x provider from working in 2.x applications.

File Under: Technology,