Skip to content

Commit 21b728e

Browse files
committed
Fixes 4964. Also adds an unit test to prove that the default settings will be loaded even if the file is missing. Also, the InitializeAddIn is now completely wrapped in the try/catch to ensure that if exception are thrown anywhere else, we will get an error message and logs rather than just silently loading a non-working instance.
1 parent 4e2af2a commit 21b728e

File tree

3 files changed

+72
-57
lines changed

3 files changed

+72
-57
lines changed

Rubberduck.Main/Extension.cs

Lines changed: 50 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -134,69 +134,71 @@ public void OnDisconnection(ext_DisconnectMode RemoveMode, ref Array custom)
134134

135135
private void InitializeAddIn()
136136
{
137-
if (_isInitialized)
138-
{
139-
// The add-in is already initialized. See:
140-
// The strange case of the add-in initialized twice
141-
// http://msmvps.com/blogs/carlosq/archive/2013/02/14/the-strange-case-of-the-add-in-initialized-twice.aspx
142-
return;
143-
}
144-
145-
var configLoader = new XmlPersistanceService<GeneralSettings>
146-
{
147-
FilePath =
148-
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
149-
"Rubberduck", "rubberduck.config")
150-
};
151-
var configProvider = new GeneralConfigProvider(configLoader);
152-
153-
_initialSettings = configProvider.Create();
154-
if (_initialSettings != null)
137+
Splash splash = null;
138+
try
155139
{
156-
try
140+
if (_isInitialized)
157141
{
158-
var cultureInfo = CultureInfo.GetCultureInfo(_initialSettings.Language.Code);
159-
Dispatcher.CurrentDispatcher.Thread.CurrentUICulture = cultureInfo;
142+
// The add-in is already initialized. See:
143+
// The strange case of the add-in initialized twice
144+
// http://msmvps.com/blogs/carlosq/archive/2013/02/14/the-strange-case-of-the-add-in-initialized-twice.aspx
145+
return;
160146
}
161-
catch (CultureNotFoundException)
147+
148+
var configLoader = new XmlPersistanceService<GeneralSettings>
162149
{
163-
}
164-
try
150+
FilePath =
151+
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
152+
"Rubberduck", "rubberduck.config")
153+
};
154+
var configProvider = new GeneralConfigProvider(configLoader);
155+
156+
_initialSettings = configProvider.Create();
157+
if (_initialSettings != null)
165158
{
166-
if (_initialSettings.SetDpiUnaware)
159+
try
167160
{
168-
SHCore.SetProcessDpiAwareness(PROCESS_DPI_AWARENESS.Process_DPI_Unaware);
161+
var cultureInfo = CultureInfo.GetCultureInfo(_initialSettings.Language.Code);
162+
Dispatcher.CurrentDispatcher.Thread.CurrentUICulture = cultureInfo;
163+
}
164+
catch (CultureNotFoundException)
165+
{
166+
}
167+
168+
try
169+
{
170+
if (_initialSettings.SetDpiUnaware)
171+
{
172+
SHCore.SetProcessDpiAwareness(PROCESS_DPI_AWARENESS.Process_DPI_Unaware);
173+
}
174+
}
175+
catch (Exception)
176+
{
177+
Debug.Assert(false, "Could not set DPI awareness.");
169178
}
170179
}
171-
catch (Exception)
180+
else
172181
{
173-
Debug.Assert(false, "Could not set DPI awareness.");
182+
Debug.Assert(false, "Settings could not be initialized.");
174183
}
175-
}
176-
else
177-
{
178-
Debug.Assert(false, "Settings could not be initialized.");
179-
}
180184

181-
Splash splash = null;
182-
if (_initialSettings.CanShowSplash)
183-
{
184-
splash = new Splash
185+
if (_initialSettings?.CanShowSplash ?? false)
185186
{
186-
// note: IVersionCheck.CurrentVersion could return this string.
187-
Version = $"version {Assembly.GetExecutingAssembly().GetName().Version}"
188-
};
189-
splash.Show();
190-
splash.Refresh();
191-
}
187+
splash = new Splash
188+
{
189+
// note: IVersionCheck.CurrentVersion could return this string.
190+
Version = $"version {Assembly.GetExecutingAssembly().GetName().Version}"
191+
};
192+
splash.Show();
193+
splash.Refresh();
194+
}
192195

193-
try
194-
{
195196
Startup();
196197
}
197198
catch (Win32Exception)
198199
{
199-
System.Windows.Forms.MessageBox.Show(Resources.RubberduckUI.RubberduckReloadFailure_Message, RubberduckUI.RubberduckReloadFailure_Title,
200+
System.Windows.Forms.MessageBox.Show(Resources.RubberduckUI.RubberduckReloadFailure_Message,
201+
RubberduckUI.RubberduckReloadFailure_Title,
200202
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
201203
}
202204
catch (Exception exception)
@@ -211,8 +213,8 @@ private void InitializeAddIn()
211213
RubberduckUI.RubberduckLoadFailure, MessageBoxButtons.OK, MessageBoxIcon.Error);
212214
}
213215
finally
214-
{
215-
splash?.Dispose();
216+
{
217+
splash?.Dispose();
216218
}
217219
}
218220

Rubberduck.SettingsProvider/XmlPersistanceService.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ public override T Load(T toDeserialize)
1919

2020
var doc = GetConfigurationDoc(FilePath);
2121
var node = GetNodeByName(doc, typeof(T).Name);
22+
if (node == null)
23+
{
24+
return FailedLoadReturnValue();
25+
}
2226

2327
using (var reader = node.CreateReader())
2428
{

RubberduckTests/Settings/GeneralSettingsTests.cs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using Rubberduck.VBEditor.VbeRuntime.Settings;
1010
using System;
1111
using Rubberduck.Interaction;
12+
using Rubberduck.SettingsProvider;
1213

1314
namespace RubberduckTests.Settings
1415
{
@@ -154,14 +155,22 @@ public void AutoSavePeriodIsSetInCtor()
154155
Assert.AreEqual(defaultConfig.UserSettings.GeneralSettings.AutoSavePeriod, viewModel.AutoSavePeriod);
155156
}
156157

157-
//[Category("Settings")]
158-
//[Test]
159-
//public void DelimiterIsSetInCtor()
160-
//{
161-
// var defaultConfig = GetDefaultConfig();
162-
// var viewModel = new GeneralSettingsViewModel(defaultConfig, GetOperatingSystemMock().Object);
163-
164-
// Assert.AreEqual(defaultConfig.UserSettings.GeneralSettings.Delimiter, (char)viewModel.Delimiter);
165-
//}
158+
[Category("Settings")]
159+
[Test]
160+
public void UserSettingsLoadedUsingDefaultWhenMissingFile()
161+
{
162+
// For this test, we need to use the actual object. Fortunately, the path is virtual, so we
163+
// can override that property and force it to use an non-existent path to prove that settings
164+
// will be still created using defaults without the file present.
165+
var persisterMock = new Mock<XmlPersistanceService<GeneralSettings>>();
166+
persisterMock.Setup(x => x.FilePath).Returns("C:\\some\\non\\existent\\path\\rubberduck");
167+
persisterMock.CallBase = true;
168+
var configProvider = new GeneralConfigProvider(persisterMock.Object);
169+
170+
var settings = configProvider.Create();
171+
var defaultSettings = configProvider.CreateDefaults();
172+
173+
Assert.AreEqual(defaultSettings, settings);
174+
}
166175
}
167176
}

0 commit comments

Comments
 (0)