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

时间:2010-03-01 20:57:58

标签: .net windows clickonce

我需要在控制台ClickOnce .application(可执行文件)所在的同一文件夹中编写一个文件。它发布的文件夹。

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

8 个答案:

答案 0 :(得分:232)

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

答案 1 :(得分:117)

  

路径指向c:\ Documents&下的子文件夹设置

没错。 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

答案 2 :(得分:24)

ApplicationDeployment.CurrentDeployment.ActivationUri可能会有效

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


但我认为你真正想要的是ApplicationDeployment.CurrentDeployment.DataDirectory,它为你提供了一个可以写入数据的文件夹。无论如何,当您更新应用程序时,您将丢失原始.exe文件夹中的内容,但您可以将数据目录迁移到该应用程序的新版本。您的应用程序可以使用它具有的任何日志文件写入此文件夹 - 我很确定它可以保证可写。

答案 3 :(得分:13)

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

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

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

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

上述有关服务器和台式机的工作。

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

答案 4 :(得分:3)

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

答案 5 :(得分:3)

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

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

答案 6 :(得分:1)

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

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

以下是我的用例的视觉效果:

enter image description here

  • 蓝色盒装文件夹是我的目录位置 环境的应用。
  • 红色盒装文件夹是我想要获取路径的目录 (这需要首先获取应用程序部署的文件夹位置 &#34; MyClickOnceGreatApp_1_0_0_37&#34;这与OP)相同。

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

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

解决方案是:

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

答案 7 :(得分:0)

假设问题是关于在用户PC上安装ClickOnce(true == System.Deployment.ApplicationDeploy.IsNetworkDeployed)应用程序之后访问应用程序文件夹中的文件的,它们是通过应用程序本身获取此文件夹的三种方法:

String path1 = System.AppDomain.CurrentDomain.BaseDirectory;
String path2 = System.IO.Directory.GetCurrentDirectory();    
String path3 = System.Reflection.Assembly.GetExecutingAssembly().CodeBase; //Remove the last path component, the executing assembly itself.

这些工作是从VS IDE和已部署/已安装的ClickedOnce应用程序进行的,不需要进行“ true == System.Deployment.ApplicationDeploy.IsNetworkDeployed”检查。 ClickOnce会拾取Visual Studio 2017项目中包含的所有文件,因此实际上应用程序可以使用应用程序内部的相对路径访问任何和所有已部署的文件。

这基于Windows 10和Visual Studio 2017