2010-04-27 16 views
8

Mam program C#, który używa standardu ApplicationSettingsBase, aby zapisać ustawienia użytkownika. To działało dobrze w .NET 3.5. Podana metoda Upgrade() poprawnie przeładuje te ustawienia po utworzeniu nowej wersji mojego programu.ApplicationSettingsBase.Upgrade() nie aktualizuje ustawień użytkownika po rekompilacji z .NET 4.0

Niedawno skompilowałem program z .NET 4.0. Zwiększono również numer wersji mojego programu. Ale kiedy uruchomię tę wersję, Upgrade() nie wykryje żadnych poprzednich ustawień wersji i nie "przeładuje" ich. Zaczyna być puste.

Jako test ponownie zrekompilowałem, wracając do .NET 3.5. Tym razem metoda Upgrade() zaczęła działać ponownie.

Czy istnieje sposób zezwalania na pracę Upgrade() podczas przełączania ram? Czy jest coś jeszcze, czego mi brakuje?

Odpowiedz

6

Miałem dokładnie ten sam problem i ponownie przetestowałem to kilka razy z .NET 3.5 ponownie skompilowany do .NET 4.0.

Niestety, moje rozwiązanie jest w VB.NET, ale jestem pewien, że można użyć jednego z wielu programów do konwersji, aby zobaczyć to w C# takich jak http://www.developerfusion.com/tools/convert/vb-to-csharp/

Polega ona poprzez wyliczanie wszystkich folderów w % AppData% \ CompanyName, aby znaleźć najnowszy plik user.config w nazwie folderu wersji, z której chcesz dokonać aktualizacji.

odkryłem, że mój rekompilacji aplikacji dla .NET 4.0 pod Visual Studio 2010 będzie utworzyć nowy folder o nazwie % AppData% \ NazwaFirmy \ AppName.exe_Url_blahbahblah choć nie zmieniło absolutnie żadnych innych ustawień lub kod w ogóle!

Wszystkie moje poprzednie wydania sprzed .NET 4.0 zachowały tę samą nazwę folderu i zostały pomyślnie zaktualizowane. Skopiowanie starego pliku user.config (i nazwy folderu wersji) ze starego folderu do nowej struktury folderów utworzonej w .NET 4.0 (ze starą nazwą folderu) rozwiązuje problem - teraz zostanie uaktualniony.

tym przykładzie założono, że masz ustawienia użytkownika o nazwie IUpgraded który jest ustawiony na Fałsz domyślnie (a później ustawione na true), aby sprawdzić, czy ustawienia są początkowe wartości defalt czy nie - można użyć dowolnego inna zmienna, którą utworzyłeś. Przykład pokazuje aktualizację z wersji 1.2.0.0 do czegoś późniejszego, którą można zmienić, zmieniając wartość lastVersion.

Kod ma być umieszczony w górnej części imprezy forma obciążenia swojej najnowszej (.NET 4.0) wersji aplikacji:

Imports System 
Imports System.IO 

If Not My.Settings.IUpgraded Then 'Upgrade application settings from previous version 
    My.Settings.Upgrade() 
    'The following routine is only relevant upgrading version 1.2.0.0 
    If Not My.Settings.IUpgraded Then 'enumerate AppData folder to find previous versions 
     Dim lastVersion As String = "1.2.0.0" 'version to upgrade settings from 
     Dim config_initial As System.Configuration.Configuration = System.Configuration.ConfigurationManager.OpenExeConfiguration(System.Configuration.ConfigurationUserLevel.PerUserRoamingAndLocal) 
     Dim fpath As String = config_initial.FilePath 
     For x = 1 To 3 'recurse backwards to find root CompanyName folder 
      fpath = fpath.Substring(0, InStrRev(fpath, "\", Len(fpath) - 1)) 
     Next 
     fpath = fpath.Substring(0, Len(fpath) - 1) 'remove trailing backslash 
     Dim latestConfig As FileInfo 'If not set then no previous info found 
     Dim di As DirectoryInfo = New DirectoryInfo(fpath) 
     If di.Exists Then 
      For Each diSubDir As DirectoryInfo In di.GetDirectories(lastVersion, SearchOption.AllDirectories) 
       If InStr(diSubDir.FullName, ".vshost") = 0 Then 'don't find VS runtime copies 
        Dim files() As FileInfo = diSubDir.GetFiles("user.config", SearchOption.TopDirectoryOnly) 
        For Each File As FileInfo In files 
         Try 
          If File.LastWriteTime > latestConfig.LastWriteTime Then 
           latestConfig = File 
          End If 
         Catch 
          latestConfig = File 
         End Try 
        Next 
       End If 
      Next 
     End If 
     Try 
      If latestConfig.Exists Then 
       Dim newPath As String = config_initial.FilePath 
       newPath = newPath.Substring(0, InStrRev(newPath, "\", Len(newPath) - 1)) 
       newPath = newPath.Substring(0, InStrRev(newPath, "\", Len(newPath) - 1)) 
       newPath &= lastVersion 
       If Directory.Exists(newPath) = False Then 
        Directory.CreateDirectory(newPath) 
       End If 
       latestConfig.CopyTo(newPath & "\user.config") 
       My.Settings.Upgrade() 'Try upgrading again now old user.config exists in correct place 
      End If 
     Catch : End Try 
    End If 
    My.Settings.IUpgraded = True 'Always set this to avoid potential upgrade loop 
    My.Settings.Save() 
End If 
+0

+1 I zostały wdrożone to rozwiązanie, ponieważ mamy przeniesieni z .NET 2.0 do .NET 4.0. Jedna mała próba - 'di.Exists' nie wykrywa poprawnie folderu, jeśli kończy się na' .', więc najpierw musi zostać znormalizowany z czymś takim jak [to rozwiązanie] (http://stackoverflow.com/questions/ 2281531/how-can-i-compare-directory-paths-in-c). – mellamokb

+0

Dzięki za informację, że to nie wina kodu, który utrzymuję.Prawdopodobnie zaoszczędzisz mi godzin sprawdzania i ponownego sprawdzania (poza godzinami, które już spędziłem). – Grault

4

Oto kod.

public static class SettingsUpdate 
{ 
    public static void Update() 
    { 
     try 
     { 
      var a = Assembly.GetExecutingAssembly(); 

      string appVersionString = a.GetName().Version.ToString(); 

      if(UserSettings.Default.internalApplicationVersion != appVersionString) 
      { 
       var currentConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal); 
       var exeName = "MyApplication.exe"; 
       var companyFolder = new DirectoryInfo(currentConfig.FilePath).Parent.Parent.Parent; 

       FileInfo latestConfig = null; 

       foreach(var diSubDir in companyFolder.GetDirectories("*" + exeName + "*", SearchOption.AllDirectories)) 
       { 
        foreach(var file in diSubDir.GetFiles("user.config", SearchOption.AllDirectories)) 
        { 
         if(latestConfig == null || file.LastWriteTime > latestConfig.LastWriteTime) 
         { 
          latestConfig = file; 
         } 
        } 
       } 

       if(latestConfig != null) 
       { 
        var lastestConfigDirectoryName = Path.GetFileName(Path.GetDirectoryName(latestConfig.FullName)); 

        var latestVersion = new Version(lastestConfigDirectoryName); 
        var lastFramework35Version = new Version("4.0.4605.25401"); 

        if(latestVersion <= lastFramework35Version) 
        { 
         var destinationFile = Path.GetDirectoryName(Path.GetDirectoryName(currentConfig.FilePath)); 
         destinationFile = Path.Combine(destinationFile, lastestConfigDirectoryName); 

         if(!Directory.Exists(destinationFile)) 
         { 
          Directory.CreateDirectory(destinationFile); 
         } 

         destinationFile = Path.Combine(destinationFile, latestConfig.Name); 

         File.Copy(latestConfig.FullName, destinationFile); 
        } 
       } 

       Properties.Settings.Default.Upgrade(); 
       UserSettings.Default.Upgrade(); 
       UserSettings.Default.internalApplicationVersion = appVersionString; 
       UserSettings.Default.Save(); 
      } 
     } 
     catch(Exception ex) 
     { 
      LogManager.WriteExceptionReport(ex); 
     } 
    } 
} 

Może to pomoże :)