问题
How can I make a Click-once deployed app run a startup?
The best option I found by searching was to set the Publisher on the app to Startup, so the Start menu shortcut would be placed in the Startup folder, but that seems like a huge hack and I would like there to be a Start menu icon people can find.
What options do I have?
回答1:
I feel that adding your application to the startup folder is unprofessional. I strongly recommend using a startup registry key to launch your application.
Contrary to what a lot of the material on this topic says, it is extremely simple to setup a key to launch a click once application and does not require setting up additional shortcuts. You simply use the shortcut created on install:
// The path to the key where Windows looks for startup applications
RegistryKey rkApp = Registry.CurrentUser.OpenSubKey(
@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);
//Path to launch shortcut
string startPath = Environment.GetFolderPath(Environment.SpecialFolder.Programs)
+ @"\YourPublisher\YourSuite\YourProduct.appref-ms";
rkApp.SetValue("YourProduct", startPath);
回答2:
After reading all the comments on this thread and the johnnycoder blog post mentioned above, I came up with a solution that:
- Adds your ClickOnce app to the Startup folder
- Removes the Startup item automatically when the ClickOnce app is uninstalled (after a reboot or log out/log in)
- Was tested and works on Windows XP, Windows 7, Windows Server 2000/2003, Windows 8
My Solution
Basically, your app will be writing a .bat
file to the Startup folder that launches the ClickOnce app for you. The .bat
file is smart enough to detect if the app has been uninstalled and will delete itself if the ClickOnce app cannot be found.
Step 1
Get the batch file working. Replace PUBLISHER_NAME and APPLICATION_NAME with the right values. You can find them by installing your ClickOnce app, then following the path to it on your file system:
@echo off
IF EXIST "%appdata%\Microsoft\Windows\Start Menu\Programs\PUBLISHER_NAME\APPLICATION_NAME.appref-ms" (
"%appdata%\Microsoft\Windows\Start Menu\Programs\PUBLISHER_NAME\APPLICATION_NAME.appref-ms"
) ELSE (start /b "" cmd /c del "%~f0"&exit /b)
The batch file will check if your ClickOnce app is installed (by seeing if the appref-ms file exists) and launch it if so. Otherwise, the batch file deletes itself, via a method outlined here.
Now that you have the batch file, test it out. Drop it in your Startup folder to make sure it launches your app on login.
Step 2
Now, in the code for your app, you need to write this batch file to the Startup folder. Here is an example using the batch file above in C# (note that there is some escaping, and environment variable voodoo happening):
string[] mystrings = new string[] { @"@echo off
IF EXIST ""%appdata%\Microsoft\Windows\Start Menu\Programs\PUBLISHER_NAME\APPLICATION_NAME.appref-ms"" (
""%appdata%\Microsoft\Windows\Start Menu\Programs\PUBLISHER_NAME\APPLICATION_NAME.appref-ms""
) ELSE (start /b """" cmd /c del ""%~f0""&exit /b)"};
string fullPath = "%appdata%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\StartMyClickOnceApp.bat";
//Expands the %appdata% path and writes the file to the Startup folder
System.IO.File.WriteAllLines(Environment.ExpandEnvironmentVariables(fullPath), mystrings);
There you have it. Comments / improvements welcomed.
EDIT: Fixed quotes in step 2
回答3:
All these tricks dont work on Vista unfortunately. Vista blocks these programs on startup for some reason.
As suggested by @thijs, you can easily bypass vista's "security" on this one. See blogpost on how to run clickonce apps on windows startup.
回答4:
Well there're a number of ways to make your application launch on start up, but there's a clean up problem. Even if you use start up registry key and it looks fine, anyway you should clean all you added to thesystem. You can take a look on my article, I faced same clean up problem and used automation and cutom uninstall file to solve issue.
回答5:
Thanks DiscDev and dbenham. The solution works great. Just wanted to share the updated working code based on the latest by dbenham.
const string fullPathEnvVar =
"%appdata%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\StartMyClickOnceApp.bat";
//Expands the %appdata% path
string fullPath = Environment.ExpandEnvironmentVariables(fullPathEnvVar);
if (!File.Exists(fullPath))
{
string[] mystrings =
{
@"@echo off
if exist ""%appdata%\Microsoft\Windows\Start Menu\Programs\<PublisherName>\<ApplicationName>.appref-ms"" (
""%appdata%\Microsoft\Windows\Start Menu\Programs\<PublisherName>\<ApplicationName>.appref-ms""
) else (
(goto) 2>nul & del ""%~f0""
)"
};
//write the file to the Startup folder
File.WriteAllLines(fullPath, mystrings);
}
回答6:
First off thanks for the answer Discdev. To get this to work with Å Ä Ö and other special characters this modification did it for me, using UTF-8 a different code page and no BOM.
string[] mystrings = new string[] { "chcp 65001", @"IF EXIST ""%appdata%\Microsoft\Windows\Start Menu\Programs\<Publisher>\<App_Name>.appref-ms"" (""%appdata%\Microsoft\Windows\Start Menu\Programs\<Publisher>\<App_Name>.appref-ms"") ELSE (start /b """" cmd /c del ""%~f0""&exit /b)" };
string fullPath = "%appdata%\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\StartErrandDynamicMenu.bat";
System.Text.Encoding utf8WithoutBOM = new System.Text.UTF8Encoding(false);
System.IO.File.WriteAllLines(Environment.ExpandEnvironmentVariables(fullPath), mystrings, utf8WithoutBOM);
回答7:
In terms of actually getting the application to launch at startup, having a link in the startup folder is your best bet. Or if not the startup folder then the startup reg key.
A way to work around not having the Icon in it's normal position is to have the application place a link to itself into the startup folder on Application startup. ClickOnce apps will run the first time they are installed. The application can use this startup to place a link in the Startup folder. Now the link will be in both places and you should be golden.
There is the issue though that now deleting the ClickOnce app will no longer actually delete it. ClickOnce will not track the manual link added and hence every time someone un-installs your app and reboots it will re-install. I would start considering that program to not be behaving well :(.
回答8:
You could add your app to the appropriate "Run" startup registry key at startup. Then even though you can't remove it when your app is deleted, it won't hurt anything and nobody will see the broken reference.
回答9:
In case it helps anyone else still looking for a solution to this a comment way down the bottom http://johnnycoder.com/blog/2009/02/24/clickonce-run-at-startup/ suggests setting the ClickOnce Publish options (in VS.Net 2010 that's on the project properties, publish screen and options) with Publisher name set to Startup and Suite name left blank. That does get the program shortcut into the startup folder for me on Windows 7. I don't know what other versions of Windows do.
回答10:
For some reason, windows wouldn't start my app (the ".appref-ms" file) when logging in. So, I came up with a solution others might find helpful as well.
When my app is installed for the first time (and on start up of my app), I add/verify that my applications current location string.Concat(Application.ExecutablePath, " ", "/startup")
exists in the registry "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run"
. When the application then starts, I check the args for "/startup" and if that is present, execute the following code.
var startMenuFile = Path.Combine("Programs", Company, Product + ".appref-ms");
var startMenuFolder = Environment.GetFolderPath(Environment.SpecialFolder.StartMenu);
var fileName = Path.Combine(startMenuFolder, startMenuFile);
if (File.Exists(fileName))
{
Process.Start(fileName);
return;
}
// Log that for some reason, the application doesn't exist.
This worked great for me. But, if you just add the Application.ExecutablePath
value to the registry without the "/startup"
arguement, the application will start when windows starts but not in the context of a "click once" application. This will not allow you to have access to ApplicationDeployment.CurrentDeployment
. Although, this worked great, the problem still exists that when my application is uninstalled, the registry setting isn't removed. This can be fixed by using @Ivan Leonenko custom uninstall solution. Hope this helps...
回答11:
I make this and work for me
Sub AddToStartup()
If My.Application.IsNetworkDeployed Then
Dim str As String = My.Application.Deployment.UpdatedApplicationFullName.ToString
Dim saida As String = ""
For i As Integer = 0 To str.Split(",").Length
If Not saida.Contains("msil") Then
saida += str.Split(",")(i) & ", "
End If
Next
If saida.Contains("msil") Then
saida = saida.Substring(0, saida.Length - 2)
End If
Dim name As String = My.Application.Info.Title
Dim file As String = Path.Combine(My.Application.Info.DirectoryPath, name & ".appref-ms")
My.Computer.FileSystem.WriteAllText(file, saida, False)
Dim reg As RegistryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", True)
reg.SetValue(name, file)
End If
End Sub
来源:https://stackoverflow.com/questions/401816/how-can-i-make-a-click-once-deployed-app-run-at-startup