Czy mogę kontrolować lokalizację ustawień użytkownika .NET, aby uniknąć utraty ustawień podczas uaktualniania aplikacji?

104

Próbuję dostosować lokalizację user.configpliku. Obecnie jest przechowywany z hashem i numerem wersji

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

Chcę, aby była agnostyczna w stosunku do wersji aplikacji

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

Czy można to zrobić i jak? Jakie są tego konsekwencje? Czy po aktualizacji użytkownik utraci ustawienia z poprzedniej wersji?

Muxa
źródło
Chociaż odpowiedź uzbones jest pouczająca w odniesieniu do lokalizacji pliku, uważam, że Ian jest bardziej poprawny w odniesieniu do aktualizacji.
Anthony Mastrean
4
@AnthonyMastrean Osobiście uważam, że żadne ważne ustawienia nie powinny opierać się na infrastrukturze ApplicationSettings dostarczonej przez firmę Microsoft. Muxa powinien po prostu przechowywać ustawienia, w %AppData%\[CompanyName]/[ProductName]których możemy ufać, że pozostaną.
Ian Boyd
2
Bez wątpienia moje dalsze doświadczenie z wbudowaną aplikacją i ustawieniami użytkownika było okropne. Polecam pliki json w appdata lub programdata.
Anthony Mastrean
Możesz także przechowywać swoje ustawienia w rejestrze. Zobacz stackoverflow.com/a/12127888/1273550, aby zapoznać się z alternatywnymi implementacjami klas ustawień.
Ravi Patel

Odpowiedzi:

39

Aby odpowiedzieć na pierwsze pytanie, technicznie rzecz biorąc, możesz umieścić plik w dowolnym miejscu, jednak będziesz musiał go samodzielnie zakodować, ponieważ domyślnym miejscem, do którego trafia plik, jest pierwszy z dwóch przykładów. ( link do instrukcji, jak to zrobić samodzielnie )

Jeśli chodzi o drugie pytanie, zależy to od sposobu wdrożenia aplikacji. Jeśli wdrażasz za pomocą .msi, we właściwościach projektu instalacji (z którego jest zbudowany plik msi) są dwa skróty: „kod aktualizacji” i „kod produktu”. Określają one, w jaki sposób można zainstalować msi i czy aktualizuje, nadpisuje lub instaluje obok dowolnej innej wersji tej samej aplikacji.

Na przykład, jeśli masz dwie wersje oprogramowania i mają one różne kody „uaktualnienia”, to dla systemu Windows są to zupełnie inne programy, niezależnie od nazwy. Jeśli jednak kod „uaktualnienia” jest taki sam, ale kod „produktu” jest inny, to przy próbie zainstalowania drugiego pliku msi zapyta Cię, czy chcesz zaktualizować, w którym to momencie ma skopiować wartości z stara konfiguracja do nowej konfiguracji. Jeśli obie wartości są takie same, a numer wersji się nie zmienił, nowa konfiguracja będzie w tej samej lokalizacji co stara konfiguracja i nie będzie musiała nic robić. Dokumentacja MSDN

ClickOnce jest nieco inny, ponieważ opiera się bardziej na numerze wersji ClickOnce i ścieżce adresu URL, jednak odkryłem, że dopóki będziesz kontynuować „publikowanie” w tej samej lokalizacji, nowa wersja aplikacji będzie nadal używać istniejąca konfiguracja. ( łącze do sposobu obsługi aktualizacji przez ClickOnce )

Wiem również, że istnieje sposób na ręczne scalenie konfiguracji podczas instalacji msi przy użyciu niestandardowych skryptów instalacyjnych, ale nie pamiętam dokładnych kroków, aby to zrobić ... (zobacz ten link, aby dowiedzieć się, jak to zrobić w sieci. config)

uzbones
źródło
Czy kod aktualizacji nie jest tym, który powinien pozostać niezmieniony, a kod produktu to ten, który powinien się zmieniać między wydaniami? blogs.msdn.com/b/pusu/archive/2009/06/10/understanding-msi.aspx
estanford
No! masz rację, nie mogę uwierzyć, że złapałem go wstecz (a złapanie go zajęło 2 lata). To było jak robo-podpisywanie przez chwilę w pewnym momencie mojej przeszłości :(
uzbones
Czy to oznacza, że ​​tylko instalujący użytkownik otrzymuje uaktualnienie swoich ustawień?
Micha Wiedenmann
79

Chciałem dodać ten cytowany tekst jako odniesienie, kiedy będę miał ten problem w przyszłości. Przypuszczalnie można poinstruować infrastrukturę ApplicationSettings, aby skopiować ustawienia z poprzedniej wersji, wywołując Upgrade :

Properties.Settings.Value.Upgrade();

Z posta na blogu z często zadawanymi pytaniami dotyczącymi ustawień klienta : ( archiwum )

P: Dlaczego w ścieżce user.config znajduje się numer wersji? Jeśli wdrożę nową wersję mojej aplikacji, czy użytkownik nie straci wszystkich ustawień zapisanych w poprzedniej wersji?

O: Istnieje kilka powodów, dla których ścieżka user.config jest zależna od wersji.

(1) Aby obsługiwać równoległe wdrażanie różnych wersji aplikacji (można to zrobić na przykład za pomocą Clickonce). Istnieje możliwość zapisania różnych ustawień w różnych wersjach aplikacji.

(2) Podczas uaktualniania aplikacji klasa ustawień mogła zostać zmieniona i może nie być zgodna z tym, co zostało zapisane, co może prowadzić do problemów.

Ułatwiliśmy jednak aktualizację ustawień z poprzedniej wersji aplikacji do najnowszej. Po prostu wywołaj ApplicationSettingsBase.Upgrade () , aby pobrać ustawienia z poprzedniej wersji, które pasują do bieżącej wersji klasy i zapisać je w pliku user.config bieżącej wersji. Możesz również zastąpić to zachowanie w klasie ustawień lub w implementacji dostawcy.

P: OK, ale skąd mam wiedzieć, kiedy zadzwonić do aktualizacji?

O: Dobre pytanie. W Clickonce, po zainstalowaniu nowej wersji aplikacji, ApplicationSettingsBase wykryje ją i automatycznie zaktualizuje ustawienia w momencie załadowania ustawień. W przypadkach innych niż Clickonce nie ma automatycznej aktualizacji - musisz sam zadzwonić do Upgrade. Oto jeden pomysł na określenie, kiedy zadzwonić do Upgrade:

Miej ustawienie logiczne o nazwie CallUpgrade i nadaj mu domyślną wartość true. Po uruchomieniu aplikacji możesz wykonać na przykład:

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

Zapewni to wywołanie Upgrade () tylko przy pierwszym uruchomieniu aplikacji po wdrożeniu nowej wersji.

Ani przez sekundę nie wierzę, że to faktycznie zadziała - nie ma możliwości, aby Microsoft zapewnił taką możliwość, ale metoda jest taka sama.

Ian Boyd
źródło
3
TO CAŁKOWICIE DZIAŁA! Użyłem tylko prostego if(CallUpgrade) { Upgrade(); }stwierdzenia.
Anthony Mastrean,
@Ian Boyd: Podoba mi się ten pomysł i jestem podekscytowany posiadaniem potencjalnego rozwiązania, ale jestem zdezorientowany co do jednej rzeczy. Nie mam. Properties.Settings.Value Mam tę Properties.Settingsczęść, ale czy coś mi brakuje, czy jest to specyficzne dla ciebie?
Refracted Paladin
8
Działa to dobrze, ale przypominam czytelnikom, że ścieżka konfiguracji do numeru wersji, ale z wyłączeniem numeru wersji, musi być taka sama. tzn. zobacz odpowiedź @ Amr. np. jeśli nowa wersja aplikacji jest uruchamiana z innej ścieżki do pliku niż poprzednia wersja, to Upgradenie działa.
Stephen Swensen
1
@RefractedPaladin toProperties.Settings.Default.Upgrade()
Stephen Swensen
5
Nie zapomnij dodać Properties.Settings.Default.Save();po zmianie na false :-)
Jeff
32

Plik user.config jest przechowywany pod adresem

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

<c:\Documents and Settings>to katalog danych użytkownika, niemobilny (ustawienia lokalne powyżej) lub mobilny.
<username>to nazwa użytkownika.
<companyname>to wartość CompanyNameAttribute, jeśli jest dostępna. W przeciwnym razie zignoruj ​​ten element.
<appdomainname>to AppDomain.CurrentDomain.FriendlyName. Zwykle jest to nazwa domyślna .exe.
<eid>to adres URL, StrongName lub Path, oparte na dowodach dostępnych do haszowania.
<hash>to skrót SHA1 dowodów zebranych z CurrentDomain, w następującej kolejności:
1. StrongName
2. URL:
Jeśli żaden z nich nie jest dostępny, użyj ścieżki .exe.
<version>jest ustawieniem AssemblyVersionAttribute AssemblyInfo.

Pełny opis znajduje się tutaj http://msdn.microsoft.com/en-us/library/ms379611.aspx

Amr
źródło
4

(Dodałbym to jako komentarz do odpowiedzi @ Amr, ale nie mam jeszcze wystarczającej liczby przedstawicieli, aby to zrobić.)

Informacji w artykule MSDN jest bardzo jasne i wydaje się nadal obowiązują. Jednak nie wspomina się, że skrót SHA1 jest zapisywany w kodowaniu base 32, a nie bardziej typowym base 16.

Uważam, że używany algorytm jest zaimplementowany w programie ToBase32StringSuitableForDirName, który można znaleźć tutaj w źródle odniesienia firmy Microsoft .

JulianRendell
źródło