From time to time, I get an email about Standard User Analyzer that includes a screenshot or a MessageBox text copy (you do know you can control-c a MessageBox and paste just the text, right?) that looks something like this:
Failed to load log file c:\Users\<user name>\AppData\Local\Temp\1\sua: No (valid) log file is found.
It typically is reported by people running Windows Server 2008 or Windows Server 2008 R2. What’s going on?
It turns out that it’s caused by a group policy setting enabled for Terminal Services: Do not use temporary folders per session.
Now, “session” is an unfortunately overloaded term in Windows. There is an LSA Logon Session, and there is a Remote Desktop Session (formerly known as Terminal Services Session). When you log on as a protected administrator (a member of the local administrators group with UAC enabled), you generate two LSA Logon Sessions – one for your filtered token, and one for your full token. However, you live in one Remote Desktop Session. So, it’s legitimately a bug that we’re popping over to a different temp directory for one of your tokens.
However, it’s a bug we’re not going to close at the moment, for application compatibility reasons. This bug has existed since Windows Vista, and those who have come across it have implemented workarounds – workarounds it turns out we break if we fix the bug.
App compat is one of those weird realms for engineers. If we fix bugs, we break apps, and people are unhappy. If we don’t fix bugs, then we still have bugs, and people are unhappy. That’s why we come up with features like SwitchBack and Shims – so new apps can get bug fixes, but old apps continue to get bugs. But it’s hard to always do that perfectly, particularly mid-stream.
So, what do you do to get SUA running? It turns out that you have a couple of workarounds:
Hopefully that gets some of you back up and removing admin dependencies.
Preemptive snarky comment: You can also just use LUA Buglight as a workaround. :-)
If you want to master app compat debugging, then I really only know of one approach: practice. Find things that are broken, and then find out why. If you have to look too far for something broken, then you must be significantly luckier than I am!
Now, I prefer to listen to Mötley Crüe when I debug (or drive somewhere, or sit somewhere, or walk somewhere, or…), so it seemed only fitting that I would debug something for a member of Crüe while listening to Crüe.
Now, a while back, Nikki Sixx updated his http://www.nikkisixx.net/ website. And, of course, the first thing I noticed is that it doesn’t render correctly on IE9 when in IE9 Standards mode. It renders fine, however, in IE8 or IE7 standards mode, and it also renders fine in Firefox, Chrome, Opera, and Safari. So, I figured it must be something with the new rendering engine, and went about with the assumption that our code was broken.
I first took a look with the developer tools, and spotted straight away the following error message in the Console tab:
SEC7113: CSS was ignored due to mime type mismatch
Interesting – so, perhaps it’s not a bug in IE9? I’m still a bit leery, because the fact that it works with every other engine seems to indicate something wrong with the one failing engine. So, I had a look with the new Network tab to see what I could find out about the MIME type. Here is what I found:
Content-Type text/css, charset: UTF-8
OK, so it is a CSS file, and it’s specifying a content type. So, I’m now perplexed as to what I am seeing. Of course, I’m not as conversant with the new developer tools, so I took a look with my old friend Fiddler just to make sure the headers are completely raw, and found this:
HTTP/1.1 200 OK Server: Apache/2.2.11 (Fedora) X-Powered-By: PHP/5.3.2 Last-Modified: Tue, 07 Dec 2010 19:19:31 GMT ETag: 7d2160439e3d0b054b09b638c9516e70-gzip Pragma: Content-Length: 92090 Content-Type: text/css, charset: UTF-8 Cache-Control: max-age=600 Date: Tue, 28 Dec 2010 18:04:33 GMT Connection: keep-alive Vary: Accept-Encoding
Now, this all looks fine to my uneducated eye – it looks as if we are specifying a content-type, and it appears to me that it is the correct one. But that’s the key – I’m not completely conversant in the specifications! So, let’s learn the specifications…
If you take a look here, you can see precisely what you should have for the content type, and it’s in the format:
Content-Type := type "/" subtype *[";" parameter]
Wait a minute … the specification has a semicolon and the content had a comma – it looks like this web page is actually at fault, and every other rendering engine (including ours) was just being forgiving! Wow, IE9 appears to not be shouldering the blame here! (Though admittedly we are being a little picky, given that in the past we were letting that slide.)
Of course, just to make sure, let’s test things out. First I found the request and response in Fiddler. Then, on www.nikkisixx.net/20621/global.css, I chose to right-click, Save, Response, Entire response… and placed a copy of the response on my desktop. Then, I went in to the file, and replaced that comma with a semicolon. Finally, using the auto-responder from Fiddler, I fed this modified response to test out the fix.
Voila – when the header is modified to comply with specifications, it works! IE9 is vindicated, and I have a fix for the web page which involves a single character to make it compliant with standards. Now that the heavy lifting of debugging is finished, the only remaining challenge is to find the person who owns this page and point them to the fix, and then we can go on with the show.
Updated 29-December-2010
Daniel15 (http://dan.cx) points out correctly that I didn’t go quite far enough down that spec. While the semicolon instead of a comma is all it takes to get it working, it isn’t far enough to get it up to spec. Specifically, it shouldn’t be using a colon after charset. The spec indicates:
parameter := attribute "=" value
That should be an equal sign instead. So, to be more correct the header value should be:
Content-Type: text/css; charset=UTF-8
Thanks, Daniel! And, as John points out, this is a header, so the fix would be something configured on the server and not something the designer would have submitted.
When considering application compatibility, it turns out that there are a number of differences between the biggest challenges affecting Internet-facing public websites and the biggest challenges affecting web applications run in the enterprise.
One change between Internet Explorer 6 and Internet Explorer 8 which seems to be disproportionately affecting the enterprise is Session Sharing – the fact that multiple windows and tabs share the same session. Coming from IE6, where you have one process per window, and no tabs, this can take a bit to wrap your head around.
To deeply understand what is going on, we need to explore what we are doing to make that magic happen. A web application is nothing more than a series of completely independent HTTP requests. There is no state whatsoever. We create the illusion of state by sending along a little tag with each request, indicating “hey, it’s me again – return a response custom tailored for me.” This tag can be anywhere in the request. It can be in the URL, in the headers, or in the body of the request.
Many server development environments initially implemented the illusion of state using cookies. They were hidden in the header, which was convenient if you try to bookmark something. It also gave you the flexibility to either make the cookie persistent or non-persistent. If you make the cookie persistent, then it gets saved to a file, and it comes as no surprise that this is shared by every IE window and/or tab on the computer.
Where it gets complicated is when you make the cookie non-persistent. When this is the case, the cookie is simply held in memory. Since memory is relative to a process, it won’t be shared between process. It will, however, be shared within the same process.
And here is where things begin to differ from what you were used to with Internet Explorer 6. When you double clicked on the IE icon, you typically ended up getting a new process. You didn’t have tabs. So, you ended up taking an inadvertent dependence on the particular process model of IE6. Now, this is no longer the case. Why? Because processes aren’t cheap. Having a big pile of processes lying around is extremely inefficient and degrades performance, so we take a smarter approach. Incidentally, this is not just true of Internet Explorer – you’ll see the same thing on other modern browsers.
So, we have “everything on this computer” (persistent cookies) and “everything in this process” (session cookies), but what we really want in those scenarios where session sharing is a problem (it’s often a benefit) is neither – we want “everything in this specific tab” – that’s what we happened to accidentally have in IE6 because of the particular way in which it was implemented, but we certainly don’t want to base our applications on a dated process model that isn’t supported by modern browsers in general. So, how do we achieve that?
HTML 5 has thought of this, and addressed it with sessionStorage – but until you have reached critical mass for browsers supporting HTML 5, and invest in redesigning your apps to support this, that doesn’t help you.
One option is to include the session ID in the URL – ASP.NET explicitly supports this with its Cookieless state option. However, by mangling the URL (it goes in the URL directly, rather than the query string), you create an unbookmarkable set of web pages, which is sometimes a problem, but if that is an option, it’s a fast and easy way to accomplish that.
Another alternative is to prefix the name/value pairs you are storing with a value unique to a particular window/tab. How would this work?
A final alternative is to use File / New Session to ensure you get a new process (or launch from a shortcut starting iexplore.exe with the -nomerge argument), which works fine if users are technical or can be depended upon to follow a series of steps consistently. However, this leaves you with a dependency on a legacy process model, and consequently a browser dependency as not all modern browsers provide for such an option.
Wherever possible, my hope is to help my customers remove dependencies on a dated and no-longer-used-anywhere process model, but we have a bit of a bridge to cross over until we have HTML 5 everywhere, so I hope that one of these suggestions work for you. If you have other suggestions which you have tried and were successful with I would love to hear them!
Working with a customer, I was explaining the 3 rendering engines that we have in Internet Explorer 8 (Quirks, IE7 Standards, and IE8 Standards), and how you opt into them. As we went through this, a question came up where I didn’t know the answer: what happens if you have a page whose DOCTYPE specifies Quirks mode, but which hosts an IFrame containing a page whose DOCTYPE specifies standards mode? My search engine mojo may have been inadequate that day, but I couldn’t locate an authoritative answer.
Rather than guess, I figured I would build a test. I wrote the following page, and called it guest.html:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>guest</title> <script type="text/JavaScript" language="JavaScript"> function bodyOnLoad() { if (document.getElementById("casesensitive") != null) { window.alert("IE7-"); } else { window.alert("IE8+"); } } </script> </head> <body onload="bodyOnLoad()"> <p>This is the guest</p> <div id="caseSensitive"></div> </body> </html>
What I had done was to leverage a change in case sensitivity in JavaScript, which would cause a match when in IE8 standards, or a failure to match in IE7 standards or Quirks. If you launch this page by itself, then it will pick up standards (as long as you’re not on the Local Intranet with the default group policies) and show IE8+. (You can manually set it to Quirks or IE7 using the dev tools to see it change modes.)
Now, let’s host this HTML in an IFrame inside of a page which specifies Quirks Mode:
<html> <head> <title>Mixed rendering test</title> </head> <body> <p>I am the host</p> <iframe src="guest.html"></iframe> </body> </html>
When we run it – what do we find?
IE8+.
So, a standards page inside of an IFrame on a Quirks page still runs in standards. Seeing is believing.