如何获取ClickOnce应用程序的文件夹path

我需要在控制台的ClickOnce.application(可执行文件)所在的文件夹中写入一个文件。 它从哪个文件夹启动。

我尝试使用Application.StartupPathPath.GetDirectoryName(Assembly.GetExecutingAssembly().Location)但path指向c:\Documents & Settings下的子文件夹。 如何获取.application所在的path?

要find文件夹位置,您可以运行应用程序,打开任务pipe理器(CTRL-SHIFT-ESC),select应用程序并右键单击|打开文件位置。

path指向c:\ Documents&Settings下的子文件夹

那就对了。 ClickOnce applications安装在安装它们的用户的configuration文件下。 你有没有采取从执行大会的信息检索给你的path,去检查出来?

在Windows Vista和Windows 7上,您将在这里findClickOncecaching:

 c:\users\username\AppData\Local\Apps\2.0\obfuscatedfoldername\obfuscatedfoldername 

在Windows XP上,您可以在这里find它:

 C:\Documents and Settings\username\LocalSettings\Apps\2.0\obfuscatedfoldername\obfuscatedfoldername 

ApplicationDeployment.CurrentDeployment.ActivationUri可能工作

“如果部署清单中的TrustUrlParameters属性为false,或者用户提供了UNC以打开部署或已在本地打开它,则为零长度的string;否则,返回值是用于启动应用程序的完整URL,包括任何参数。“


但我认为你真正想要的是ApplicationDeployment.CurrentDeployment.DataDirectory它给你一个文件夹,你可以写入数据。 当您更新应用程序时,您将丢失原始.exe文件夹中的内容,但可以将数据目录迁移到新版本的应用程序。 你的应用程序可以写任何日志文件到这个文件夹 – 我敢肯定它的保证是可写的。

我正在使用Assembly.GetExecutingAssembly().Location来获取在.Net 4.5.1中部署ClickOnce应用程序的path。

但是,无论部署方法如何(xcopy,ClickOnce,InstallShield,任何东西),都不应写入任何将应用程序部署到的文件夹,因为通常这些文件只能读取应用程序,特别是在较新的Windows版本和服务器环境中。

应用程序必须始终写入为此目的保留的文件夹。 您可以从Environment.SpecialFolder Enumeration开始获取所需的文件夹。 MSDN页面说明每个文件夹的用途: http : //msdn.microsoft.com/en-us/library/system.environment.specialfolder.aspx

即对于数据,日志和其他文件可以使用ApplicationData (漫游), LocalApplicationData (本地)或CommonApplicationData 。 对于临时文件,请使用Path.GetTempPathPath.GetTempFileName

以上在服务器和桌面上的工作也是如此。

编辑: Assembly.GetExecutingAssembly()在主可执行文件中调用。

ClickOnce应用程序驻留在C:\ Documents&Settings的子目录中。 它们没有“干净的”安装目录,因为本地文件实质上是“临时”下载,以允许应用程序在本地PC上运行,并且应用程序的执行由部署它们的ClickOnce服务器控制,具体取决于发布设置(检查更新,版本要求等)。

以下是我发现能够获取我的clickonce应用程序的已部署文件夹位置的工作,并且在我的search中看到的任何地方都没有提及,这是我的类似的特定情况:

  • clickonce应用程序部署到公司LANnetworking文件夹。
  • clickonce应用程序设置为可在线或离线使用。
  • 我的项目属性中的clickonce安装URL和更新URL没有任何指定。 也就是说,没有单独的安装或更新位置。
  • 在我的发布选项中,我为clickonce应用程序创build了一个桌面快捷方式。
  • 我想要在启动时获取path的文件夹是我希望由应用程序的DEV,INT和PROD版本访问的文件夹,而不用硬编码path。

这是我的使用案例的视觉效果:

在这里输入图像说明

  • 蓝色方框文件夹是我的目录位置为每个环境的应用程序。
  • 红色方块文件夹是我想要获取path的目录(这需要先获取与OP相同的应用程序的已部署文件夹位置“MyClickOnceGreatApp_1_0_0_37”)。

我没有在这个问题中find任何build议或他们的意见,以返回clickonce应用程序部署到的文件夹(然后我将相对于此文件夹移动以find感兴趣的文件夹)。 没有其他的互联网search或相关的SO问题也出现了答案。

所有build议的属性或者由于对象(例如ActivationUri)为空或者指向本地PC的caching安装的应用程序文件夹而失败。 是的,我可以通过检查IsNetworkDeployed来优雅地处理空对象 – 这不是一个问题 – 但令人惊讶的是,即使我实际上有clickonce应用程序的networking部署文件夹位置IsNetworkDeployed返回false。 这是因为应用程序是从本地高速caching位运行的。

解决办法是看看:

  • AppDomain.CurrentDomain.BaseDirectory当应用程序正在我的开发和Visual Studio中运行
  • System.Deployment.Application.ApplicationDeployment.CurrentDeployment.UpdateLocation当它正常执行。

在所有情况下, System.Deployment.Application.ApplicationDeployment.CurrentDeployment.UpdateLocation正确返回我的clickonce应用程序部署到的networking目录。 也就是说,通过以下方式启动时:

  • SETUP.EXE
  • MyClickOnceGreatApp.application
  • 首次安装并启动应用程序时创build的桌面快捷方式。

这是我在应用程序启动时使用的代码,以获取WorkAccounts文件夹的path。 获取部署的应用程序文件夹很简单,只是不进入父目录:

 string directoryOfInterest = ""; if (System.Diagnostics.Debugger.IsAttached) { directoryOfInterest = Directory.GetParent(Directory.GetParent(Directory.GetParent(AppDomain.CurrentDomain.BaseDirectory).FullName).FullName).FullName; } else { try { string path = System.Deployment.Application.ApplicationDeployment.CurrentDeployment.UpdateLocation.ToString(); path = path.Replace("file:", ""); path = path.Replace("/", "\\"); directoryOfInterest = Directory.GetParent(Directory.GetParent(path).FullName).FullName; } catch (Exception ex) { directoryOfInterest = "Error getting update directory needed for relative base for finding WorkAccounts directory.\n" + ex.Message + "\n\nUpdate location directory is: " + System.Deployment.Application.ApplicationDeployment.CurrentDeployment.UpdateLocation.ToString(); } } 

经过一番彻底的search,我终于find了一种方法来通过registryfind混淆的文件夹名称。 这里有一个简单的方法来获取它们:

 private static Tuple<string, string> GetClickonceDirectories() { var appToken = (string) Registry.GetValue(@"HKEY_CURRENT_USER\SOFTWARE\Classes\Software\Microsoft\Windows\CurrentVersion\Deployment\SideBySide\2.0", "ComponentStore_RandomString", null); var dataToken = (string) Registry.GetValue(@"HKEY_CURRENT_USER\SOFTWARE\Classes\Software\Microsoft\Windows\CurrentVersion\Deployment\SideBySide\2.0\StateManager", "StateStore_RandomString", null); if (string.IsNullOrWhiteSpace(appToken) || string.IsNullOrWhiteSpace(dataToken)) { throw new Exception("Unable to find clickonce directories."); } var appDir = $@"{appToken.Substring(0, 8)}.{appToken.Substring(8, 3)}\{appToken.Substring(11, 8)}.{appToken.Substring(19, 3)}"; var dataDir = $@"Data\{dataToken.Substring(0, 8)}.{dataToken.Substring(8, 3)}\{dataToken.Substring(11, 8)}.{dataToken.Substring(19, 3)}"; var rootPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); rootPath = Path.Combine(rootPath, "Apps", "2.0"); return new Tuple<string, string>(Path.Combine(rootPath, appDir), Path.Combine(rootPath, dataDir)); }