Puis-je contrôler l'emplacement des paramètres utilisateur .NET pour éviter de perdre des paramètres lors de la mise à niveau de l'application?

104

J'essaye de personnaliser l'emplacement du user.configfichier. Actuellement, il est stocké avec un hachage et un numéro de version

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

Je veux qu'il soit indépendant de la version de l'application

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

Est-ce possible de le faire et comment? Quelles sont les implications? L'utilisateur perdra-t-il ses paramètres de la version précédente après la mise à niveau?

Muxa
la source
Bien que la réponse d'uzbones soit informative en ce qui concerne l'emplacement du fichier, je pense que celle d' Ian est plus correcte en ce qui concerne la mise à niveau.
Anthony Mastrean
4
@AnthonyMastrean Je pense personnellement que les paramètres importants ne devraient pas dépendre de l' infrastructure ApplicationSettings fournie par Microsoft. Muxa devrait simplement stocker les paramètres %AppData%\[CompanyName]/[ProductName]là où nous pouvons être sûrs qu'il restera.
Ian Boyd
2
Sans aucun doute, mon expérience continue avec l'application intégrée et les paramètres utilisateur a été terrible. Je recommande les fichiers json dans appdata ou programdata.
Anthony Mastrean
Vous pouvez également stocker vos paramètres dans un registre. Voir stackoverflow.com/a/12127888/1273550 pour une implémentation alternative de la classe de paramètres.
Ravi Patel

Réponses:

39

Pour répondre à la première question, vous pouvez techniquement placer le fichier où vous le souhaitez, mais vous devrez le coder vous-même, car l'emplacement par défaut du fichier est le premier de vos deux exemples. ( lien vers comment le faire vous-même )

Quant à la deuxième question, elle dépend de la façon dont vous déployez l'application. Si vous déployez via un .msi, il y a deux hachages dans les propriétés du projet d'installation (à partir duquel le msi est construit), le «code de mise à niveau» et le «code produit». Celles-ci déterminent comment le msi peut être installé et s'il est mis à niveau, écrasé ou installé à côté de toute autre version de la même application.

Par exemple, si vous avez deux versions de votre logiciel et qu'elles ont des codes de «mise à niveau» différents, alors pour Windows, ce sont des logiciels complètement différents, quel que soit le nom. Cependant, si le code de `` mise à niveau '' est le même, mais que le code `` produit '' est différent, lorsque vous essayez d'installer le 2ème msi, il vous demandera si vous souhaitez mettre à niveau, moment auquel il est censé copier les valeurs du ancienne config vers une nouvelle config. Si les deux valeurs sont identiques et que le numéro de version n'a pas changé, la nouvelle configuration sera au même emplacement que l'ancienne configuration, et elle n'aura rien à faire. Documentation MSDN

ClickOnce est un peu différent, car il est basé davantage sur la version ClickOnce # et le chemin de l'URL, mais j'ai constaté que tant que vous continuez à `` publier '' au même emplacement, la nouvelle version de l'application continuera à utiliser le config existante. ( lien vers la façon dont ClickOnce gère les mises à jour )

Je sais aussi qu'il existe un moyen de fusionner manuellement les configurations lors de l'installation du msi à l'aide de scripts d'installation personnalisés, mais je ne me souviens pas des étapes exactes pour le faire ... (voir ce lien pour savoir comment le faire avec un site Web. config)

uzbones
la source
Le code de mise à niveau n'est-il pas celui qui est censé rester constant, et le code produit celui qui est censé changer entre les versions? blogs.msdn.com/b/pusu/archive/2009/06/10/understanding-msi.aspx
estanford
Doh! vous avez raison, je ne peux pas croire que j'ai eu celui-là à l'envers (et il a fallu 2 ans pour l'attraper). C'était comme une signature robotique pendant un certain temps à un moment donné de mon passé :(
uzbones
Cela signifie-t-il que seul l'utilisateur installateur obtient la mise à niveau de ses paramètres?
Micha Wiedenmann
79

Je voulais ajouter ce texte cité comme référence lorsque j'aurai ce problème à l'avenir. On suppose que vous pouvez demander à l'infrastructure ApplicationSettings de copier les paramètres d'une version précédente en appelant Upgrade :

Properties.Settings.Value.Upgrade();

À partir du billet de blog de la FAQ sur les paramètres du client : ( archive )

Q: Pourquoi y a-t-il un numéro de version dans le chemin user.config? Si je déploie une nouvelle version de mon application, l'utilisateur ne perdra-t-il pas tous les paramètres enregistrés par la version précédente?

R: Il y a deux raisons pour lesquelles le chemin user.config est sensible à la version.

(1) Pour prendre en charge le déploiement côte à côte de différentes versions d'une application (vous pouvez le faire avec Clickonce, par exemple). Il est possible que différentes versions de l'application aient différents paramètres enregistrés.

(2) Lorsque vous mettez à niveau une application, la classe des paramètres peut avoir été modifiée et ne pas être compatible avec ce qui a été sauvegardé, ce qui peut entraîner des problèmes.

Cependant, nous avons simplifié la mise à niveau des paramètres d'une version précédente de l'application vers la dernière. Appelez simplement ApplicationSettingsBase.Upgrade () et il récupérera les paramètres de la version précédente qui correspondent à la version actuelle de la classe et les stockera dans le fichier user.config de la version actuelle. Vous avez également la possibilité de remplacer ce comportement dans votre classe de paramètres ou dans votre implémentation de fournisseur.

Q: D'accord, mais comment savoir quand appeler Upgrade?

R: Bonne question. Dans Clickonce, lorsque vous installez une nouvelle version de votre application, ApplicationSettingsBase la détecte et met automatiquement à niveau les paramètres pour vous au moment où les paramètres sont chargés. Dans les cas non-Clickonce, il n'y a pas de mise à niveau automatique - vous devez appeler Upgrade vous-même. Voici une idée pour déterminer quand appeler Upgrade:

Ayez un paramètre booléen appelé CallUpgrade et donnez-lui une valeur par défaut de true. Lorsque votre application démarre, vous pouvez faire quelque chose comme:

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

Cela garantira que Upgrade () n'est appelé que la première fois que l'application s'exécute après le déploiement d'une nouvelle version.

Je ne crois pas une seconde que cela puisse réellement fonctionner - il n'y a aucun moyen pour Microsoft de fournir cette capacité, mais la méthode est la même.

Ian Boyd
la source
3
CELA FONCTIONNE TOTALEMENT! J'ai utilisé juste la simple if(CallUpgrade) { Upgrade(); }déclaration.
Anthony Mastrean
@Ian Boyd: J'aime cette idée et je suis totalement ravi d'avoir une solution potentielle, mais je suis confus sur une chose. Je n'ai pas Properties.Settings.Value je la Properties.Settingspartie , mais que je manque quelque chose ou est - ce spécifique à vous?
Réfracté Paladin le
8
Cela fonctionne bien, mais je rappelle aux lecteurs que le chemin de la configuration jusqu'à, mais à l'exclusion du numéro de version, doit être le même. ie voir la réponse de @ Amr. Par exemple, si une nouvelle version de l'application est lancée à partir d'un chemin de fichier différent de celui d'une version précédente, Upgradecela ne fonctionne pas.
Stephen Swensen
1
@RefractedPaladin it'sProperties.Settings.Default.Upgrade()
Stephen Swensen
5
N'oubliez pas d'ajouter Properties.Settings.Default.Save();après l'avoir changé en faux :-)
Jeff
32

Le fichier user.config est stocké dans

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

<c:\Documents and Settings>est le répertoire de données utilisateur, non itinérant (paramètres locaux ci-dessus) ou itinérants.
<username>est le nom d'utilisateur.
<companyname>est la valeur CompanyNameAttribute, si disponible. Sinon, ignorez cet élément.
<appdomainname>est le AppDomain.CurrentDomain.FriendlyName. Cela prend généralement par défaut le nom .exe.
<eid>est l'URL, StrongName ou Path, basé sur les preuves disponibles pour le hachage.
<hash>est un hachage SHA1 de preuves collectées à partir de CurrentDomain, dans l'ordre de préférence suivant:
1. StrongName
2. URL:
si aucun de ces éléments n'est disponible, utilisez le chemin .exe.
<version>est le paramètre AssemblyVersionAttribute de AssemblyInfo.

La description complète est ici http://msdn.microsoft.com/en-us/library/ms379611.aspx

Amr
la source
4

(J'ajouterais ceci en commentaire à la réponse de @ Amr, mais je n'ai pas encore assez de représentants pour le faire.)

Les informations contenues dans l'article MSDN sont très claires et semblent toujours s'appliquer. Cependant, il ne mentionne pas que le hachage SHA1 est écrit en base 32 codé, plutôt que la base 16 plus typique.

Je crois que l'algorithme utilisé est implémenté dans ToBase32StringSuitableForDirName, qui peut être trouvé ici dans la source de référence Microsoft .

JulianRendell
la source