2010-03-01 208 views
129

我需要在控制台ClickOnce .application(可执行文件)所在的同一文件夹中编写一个文件。它从中启动的文件夹。如何获取ClickOnce应用程序的文件夹路径

我尝试使用Application.StartupPath & Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) 但路径c:\Documents & Settings下指向一个子文件夹。我如何获得.application所在的路径?

回答

3

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

+0

我无法访问服务器上的C:\ Documents&Settings文件夹,这意味着我无权访问应用程序创建的文件。我从某个文件夹运行应用程序。这是该应用发布的文件夹。我如何获得该文件夹的路径? – 2010-03-01 21:20:32

+0

哦,你想要部署网址。对不起,我一点都没有。您是否试图从ClickOnce应用程序或外部应用程序中获取它? – RobinDotNet 2010-03-10 09:52:12

107

路径在C指向一个子文件夹:\文件&设置

这是正确的。 ClickOnce applications安装在安装它们的用户的配置文件下。你是否已经从正在执行的程序集中获取信息的路径提供给你,然后去检查它?

在Windows Vista和Windows 7中,你会发现的ClickOnce缓存这里:

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

在Windows XP中,你会发现它在这里:

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

我明白这一切。我想从我点击应用程序的位置获取文件夹。我没有权限访问C:\ Documents and Settings,因此如果我要使用该函数返回的文件夹路径,并且我不想使用硬编码的路径值,那么我将无法访问日志文件。 – 2010-03-09 20:10:00

23

ApplicationDeployment.CurrentDeployment.ActivationUri可能工作

“如果部署清单中的TrustUrlParameters属性为false,或者用户提供了UNC以打开部署或已打开部署,则为零长度字符串LLY。否则,返回值是用来启动应用程序的完整URL,包括任何参数。”


但我觉得你真正想要的是ApplicationDeployment.CurrentDeployment.DataDirectory,让你可以将数据写入到一个文件夹,当你更新应用程序无论如何都会丢失原始.exe文件夹中的内容,但是您可以将数据目录迁移到新版本的应用程序中。您的应用程序可以使用它的任何日志文件向此文件夹写入数据 - 而且很确定它的保证是可写的。

+2

+1用于指出DataDirectory。感谢那 – 2012-11-07 21:01:20

+0

我什么都没做,但是在部署之后,旧DataDirectory中的文件会自动复制到新的DataDirectory中。还没有.pre目录。 (.NET Framework 3.5和4.5) – 2014-03-25 07:02:58

197

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

+2

嘿,亲提示!但它不适用于老旧的XP机器。 :) – Jalal 2012-12-16 07:27:36

+4

@Jalal for“老蹩脚的机器”去www.SysInternals.com并下载Process Explorer。我怀疑Win7的TaskManager中的变化,然后Win8只是从它复制。 – 2013-03-21 19:16:07

+1

如何在客户计算机上运行的应用程序中实现这一目标? – user3285954 2015-09-10 16:46:00

12

我正在使用Assembly.GetExecutingAssembly().Location获取在.Net 4.5.1中部署的应用程序的路径ClickOnce。但是,不管部署方法如何(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()在主可执行文件中调用。

+0

伟大的答案。谢谢 – stigzler 2015-11-09 13:42:17

+0

这一直在为我工作的ClickOnce应用程序,以及也在VS开发环境中工作,同时调试同一个应用程序。 – Developer63 2016-06-02 19:08:47

0

这里是我发现,工作了,能够让我的ClickOnce应用程序的部署文件夹位置并没有被提及任何地方我在搜索看到,我的同类,具体情况:

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

这里是一个可视化我的使用情况:

enter image description here

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

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

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

解决的办法是看:

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

System.Deployment.Application.ApplicationDeployment.CurrentDeployment.UpdateLocation正确地返回我的clickonce应用程序部署到的网络目录,在所有情况下。也就是说,当它通过推出:

  • SETUP.EXE
  • MyClickOnceGreatApp.application
  • 创建在第一次安装并启动应用程序的桌面快捷方式。

下面是我在应用程序启动时使用的代码,以获取WorkAccounts文件夹的路径。获取部署的应用程序文件夹是只是没有踏着高达父目录简单:

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(); 
    } 
} 
1

经过一番详尽的搜索,我终于找到了一种方法找到通过注册表混淆的文件夹名称。以下是一个简单的方法:

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 = 
      [email protected]"{appToken.Substring(0, 8)}.{appToken.Substring(8, 3)}\{appToken.Substring(11, 8)}.{appToken.Substring(19, 3)}"; 

    var dataDir = 
      [email protected]"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)); 
} 
相关问题