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

160

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

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

Tony_Henrich
источник

Ответы:

253

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

Эрик Вуллингс
источник
3
эй, про совет! но это не доступно на старых дрянных машинах XP. :)
Джалал
5
@Jalal для "старых дрянных машин" зайдите на www.SysInternals.com и загрузите Process Explorer. Я подозреваю, что изменения в TaskManager для Win7, а затем Win8 были просто скопированы с него.
Ариох '21
1
Как этого добиться в приложении, работающем на компьютере клиента?
user3285954 10.09.15
2
Что делать, если я не могу запустить приложение, потому что оно удалит файл журнала, который мне крайне необходим?
Томаш Зато - Восстановить Монику
2
@Tony_Henrich Вы должны пометить это как правильный ответ
sparkyShorts
120

путь указывает на подпапку в папке c: \ Documents & 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
RobinDotNet
источник
1
Я все это понимаю. Я хочу папку, откуда я нажал на приложение. У меня нет доступа к C: \ Documents and Settings, поэтому у меня не будет доступа к файлу журнала, если я собираюсь использовать путь к папке, возвращенный этой функцией, и я не хочу использовать жестко закодированные значения пути ,
Tony_Henrich
25

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

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


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

Simon_Weaver
источник
Я ничего не делал, но файлы из старого DataDirectory автоматически копируются в новый DataDirectory после развертывания. Также нет каталогов .pre. (.NET Framework 3.5 и 4.5)
Der_Meister
15

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

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

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

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

Вышеперечисленное работает и на серверах, и на десктопах.

РЕДАКТИРОВАТЬ: Assembly.GetExecutingAssembly()вызывается в основном исполняемом файле.

user3285954
источник
Это работает для меня в приложении ClickOnce, а также в среде VS dev при отладке того же приложения.
Developer63
3

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

NebuSoft
источник
У меня нет доступа к папке C: \ Documents & Settings на сервере, что означает, что у меня нет доступа к файлу, который создает приложение. Я запускаю приложение из определенной папки. Это папка, в которой опубликовано приложение. Как мне получить путь к этой папке?
Tony_Henrich
О, вы хотите URL развертывания. Извини, я этого совсем не понял. Вы пытаетесь получить его из приложения ClickOnce или из внешнего приложения?
RobinDotNet
1

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

  • Приложение clickonce развернуто в сетевой папке компании.
  • Приложение clickonce должно быть доступно онлайн или офлайн.
  • Мои URL-адреса установки clickonce и 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();
    }
}
Кент Крукеберг
источник
0

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

BoiseBaked
источник