2007-05-21

Reading List

Initially, I was going to start off by saying that I've been reading more books and less content online, but that wouldn't be accurate. I've actually picked up more online reading, but I'm also more frequently finding myself with a good book in hand before bed. Currently, I'm finding my way through Eldad Eilam's Reversing: Secrets of Reverse Engineering. It's a good read so far and I hope to learn a lot.

I've ALWAYS got Russinovich & Solomon's Windows Internals open, and I've been through it cover to cover a few times as well. There's just so much good stuff there, and I've got a memory like a goldfish... =8->

Recently, I also read Hoglund and Butler's Rootkits: Subverting the Windows Kernel for the second time. The chapter on DKOM is probably my favorite.

I just finished Raymond Chen's The Old New Thing: Practical Development Throughout the Evolution of Windows. The anecdotes range from light to heavy, and the lessons to be learned are well presented. I like Raymond's writing style and it is good to hear his perspectives on why things are the way they are. For whatever reason I hadn't picked up Raymond's blog on MSDN, "The Old New Thing", though I was well aware of it. Probably had something to do with the volume; two posts per day seems quite high to me. After reading the book, though, I'm subscribed! Sigh. I'm not a fan of the "bonus online chapters" concept, though I am sure that I'm going to go and read them sometime. Kind of detracts from the whole "book" experience if the whole book isn't... well, whole, I suppose.

A later post will detail some of the stuff I'm subscribed to online.

»

2007-05-06

Hey! Where'd my E: Drive Go, Vista?

I use ReadyBoost in Vista. One day, I went to power up my laptop and when Vista resumed from hibernation I noticed that the light on the USB Flash-memory Device (UFD) was not on. Finding this a bit odd, I jumped into Windows Explorer, double-clicked on the E drive (the letter assigned to the UFD), and was presented with an interesting dialog:


Title: Item Not Found
Text: Could not find this item
This is no longer located in <%3 NULL:OpText>.
Verify the item's location and try again.
Removable Disk

Try Again Cancel
 

So I looked at the back of my laptop to verify the item's location, and deciding that the item was still there I clicked "Try Again". (I know, I know - not really what the person who wrote the message for the dialog intended...) I don't recall if the dialog dismissed and another instance reappeared, or if it was just that nothing happened. Either way, I wasn't getting anywhere. I unplugged the UFD, and plugged it back in again and things were fine.

A few days later, the same thing happened. I suspect I'll be dealing with this for a while.

Procedurally, I hate to think that I'm going to have to eject the device prior to hibernating, and then plug the device in again when Vista resumes - that's too tedious for my tastes. ReadyBoost would have to have a significant impact on performance for me to go through that rigamarole, and at this point I'm just not convinced that's the case.

Anyone else coping with %3 NULL:OpText? How are you dealing with it?


»

2007-05-01

Setting the Priority of a Service Process via Script

Previously (here and here), I've written about isolating shared services so that they run in their own process, with a specific focus on the Windows Update Automatic Updates Service (wuauserv) that typically runs in the NETSVCS SVCHOST.EXE instance. One thing that can be done once this is accomplished is to lower the priority of the process so that when the service winds up consuming 100% of the CPU, the system doesn't become unresponsive.

Since we're dealing with a service, setting the priority of such a SVCHOST.EXE process can become problematic - the service may already be running, or, because it is a service, it is not started as non-service processes are, so one is not able to use START / [LOW NORMAL HIGH REALTIME ABOVENORMAL BELOWNORMAL] to impose a priority when the process starts. One can use a utility like Task Manager or Process Explorer to set the priority of a process on an ad hoc basis, but when the service restarts or the system reboots one has to remember to set the priority again.

Though not an ideal solution the following scripts (VBS using WMI, and PowerShell) can be used to set the priority of the SVCHOST.EXE instance hosting the isolated Windows Update Automatic Updates Service service to "below normal". Note that no check is done to ensure that the SVCHOST.EXE instance is only hosting one service - if wuauserv is found to be a service inside of the process, the priority is adjusted. Note also that no error handling is implemented.

I'll try to format the code so it looks nice, but I fear I will be limited...

Here's the code for the VBS / WMI script:



Const BELOW_NORMAL = 16384
Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2")
Set colServices = objWMIService.ExecQuery( _
"SELECT * FROM Win32_Service where name='wuauserv'")
For Each oService in colServices
Set colProcesses = objWMIService.ExecQuery( _
"SELECT * FROM Win32_Process where ProcessId=" & oService.ProcessId )
For Each oProcess in colProcesses
oProcess.SetPriority(BELOW_NORMAL)
Next
Next


Here's the code for the PowerShell script:



(gps -id (get-wmiobject win32_service where {$_.name -eq "wuauserv"}).ProcessId).PriorityClass="BelowNormal"


The different values for the priority parameter of the SetPriority method of the Win32_Process WMI class can be found in the documentation for the SetPriority method.

The different values for the PriorityClass in the PowerShell script are "Normal", "Idle", "High", "RealTime", "BelowNormal", or "AboveNormal". Or, to get a list of the available options, one can use the following PowerShell command:



[ENUM]::getNames("System.Diagnostics.ProcessPriorityClass")

Once the script is in place and working, one can cause it to be invoked at will, or via scheduled task at specific times, or after logon, or any other way that one can get something to happen when Windows boots or a user logs on.


»

2007-04-27

User-Mode Debugging Internals

Alex Ionescu has posted some publications at his blog. I've only had an opportunity to go through the three-part series on Windows XP / 2003 User-Mode Debugging Internals, but I found them to be quite interesting and I hope to go through the rest of the publications which cover topics like Process Internals, VB File Format, NTFS ADS, and Subverting Windows 2003 SP1 Kernel Integrity Protection.

One thing (probably trivial) that I am curoius about in the User-Mode Debugging Internals papers is the analysis of NtDebugActiveProcess. Alex comments in his analysis in part 3 "Don't allow debugging the initial system process". The check for the initial system process is made, and STATUS_ACCESS_DENIED is returned if indeed it is the initial system process that is the subject of the debug attempt. I am curious as to why, prior to returning in this case, the process is not dereferenced (ObDereferenceObject(Process);)? Is it simply the nature of the system process that this is not required, though perhaps it might be considered good practice to call ObDereferenceObject(Process) in this case? Or is there some other reason?

Does anyone have any thoughts on the above?

»

2007-04-23

The Joy of Tagging (or Labeling)

OK... I admit it. I'm jumping on the whole "tagging" thing (or as Blogger likes to call it, "Labels") a bit late. Shortly after converting to the "new" Blogger, I made a rather unconscious decision to ignore the field that allows for tagging new items. So there are many posts that were made with the new blogger that don't have tags. I plan on tagging a few at a time, but with 140+ posts, this could take a bit of time.

»

2007-04-16

Part 2: Background - What's using my CPU?

Previously (Part 1: Introduction - What's using my CPU?), I kicked off what I expect to be a multi-part series on determining what is causing excessive CPU consumption, outside of the normal "which process has the highest value in the CPU column in Task Manager".

Before I get into things, a little bit of background may prove useful or mildly entertaining. Over on "Sysinternals Forums", there were recently two similar problems that both involved excessive CPU utilization that was not attributable to a specific process. I became involved in both problems and attempted to use similar techniques to get additional information with the hopes of ultimately being able to pinpoint the problem. What may make this mildly entertaining is that in both cases, there was limited or no success in detetmining the cause of or solution to the problem. In the end, one problem was resolved by disabling the floppy disk controller, and the other problem appears to be as of yet unresolved. (In the latter case, the poster did admit that the system was experiencing hardware problems - the chipset fan was dying and there were diagnostic beep codes during / after POST. These hardware problems could be related to the problem.) Despite the lack of success in determining the cause of the problems I do feel that I learned a bit about this type of problem and gained some insight into the use of some tools that can come in handy in this situation.

In the two cases, the problem consisted of the CPU spending a lot of time servicing interrupts and deferred procedure calls (DPCs). What are interrupts and DPCs? "Windows Internals, Chapter 3 - System Mechanisms" says:

Interrupts ... are operating system conditions that divert the processor to code outside the normal flow of control. An interrupt is an asynchronous event (one that can occur at any time) that is unrelated to what the processor is executing. Interrupts are generated primarily by I/O devices, processor clocks, or timers.
A deferred procedure call (DPC) is a function that performs a system task—a task that is less time-critical than the current one. The functions are called deferred because they might not execute immediately.
It is interesting to note that one may have a problem with excessive CPU use but may not be able determine it by using Windows' Task Manager. This is because for whatever reason, Task Manager adds time the CPU spends servicing interrupts and DPCs to the "System Idle Process". Microsoft's / Sysinternals' Process Explorer includes separate "artificial" processes for interrupts and DPCs so that one can see how much time the CPU spends dealing with each. Per Process Explorer's help file, "high CPU consumption by these activities can indicate a hardware problem or device driver bug".

Another thing that could be consuming CPU is the SYSTEM process. The process of determining what system thread is consuming the CPU is similar to determining what thread in a user-mode process is utilizing the CPU. However, excessive CPU utilization by the SYSTEM process might be a little more serious as it is an indication that some driver is possibly running rampant.

Next time, I plan to introduce some tools that can be useful in exploring DPC and interrupt activity on a system, as well as discussing how to determine what driver might be inolved with excessive CPU utilization in the SYSTEM process.


»

2007-03-26

Visual Studio's Tacit Endorsement of MadLibs

Formatting strings can be a tricky job...


I'm sure there's a logical explanation, but still... It really {0} me off when {1} Visual Studio 2005 SP1 decided to throw this {2} my way.

»

2007-03-19

Patch that Might Help with 0x8ddd0009 as well as high SVCHOST.EXE CPU Utilization?

In the past, I've written about both high CPU utilization by SVCHOST.EXE as well as the 0x8ddd0009 Windows Update / Microsoft Update error, so I thought I would mention this...

MS KB 932494 (When you use Automatic Updates to scan for updates or to apply updates to applications that use Windows Installer, you experience issues that involve the Svchost.exe process) references problems that are addressed by MS KB 916089 (FIX: When you run Windows Update to scan for updates that use Windows Installer, including Office updates, CPU utilization may reach 100 percent for prolonged periods) and MS KB 927891 (You receive an access violation when you try to install an update from Windows Update after you apply hotfix package 916089). However, even after applying the patch associated with 927891 (which replaces the patch associated with 916089), 932494 indicates that the following problems remain:

1) Certain 100 percent CPU issues are still present when you use the Svchost.exe process.
2) An access violation may occur in the Svchost.exe process.
I (as well as others) have speculated in the past that 916089 (and its succedent patches) can also help with the 0x8ddd0009 error message that one might receive from Windows Update / Microsoft Update.

»

2007-03-06

Part 1: Introduction - What's using my CPU?

Recently, I have been involved in attempting to diagnose problems with excessive CPU utilization. Often times, this type of thing is relatively easy to identify - at least as far as pointing the finger at the thing that is consuming CPU cycles. Task Manager can be used for this - simply sort the "CPU" column in descending order and note the process that is at the top of the list. One can use a similar technique with Process Explorer.

In the past (here and here), I've given examples that demonstrate various techniques that can be used to try to determine what a process is doing when it is consuming so much CPU. Sometimes, you can do something about it - if you have the debugging symbols, perhaps there is something in the stack of the thread or threads in the process that is consuming the CPU that will lead you to some setting, feature, or configuration piece that can be manipulated so as to avoid the problem. Or perhaps just knowing the module name is enough information to identify the problem software - a recently installed add-in / plug-in, or a new utility, perhaps. Sometimes you are forced to work around the problem - you don't have any control over it and don't want to stop using the program, or have no choice but to keep using the program.

But what happens when the excessive CPU utilization is not attributable to a "standard" process? In the coming series of articles, I hope to explore some of the things that can be done to diagnose and troubleshoot this type of scenario. Stay tuned...

»

2007-03-02

Seriously! The dog ate it!

I'll make this one brief...

Sorry for the lack of updates lately - I'm working on a number of other things and haven't found a lot of time to write. I have something kind of fun planned that may be a three or four parter but it will probably be a bit slow in coming. It will also be a learning experience for me, so that should be cool. I will post things as I finish them, but there may be revisions to the content when the later parts are posted. I hope to have the first one (introduction) up by the end of the coming weekend.

I appreciate your patience, understanding, and continued readership. Thank you.

»

2007-02-18

Ideas For Features / Enhancements to Sysinternals' Process Monitor

I've written about Sysinternals' Process Monitor utility before:

I have had a few months now to work with Process Monitor, and it certainly is amazing. The filtering capabilities are great, and the fact that the filters are not destructive makes slicing and dicing the data many ways quite simple. The ability to capture all of the data that the utility can capture makes it quite powerful, and the ability to get stack traces for each event is extremely useful.

Going off the observation that Process Monitor is currently at version 1.01, and the assumption that the utility will see further development, I have hopes that the following relatively small ideas will be taken into consideration for future releases, and that further discussion and conversation is sparked.

1) Allow for the use of CTRL+C to copy selected data to the clipboard. Some data can be copied in this fashion, but from my experience not much. In many cases, one can right-click and choose "Copy" from the context menu, but that's inconvenient. For example, on Event properties, on the Event tab for a Profiling Interrupt, I can select the User and Kernel times and press CTRL+C, and the data will go to the clipboard. However, if I select the date, the result, or the sequence #, the only way to copy the selection is by using the mouse.

2) Along the same lines, it would be useful to have a "Copy details to clipboard" button on each tab of the Event properties - it would simply grab all of the displayed data and copy it to the clipboard with the click of a button. Or the use of a hotkey accelerator. This would have come in handy on the Stack tab, but there I was at least able to save the data to a CSV file and work with it in that fashion.

3) I would like to be able to sort by each of the columns displayed on Process tab of the Event's properties, in the "DLLs" section. It might also be nice to toggle display of path (this would affect sort as well), or perhaps add another column for just the module name.

4) In Options --> "History Depth", the edit part of the spin control could be a bit wider - there is plenty of room on the dialog...

5) It might be inferred that I prefer to avoid using the mouse. As such, it pains me when there are no hotkeys on a dialog box. I find myself constantly wanting to "ALT+A" to add a filter on the "Process Monitor Filter" dialog, or "ALT+R" to remove, or whatever. Other dialogs, such as Configure Symbols, Select Columns, Show Unique Values, etc, could also benefit from hotkeys. I do love the fact that so many things in the main UI are accessible with the CTRL key - CTRL+L for the filter, CTRL+J for jump to, etc.

For further exploration / discussion:
-- I realize it can be difficult to determine what to do for an implementation of "Jump to" for certain classes - what would one "jump to" for a profiling interrupt, for example? For Process and Thread activity, one might wish to "Jump to" Dependency Walker for "Process Create" and "Load Image" operations. For "Thread Create" and "Thread Exit" events, however, a relevant action is not clear. Does anyone have any thoughts or ideas?

[Note: The spirit of the above was posted by me to the Process Monitor forum on Sysinternals' Forums at "Process Monitor - Feature Requests". Reprinting here with my own permission. Apologies if you've seen this before. I also apologize for my client's rude behavior.]

»

2007-02-08

More on Isolating Shared Services in Windows

Previously (Troubleshooting Performance Issues with Automatic Updates / How to Isolate A Shared Service Hosted by SVCHOST.EXE) I had detailed some steps that one could follow to isolate a shared service hosted by SVCHOST.EXE, in the context of the Windows Update Automatic Updates service. There are a couple of other ways to isolate a shared service, with different implications.

The intention / desire of a service to be "shared" or not is typically indicated when the service is created - the fifth parameter to CreateService is dwServiceType, which for our interests can be, among other things, SERVICE_WIN32_OWN_PROCESS (0x10) or SERVICE_WIN32_SHARE_PROCESS (0x20). Once a service has been created, the dwServiceType setting can be changed by calling ChangeServiceConfig with the appropriate parameters.

Windows XP and Server 2003 ship with a utility program called "SC.exe". (I seem to recall using SC.EXE on NT 4.0, after it was included in some resource kit, but I could be mistaken. The DLL Help Database listing for SC.EXE puts the earliest version as having shipped with Visual Studio .NET 2002.) SC presumably stands for "Service Controller". At any rate, one can use SC to change the configuration of a service, including the "service type" - "shared" or "own". So, using wuauserv - the Windows Update Automatic Updates service - as a guinea pig, one could execute from a CMD prompt:

sc config wuauserv type= own
to cause the service to run in its own process. (The service will need to be restarted for this to happen.) To change it back to a shared service, use the following command:

sc config wuauserv type= share
Note that in both commands, the space after the '=' character is critical. For this change (back to "shared") to take effect, the system will likely need to be rebooted as the "original" SVCHOST group that this service was a part of is already running. This is also the case when un-doing the configuration to make the service run in its own SVCHOST group.

The SC commands above are actually just manipulating the registry - you could make the change directly to achieve the same outcome. The setting in question (again, using wuauserv as a guinea pig) is located at [HKEY_LOCAL_MACHINE\SYSTEM\ CurrentControlSet\Services\wuauserv] - the "Type" REG_DWORD value. The type corresponds to the aforementioned dwServiceType, which can be (for our purposes here) SERVICE_WIN32_OWN_PROCESS (0x10) or SERVICE_WIN32_SHARE_PROCESS (0x20). To isolate the service, set type to 0x10, and to undo the change, set type back to 0x20 (keeping in mind the restart considerations previously mentioned).

Another thing to keep in mind is the consideration that perhaps a service is not meant to be isolated; those concerns are discussed a wee bit more here.

One subtle difference in techniques is that if you isolate a service into its own SVCHOST group, the command line for the svchost.exe process changes to reflect the group name you speficied when setting up the configuration. However, if you use the SC.EXE / "Type" registry value change technique, the command line for the svchost.exe process remains the same - in the case of wuauserv, the "netsvcs" group is still specified on the command line even though the SVCHOST instance will only be hosting one service.

»

2007-02-01

Unspecified Potential Security Risk! Take 2

Some additional questions have been raised here and elsewhere about what precisely causes the "Unspecified Potential Security Risk" dialog - the one from Internet Explorer that looks like:


Internet Explorer

This page has an unspecified potential security risk.
Would you like to continue?

The dialog is displayed when the setting "Launching applications and unsafe files" is set to "Prompt" for the security zone that Windows / Internet Explorer believes itself to be operating in.

Changing the setting to "Enable" for the specific zone eliminates the dialog, while changing the setting to "Disable" produces a "Security Alert" dialog stating that "Your current security settings do not allow this action."


»

2007-01-28

Troubleshooting Performance Issues with Automatic Updates

...or,
How to Isolate A Shared Service Hosted by SVCHOST.EXE

There are a number of articles in the Microsoft Knowledge Base about performance issues with Windows Update / Microsoft Update, as well as other problems related to the scanning mechanisms used by automatic-type update services. There are some fixes, and fixes for some fixes, but no "ultimate" solution. Stepping back a bit, how can you even determine if Automatic Updates is causing performance issues on your system?

The Automatic Updates service is not a stand-alone process, so it is not sufficient to simply look for which process is consuming the most CPU time or the most memory. Rather, Automatic Updates is integrated into the "netsvcs" SVCHOST service hosting instance. On the systems that I have examined, this instance hosts over 20 services - 25 services on the system I am using to write this. How can you see what services are running inside of a process? One way is to use "tasklist /svc", and examine the "Services" column. Another way is to use Process Explorer - simply hover the mouse pointer over a process and any services that are contained in the process are listed in a tooltip. Or, view the Process' "Properties" page and examine the "Services" tab for more details.

This sharing of services in one process isn't a bad thing - Windows has been doing this for some time. There are times when it makes sense, and times when it doesn't. Basically, processes are expensive and the more you have the more resources they consume. If you are able to share services in the address space of a process, you are conserving resources. But if the services have different security needs, for example, then you should probably split them into two separate processes to "isolate" the functionality that requires greater privileges.

Back to the task at hand... The fact that services can share a process is nice, but this really gets in the way of troubleshooting a service you suspect may be causing problems. So it can be useful to extract a shared service and make it run in its own process. With services hosted by SVCHOST, the configuration is controlled in the registry. Microsoft doesn't publicly document the interfaces for SVCHOST.EXE as it doesn't want people writing services and making them run in the same address space of processes that host Windows built-in services - if the service is poorly written it can cause SVCHOST.EXE to crash, and subsequently kill all of the other services running in that instance of SVCHOST.EXE. That doesn't mean you can't manipulate the built-in Windows services to use a configuration you desire, though...

The SVCHOST services are controlled by registry settings in [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SvcHost]. (Standard warnings about editing the registry apply.) Each REG_MULTI_SZ in this key represents a SVCHOST group containing a list of one or more services to run in an instance of SVCHOST.EXE. So if one wishes to isolate the Automatic Updates service, one needs to find which group it is in. The "name" of the Automatic Updates service is "wuauserv" - Windows Update Automatic Updates service. This service resides in the "netsvcs" group. So, since the desire is to create a new SVCHOST instance to run the service in, remove wuauserv from the list in the netsvcs value. Then, create a new REG_MULTI_SZ value and give it an appropriate name, such as AutomaticUpdates. Add wuauserv to this value.

Next, navigate to [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet \Services\wuauserv] and change the ImagePath (which specifies the program and arguments the Service Control Manager is to use to invoke the service) from:
%systemroot%\system32\svchost.exe -k netsvcs
to:
%systemroot%\system32\svchost.exe -k AutomaticUpdates

That's it. Stop and restart the Automatic Updates service (net stop wuauserv / net start wuauserv) and you should see a new instance of SVCHOST.EXE that contains only the Automatic Updates service. Now you can monitor the performance of this process, drop its priority (Task Manager or Process Explorer), etc.

The same technique can be applied to isolate other SVCHOST hosted services as well. However, some caution and investigation should be applied on a case-by-case basis- it should be noted that some services may have some dependence on residing in the same address space as another service. This may or may not be intentional; if intentional I suspect that it probably has to have some relation to performance. If not intentional, it is likely a bug.

»

2007-01-24

Vista Features You'll Never See

A quick one this week...

Ran into an interesting posting at shell: revealed about features of Longhorn that didn't make the cut. The post paints the picture that after the Longhorn reset (described here), a lot of features were yanked, and then goes on to describe some rather humorous things that just make you think... "What if?"

»

2007-01-18

Fix Available for Performance Problems with Internet Explorer 7's Phishing Filter

I don't know how I missed it (well, I suspect it's related to quirks in the method(s) in which Microsoft makes notifications of new KB articles available), but it seems that Microsoft has released an update to Internet Explorer 7 to address the performance issues with the Phishing Filter that I had previously (here and here) encountered.

The KB article (The computer may respond very slowly as the Phishing Filter evaluates Web page contents in Internet Explorer 7) is dated December 12, 2006, and contains links to download pages for various versions of Windows that Internet Explorer 7 can run on. Your copy of Windows has to pass the Windows Genuine Advantage (WGA) check before Microsoft will allow you to download the fix. Once downloaded, installation is straightforward; depending on what programs you have open at the time, you may be required to reboot after the installation finishes.

It is interesting to note that the Cause section (below) explains exactly the conditions I was operating in, and the behavior I observed.


CAUSE

This problem occurs when one or more of the following conditions are true:
• The Web page contains many frames.
• You browse many frames in a short time.
Internet Explorer 7 evaluates the whole Web page when you browse a frame. Therefore, CPU usage may be very high.



Additionally, the workaround (at the bottom of the article) is to disable the Phishing Filter on the "Advanced" tab of the "Internet Options".

Prior to installing the update, I set the Phishing Filter to "Turn off automatic website checking" ("Advanced" tab of "Internet Options") and made sure it was "Enabled" for the Internet Explorer Security Zone I was working in. I then verified that I was able to recreate the behavior I witnessed in The Case of the Sluggish Internet Explorer 7.

I installed the update and needed to reboot (I forgot I had SharpReader open, and it had loaded MSHTML.DLL). Upon reboot I attempted to cause the CPU to spike by doing precisely the things that had caused the problem in the past. I didn't have any luck in doing so. In fact, none of the threads in the iexplore.exe process were consuming an inordinate amount of CPU. It would appear that the fix involved, to some extent at least, changing the technique Internet Explorer uses to queue up requests to have something evaluated by the Phishing Filter (previously, I had hypothesized that Internet Explorer 7 was using the ThreadPool API and was creating a new thread for each request). Based on my explorations so far, the fix takes care of the problem. Kudos to Microsoft for recognizing the problem and taking appropriate steps to address it.

The fix updates 2 Windows / Internet Explorer program files in %windir%\system32 - ieapfltr.dll (the "Microsoft Phishing Filter") and mshtml.dll (the "Microsoft (R) HTML Viewer"). I didn't take the time to save off copies of the previous versions of these DLLs to try to compare differences (perhaps an exercise for another day). However, the new MSHTML.DLL has a date of 2006-11-09, and the new IEAPFLTR.DLL has a date of 2006-11-08. Internet Explorer 7.0 was released on 2006-10-18. So it appears that Microsoft knew of problems with the Phishing Filter performance prior to launch; obviously this wasn't a showstopper issue. It also would appear to have taken just over 1 month for the fix to make its way through the testing / release process. I guess that's not too bad, considering that some high-priority / critical security updates take at least that long. On the other hand, this is a new feature so it didn't have the legacy behind it that some of the security updates have to contend with. I guess I should just be happy to have a fix... ;)

»

2007-01-17

Unspecified Potential Security Risk!

Oh, my. Two weeks in a row with ambiguous security-related messages from a web browser.

This week, we have the following:


Internet Explorer

This page has an unspecified potential security risk.
Would you like to continue?

If it wasn't for the fact that I wasn't browsing the web - I was trying to open a ZIP file on a network share - I probably would have said "No". But since I really needed to get into the ZIP file, I decided to take my unspecified potential chances. I think I'm OK.

»

2007-01-10

Puritanical Security? And a Few Other Notes on HTML Help

I was going through some CHM help files the other day and I wound up copying one of the links to the clipboard and tossing it into Maxthon. I wasn't even really aware of what I was doing (just plodding along mindlessly) so I was rather surprised when I was presented with the following dialog:


Security Warning !

Using MK: protocol in browser may cause puritanical security problems.
Do you really want to enable this protocol during this session?


Of course, I had no desire to cause puritanical security problems, so I went with the default "No". The URL I had copied was in fact a "Microsoft Infotech" protocol link in the form of:
mk:@MSITStore:f:\file.chm::/Whatever/Whatever.html

The InfoTech protocol has changed several times over the last few years to reduce security vulnerabilities in HTML help. See MS05-026: A vulnerability in HTML Help could allow remote code execution and MS04-023: Vulnerability in HTML Help could allow code execution for more information.

Another issue that is seen rather frequently is the inability to open CHM / HTML Help files from a network path (UNC path or mapped drive). The article "You cannot open remote content by using the InfoTech protocol after you install security update 896358, security update 840315, or Windows Server 2003 Service Pack 1" discusses various registry settings that can be manipulated to allow the display of content in CHM files in this scenario.

»

2007-01-02

mtpstoolkit RatingBehavior related to AJAX?

Unfortunately, I forgot what website I was visiting when I encountered the following dialog:



Assertion Failed: Unrecognized tag mtpstoolkit:RatingBehavior

Break into debugger?

I have no concrete idea what the dialog is related to, but I suspect it has to do with some AJAX framework. Interestingly, googling mtpstoolkit (groups search here) currently proves to be rather fruitless. The stack of the thread "owning" the dialog (with a large number of calls in jscript.dll) seems to support the AJAX theory:

ntoskrnl.exe!KiSwapContext+0x2e
ntoskrnl.exe!KiFastCallEntry+0xf8
ntdll.dll!KiFastSystemCallRet
USER32.dll!NtUserWaitMessage+0xc
USER32.dll!InternalDialogBox+0xd0
USER32.dll!SoftModalMessageBox+0x938
USER32.dll!MessageBoxWorker+0x2ba
USER32.dll!MessageBoxIndirectW+0x56
ieframe.dll!SHFusionMessageBoxIndirect+0x26
ieframe.dll!CDocHostUIHandler::ShowMessage+0x128
ieframe.dll!CDocHostUIHandler::Exec+0xe6
ieframe.dll!CDocObjectHost::OnExec+0xcb1
ieframe.dll!CDocObjectHost::Exec+0xd7
mshtml.dll!CreateHTMLPropertyPage+0x2503b
mshtml.dll!CreateHTMLPropertyPage+0x22f72
mshtml.dll!CreateHTMLPropertyPage+0x8980
mshtml.dll!CreateHTMLPropertyPage+0x3f40c
mshtml.dll!DllGetClassObject+0xc53d3
mshtml.dll!DllGetClassObject+0xca51f
mshtml.dll!DllGetClassObject+0xca498
mshtml.dll!DllGetClassObject+0xca353
jscript.dll!IDispatchExInvokeEx2+0xac
jscript.dll!IDispatchExInvokeEx+0x56
jscript.dll!InvokeDispatchEx+0x78
jscript.dll!VAR::InvokeByDispID+0x7e
jscript.dll!CScriptRuntime::Run+0x1675
jscript.dll!ScrFncObj::Call+0x8d
jscript.dll!NameTbl::InvokeInternal+0x40
jscript.dll!VAR::InvokeByDispID+0xfd
jscript.dll!VAR::InvokeByName+0x165
jscript.dll!VAR::InvokeDispName+0x43
jscript.dll!VAR::InvokeByDispID+0xb9
jscript.dll!CScriptRuntime::Run+0x16c9
jscript.dll!ScrFncObj::Call+0x8d
jscript.dll!NameTbl::InvokeInternal+0x40
jscript.dll!VAR::InvokeByDispID+0xfd
jscript.dll!VAR::InvokeByName+0x165
jscript.dll!VAR::InvokeDispName+0x43
jscript.dll!VAR::InvokeByDispID+0xb9
jscript.dll!CScriptRuntime::Run+0x1675
jscript.dll!ScrFncObj::Call+0x8d
jscript.dll!NameTbl::InvokeInternal+0x40
jscript.dll!VAR::InvokeByDispID+0xfd
jscript.dll!VAR::InvokeByName+0x165
jscript.dll!VAR::InvokeDispName+0x43
jscript.dll!VAR::InvokeByDispID+0xb9
jscript.dll!CScriptRuntime::Run+0x1675
jscript.dll!ScrFncObj::Call+0x8d
jscript.dll!NameTbl::InvokeInternal+0x40
jscript.dll!VAR::InvokeByDispID+0xfd
jscript.dll!VAR::InvokeByName+0x165
jscript.dll!VAR::InvokeDispName+0x43
jscript.dll!VAR::InvokeByDispID+0xb9
jscript.dll!CScriptRuntime::Run+0x1675
jscript.dll!ScrFncObj::Call+0x8d
jscript.dll!NameTbl::InvokeInternal+0x40
jscript.dll!VAR::InvokeByDispID+0xfd
jscript.dll!VAR::InvokeByName+0x165
jscript.dll!VAR::InvokeDispName+0x43
jscript.dll!VAR::InvokeByDispID+0xb9
jscript.dll!CScriptRuntime::Run+0x1675
jscript.dll!ScrFncObj::Call+0x8d
jscript.dll!NameTbl::InvokeInternal+0x40
jscript.dll!VAR::InvokeByDispID+0xfd
jscript.dll!JsFncCall+0x8e
jscript.dll!NatFncObj::Call+0x41
jscript.dll!NameTbl::InvokeInternal+0x40
jscript.dll!VAR::InvokeByDispID+0xfd
jscript.dll!VAR::InvokeByName+0x165
jscript.dll!VAR::InvokeDispName+0x43
jscript.dll!VAR::InvokeByDispID+0xb9
jscript.dll!CScriptRuntime::Run+0x1675
jscript.dll!ScrFncObj::Call+0x8d
jscript.dll!NameTbl::InvokeInternal+0x40
jscript.dll!VAR::InvokeByDispID+0xfd
jscript.dll!VAR::InvokeByName+0x165
jscript.dll!VAR::InvokeDispName+0x43
jscript.dll!VAR::InvokeByDispID+0xb9
jscript.dll!CScriptRuntime::Run+0x1675
jscript.dll!ScrFncObj::Call+0x8d
jscript.dll!NameTbl::InvokeInternal+0x40
jscript.dll!VAR::InvokeByDispID+0xfd
jscript.dll!VAR::InvokeByName+0x165
jscript.dll!VAR::InvokeDispName+0x43
jscript.dll!VAR::InvokeByDispID+0xb9
jscript.dll!CScriptRuntime::Run+0x16c9
jscript.dll!ScrFncObj::Call+0x8d
jscript.dll!NameTbl::InvokeInternal+0x40
jscript.dll!VAR::InvokeByDispID+0xfd
jscript.dll!JsFncApply+0xc4
jscript.dll!NatFncObj::Call+0x41
jscript.dll!NameTbl::InvokeInternal+0x40
jscript.dll!VAR::InvokeByDispID+0xfd
jscript.dll!VAR::InvokeByName+0x165
jscript.dll!VAR::InvokeDispName+0x43
jscript.dll!VAR::InvokeByDispID+0xb9
jscript.dll!CScriptRuntime::Run+0x1675
jscript.dll!ScrFncObj::Call+0x8d
jscript.dll!NameTbl::InvokeInternal+0x40
jscript.dll!VAR::InvokeByDispID+0xfd
jscript.dll!CScriptRuntime::Run+0x16c9
jscript.dll!ScrFncObj::Call+0x8d
jscript.dll!CSession::Execute+0xa1
jscript.dll!NameTbl::InvokeDef+0x179
jscript.dll!NameTbl::InvokeEx+0xcb
mshtml.dll+0x2234
mshtml.dll!DllGetClassObject+0x24151
mshtml.dll!DllGetClassObject+0x77fb6
mshtml.dll!DllGetClassObject+0x7925f
mshtml.dll!DllGetClassObject+0x6f679
mshtml.dll!DllGetClassObject+0x9f5de
mshtml.dll!DllGetClassObject+0xb63c7
USER32.dll!InternalCallWinProc+0x28
USER32.dll!UserCallWinProcCheckWow+0x150
USER32.dll!DispatchMessageWorker+0x306
USER32.dll!DispatchMessageW+0xf
avant.exe+0x5df02
avant.exe+0x5df5b
avant.exe+0x39941f

Anyone know what precisely mtpstoolkit is a part of?

»

2006-12-26

Using Process Monitor to Troubleshoot Internet Explorer 7 Performance Issues

[Added 2007-01-18: Fix Available for Performance Problems with Internet Explorer 7's Phishing Filter ...]

Previously, I wrote about sluggish behavior with Internet Explorer 7. I had used Process Explorer to help pinpoint the cause of the sluggishness - in this case, it was Internet Explorer 7's (anti)phishing filter. I could also have used a relatively new tool from Microsoft's Windows Sysinternals - Process Monitor.

In Process Monitor, it is easy to get inundated with all of the data that the tool collects. Filters are very critical to enabling one to find the desired information, and the implementation of filters in Process Monitor is top notch. For this exercise, after starting Process Monitor and checking "Generate Profiling Events" on the "Options" menu, I captured events while exercising the web application with the Phishing Filter set to "Turn off automatic website checking" and "Enabled" for the Security zone the web application was in. After capturing events for a minute or so, I set the following filters:
-Process Name is iexplore.exe then Include
-Event Class is Registry then Exclude
-Event Class is File System then Exclude
-Event Class is Process then Exclude

This displayed all "profiling" events for the iexplore.exe process. I double-clicked an event to bring up the "Event Properties" dialog and clicked on the "Stack" tab, which had the following information:

ntdll.dll!KiFastSystemCallRet
kernel32.dll!WaitForSingleObject + 0x12
ole32.dll!GetToSTA + 0x6f
ole32.dll!CRpcChannelBuffer::SwitchAptAndDispatchCall + 0xf6
ole32.dll!CRpcChannelBuffer::SendReceive2 + 0xb9
ole32.dll!CAptRpcChnl::SendReceive + 0xab
ole32.dll!CCtxComChnl::SendReceive + 0x113
RPCRT4.dll!NdrProxySendReceive + 0x43
RPCRT4.dll!NdrClientCall2 + 0x1fa
OLEAUT32.dll!IDispatch_RemoteInvoke_Proxy + 0x1b
OLEAUT32.dll!IDispatch_Invoke_Proxy + 0xb6
ieapfltr.dll!ATL::CComPtr::GetProperty + 0x56
ieapfltr.dll!FieldContainer::VisitInput + 0x1b9
ieapfltr.dll!FieldContainer::VisitAllElements + 0x21d
ieapfltr.dll!FieldContainer::ExtractFieldCount + 0x10e
ieapfltr.dll!FieldContainer::InitFieldCount + 0x9
ieapfltr.dll!PageDetails::Init + 0x315
ieapfltr.dll!PageDetails::Factory + 0x59
ieapfltr.dll!HeuristicsFeatures::InnerExecute + 0x15b
ieapfltr.dll!HeuristicsFeatures::Execute + 0x55
ieapfltr.dll!ProcessingThread::RunPageAnalysis + 0x1b4
ieapfltr.dll!ProcessingThread::RunUrlAndPageAnalysis + 0xdb
ieapfltr.dll!ProcessingThread::Analyze + 0xd3
ieapfltr.dll!ProcessingThread::AnalyzeFrame + 0x249
ieapfltr.dll!ProcessingThread::EnumerateFrames + 0x2e5
ieapfltr.dll!ProcessingThread::EnumerateFrames + 0x249
ieapfltr.dll!ProcessingThread::Evaluate + 0x1ec
ieapfltr.dll!ProcessingThread::Execute + 0x78
ieapfltr.dll!ProcessingThread::Process + 0x24e
ieapfltr.dll!ProcessingThread::Start + 0x72
ieapfltr.dll!Evaluator::ContinueProcessing + 0x21f
ieapfltr.dll!Evaluator::ContinueProcessingWrapper + 0x21
ntdll.dll!RtlpWorkerCallout + 0x70
ntdll.dll!RtlpExecuteWorkerRequest + 0x1a
ntdll.dll!RtlpApcCallout + 0x11
ntdll.dll!RtlpWorkerThread + 0x87
kernel32.dll!BaseThreadStart + 0x37

With this information from Process Monitor, one could come to a similar conclusion - the Phishing Filter in Internet Explorer 7 seems to cause Internet Explorer 7's performance to degrade in certain environments.

»

2006-12-19

The Case of the Sluggish Internet Explorer 7

[Added 2007-01-18: Fix Available for Performance Problems with Internet Explorer 7's Phishing Filter ...]

I like Internet Explorer 7. I've installed it many, many times and on
many systems. I've never had a problem with it. That is, until I had to spend some time working with a web-based application on an Intranet. I had to go through several iterations of repetetive steps in this application. It was the kind of work where it would have been more fun to write a program to achieve the end result, but it would probably have taken more time to write the program than it would to go through the tedious process. That, and the fact that I didn't immediately have access to some of the information that would be required to write the app, prevented me from taking the fun route. So I was stuck copying, clicking, pasting, and... WAITING.

The problem wasn't the responsiveness of the web server - the problem was localized to my system. As I was working on a laptop, I could hear the fan kick into high gear as CPU utilization hit 100%... and stayed there. When I paused for a bit, the CPU usage went back down. So, interacting with the web application was causing the behavior. The task took about 90 minutes to complete, and when I was done, Process Explorer showed iexplore.exe as having used nearly 90 minutes of CPU time. I didn't have this problem with Internet Explorer 6! In communicating with the vendor of the web application, they indicated that they hadn't had problems of this sort in any of their experiences with IE7 or with other customers.

I surmised that there was likely a setting in Internet Explorer 7 that was affecting the performance. But IE7 has no shortage of settings, and to try each one was not a task that I wanted to undertake. I fired up IE7, loaded the web-based app, and started working. Then, while the CPU was taxed, I went to Process Explorer, hit the properties of the iexplore.exe process, and checked the "Threads" tab. There were 89 threads, most having a start address of "ndtll.dll!RtlpWorkerThread", and all vying for CPU time. It appeared that a new thread was created for each request that was made, which seems rather "wasteful". At any rate, RtlpWorkerThread is a private "run-time library" worker thread threadproc function, presumably the threadproc used when one uses the Thread Pool API. The stack of one of these threads at the point that I captured it (obtained with Process Explorer and properly configured debugging symbols) is rather deep:

ntkrnlpa.exe!KiSwapContext+0x2e
ntkrnlpa.exe!KiSwapThread+0x46
ntkrnlpa.exe!KeWaitForMultipleObjects+0x284
ntkrnlpa.exe!NtWaitForMultipleObjects+0x2a2
ntkrnlpa.exe!KiFastCallEntry+0xf8
ntdll.dll!KiFastSystemCallRet
ntdll.dll!ZwWaitForMultipleObjects+0xc
kernel32.dll!WaitForMultipleObjectsEx+0x12c
ole32.dll!CoWaitForMultipleHandles+0x100
ieapfltr.dll!AntiPhishingMutex::AntiPhishingMutex+0x91
ieapfltr.dll!AntiPhishingHashTable::Find+0xaf
ieapfltr.dll!CacheManager::FindUrlInUrsCache+0xa5
ieapfltr.dll!AntiPhishDataSeeker::MatchRollUps+0x2cf
ieapfltr.dll!AntiPhishDataSeeker::MatchRollUpsInCache+0x43
ieapfltr.dll!AntiPhishDataSeeker::FindOMOTarget+0x2d
ieapfltr.dll!PageDetails::CountTargetRollups+0x34
ieapfltr.dll!PageDetails::Init+0x1da
ieapfltr.dll!PageDetails::Factory+0x59
ieapfltr.dll!HeuristicsFeatures::InnerExecute+0x15b
ieapfltr.dll!HeuristicsFeatures::Execute+0x55
ieapfltr.dll!ProcessingThread::RunPageAnalysis+0x1b4
ieapfltr.dll!ProcessingThread::RunUrlAndPageAnalysis+0xdb
ieapfltr.dll!ProcessingThread::Analyze+0xd3
ieapfltr.dll!ProcessingThread::AnalyzeFrame+0x249
ieapfltr.dll!ProcessingThread::EnumerateFrames+0x2e5
ieapfltr.dll!ProcessingThread::EnumerateFrames+0x249
ieapfltr.dll!ProcessingThread::Evaluate+0x1ec
ieapfltr.dll!ProcessingThread::Execute+0x78
ieapfltr.dll!ProcessingThread::Process+0x24e
ieapfltr.dll!ProcessingThread::Start+0x72
ieapfltr.dll!Evaluator::ContinueProcessing+0x21f
ieapfltr.dll!Evaluator::ContinueProcessingWrapper+0x21
ntdll.dll!RtlpWorkerCallout+0x70
ntdll.dll!RtlpExecuteWorkerRequest+0x1a
ntdll.dll!RtlpApcCallout+0x11
ntdll.dll!RtlpWorkerThread+0x87
kernel32.dll!BaseThreadStart+0x37


As you can see, after the thread pool plumbing is out of the way, the first function in the stack is ieapfltr.dll!Evaluator::ContinueProcessingWrapper - a function in ieapfltr.dll. ieapfltr.dll describes itself as "Microsoft Phishing Filter", though I suspect IEAP is an acronym for Internet Explorer Anti-Phishing. At any rate, it certainly seemed that the settings surrounding the (anti)phishing filter would be a good place to start.

I went into "Internet Options" in the Control Panel (Start Run inetcpl.cpl) and hit the "Advanced" tab. Toward the bottom was a setting for the Phishing Filter where there were three options:
-Disable Phishing Filter
-Turn off automatic website checking
-Turn on automatic website checking

Mine was set to "Turn off automatic website checking". I changed it to "Disable Phishing Filter" and hit OK, and re-tried the web application. The application was responsive as ever, and the "excess" threads that were previously being created were nowhere to be seen. Changing the setting back to "Turn off automatic website checking", and hitting the web application again caused iexplore.exe to consume as much of the CPU as it could. It appeared that I found the cause of the sluggish performance.

It is worth noting that in the "Internet Options", on the Security tab, each Internet Explorer Zone has its own setting for the Phishing Filter. If one selects a Zone, and clicks the "Custom level..." button, about 75% of the way down is a setting for "Use Phishing Filter" that has 2 options - Disable or Enable. The setting on the Advanced tab overrides this - if the Security zone setting is set to "Enable" and the Advanced setting is set to "Disable Phishing Filter", the Phishing Filter is disabled for all zones. However, if the Advanced setting is set to "Turn off automatic website checking" or "Turn on automatic website checking", one can exercise more granular control over each Security zone by choosing to enable / disable the filter where it makes sense.

»

2006-12-14

Driver Framework Resources

Finally got through watching some good overview videos on MSDN's Channel 9.

Doron Holan talks about the Kernel Mode Driver Framework (KMDF) in this Channel 9 Video Segment. Check out the state machine diagrams!

Peter Wieland goes over the User Mode Driver Framework (UMDF) in this video segment. There's even some discussion about writing a driver with managed code (C# / VB.NET).

»

2006-12-09

How DOES this warrant a KB article?

In How does this warrant a KB article?, I pondered the existence of a Microsoft KnowledgeBase article that discussed how to set the SmtpMail.SmtpServer property of the System.Web.SmtpMail class.

In my travels, I encountered a blog posting in the "The CDOs and CDONTS of Messaging Development" blog - MYTH: SmtpMail.SmtpServer.Insert(0,"127.0.0.1") Actually Does Something. This posting is interesting because it's possible that it prompted the aforementioned KB article (922777: You receive an error message when you try to send an e-mail message by using the System.Web.Mail namespace in the .NET Framework 1.0). It's also interesting because it talks about the source of the infamous code - a Code Project article.

»

2006-12-06

Brief Frustration With Global.asax

It was maddening, I tell you. I like to write C# code in a C# source file, not inline in a script tag. So I went about modifying Global.asax to allow me to do so:

<%@ Application language="C#" CodeBehind="Global.asax.cs" Inherits="Global" %>

I then went about defining a class called "Global" in Global.asax.cs. I added the code I needed and proceeded to build the ASP.NET app in Visual Studio 2005. But I got an error:

Global.asax(1): Build (web): Could not load type 'Global'.

Of course, I was perplexed. Why not? Why couldn't the type be loaded?
I thought for a bit, but then went about doing some more coding. Eventually, I had to address the problem, though. How? On a whim I placed Global.asax.cs in the App_Code ASP.NET folder. Once I did that, I was able to build the app.

»

2006-11-30

Microsoft / Sysinternals Process Monitor

Microsoft / Sysinternals recently released a new tool named "Process Monitor" (that Mark Russinovich has talked about for over a year). Process Monitor blows FileMon and RegMon (great tools in their own rite) out of the water with a well thought out filtering mechanism and NON DESTRUCTIVE filters! Filtering data no longer destroys the original! Now, since all events are captured, the amount of disk space required to store the events can grow quickly - it's easy to get a few GB of data in a short amount of time - but the data can be captured and stored for later analysis. There are plenty of other features in Process Monitor including the ability to get the FULL stack (userland and kernel!) of a thread at the time of an event, the ability to organize and persist filter sets, highlighting, and more. Thanks Mark & Bryce / Microsoft!

Note that Process Monitor does require a "modern" operating system - Windows XP SP2 or later, Windows Server 2003 SP1, Windows 2000 SP4 with Update Rollup 1, Vista, and x64 versions of XP, Server 2003 SP1, and Vista. Some people have issues with this, but the requirements are not arbitrary. Bryce explains a bit here.

»

2006-11-26

Microsoft Vista and Application Compatibility

There's an article entitled "Inside the New Microsoft Application Compatibility Toolkit" on TechNet that (surprise!) discusses some things about compatibility of applications running on Vista. It provides a good overview of some of the changes that can affect compatibility and some of the progress that has been made with Vista. For example, Windows Resource Protection redirects / sandboxes file and registry accesses to resources that the app wouldn't generally have permissions to when run under a standard account. The changes aren't persisted across invocations of the application, but nonetheless it could enable apps to work under a standard account when they previously were "admin or bust".

The article also discusses how to go about analyzing the applications running on one's computers and assessing the compatibility impact. There is a central database of applications called the "Microsoft Compatibility Exchange" which contains information provided by other community members about the compatibility "levels" of various applications. I like the idea of leveraging community experiences for the benefit of all.

The "Application Compatibility Toolkit" has other capabilities that are touched on in the article and are described in more detail in the documentation that accompanies the toolkit and at the Windows Application Compatibility website.

»

2006-11-22

Physician, Heal Thyself

I was working on a system that was suspected of being infested with malware. Sadly, it was clean - the flakiness was caused by all of the security utilities and software that had been installed on the system. But that's a rant for a different day. In the process of dealing with the system, an application crashed. I don't recall specifically what it was, but whilst gathering information about the crash, Dr. Watson had some problems himself. The good doctor just couldn't cope, apparently.

I cracked open Process Explorer and looked at the process hierarchy. It seemed a bit odd to have Dr. Watson spawn Dr. Watson (drwtsn32.exe was the parent of drwtsn32.exe).

I love the standard wording: "DrWatson Postmortem Debugger has encountered a problem and needs to close. We are sorry for the inconvenience."

I think in this case I chose to send the error report to Microsoft. =8->

»

2006-11-12

Key Containers and Visual Studio 2005: What's Microsoft Trying To Say?

As noted in Signing Assemblies in Visual Studio 2005 with Key Containers, Visual Studio 2005 doesn't exactly deal well with key containers (there's no way to use the UI to specify one, as one can do with key files).

And when I was exploring Web Deployment Projects, I was reviewing "Managing ASP.NET Precompiled Output for Deployment Using the aspnet_merge.exe Command" (aspnet_merge.exe is used by Web Deployment Projects to combine the assemblies produced by aspnet_compiler.exe). That article states that "...you can use the following options with aspnet_merge.exe: -keyfile, -keyContainer, or -delaysign...". I'm a strong advocate of signing assemblies. While there may not be a strong (ha, ha) case for doing it in this instance, it at least provides some level of assurance that the code deployed is truly the code that is supposed to be running. And I prefer key containers to key files. So given the way that specifying a key container works in Visual Studio 2005, I was excited to see that aspnet_merge.exe supported key containers.

Then I checked out the Web Deployment Project property pages. The Signing tab had a place to specify a key file location, but no way to specify a key container.



Argh! Here we go again, I thought. So I went about the process of trying to tear up the .WDPROJ file that is the Visual Studio 2005 project file for Web Deployment Projects. I tried the same technique that worked for .CSPROJ files, but that didn't work. I checked Microsoft.WebDeployment.targets in %programfiles%\MSBuild\Microsoft\WebDeployment\v8.0 to see if there was some way to specify a key container there. I couldn't find anything for key containers, but there were certainly ways to specify a key file and that the merged assembly should be delay signed. Dead end there.

Next I cracked open Reflector and inspected Microsoft.WebDeployment.Tasks.dll (also from %programfiles%\MSBuild\Microsoft\WebDeployment\v8.0). In that assembly, there is a class named "AspNetMerge" that implements the merge task as instructed by MSBuild. (The class inherits from Microsoft.Build.Utilities.ToolTask.) The "AspNetMerge" class has the following private fields (as reported by Reflector):


private string _applicationPath;
private string _assemblyInfo;
private string _contentAssemblyName;
private bool _copyAttributes;
private bool _debug;
private bool _delaySign;
private bool _errorStack;
private string _exePath;
private string _keyFile;
private string _logErrorFile;
private bool _mergeXmlDocs;
private bool _nologo;
private string _prefix;
private bool _removeCompiledFiles;
private string _singleAssemblyName

Sigh. A setting for a key container name is nowhere to be found. If the tool doesn't support key containers, no amount of creative configuration will get it there.

The next thing I did, in retrospect, was probably the first thing I should have done:
aspnet_merge -?
In short, aspnet_merge only supports the following parameters:
  • -?
  • applicationPath
  • -keyfile
  • -delaysign
  • -o
  • -w
  • -prefix
  • -copyattrs
  • -debug
  • -nologo
  • -errorstack
  • -r
  • -xmldocs
  • -a
  • -log

Aspnet_merge.exe does NOT support the -keycontainer option, as the "Managing ASP.NET Precompiled Output for Deployment Using the aspnet_merge.exe Command" article had stated.

So, given that there's no way to use a Web Deployment Project / aspnet_merge.exe to use a key container to sign an assembly, and one needs to edit the raw .CSPROJ file to get VS2005 to use a key container to sign an assembly, it seems that Microsoft is trying to say something about key containers.

I wouldn't be surprised to see key containers completely dropped in Orcas...

2006-11-06

Deploying ASP.NET 2.0 Applications

I was recently exploring deployment options for ASP.NET applications and I encountered a couple of Visual Studio 2005 add-ons - Visual Studio 2005 Web Deployment Projects and Visual Studio 2005 Web Application Projects. I could go into some detail about each of these post-Visual Studio 2005 release features, but Rick Strahl's got it covered with an extensive article entitled Compilation and Deployment in ASP.NET 2.0.

Visual Studio 2005 Web Application Projects bring ASP.NET 1.x style deployment capabilities (website compiles to an assembly at build time for later deployment with the display-side components compiled when accessed at runtime). Visual Studio 2005 Web Deployment Projects allow one to manage web application build configuration and deployment options, and provide a tool to merge multiple assemblies into one. This allows one to, if desired and configured, deploy a web application rolled up into one assembly and a number of "marker" files. Display-side components can even be compiled into the assembly. Note that other assemblies that the web application depends on - such as assemblies from the Enterprise Library - and other resource files such as images also need to be deployed. One could potentially use ILMerge (here and here) to merge all required assemblies into one, if that was important.

I really like the idea of minimizing the number of files that need to be deployed to a web server so I hope to work with Web Deployment Projects and Web Application Projects more in the future.

2006-11-01

Determining System Uptime, and A Bit More

I'm probably being way too picky here.

A new Community Solutions article in the Microsoft Knowledge Base entitled How to find Windows uptime? has been posted. The article is short (four steps and a summary for Option 1), but from my perspective this short article has a couple of errors, and / or at least could be a bit clearer.

While I know what is meant by uptime (how long the computer has been "up" or running), someone looking for this information may not know that's what to call it or what it might mean, so in the event they are able to find the article they may gloss over it because they don't recognize the term. Perhaps a brief description of what is meant by "uptime" in the context of this article would be appropriate.

Further, the steps detailed in the article (basically, instructions on how to run a command - net statistics server - and then parse the output) don't provide one with the information the article indicates will be provided. Granted, this is likely an academic detail, but the command really displays the amount of time that the Server service has been running - not the amount of time that the computer has been up. It is possible (but admittedly not all that likely) that the Server service has been restarted since the computer was booted.

As an alternative, I might suggest using Process Explorer. (Boy, it seems that I've been pushing PE a lot lately. Oh well. It's a great tool.) One can get a pretty good figure on the system uptime by examining the start time of the Session Manager process - smss.exe. Smss.exe is the first user-mode process created when the system boots. It is created by Ntoskrnl.exe and is a purely native application - it doesn't use Windows APIs. Instead, it uses what is known as the Windows Native API. An overview of the Native API can be found on the Sysinternals site at Inside the Native API. Gary Nebbett also wrote the book on the Native API - Windows NT/2000 Native API Reference.