Archive for December, 2007

ClickOnce limitations

Posted in Microsoft.NET on December 17, 2007 by vasudevan

The advantages of ClickOnce are good but it has its own limitations. I had a scenario in my company where I need to uninstall a SmartClient application programatically in a silent way and there is no easy way of doing it. I researched on the problem and even peeped into the API calls inside dfshim.dll by doing this:

dumpbin /exports /out:c:\dfshim.txt c:\windows\system32\dfshim.dll and the output is shown below:
Dump of file c:\windows\system32\dfshim.dll

File Type: DLL

Section contains the following exports for dfshim.dll

00000000 characteristics
4333AC7B time date stamp Fri Sep 23 00:19:23 2005
0.00 version
1 ordinal base
17 number of functions
17 number of names

ordinal hint RVA      name

8    0 00002C45 CleanOnlineAppCache
9    1 00004245 CreateActContext
10    2 00004225 CreateCMSFromXml
11    3 00002A09 DllCanUnloadNow
12    4 000028FD DllGetClassObject
13    5 0000425A GetCurrentActContext
14    6 00002BD0 GetDeploymentDataFromManifest
15    7 000041EB GetUserStateManager
16    8 000041CE GetUserStore
1    9 00002C36 KillService
17    A 00004208 ParseManifest
2    B 00002BAE ShArpMaintain
3    C 00002B8C ShArpMaintainW
4    D 00002B79 ShOpenVerbApplication
5    E 00002B66 ShOpenVerbApplicationW
6    F 00002B53 ShOpenVerbShortcut
7   10 00002B40 ShOpenVerbShortcutW

Summary

2000 .data
2000 .reloc
8000 .rsrc
B000 .text
There is no API call from dfshim.dll that can make the ClickOnce “Application Maintenance” dialog to be completely hidden. I really wanted the user to click on the OK button in the dialog to enable us to install a new version using Windows Installer instead of the crappy ClickOnce technology. There is no way to force the user to click on the OK button. So, what do we do?

I thought about it for a while and it occured to me that I can make good use of Win32 API to do some tricks to force the OK button to be clicked for the users. So, the steps outlined are:

1. Using ShellExecuteEx, run this: rundll32.exe dfshim.dll,ShArpMaintain <application_name>.application, Culture=neutral, PublicKeyToken=99a12388f7gh6f76, processorArchitecture=msil will show up this dialog: (I intentionally modified the name of the application and also changed the title name and erased some of the text inside the image).

2. Wait for the dialog to show (I’m not going to show the code for this as this is pretty simple). clickonce-uninstall-dialog-2.jpg

3. Call FindWindow by passing the ClickOnce “Application Maintenance” title name and pass the handle to SetForegroundWindow.

4. Call SetForegroundWindow to force the “Application Maintenance” dialog to get focus and stays visible to the user.

5. Use .NET’s SendKeys class to programatically click on the OK button in the “Application Maintenance” dialog:

SendKeys.Send(“+{TAB}”);   // + indicates SHIFT key which shifts the focus to the OK button as the focus defaults to Cancel button
SendKeys.Send(“{ENTER}”); // ENTER makes the OK button to fire which will do the uninstall for the users.

Had M$ provided us with a way to silently uninstall a ClickOnce app, then it would have been a piece of cake.

Advertisements