ClickOnce as your default Shell- by a click of a button!

I recently needed to write some application that will run as the sole application on a Windows machine. Searching around a bit using shell in the registry looked very promising. I also liked the idea of using the ClickOnce self update mechanism.. but ran into a problem...

When you launch your applciation of the website you published it to.. and your code uses the "ApplicationDeployment.IsNetworkDeployed" to check if it is running in a deployabale mode, it runs ok. When you click on the shortcut created in the menu it also runs fine.

Allot of people compalined that there just was not way to get a ClickOnce application to start up using the Autostart feature.. and the same thing happens when changing the default shell.

The outcome varies from XP/Vista and Win7 - From the applciation not starting at all or starting in "offline" mode- not letting you get all the wonderful  " ApplicationDeployment " methods.

In vista/7 ClickOnce always deploys its shortcut to

C:\Users\\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\[PUBLISHER NAME] \ [PRODUCT NAME] .appref-ms

The actual data is put into the .NET isolated storage for the user only. Launching the app directly will always launch it in offline mode.

Ok- Great so what?! Well for some reason using registry shell, process.start, autostart, launch in IE jsut does not start the freakin ClickOnce app!

Here is some VB.NET 3.5 Code that will solve this problem- FOREVER in a click of a button



Public Sub buttonClick()
 
If MessageBox.Show("WARNING! Chaning shell!.""Shell Install", MessageBoxButtons.OKCancel) = Windows.Forms.DialogResult.OK Then

 Dim appPath = Environment.GetFolderPath(Environment.SpecialFolder.Programs) & "\[PUBLISHERNAME]\"
 Dim appFile = "PersonenRegistrasie.appref-ms"
 
 
 If My.Computer.FileSystem.FileExists(appPath & appFile) Then
   MessageBox.Show("Found file will add it now...")
 Else
   MessageBox.Show("Could not find file please select the '[PRODUCT NAME]' file...")

   Dim ofd As OpenFileDialog = New OpenFileDialog
   ofd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Programs)
   ofd.Filter = "MS Application|*.appref-ms"
   If ofd.ShowDialog = Windows.Forms.DialogResult.OK Then
     appPath = ofd.FileName.Substring(0, ofd.FileName.LastIndexOf("\"))
     appFile = ofd.FileName.Substring(ofd.FileName.LastIndexOf("\"), ofd.FileName.Length)
   End If
End If
 
Dim mystring As String = "start /D""" & appPath & """  " & appFile
MessageBox.Show(mystring)
 
 
My.Computer.FileSystem.WriteAllText(appPath & "\shell.cmd", mystring, False, System.Text.Encoding.ASCII)
 
'Note this once needs administrator rights for the Current USER
My.Computer.Registry.SetValue("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\IniFileMapping\system.ini\boot""Shell""USR:Software\Microsoft\Windows NT\CurrentVersion\Winlogon")
 
'This will change the shell to your program for THIS LOGGED IN user- after re logon bye bye 
exploerer shell hello custom app!
'My.Computer.Registry.SetValue("HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Winlogon", "Shell", appPath & "\shell.cmd")
 
 
End Sub



So what is the trick here? Go old school! use a batch (CMD) file to start the appreff-ms and it will launch as if you clicked on the menu link your self- check for update and launch in online mode


The cmd file needs to look something like this- if you just want to put it in autostart.

start /D"C:\Users\[USER]\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\[PUBLISHER NAME]\"  [PRODUCT NAME].appref-ms



The .NET code higher will change the registry setting in the correct places- but run the code on the User that you want the default shell to change. log off and back in.. Its just your app!

Most windows hot short cuts will be un handled, and disabling taksmanger and other things needs to be done in the group policy.. and done on you own risk

Talk about ClickOnce Shell Deployment 

Remember that doing this is completed out ot ClickOnce deoplyemnt specifications and you should use an Installer package to do this instead- implementing  your own update checker...
1