我该如何让Click-once部署的应用在启动时自动运行?
通过搜索,我找到的最佳选项是将应用程序的发布者设置为“启动”,这样开始菜单快捷方式就会放置在启动文件夹中,但这似乎是一个巨大的破解,我希望有一个可以让人们找到的开始菜单图标。
我有哪些选择?
我认为将应用程序添加到启动文件夹是不专业的。我强烈建议使用启动注册表键来启动您的应用程序。
与许多有关此主题的资料相反,设置一个键以启动单击一次应用程序非常简单,并且不需要设置其他快捷方式。您只需使用安装时创建的快捷方式即可:
// 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);
阅读了本主题中的所有评论和上述提到的johnnycoder博客文章后,我想出了以下解决方案:
我的解决方案
基本上,您的应用程序将会向启动文件夹写入一个.bat
文件,以便为您启动ClickOnce应用程序。这个.bat
文件足够聪明,可以检测应用程序是否已被卸载,并且如果找不到ClickOnce应用程序,它会自行删除。
第一步
让批处理文件正常工作。用正确的值替换PUBLISHER_NAME和APPLICATION_NAME。您可以通过安装ClickOnce应用程序,然后按照其在文件系统上的路径找到它们:
@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)
批处理文件将检查您的ClickOnce应用程序是否已安装(通过查看是否存在appref-ms文件),如果已安装,则启动它。否则,批处理文件将通过这里概述的方法删除自身。
现在您有了批处理文件,请测试一下。将其放入启动文件夹中,以确保在登录时启动您的应用程序。
第二步
现在,在您的应用程序代码中,您需要将此批处理文件编写到启动文件夹中。以下是在C#中使用上面的批处理文件的示例(请注意,其中涉及一些转义和环境变量):
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);
以上就是全部内容。欢迎评论或提出改善意见。
编辑:修正了第2步中的引号。
很不幸,所有这些技巧都不能在Vista上使用。由于某种原因,Vista会在启动时阻止这些程序。
如@thijs所建议的那样,您可以轻松绕过vista的“安全”设置。请参阅有关如何在Windows启动时运行clickonce应用程序的博客文章。
首先感谢Discdev的回答。为了让这个工作与Å Ä Ö和其他特殊字符一起工作,我进行了修改,使用UTF-8不同的代码页和没有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);
感谢DiscDev和dbenham。这个解决方案非常好用。我想分享最新的、基于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);
}
有多种方法可以使您的应用程序在启动时启动,但存在清理问题。即使您使用了启动注册表键并且看起来很好,无论如何,您都应该清除系统中添加的所有内容。 您可以查看我的文章,我遇到了同样的清理问题,并使用自动化和自定义卸载文件解决了这个问题。
就实际启动应用程序而言,在启动文件夹中放置链接是最好的选择。如果不是在启动文件夹中,则可以使用启动注册表键。
解决图标未处于正常位置的方法是,让应用程序在启动时将自己的链接放置到启动文件夹中。ClickOnce 应用程序将在首次安装时运行。应用程序可以利用此启动来将链接放置在启动文件夹中。现在链接将出现在两个位置,您应该会很满意。
但问题在于,现在删除 ClickOnce 应用程序将不再真正删除它。ClickOnce 不会跟踪手动添加的链接,因此每次有人卸载您的应用程序并重新启动时,它都会重新安装。我会开始考虑该程序的行为是否良好 :(。
你可以将你的应用程序添加到适当的“运行”启动注册表键中。这样,即使在删除应用程序时无法删除它,也不会对任何东西造成伤害,也不会有人看到损坏的引用。
我做了这个,对我有用
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