This is a question that has been coming up a lot lately, so I figured I would answer the question once here, so I can just start handing out the link when it gets asked again in the future. Here is the essence of the question:
“I am trying to create a process as another user, using CreateProcessWithLogonW. Even if I launch it from an elevated process, it spawns a Medium IL process. If I mark it as requireAdministrator, it returns ERROR_ELEVATION_REQUIRED. What gives?”
First, let’s explain why you always get a filtered token. When you are launching an application using this API, somewhere behind the scenes you are logging on that user. With UAC enabled, if you are a member of the local Administrators group, that’s going to result in generating two different user tokens: your full administrator’s token, and a filtered administrators token. So, you’ll end up with both logon sessions (and tokens) generated, but then we’ll use the filtered one until you explicitly elevate.
OK, so far so good. The logon event itself causes me to generate both logons and use the less powerful one by default. (Assuming it’s an interactive login, that is.) I get that, so now I’m going to manifest my application to get around that and use the more powerful one, and I bounce into failure again (and failure sucks). Why is that happening? ERROR_ELEVATION_REQUIRED? I mean, come on – I know that, that’s why I’m trying to elevate!
Well, there’s a good explanation for that one too. This is based on the layering work we’re doing in Windows. Rather than letting any Windows binary depend on any other Windows binary, we invest huge efforts in maintaining the architectural purity of layering in Windows. Binaries that are at a low layer just can’t depend on binaries in a higher layer.
Larry describes the layering process here: http://blogs.msdn.com/larryosterman/archive/2005/08/23/455193.aspx.
What’s the layering problem? Well, CreateProcess is really low in the layers. What can you do without the ability to create a process? Not a whole lot. Elevation, however, is a different story. It requires a trip to the app elevation service. This then calls into consent.exe, which has to know how to read group policy and, if necessary, switch to the secure desktop and pop open a window and ask the user for permission / credentials, etc. We don’t even need to take all of these features, let’s just take the dialog box. What can you do on a system with processes but not a CreateWindow function? Why, be server core, of course!
Now, for creating a process that requires elevation, normally you just switch up APIs. The shell sits in a much higher layer, and consequently is able to take a dependency on elevation. So, you’d just swap out your call to CreateProcess with a call to ShellExecute. So far, so good. But wait … if you do a web search on ShellExecuteWithLogon, you return 0 hits. That’s right, there is no API for this!
So, how can you work around this? You need a bootstrapper. Some process which will let you do the transition to the alternate user, which could be responsible for running the requireAdministrator application. So, you could design something like this:
We did something very similar to this for Sysinternals’ ShellRunAs, only instead of writing a bootstrapper, Jon used cmd.exe to bounce through to the target executable (which is a technique you could use as well, though Mark had to do a bit of work to try to keep this hidden wherever possible).
(Why did we use cmd.exe? Because there’s a lot of logic built into this already, such as handling different file types and targets, which would have been challenging to get as correct as this already extensively tested application.)
Why don’t we just create the ShellExecuteWithLogonW API? I’ll never say never, and we might at some point. But today, the use cases for this APIs have been use cases where there has been an alternate design which is superior. The most common request is for people writing home-grown software deployment software, where they’d like to encode credentials right into the app and elevate their own process. The real problem here is not the lack of the API, it’s that you have admin credentials encoded in your app for the world to read. If you have that, what you want is a way to get to a place where you do not have that as quickly as possible, not make it easier to build on that design. I’ve also seen scenarios where moving the code in question to a service was the better design. (Adding new APIs is a big deal, so we tend to look for whitespace with no workarounds if we’re going to do that.)
There are a number of terms thrown around in the world of app compat that are vaguely defined at best. Now, I’m not one to suggest that tedium is a good practice in general, but in some cases understanding the true technical definition of a term can lead to significant time savings when that definition is applied to a project.
Compatible is the most important one. What does it mean to call an application Compatible with Windows 7? (Some people refer to this as Windows 7 Compliant also.) I have found some significant variation in peoples’ understanding of this, and the wrong understanding can lead to you chasing unachievable goals.
At the most abstract, that means that it works with the target operating system. So, today you may know it is compatible with Windows XP, and you are questioning if it is compatible with Windows 7 as well. But all you’ve done here is shift the ambiguity from the word “compatible” to the word “works”, and then you think about defining what “works” means – interpreted by some, this could mean that it doesn’t have any bugs on that platform. But think about that for a second – do you really want to wait until an application has no bugs on a platform? Because, if so, you’ll be waiting a really long time – all software has bugs. So that clearly doesn’t work.
Some peoples’ perception is that there are a series of criteria to follow, and once you follow those, it’s “compatible” (and, therefore, bug free). Things like the Application Compatibility Cookbook, with its enumerated list, bolster that perception. But compatibility is not as simple as filling out a checklist. There are all kinds of things that could go wrong along the way that won’t wind up on a checklist. I have debugged an app that ended up in a race condition because of the assumption that a particular shell function would be executed on the same thread, and it no longer was (you won’t find that in the cookbook). Heck, even Solitaire had a really bizarre bug which was based entirely on computer speed (we didn’t used to have a timer on the “card cascade” if you won the game – we rendered those little cards just as fast as we could, which these days is pretty insanely fast, some would even say instantaneous). Those don’t show up on the list – and in fact there are a near infinite number of ways that an app can end up having a problem on your new target hardware and software platform.
So, my small, manageable checklist is helpful but incomplete, an infinitely long checklist is clearly no better, and bug free isn’t my goal – what are the standards that I usually apply as a matter of practical execution? I normally layer things into 3 groups:
Compatible with Windows 7: The application has no bugs which stop you from getting your work done. It may have bugs, but they don’t affect your business. In the end, this is all that matters to you! Note, however, that this also means that the only person who can verify this is you! An app may let somebody else get their work done (and, thus, to them is compatible) but the critical functionality you need might be the bit with the bug in it. The only way to tell is to try getting your work done using the application. (Incidentally, this is one of the shortcomings of static analysis – it finds bugs everywhere, and not just in the bits of the code that you use – but we’ll talk more about that in another post.) You should only invest time and money fixing the bugs that stop you from getting your work done.
Supported with Windows 7: The application is supported by the vendor on your platform. That’s fantastic, because it means that if there are any bugs which stop you from getting work done, the vendor promises to fix them. But a promise to fix them is not the equivalent of being compatible (using the definition given above) for, since all software has bugs it’s completely possible that some of those bugs will be in a place that is a problem for you. Yes, you have a path for getting them fixed, but your business is still disrupted, and that costs you money! So, I tend to view support as a great indicator (since the vendor wants to minimize their risk of high support costs), but I don’t take it as fully equivalent to my Compatible with Windows 7 definition when doing my risk / benefit computations. But, for many apps, this is a requirement right beside my compatibility requirement, depending on business criticality.
Logo Certified for Windows 7: The application is not only supported, but the vendor has passed a set of tests that ensure a high level of quality for the application. When I see a logo, I tend to see a vendor who really stands behind the product. Logo certified apps tend to crash less frequently (since logo certification necessitates tests which detect and require you to fix many causes of application crashes), and have higher quality across the bar. It’s certainly not exclusively true (you can build an extremely high quality app, and just not want to bother getting the certificate required to sign up for the partner program – the only cost you have for Windows 7), but it’s a good indicator. But logo certification tests do not prove an application bug free, so again, it’s not the functional equivalent of verifying compatibility for you, but it’s another good indicator of whether or not to fast-track an application.
It’s been a long road to get here, but the checklist is now complete. Vendor data for Windows 7 application compatibility, previously available on the web and as a downloadable Excel sheet, is finally integrated into ACT 5.5!
Here is some information on this data, courtesy of the team:
How many applications do we have data for?
We have data for around 7,000 applications. What is interesting is that there is more work than just 7,000 – each application may map to more than one app ID, and in fact we have data for around 38,000 distinct AppIDs. (Incidentally, if you don’t see data for an application in ACT but it’s on the web, this could be caused by repackaging, by interim releases we are unaware of, or a number of other things. AppIDs are very literal and require perfect fidelity input to deliver comprehensive output.)
How frequently will this data be updated?
Initially, ever 2 weeks, so make sure you sync ever so often to see the latest data. As the vendor input tapers off, we may reduce this in the future.
Will the data have complete parity with the compatibility center?
It’s the same back end, but since we use different AppIDs we have to use heuristics to match between the different AppID schemes. Heuristics, by definition, can be imperfect. Add to this the potential issues above (repackaging, lesser known versions) and this would explain any delta in the data. We’re constantly reviewing our heuristics and improving them, plus we have long term plans to consolidate on a single AppID scheme.
Will I see compatibility status for 64-bit applications?
Today, it’s just 32-bit status, as that is what ACT 5.5 supports. ACT 6.0 will support 64-bit Windows and include 64-bit compatibility status. It should be released later this year.
Congratulations to the team for achieving this long-awaited milestone! I know I have already synced up my database.
A couple of weeks ago, I had a chance to sit in on a webinar delivered by Flexera Software and chat about Windows 7 Application Compatibility. The recording of the webinar is now online and available here:
http://mktg.flexerasoftware.com/mk/get/BPWin7CompatApp_wbnr?mc=eml-flw
A few weeks ago, I spoke about how our information on vendor data was slowly making it through the channel, beginning with the compatibility center (complete), moving on to the downloadable Application Compatibility List for IT Pros (complete), and finally getting to ACT. I suggested, “The target date for this integration is mid-December 2009.” To call December 22 “mid-December” is already stretching it, and yet it’s still not showing up in ACT. What gives?
Well, let’s talk a little bit about the data and how it has to move through the system. In the end, it all comes from the same database. The compat center, the downloadable list, the data that feeds the upgrade advisor – all from the same source. What is taking so long to turn on the spigot for ACT?
Well, the big challenge is data transformation. First, the App ID has to be translated. The 3 live services all use a new algorithm for determining an application ID. ACT hopes to transition to use this new algorithm in the next version, but it’s one of those “running in place” changes where, after spending a lot of time and money, the end result looks identical to the user, so it’s difficult to justify rushing the transition (particularly since invalidating an existing inventory full of old App IDs is a terrible idea, so the application will need to support both old and new, and be able to differentiate between them). That translation needs to be automated so it can run in perpetuity, and that process has to be build. Then, the web service that feeds ACT is the old version (v1) while the others are using a much newer version (v4), so the old web service interface has to be modified to leverage the new database feeding it. So, there are two feats of engineering that need to be implemented, tested, and proven at scale.
We’re still hoping to have this done the first week of January, but vacations and winter colds are making this more challenging. Rest assured, this data is coming and we are terrible sorry for any inconvenience the delay is causing – we really do want the data to be accessible and convenient and are not neglecting the value this has to customers.
Earlier today, I received this request from a customer:
This (http://www.microsoft.com/downloads/details.aspx?FamilyID=07fb0bd8-f390-458d-a629-6f0258ac7cdf) is a .NET 1.1 app and I have installed .NET 1.1 SP1 on Windows 7 32-bit and all .NET 1.1 SP1 security patches but it doesn't run. Gives me this error: An internal error has occurred: Object reference not set to an instance of an object" and then it quits.
Always being up for a challenge, I decided to have a look and see what wasn’t working. Reproducing the error is pretty straightforward. Just run the app – it’ll gladly crash for you. But the question is, why? And can you fix it?
If you hit this with a debugger, you’ll find the following stack when you hit an AV:
0:000> !dumpstack -ee
Current frame: (MethodDesc 0x2098d28 +0x1c SystemTimeZone.ConvertToTimeZoneInfoStructure)
ChildEBP RetAddr Caller,Callee
0018f4f4 0206d4ab (MethodDesc 0x2098d08 +0x43 SystemTimeZone.ToLocalTime)
0018f55c 0206cfc0 (MethodDesc 0x2098cd8 +0x38 SystemTimeZone.Convert)
0018f574 0206a484 (MethodDesc 0x2e5680 +0x15c frmMain.ShowCurrentTimes_Click)
0018f5d8 02067686 (MethodDesc 0x2e56d0 +0x446 frmMain.frmMain_Load)
0018f61c 02060365 (MethodDesc 0x2e5620 +0x2ed frmMain.Main)
Now, you could take a stab at this with SOS and start pulling out objects, but I didn’t believe that this would be the easiest way to solve the problem. Instead, I decided to reverse engineer the code and have a look. If you take a peek at the structure you’re trying to create from the SystemTimeZone class, you’ll find where the instance of the time zone came from – the code was rampaging through the registry looking for it. Here’s the method in question:
public TimeZoneList()
{
m_TZHash = new Hashtable();
m_TZList = new ArrayList();
RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\");
string[] subKeyNames = key.GetSubKeyNames();
Type t = typeof(TZIStructure);
int num2 = Marshal.SizeOf(t);
int num3 = subKeyNames.Length - 1;
for (int i = 0; i <= num3; i++)
{
RegistryKey key2 = key.OpenSubKey(subKeyNames[i]);
SystemTimeZone zone = new SystemTimeZone();
SystemTimeZone zone2 = zone;
zone2.DaylightName = StringType.FromObject(key2.GetValue("Dlt"));
zone2.DisplayName = StringType.FromObject(key2.GetValue("Display"));
zone2.Index = IntegerType.FromObject(key2.GetValue("Index"));
zone2.MapId = StringType.FromObject(key2.GetValue("MapID"));
zone2.StandardName = StringType.FromObject(key2.GetValue("Std"));
zone2.Name = key2.Name.Substring(key2.Name.LastIndexOf(@"\") + 1);
zone2 = null;
byte[] buffer = (byte[]) key2.GetValue("TZI");
key2.Close();
if ((buffer != null) && (buffer.Length >= num2))
{
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
IntPtr ptr = handle.AddrOfPinnedObject();
zone.TZI = (TZIStructure) Marshal.PtrToStructure(ptr, t);
handle.Free();
if (!m_TZHash.Contains(zone.Index))
{
m_TZHash.Add(zone.Index, zone);
m_TZList.Add(zone);
}
}
}
key.Close();
}
If you spend enough time with the !do command, you can eventually stumble upon the answer, but the easier approach is, again, to stay out of the debugger and leverage your favorite search engine. Here’s a KB article that points out the problem:
http://support.microsoft.com/kb/935369
Relevant information: “The Index registry value does not exist in Windows Vista and in Windows Server 2008.”
Aha. See the source code above? It wants that value, and it’s not there. Root cause found.
Now, on to solutions.
First of all, I wonder if you need a solution at all. If you click on the clock, and then click on Change date and time settings… you will get to the Date and Time control panel. Click on the Additional Clocks tab, and you can add 2 additional clocks for 2 new time zones. If you need more, you can always use Gadgets to fill the rest of your needs. So, for most people, this should provide a built-in solution to the problem – you don’t need the app any more because the OS provides 2 solutions already.
But, if you really really love that particular app, you could always copy that piece of the registry from Windows XP onto your Windows 7 computer, drop it in a new place inside of the registry, and then use the VirtualRegistry shim to redirect that app’s checks of the timezone portion of the registry to the copy you brought over.
Special thanks to my friend Gov for pointing me to the KB article, and for coming up with the VirtualRegistry workaround idea.
Are your business-critical applications compatible with Windows 7? Join Microsoft's "App Compat Guy" Chris Jackson to learn best practices for how IT teams are resolving Windows 7 application compatibility issues. Hear about his experiences with early Windows 7 adopters, including the most common application compatibility issues and their root causes. Tips in this webinar will help your IT team minimize risk and make a smoother move to Windows 7.
Webinar Details
Thursday, December 17
12pm EST (9am PST, 5pm GMT)
One curious observation I have made while doing app compat work over the past few years: The ownership of the project is assigned to the packaging team more so than any other team. Perhaps that’s because it’s the only centralized group dealing with every application, or perhaps it’s because installation failures on the new OS are the first things you notice – the rationale varies. But regardless, the team responsible for packaging definitely is an extremely interested party, if not the outright owner of the project.
As a result, when I sat down for dinner with several execs from Flexera Software (makers of InstallShield and AdminStudio, among other things), they expressed this as an area of great concern for their customers. So, in between our discussion of which tapas was the tastiest (I assure you, there was some extremely tasty tapas), we were brainstorming how we can better work together to help people who are interested in packaging be more successful when an app compat project comes along.
One idea? Let’s work on a webinar together. Flexera has a pretty successful webinar series, so let’s just partner up on one of those. So, on Thursday, December 17, 2009 at 11:00 am Central, we’ll be doing that. It will be relatively quick and will be presented at an overview level, so if you’re looking for a debugging deep dive this probably isn’t your best bet, but one thing it will emphatically not be is marketing speak. If this perspective is useful to you, come and join us. Feel free to ask the hardest, nastiest questions you can think of!
http://mktg.flexerasoftware.com/mk/get/BPWin7CompatApp_wbnr
In the world of app compat, sometimes you get lucky and have the app itself clearly not working, and you debug it. (Well, I guess if you’re really going to get lucky, you’ll have the app just work.) Things get murkier when an app has a bad interaction with another app, but not stand-alone (in which case you could miss the interaction until you’ve deployed to end users, since labs generally start with a clean slate). This is where the finger pointing begins – the great “blame game” where each support organization points their finger at the other one.
And, of course, the most fun is when you have an app compat problem where it makes it look like the operating system just plain doesn’t work. When you see a message like, “The network path was not found” or “File or network path no longer exists”, do you think app compat problem? No, you think you were sold a busted up old operating system. Sometimes you’re right. (We have bugs too.) Sometimes it’s your network. And, yes, sometimes it’s an app compat problem.
Such is the case for a number of support incidents we’ve seen recently with Windows Server. We debug each one, and what we found was a deadlock in srtsp.sys / srtsp64.sys. I’ve seen deadlocks all over the place – they’re one of those equal-opportunity-style bugs, because multi-threaded programming is insanely hard to do perfectly. It just so happened that these deadlocks would rather unluckily take place on the kernel mode threads servicing SMB negotiation requests.
The vendor, of course, wants happy customers, so they released a patch. If you are running older versions of Symantec Endpoint Protection 11 and Symantec Antivirus 10.2 you should get the solution from Symantec. Symantec confirms that this is a known issue and there are updates to resolve the problem. This is one of those insanely useful patches to get (as opposed to patches that fix problems that you may never see in your lifetime). See: http://service1.symantec.com/SUPPORT/ent-security.nsf/docid/2007102613484948
My friend Robert put together a post on this over in the Windows Server Division Weblog.
I’m kind of disappointed that there isn’t a disturbing amount of debugger information in the post, given who wrote it (though you’ll see there is enough to communicate the message). Robert is the kind of guy where it only takes a few minutes of watching him work to realize just how profoundly dumb you are. I had one app I was debugging once, and I was just plain stuck. (It happens.) So, I asked him for his thoughts. He dumped hex to the screen, pointed to a bit of it, said, “there’s the problem, try this fix.” And he was right. (Of course, I later realized that I was just as bad when I told my friend Gov a joke in hex, and he got it.)
(Wow, I’m doing a lot more posting today than normal. Things kind of piled up while I was on leave.)
There is a ton of activity going on in the world regarding Windows 7 deployments, and one of the hottest topics we’re finding is x64. People are very interested in moving to the 64-bit version of the operating system, but one obvious question is, will my applications be broken?
The next version of the Application Compatibility Toolkit, ACT 6.0, is scheduled to have far more robust x64 support. (It’s scheduled to support it at all, which is already a bonus.) But what about in the interim?
First of all, there is the Setup Analysis Tool. This will detect 16-bit binaries (probably a problem for 64-bit Windows, unless setup is detecting the bitness of the OS and dropping file appropriately) and driver installation (possibly a problem for 64-bit Windows, unless setup is detecting the bitness of the OS and dropping files appropriately). But this requires a fair amount of work to get configured and running, and it also means that you have to have the setup files. Depending on how managed your environment is, that may be a problem.
If you’re the sort that doesn’t mind undocumented secrets, I’ll let you in on one: ACT already collects the bitness of the files it finds in an inventory scan, it just doesn’t surface that in the UI today. So, how can you view this information? Why, hack the database of course. My SQL skills are so rusty these days I’m beyond embarrassed of what I crufted together, but here is a query I hacked up to display all of the files that are neither 32-bit (user mode 32-bit is probably OK) nor 64-bit (definitely OK) in your ACT database:
USE ACT55
GO
SELECT DISTINCT Applications.appName, Static_App_Properties.fileName, fileModuleType
FROM Static_App_Properties
INNER JOIN Application_Instance_Files
ON Static_App_Properties.identity_hash = Application_Instance_Files.filePropertyID
INNER JOIN Applications
ON Application_Instance_Files.appID = Applications.identity_hash
WHERE fileModuleType<>'32BIT' AND fileModuleType<>'64BIT' AND propertyType='File'
ORDER BY appName
GO
The schema is, as always, undocumented and subject to change, but I have found this helpful in a few scenarios to quickly zero in on apps to specifically test on 64-bit when targeting a mixed environment. I suspect you’ll have to do less hacking with ACT 6.0.
This one has been on my to-do list for a while, so it’s far from breaking news. I use these posts as a resource to gauge how we’re doing with our presentation content. Typically these posts don’t generate a lot of feedback, but it is always welcome.
At TechReady 9, I presented the following sessions:
CLI323
The MCS Application Compatibility Strategy Engagement: Predicting the Unpredictable
CLI313
Application Compatibility Remediation: The Dark Magic of Fixing Broken Applications
CLICT300-R1
Application Compatibility - Tools discussion (Part One – AppDNA and ACT)
CLICT300-R2
Application Compatibility - Tools discussion (Part Two – ACT and ChangeBase)
CLI207
What EVERYONE should know about Application Compatibility (with Aaron Margosis)
CLI401
Not for the Faint of Heart: Hard Core App Compat Debugging (with Gov Maharaj)
SOLNCT202
How to Navigate the Microsoft Services Application Compatibility Offerings and Deploy Windows 7 at Your Customers
The rating criteria were:
Q1 - The speaker was knowledgeable about the subject matter.
Q2 - The speaker's presentation skills helped me better understand the material.
Q3 - The content was effective in achieving the stated learning objectives.
Q4 - The demonstration(s) were effective.
Q5 - This session builds skills improving how I sell, market, and/or provide services to our customers and partners.
Q6 - The knowledge/skills I gained are relevant to my role.
Q7 - This readiness solution was worth the investment of my time.
Q8 - I will recommend this readiness solution to others.
Q9 - Overall, I was satisfied with this Session/Chalk Talk.
Q10 - Content Level: Please rank the level of technical information actually delivered.
Q11 - Please provide additional constructive comments, suggestions, feedback.
QAvg - Average for all questions combined
Here are the rankings. I kind of vacillate between displaying rankings as raw numbers or as raw percentages. In this case, I have enough of a distribution that the raw numbers can be misleading, so I’m using percentages:
| | CLI207 | CLI313 | CLI323 | CLI401 | CLICT300-R1 | CLICT300-R2 | SOLNCT202 |
| Q1 | 24% | 10% | 9% | 27% | 14% | 23% | 28% |
| Q2 | 35% | 18% | 8% | 26% | 17% | 26% | 26% |
| Q3 | 35% | 13% | 8% | 19% | 22% | 29% | 25% |
| Q4 | 30% | 8% | 19% | 31% | 20% | 39% | 26% |
| Q5 | 36% | 14% | 5% | 26% | 17% | 30% | 22% |
| Q6 | 34% | 11% | 9% | 37% | 15% | 23% | 10% |
| Q7 | 36% | 13% | 9% | 27% | 16% | 26% | 24% |
| Q8 | 39% | 13% | 9% | 29% | 17% | 29% | 36% |
| Q9 | 39% | 12% | 8% | 25% | 19% | 31% | 29% |
| Qavg | 33% | 10% | 6% | 24% | 19% | 25% | 24% |
Analysis
People are interested in both the technology and the business approach. My two top sessions? A technology session, and a strategy session that didn’t include a single demo (which is incredibly odd for me). This was one of my areas targeted for improvement, and it seems as if we’re finally getting that story put together.
Hard core debugging is still a polarizing session. This session still generates one of two pieces of feedback. Either someone thinks it’s the best thing ever, or they think it’s impossibly obtuse and not useful. There is nothing in between. I threw in a demo this time of “debugging without a debugger” which has traditionally been really powerful with the folks who actually do the work, but for a general audience, it fell flat. They wanted to see hex, apparently. :-)
Don’t be depressing. Our “what everyone wants to know” session was still in the top half, but boy, it isn’t at all what I like to see in my scores. We raced through topic after topic, painting a horribly depressing picture in an effort to be “real.” But it’s not this incredibly depressing thing – you actually can do it. We didn’t leave any hope, only despair. It turns out people don’t really like that much. Do-over.
Don’t leave your technical guys behind. I did a series of 2 sessions – one with AppDNA and the other with ChangeBase. AppDNA sent their CEO and their CTO. It’s lit up in green. ChangeBase’s technical director didn’t make it, leaving only their director of sales. They are awash in a sea of red and orange as a result. Technical audiences like hearing it straight form the geeks’ mouths.
We need to keep our remediation sessions current. I did a minor revision of this content for TechReady 9, and have a major overhaul in store for the 2010 conference season. It’s still getting consistently high scores, which tells me to keep it current and continue to include it.
今日は。Guten Tag. Bonjour. ¡Hola! 안녕하세요. 你好. Ciao. Здравствуйте. Olá.
I’ve been on leave for a while, so my apologies for being quiet lately. I’ve been sitting on this news for a while, though I think these links might come in handy if you are touching a global audience. We have localized the documentation for ACT into 10 different languages:
日本語 (Japanese)
Deutsch (German)
Français (French)
Español (Spanish)
한국어 (Korean)
汉语 (Chinese - Mainland)
汉语 - 台灣 (Chinese – Taiwan)
Italiano (Italian)
русский язык (Russian)
Português (Portuguese – Brazil)
If there is one thing I have noticed in my travels, it’s that language is a hard barrier to cross. This is a small but important step. As group after group stretches their brains to understand my English (or my horrible Japanese), we’re taking a few more steps to meet in the middle. I’ve also been doing some work to build more labs – things with fewer words that let the products and experiences do the teaching so they are shorter and less expensive to translate, but still deliver the core knowledge. Because, no matter where you are in this little world of ours, we’re all in this together.
It’s finally here!
We released the Windows 7 Compatibility Center a few weeks ago. This lets you look up one application at a time. You can find that at http://windows.com/compatibility.
Today, we have a downloadable list indicating vendor support. If you want to write some automated matching against your list of application, you can use this – it is an Excel download of all known information from vendors. You can find that at http://www.microsoft.com/downloads/details.aspx?FamilyID=890e522e-e39e-4278-aebc-186f81e29173&displaylang=en.
The final step will be to have this information integrated directly into ACT. The target date for this integration is mid-December 2009. We’re getting there! We’re also planning to keep this data updated bi-weekly.
Enjoy!
We shipped ACT 5.5 back in April 2009, several months before we shipped Windows 7. Helpfully (I guess) we decided to label it Windows 7 RC in the UI so you could specifically track your testing against the release candidate. We had the idea that we could update this via our web service, so that once we hit RTM we could just push out an update to modify this.
And apparently we forgot to turn this little bit of code on.
So, now we have a bunch of folks around the world who wonder why ACT seems to be in a beta phase and not ready for Windows 7 RTM.
Well, it is ready for Windows 7 RTM, and I bet some of you would like it to look ready. We’re really sorry we can’t do that using the mechanisms we planned to use, so I figured I’d let you in on the secret to the planned update.
We were going to update 2 fields in the database.
So, if you want your ACT UI to look ready for the future present, you can run this bit of SQL:
UPDATE dbo.OS
SET osName='Windows 7'
WHERE osName='Windows 7 RC'
GO
UPDATE dbo.OS
SET osName='Windows Server 2008 R2'
WHERE osName='Windows Server 2008 R2 RC'
GO
Enjoy, and sorry for the inconvenience.
Today, I just might ruffle a few feathers by doing so, but I figured I’d go through and demonstrate the process of reversing some incompletely documented stuff in Windows in order to fix a problem that was causing me some personal pain.
Specifically, I’m going to talk about sound schemes in Windows 7. With Windows Vista, we had only 1 sound scheme (unless you bought Ultimate, in which case the additional sound schemes were provided as Ultimate Extras). With Windows 7, you get multiple sound schemes.
And for a while, I was terrified of using any of them other than the one I had originally selected.
You see, every time I would change the sound scheme, I would lose sounds in a number of my other programs. Pretty much anything that wasn’t Windows. I like my computer making little beeps and boops all the time (seriously – I still add in the Office 97 sounds, because I like the audio feedback I get when deleting, moving copying – it feels bizarre not to have it after more than a decade of always hearing it).
When we released a whole bunch of new themes for Windows 7 on the day we reached General Availability, I had reached the last straw. The themes all changed my sound scheme, and I don’t want to lose the sound from my other programs thank you very much. So, I set out to figure out how to fix that.
Here’s a blog post that described how to set up the sounds:
A Peek Behind the Beep
Put sounds in .current, eh? Well, time to go spelunking. For the sounds that do switch around, I notice more in the registry than just .Current. I notice that each event not only has a .current subkey, it also has a subkey with the name of each of the sound schemes. So, it seems likely that everyone who adds a new set of application sounds would only affect the current sound scheme, and as soon as you changed it, those settings would go away!
A quick check with process monitor would confirm that:
8:08:59.2736148 PM rundll32.exe 4796 RegOpenKey HKCU\AppEvents\Schemes\Apps\Communicator\COMMUNICATOR_appinvite\Delta SUCCESS Desired Access: Maximum Allowed, Granted Access: All Access
8:08:59.2736558 PM rundll32.exe 4796 RegQueryValue HKCU\AppEvents\Schemes\Apps\Communicator\COMMUNICATOR_appinvite\Delta\(Default) BUFFER OVERFLOW Length: 144
8:08:59.2737043 PM rundll32.exe 4796 RegQueryValue HKCU\AppEvents\Schemes\Apps\Communicator\COMMUNICATOR_appinvite\Delta\(Default) SUCCESS Type: REG_SZ, Length: 172, Data: C:\Program Files (x86)\Microsoft Office Communicator\Media\COMMUNICATOR_appinvite.wav
8:08:59.2741839 PM rundll32.exe 4796 RegCloseKey HKCU\AppEvents\Schemes\Apps\Communicator\COMMUNICATOR_appinvite\Delta SUCCESS
8:09:00.4227580 PM rundll32.exe 4796 RegOpenKey HKCU\AppEvents\Schemes\Apps\Communicator\COMMUNICATOR_appinvite SUCCESS Desired Access: Maximum Allowed, Granted Access: All Access
8:09:00.4227946 PM rundll32.exe 4796 RegQueryKey HKCU\AppEvents\Schemes\Apps\Communicator\COMMUNICATOR_appinvite SUCCESS Query: HandleTags, HandleTags: 0x0
8:09:00.4228254 PM rundll32.exe 4796 RegCreateKey HKCU\AppEvents\Schemes\Apps\Communicator\COMMUNICATOR_appinvite\Delta SUCCESS Desired Access: Set Value
8:09:00.4228632 PM rundll32.exe 4796 RegSetValue HKCU\AppEvents\Schemes\Apps\Communicator\COMMUNICATOR_appinvite\Delta\(Default) SUCCESS Type: REG_SZ, Length: 172, Data: C:\Program Files (x86)\Microsoft Office Communicator\Media\COMMUNICATOR_appinvite.wav
8:09:00.4229075 PM rundll32.exe 4796 RegCloseKey HKCU\AppEvents\Schemes\Apps\Communicator\COMMUNICATOR_appinvite\Delta SUCCESS
8:09:00.4229383 PM rundll32.exe 4796 RegQueryKey HKCU\AppEvents\Schemes\Apps\Communicator\COMMUNICATOR_appinvite SUCCESS Query: HandleTags, HandleTags: 0x0
8:09:00.4229707 PM rundll32.exe 4796 RegCreateKey HKCU\AppEvents\Schemes\Apps\Communicator\COMMUNICATOR_appinvite\.current SUCCESS Desired Access: Set Value
8:09:00.4230081 PM rundll32.exe 4796 RegSetValue HKCU\AppEvents\Schemes\Apps\Communicator\COMMUNICATOR_appinvite\.Current\(Default) SUCCESS Type: REG_SZ, Length: 172, Data: C:\Program Files (x86)\Microsoft Office Communicator\Media\COMMUNICATOR_appinvite.wav
8:09:00.4230401 PM rundll32.exe 4796 RegCloseKey HKCU\AppEvents\Schemes\Apps\Communicator\COMMUNICATOR_appinvite\.Current SUCCESS
Yes, indeed – when you change the sound scheme, you copy the values over from the subkey with the new scheme name into the .current key. And none of the program sounds from external programs contained subkeys for each (or any) of the schemes!
So, I’m thinking I’ve reversed the secret to carrying my program sounds over from scheme to scheme – could it be that simple? Only one way to find out – populate them! But, if there were so few that I could do so easily by hand, then I wouldn’t be reversing this stuff in the first place. So, it looks like it’s time for a PowerShell Script! Here’s what I wrote:
foreach ($app in Get-ChildItem -Path "HKCU:\AppEvents\Schemes\Apps")
{
if (($app.PSChildName -ne ".Default") -and ($app.PSChildName -ne "Explorer") -and ($app.PSChildName -ne "sapisvr"))
{
foreach ($events in Get-ChildItem -Path $app.PSPath)
{
$event = $events.PSPath
foreach ($soundSchemes in Get-ChildItem -Path "HKCU:\AppEvents\Schemes\Names")
{
$soundScheme = $soundSchemes.PSChildName
if (($soundScheme -ne ".Default") -and ($soundScheme -ne ".None"))
{
$defaultPath = $event + "\.current"
$newPath = $event + "\" + $soundScheme
if (Test-Path $newPath)
{
Remove-Item -Path $newPath
}
Copy-Item -Path $defaultPath -Destination $newPath
}
}
}
}
}
I ran this script, and tried changing my sound scheme. Sure enough, it worked! I was able to swap out my sound schemes, and the other applications which extend the sound scheme mechanism in Windows still generate the sounds which makes their use so much more satisfying! (Or, in the case of Communicator, it’s downright critical to the way I use the application.) Hooray!
Now, this is kind of a klugy workaround, which depends on my reversing and guessing correctly on a couple of things. What could we do differently? Well, ideally the application developer would have enumerated the schemes, which is something they wouldn’t have had to do with Windows Vista (except in the case of Ultimate Extras), and added their sound events to each of the schemes. But, it’s a little bit late for that now – these apps already exist. The sound schemes already exit, and there is no API we can intercept – the apps are just writing to the registry. So, if we wanted to do something about this within Windows, we’d have to do something proactive to mitigate the issue with other programs in response to a sound scheme change event. That’s getting a little bit harder to argue for in a service pack, but you never know. It’s worth a try at least.
For now, you can use my workaround, and carry your sounds around with you from scheme to scheme. Happy dinging!