Могу ли я контролировать расположение пользовательских настроек .NET, чтобы избежать потери настроек при обновлении приложений?

Я пытаюсь настроить расположение файла user.config. В настоящее время он хранится с хешем и номером версии

%AppData%\[CompanyName]\[ExeName]_Url_[some_hash]\[Version]\

Я хочу, чтобы это было агностически для версии приложения

%AppData%\[CompanyName]\[ProductName]\

Можно ли это сделать и как? Каковы последствия? Пользователь потеряет свои настройки из предыдущей версии после обновления?

Ответ 1

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

Что касается второго вопроса, это зависит от того, как вы развертываете приложение. Если вы развертываете через .msi, то в свойствах проекта установки (из которого построен msi) есть два хэша, "код обновления" и "код продукта". Они определяют, как можно установить msi, и если он обновляет, перезаписывает или устанавливает рядом с любой другой версией того же приложения.

Например, если у вас есть две версии вашего программного обеспечения, и у них разные коды обновления, то в окна они совершенно разные части программного обеспечения независимо от имени. Однако, если код "обновления" одинаков, но код "продукта" отличается, тогда, когда вы пытаетесь установить второй msi, он спросит вас, хотите ли вы обновить его, и в это время он должен скопировать значения из старой конфигурации в новую конфигурацию. Если оба значения одинаковы, а номер версии не изменился, новая конфигурация будет находиться в том же месте, что и в старой конфигурации, и ей ничего не нужно будет делать. Документация MSDN

ClickOnce немного отличается, потому что он больше основан на версии и URL-адресе ClickOnce версии, однако я обнаружил, что до тех пор, пока вы продолжаете "публиковать" в том же месте, новая версия приложения будет продолжена для использования существующей конфигурации. (ссылка на то, как ClickOnce обрабатывает обновления)

Я также знаю, что есть способ вручную слить конфиги во время установки msi с помощью пользовательских сценариев установки, но я не помню точных шагов для этого... (см. эта ссылка, как это сделать с помощью web.config)

Ответ 2

Я хотел добавить этот цитируемый текст в качестве ссылки, когда у меня возникнет эта проблема в будущем. Предположительно вы можете проинструктировать инфраструктуру ApplicationSettings для копирования настроек из предыдущей версии, вызвав Upgrade:

Properties.Settings.Value.Upgrade();

Из Часто задаваемые вопросы по настройкам клиента Сообщение в блоге:

В: Почему в пути user.config есть номер версии? Если я развожу новую версию своего приложения, не потеряет ли пользователь все настройки, сохраненные предыдущей версией?

A: Есть несколько причин, по которым путь user.config зависит от версии.

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

(2) Когда вы обновляете приложения, класс настроек может были изменены и не могут быть совместимый с тем, что удалось сохранить, что может привести к проблемам.

Однако мы упростили обновить настройки из предыдущего версия приложения к последний. Просто позвоните ApplicationSettingsBase.Upgrade() и он будет извлекать настройки из предыдущая версия, соответствующая текущая версия класса и хранилища их в текущей версии файл user.config. У вас также есть возможность переопределения этого поведения либо в вашем классе настроек, либо в вашей реализации поставщика.

Q: Хорошо, но откуда я знаю, когда вызвать обновление?

A: Хороший вопрос. В Clickonce, когда вы устанавливаете новую версию своего application, ApplicationSettingsBase обнаружит его и автоматически настройки обновления для вас в точке загружаются настройки. В не-Clickonce случаев нет автоматического обновления - вам нужно позвонить в Upgrade самостоятельно. Вот одна из идей для определения того, когда для вызова Upgrade:

Введите логическую настройку, называемую CallUpgrade и присвойте ему значение по умолчанию значение true. Когда начнется ваше приложение вы можете сделать что-то вроде:

if (Properties.Settings.Value.CallUpgrade)
{
   Properties.Settings.Value.Upgrade();
   Properties.Settings.Value.CallUpgrade = false;    
}

Это обеспечит, что Upgrade() будет называется только в первый раз приложение запускается после новой версии.

Я не верю, что на самом деле это может сработать - Microsoft не предоставит эту возможность, но метод существует точно так же.

Ответ 3

Файл user.config хранится в

c:\Documents and Settings>\<username>\[Local Settings\]Application Data\<companyname>\<appdomainname>_<eid>_<hash>\<verison>

<c:\Documents and Settings> - это каталог пользовательских данных, либо не роуминг (локальные настройки выше), либо роуминг.
<username> - имя пользователя.
<companyname> - это значение CompanyNameAttribute, если оно доступно. В противном случае игнорируйте этот элемент.
<appdomainname> - это AppDomain.CurrentDomain.FriendlyName. Обычно это означает имя .exe.
<eid> - это URL, StrongName или Path, основанный на данных, доступных для хэша.
<hash> представляет собой SHA1 хэш доказательств, собранных из CurrentDomain, в следующем порядке предпочтения:
  1. StrongName
  2. URL:
Если ни один из них не доступен, используйте путь .exe.
<version> - это параметр AssemblyInfo AssemblyVersionAttribute.

Полное описание здесь http://msdn.microsoft.com/en-us/library/ms379611.aspx

Ответ 4

(Я бы добавил это в качестве комментария к ответу @Amr, но пока у меня не хватит репутации.)

информация в статье MSDN очень понятна и, похоже, по-прежнему применяется. Однако не упоминается, что хэш SHA1 выписывается с базовым 32, а не с более типичной базой 16.

Я считаю, что используемый алгоритм реализован в ToBase32StringSuitableForDirName, который можно найти здесь, в справочном источнике Microsoft.