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

104

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

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

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

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

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

Muxa
источник
Хотя ответ uzbones информативен в отношении местоположения файла, я считаю, что Иэн более прав в отношении обновления.
Энтони Мастрян,
4
@AnthonyMastrean Я лично считаю, что любые важные настройки не должны полагаться на инфраструктуру ApplicationSettings, предоставленную моим Microsoft. Muxa должен просто хранить настройки %AppData%\[CompanyName]/[ProductName]там, где мы можем быть уверены, что они останутся.
Ian Boyd
2
Без сомнения, мой опыт работы со встроенным приложением и пользовательскими настройками был ужасен. Я рекомендую файлы json в appdata или programdata.
Энтони Мастрян
Вы также можете сохранить свои настройки в реестре. См. Stackoverflow.com/a/12127888/1273550 для альтернативной реализации класса настроек.
Рави Патель,

Ответы:

39

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

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

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

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

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

узбоны
источник
Разве код обновления не тот, который должен оставаться постоянным, а код продукта - тот, который должен изменяться между выпусками? blogs.msdn.com/b/pusu/archive/2009/06/10/understanding-msi.aspx
estanford
Дох! Вы правы, не могу поверить, что я понял это задом наперед (и понадобилось 2 года, чтобы его поймать). В какой-то момент в моем прошлом это было
похоже на подписку на роботов
Означает ли это, что только устанавливающий пользователь обновляет свои настройки?
Micha Wiedenmann
79

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

Properties.Settings.Value.Upgrade();

Из сообщения блога FAQ по настройкам клиента : ( архив )

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

О: Путь user.config зависит от версии по нескольким причинам.

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

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

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

В: Хорошо, но как мне узнать, когда следует вызывать обновление?

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

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

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

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

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

Ян Бойд
источник
3
ЭТО ВСЕГО РАБОТАЕТ! Я использовал простое if(CallUpgrade) { Upgrade(); }утверждение.
Энтони Мастрян,
@ Ян Бойд: Мне нравится эта идея, и я полностью доволен тем, что у меня есть потенциальное решение, однако меня смущает одна вещь. У Properties.Settings.Value меня нет Properties.Settingsдетали, но я что-то упускаю или это характерно для вас?
Refracted Paladin
8
Это работает хорошо, но я напоминаю читателям, что путь к конфигурации, но без номера версии, должен быть таким же. т.е. см. ответ @ Amr. например, если новая версия приложения запускается с другого пути к файлу, чем предыдущая версия, то Upgradeне работает.
Стивен Свенсен
1
@RefractedPaladin этоProperties.Settings.Default.Upgrade()
Стивен Свенсен
5
Не забудьте добавить Properties.Settings.Default.Save();после изменения на false :-)
Джефф
32

Файл 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>- это параметр AssemblyVersionAttribute AssemblyInfo.

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

Амр
источник
4

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

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

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

Джулиан Ренделл
источник