Как получить путь к папке для приложения ClickOnce

Мне нужно написать файл в той же папке, где находится консоль ClickOnce .application (исполняемый файл). Папка, из которой она запускается.

Я попытался использовать Application.StartupPath и Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) но путь указывается на подпапку под c:\Documents & Settings. Как получить путь, в котором находится .application?

Ответ 1

Чтобы найти местоположение папки, вы можете просто запустить приложение, открыть диспетчер задач (CTRL-SHIFT-ESC), выбрать приложение и щелкнуть правой кнопкой мыши | Открыть расположение файла.

Ответ 2

путь указывает на подпапку в папке c:\Documents and Settings

Это правильно. 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

Ответ 3

ApplicationDeployment.CurrentDeployment.ActivationUri может работать

"Строка с нулевой длиной, если свойство TrustUrlParameters в манифесте развертывания является ложным или если пользователь предоставил UNC для открытия развертывания или открыл его локально. В противном случае возвращаемое значение будет полным URL-адресом, используемым для запуска приложение, включая любые параметры."


НО, что я думаю, что вы действительно хотите, ApplicationDeployment.CurrentDeployment.DataDirectory, который дает вам папку, в которую вы можете записать данные. Когда вы все время обновляете приложение, вы потеряете то, что было в исходной папке .exe, но вы можете перенести каталог данных в новую версию приложения. Ваше приложение может писать в эту папку с любыми файлами журналов, которые у вас есть, - и я уверен, что он гарантированно доступен для записи.

Ответ 4

Я использую Assembly.GetExecutingAssembly().Location, чтобы получить путь к развертываемому приложению ClickOnce в .Net 4.5.1.

Однако вы не должны писать в любую папку, где ваше приложение будет развернуто, независимо от способа развертывания (xcopy, ClickOnce, InstallShield, что-либо), поскольку они обычно читаются только для приложений, особенно в новых версиях Windows и сервере сред.

Приложение должно всегда записывать в папки, зарезервированные для таких целей. Вы можете получить нужные папки, начиная с Environment.SpecialFolder Enumeration. На странице MSDN объясняется, для каждой папки: http://msdn.microsoft.com/en-us/library/system.environment.specialfolder.aspx

т.е. для данных, журналов и других файлов можно использовать ApplicationData (роуминг), LocalApplicationData (локальный) или CommonApplicationData. Для временных файлов используйте Path.GetTempPath или Path.GetTempFileName.

Вышеописанная работа над серверами и рабочими столами.

EDIT: Assembly.GetExecutingAssembly() вызывается в основном исполняемом файле.

Ответ 5

Приложения ClickOnce находятся в подкаталоге C:\Documents and Settings. У них нет "чистых" каталогов установки, потому что локальные файлы по существу "временно" загружаются, чтобы приложение могло запускаться на локальном ПК, а выполнение приложения контролируется с сервера ClickOnce, который они развернут, в зависимости от настроек публикации (Проверка обновлений, требований к версии и т.д.).

Ответ 6

После некоторого исчерпывающего поиска, я наконец нашел способ найти обфускацию имен папок через реестр. Вот простой способ их извлечения:

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

Ответ 7

Вот что я нашел, что работал на то, чтобы получить локализованное расположение папки моего приложения clickonce и которое не упоминалось нигде, которое я видел в моих поисках, для моего сходного, конкретного сценария:

  • Приложение clickonce развертывается в сетевой сетевой папке компании.
  • Приложение clickonce настроено на доступ к сети онлайн или офлайн.
  • Мой URL-адрес установки URL-адреса кликов и URL-адреса обновлений в моих свойствах проекта не имеют ничего определенного. То есть, нет отдельного места для установки или обновления.
  • В моих вариантах публикации у меня есть ярлык на рабочем столе, созданный для приложения clickonce.
  • Папка, в которой я хочу получить путь при запуске, - это тот, к которому я хочу получить доступ к версиям приложения DEV, INT и PROD, без жесткого кодирования пути.

Вот пример моего использования:

введите описание изображения здесь

  • Пакеты с синим коробочным ящиком - это места моего каталога для каждого окружающей среды.
  • Красная папка в папке - это каталог, в который я хочу получить путь для (для чего требуется сначала получить местоположение развернутой папки приложения "MyClickOnceGreatApp_1_0_0_37", который совпадает с OP).

Я не нашел ни одного из предложений в этом вопросе или их комментариях для работы в возвращении папки, в которую было развернуто приложение clickonce (чтобы я мог перемещаться относительно этой папки, чтобы найти интересующую папку). Никакой другой поиск в Интернете или связанные с ним вопросы не вызывали ответа.

Все предлагаемые свойства либо не выполнялись из-за того, что объект (например, ActivationUri) был нулевым, либо указывали на локальную папку с установленным приложением для ПК. Да, я мог бы изящно обрабатывать нулевые объекты с помощью проверки на 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();
    }
}

Ответ 8

Если предположить, что вопрос заключается в доступе к файлам в папке приложения после того, как приложение 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