Scott Hanselman

August Madness - A tale of Classic ASP, Two CLRs, IIS, and COM Interop

August 22, '06 Comments [16] Posted in ASP.NET
Sponsored By

UPDATE: Here is how we solved this problem.

So, this is bizarre. The idea is this:

We want to share FormsAuth cookies between two ASP.NET sites on the same box. No biggie, right? However, one of the ASP.NET sites also has some Classic ASP pages in it. Still, no worries, right?

  • The Classic ASP pages happen to use .NET objects that expose themselves to Classic ASP via COM Interop…
  • If ASP.NET pages are hit ONCE in both sites (pools/appdomains) to 'bootstrap' the CLR, all is well and FormsAuthTickets will be sharable and jointly decryptable.
    • .NET 1.1 and .NET 2.0 are installed on the systems
    • Both ASP.NET applications/vdirs are configured to use .NET 1.1 in IIS

PROBLEM: If the site that creates the FormsAuthenticationTickets instead has the CLR 'bootstrapped' into the process/pool/domain by hitting a Classic ASP page that calls the COM-interop DLL, it causes later FormsAuthentication crypto to produce tickets that can't be decrypted by the other application.

QUESTION: What's going on? Both sites have web.config files with synchronized machinekeys (the machinekey is used by FormsAuth).

PARTIAL ANSWER: Turns out that if the Classic ASP page (that uses the .NET object that is used via COM) is hit first then .NET 2.0 gets loaded up inside that IIS Managed Application even if the ASP.NET application is set to use .NET 1.1!

Am I missing something? Does this mean that I can't have two classic ASP apps that use .NET objects via Interop, one using 1.1 and one using 2.0 on the same computer? Seems like it.

The issue is that ASP.NET doesn't start up the CLR because it's not hit first. The Classic ASP page is hit first, and apparently can't control the CLR version it gets! By the time someone hits an ASP.NET page, the CLR is already loaded up with a different version.

HERE'S THE KICKER: I don't yet understand why (on Win2k3, in our tests) the problem only happens when the anonymous identity for the web site is a domain account.  If the anonymous identity was left as the default IUSR_xxxx, the CLR loaded is still 1.1 when a CCW is created. (!)

OUR WORKAROUND: We just let .NET 2.0 load up anyway and run our 1.1 application. We have to synchronize the machinekeys in BOTH CLR versions' machine.config files though.

Kudos to Peter Wong for figuring this stuff out. Now the question is - is there a good workaround or better explanation? My guess is we'll hear "functions as designed" but it seems to me that even though you can't indicate in the COM Registration stuff in the Registry what CLR Version to use (it's listed in the Registry, but the values are ignored) there should be some way.

Repro attached. Unzip this file into a c:\inetpub\wwwroot\wong test and make an IIS Application (isolated, or in its own AppPool in IIS). Get Process Explorer from SysInternals and hit x.asp after a fresh reset.

File Attachment: NET11_NET20_ASP.zip (894 bytes)

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Google Sitemaps

August 22, '06 Comments [11] Posted in ASP.NET | DasBlog
Sponsored By

ScottongoogleI just checked in support for generation of Google Sitemaps directly from DasBlog. Omar anticipates a release this week. We also have a continuous integration build going internally thanks to Paul van Brenk so we may be able to have always-fresh" releases soon (remember to back up your stuff and manually merge the httpHandlers section of your web.config). We also will have an AJAX-based "autosave draft" feature as well thanks to Steven Rockarts and Justice Gray.

NOTE: The daily builds from Paul are DAILY BUILDS. They are not the official release. We'll release the final one SourceForge. However, I'm ALWAYS running the daily build on this blog, so it's pretty baked. Upgrading is just copying a few new files and merging your web.config.
UPDATE: Daily Builds of DasBlog are at
http://dasblog.info/dbftp/

If you haven't yet, go log into Google Webmaster Tools and check out what Google knows about your site. It includes a robots.txt validator and lets you know what keywords folks are using to get to your site.

Google sitemaps are very simple and a pretty good idea, I think. It lets me, as a blog publisher, provide a great deal of context and "freshness" data to Google that I have stored (trapped) inside the blog.

Sure, arguably they could get a lot of that information by gleaning it from If-Modified-Since headers, but this is such a simple format, why NOT do it?

Here's an example snippet. The lastmod element can include time detail as well, but I think date is enough for blog purposes. The priority is pretty much relative. In this case, the home page is more important than a post and a comments page is less important than a post page.

<?xml version="1.0"?>
<urlset xmlns:xsd="
http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.google.com/schemas/sitemap/0.84">
  <url>
    <loc>http://www.hanselman.com/blog/default.aspx</loc>
    <changefreq>daily</changefreq>
    <priority>1.0</priority>
    <lastmod>2006-08-22</lastmod>
  </url>
  <url>
    <loc>http://www.hanselman.com/blog/archives.aspx</loc>
    <changefreq>daily</changefreq>
    <priority>1.0</priority>
    <lastmod>2006-08-22</lastmod>
  </url>
  <url>
    <loc>http://www.hanselman.com/blog/CommentView.aspx?...</loc>
    <changefreq>daily</changefreq>
    <priority>0.7</priority>
    <lastmod>2006-08-22</lastmod>
  </url>
  <url>
    <loc>http://www.hanselman.com/blog/FinePrintChangesTheWayIPrint.aspx</loc>
    <changefreq>daily</changefreq>
    <priority>0.9</priority>
    <lastmod>2006-08-22</lastmod>
  </url>
....SNIP....

Aside, I had no idea I was the 3rd (or so) Scott if you search just for "Scott" on Google One day I'll crush Scott Fly Rods, but until that day, it's the Bronze for me. ;)

I also encourage folks to "sesha iWeb" with Google ngaisiZulu. ;)

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

FinePrint changes the way I print.

August 22, '06 Comments [9] Posted in Reviews | Tools
Sponsored By

Fineprint1I blogged about FinePrint last year. I literally can't overstate how much this application has changed the way I use my computer and my printer.

Here's what I said last year:

It's a "fake" (virtual) printer driver that basically sits between you and your real printer. You print everything to FinePrint and it gives you an opportunity to mess with the pending print job.

Most interestingly, you can change 1:1 print jobs to 2, 4 or 8 up. This ROCKS. I can take 4 page long meeting agendas and print them on one page to any printer. (Some expensive copier/printer drivers support this in the driver, FinePrint works with all printers.)

How many times have you seen hundreds of sheets of paper (color ink, even) sitting printed in your company's copy room/office that one sided. Seriously, makes my heart ache. With this thing you can print double sided easily and do booklets as well. [Me in the past]

FinePrint isn't a print queue or fake printer. It's Tivo for your printer. It lets you remove sheets, remove graphics, print 1,2,4 up or booklets. You can print to it, then save the output as a JPEG or TIFF. You can print to the clipboard.

One of my favorite features is "Collect Jobs." You can print from multiple applications and consolidate all the jobs into one Fineprint session, remove pages, make changes, then print the whole thing as one print job.

The margin adjustment is nice also...you can change the margins after the source app has printed the job. You can also create virtual printer "instances," like one that does double sided, one that does letterhead or watermarks.

It also creates an AutoSave folder, if you like, in your My Documents folder with the last, say, 10 documents printed, so you can open the jobs up again and reprint them. You can also use this as an offline printer. I printed a number of things on the plane today and saved them as Fineprint files. (Yes, I know that Windows supports some offline printing, but FinePrint lets you select different printers, while with Windows you can't move jobs between printers.) Then I printed them in the Hilton Business Center when I arrived.

All this for $49.95. That's the magic price for me...$50, no way. But <$50, heh, sold. Don't trust just me, though. You can download a trial here.

NOTE: I wrote this on my own because I use this tool all the time. Today I needed a TIFF of a Print Job and FinePrint was there to make it happen. I needed to reprint something I'd printed last week and it was saved in my AutoSave folder. When I dig something, I like to share it with other folks. I don't know the guys at FinePrint.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Hanselminutes available on iTunes

August 21, '06 Comments [6] Posted in Podcast
Sponsored By

Ituneshanselminutes2

A friendly reminder, and some news...you can subscribe to Hanselminutes, my weekly Podcast with Carl Franklin within iTunes. If you have iTunes installed, just click here.

Here's the main feeds:

And, for the news. By popular demand, and expanded bandwidth, you can now see the last 20, yes TWENTY, Hanselminutes shows within iTunes. So, go stock up for the holidays.

One other thing, we're looking for sponsors for Hanselminutes to help pay for the bandwidth (which is crushing). If you're a technology company or ISV who usually does magazine advertising, consider advertising on my podcast. It's a very cost effective way of reaching literally tens of thousands of hardcore geeks. Email myself or Carl for details.

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

WATIR for .NET - WatiN approaches 0.8 release and automating IE from PowerShell

August 18, '06 Comments [7] Posted in ASP.NET | PowerShell | Ruby | Watir
Sponsored By

I'm a big fan of WATIR (pronounced "Water"). However many folks have said they wish they could have a similar tool in .NET. WatiN may be that tool. Looks like they'll be releasing 0.8.0 around September 1st with these changes:

  • An even more Watir like syntax to access an element. There's no need anymore to use MainDocument to access, for example, a TextField. You will now write code like:
    ie.TextField("textfieldid).Text 
  •  Support for finding matching element attribute values by using regular expressions.
  • Out of the box support for finding images by their Src attribute (no need to create your own AttributeValue class for this anymore).
  • Updated documentation.

Looks like a pretty nice, pretty clean implementation of an IE abstraction layer for .NET that will be getting even cleaner very soon. 

Aside: Another great .NET-based IE Automator is Alex Furman's SWExplorerAutomation. Here's an example of integrating SWEA with NUnit.

Back on the Watir side, one of the coolest things about Watir is "putting IE on a string" from the Interactive RuBy shell, or IRB. Leon has a great 3 mins to Watir tutorial that uses the IRB with Watir to interactively poke around at a site. Many folks find this more useful and interesting than using a recorder tool.

For example, assuming you've installed Ruby with the Windows Ruby Installer, open up a cmd.exe prompt and run

gem install Watir

to get Watir. Then run IRB.exe (Interactive Ruby) and do this:

irb(main):001:0> require 'watir'
irb(main):002:0> include Watir
irb(main):003:0> ie = Watir::IE.new
irb(main):004:0> ie.goto("
http://google.com")
irb(main):005:0> ie.text_field(:name, "q").set("Scott Hanselman")
irb(main):006:0> ie.button(:name, "btnG").click

And that's interactive Watir, right? Yay.

So, if I take a look at this WatiN (pronounced WHAT'n as in What'n'tha'heck maybe?) using the only interactive .NET Shell I have available to me...could I do Watir/IRB style interactive work using PowerShell?

PS[1] C:\WatiN-0.7.0.4000\bin
> [System.Reflection.Assembly]::LoadFile((get-item WatiN.Core.dll).FullName)

GAC    Version        Location
---    -------        --------
False  v1.1.4322      C:\WatiN-0.7.0...

PS[2] C:\WatiN-0.7.0.4000\bin
> $ie = new-object WatiN.Core.IE("
http://www.google.com")
New-Object : Exception calling ".ctor" with "1" argument(s): "Could not load fi
le or assembly 'Interop.SHDocVw, Version=1.1.0.0, Culture=neutral, PublicKeyTok
en=null' or one of its dependencies. The system cannot find the file specified.
"
At line:1 char:17
+ $ie = new-object  <<<< WatiN.Core.IE("
http://www.google.com")

Looks like since he's using an unsigned IE interop assembly it can't load it from the current application directory. That's c:/Program Files/Windows PowerShell/v1.0/, not the current directory. At this point I have two choices. I can copy the unsigned intern assembly Interop.SHDocVw.dll to the PowerShell folder, or I can rebuild the project against a Signed Primary Interop Assembly for IE. I'll copy it over for now.

PS[1] C:\WatiN-0.7.0.4000\bin
> [System.Reflection.Assembly]::LoadFile((get-item WatiN.Core.dll).FullName)

GAC    Version        Location
---    -------        --------
False  v1.1.4322      C:\WatiN-0.7.0...

PS[2] C:\WatiN-0.7.0.4000\bin
> $ie = new-object WatiN.Core.IE("
http://www.google.com")
New-Object : Exception calling ".ctor" with "1" argument(s): "Specified cast is
 not valid."
At line:1 char:17
+ $ie = new-object  <<<< WatiN.Core.IE("
http://www.google.com")

Yikes. Looks like folks are pissed off; so pissed off this forcibly closed PowerShell also.

Ok, so WatiN is doing something tricky that PowerShell doesn't like. Well, since PowerShell has its own concept of how .NET and COM should interact. Let's cut out the middle man (WatiN in this case) and go direct to IE from PowerShell .

PS[1]>$psie = new-object -com InternetExplorer.Application
PS[2]>$psie.Navigate("
http://www.google.com")
PS[3]>$q = ($psie.Document.GetElementsByTagname("input") | where { $_.Name -eq "q" } #get the input box called "q"
PS[4]>$q.value = "Scott Hanselman"
PS[5]>$search = $psie.Document.GetElementsByTagname("input") | where { $_.Name -eq "btnG" }
PS[6]>$search.click()

Gross, not easy, but shows potential. You know, a weekend, some UpdateType-Data action and a few functions and one could get a WatiPSH (!?) prototype running that would be very PowerShelly...I wonder if the PowerShell type extension stuff works as nicely with COM objects...

If the WatiN team considers PowerShell in their use cases, their abstraction layer might make a suitable interface for PowerShell scripting. Or, perhaps a few well written PowerShell scripts could give Watir-like syntax on PowerShell. Either way, WatiN has the potential to be pretty useful, particularly within NUnit if you find the Watir NUnit Integration distasteful (some do, I don't, I started it).

For now, I'll stick with the simplicity and IJW of Watir, but I'm keeping my eye on WatiN.

Now playing: Stephen Lynch - Superhero

About Scott

Scott Hanselman is a former professor, former Chief Architect in finance, now speaker, consultant, father, diabetic, and Microsoft employee. He is a failed stand-up comic, a cornrower, and a book author.

facebook twitter subscribe
About   Newsletter
Sponsored By
Hosting By
Dedicated Windows Server Hosting by SherWeb

Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.