diff --git a/source/AccUnit/AccessCodeLib.AccUnit.csproj b/source/AccUnit/AccessCodeLib.AccUnit.csproj index 8d94471..ac1dc8d 100644 --- a/source/AccUnit/AccessCodeLib.AccUnit.csproj +++ b/source/AccUnit/AccessCodeLib.AccUnit.csproj @@ -144,8 +144,10 @@ + + @@ -250,6 +252,7 @@ Settings.settings + diff --git a/source/AccUnit/Configuration/AccUnitInfo.cs b/source/AccUnit/Configuration/AccUnitInfo.cs new file mode 100644 index 0000000..e00a307 --- /dev/null +++ b/source/AccUnit/Configuration/AccUnitInfo.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Reflection; +using System.Text; + +namespace AccessCodeLib.AccUnit.Configuration +{ + public class AccUnitInfo + { + public static string FileVersion + { + get + { + var version = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location); + return version.FileVersion; + } + } + + public static string Copyright + { + get + { + var version = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location); + return version.LegalCopyright; + } + } + } +} diff --git a/source/AccUnit/Configuration/Configurator.cs b/source/AccUnit/Configuration/Configurator.cs index f89f56d..9f8da14 100644 --- a/source/AccUnit/Configuration/Configurator.cs +++ b/source/AccUnit/Configuration/Configurator.cs @@ -2,6 +2,8 @@ using AccessCodeLib.Common.VBIDETools; using Microsoft.Vbe.Interop; using System; +using System.Diagnostics; +using System.Reflection; using System.Runtime.InteropServices; namespace AccessCodeLib.AccUnit.Configuration diff --git a/source/AccUnit/Integration/UserSettings.cs b/source/AccUnit/Integration/UserSettings.cs new file mode 100644 index 0000000..865a4ca --- /dev/null +++ b/source/AccUnit/Integration/UserSettings.cs @@ -0,0 +1,110 @@ +using AccessCodeLib.AccUnit.Properties; +using AccessCodeLib.Common.Tools.Logging; +using System; +using System.ComponentModel; + +namespace AccessCodeLib.AccUnit +{ + public class UserSettings + { + #region Static members + + /// + /// Unloads the previously loaded instance provided via property Current. + /// This method is mainly needed to support testing the singleton implementation in property Current. + /// + public static void UnloadCurrent() + { + _current = null; + } + + private static UserSettings _current; + public static UserSettings Current + { + get + { + if (_current == null) + { + _current = new UserSettings(); + _current.Load(); + } + return _current; + } + set + { + _current = value ?? throw new ArgumentNullException(); + } + } + + #endregion + + private UserSettings() + { + } + + public UserSettings Clone() + { + var clone = new UserSettings + { + ImportExportFolder = ImportExportFolder, + SeparatorChar = SeparatorChar, + SeparatorMaxLength = SeparatorMaxLength + }; + return clone; + } + + #region Load/Save + + private void Load() + { + using (new BlockLogger()) + { + ImportExportFolder = Settings.Default.ImportExportFolder; + SeparatorMaxLength = Settings.Default.SeparatorMaxLength; + SeparatorChar = Settings.Default.SeparatorChar; + } + } + + public void Save() + { + Settings.Default.ImportExportFolder = ImportExportFolder; + Settings.Default.SeparatorMaxLength = SeparatorMaxLength; + Settings.Default.SeparatorChar = SeparatorChar; + Settings.Default.Save(); + } + + #endregion + + #region Setting Properties + + private string _importExportFolder; + public string ImportExportFolder + { + get + { + return _importExportFolder; + } + set + { + _importExportFolder = value.TrimEnd('\\', ' ').TrimStart(); + } + } + + [Category("Text output")] + [DefaultValue(60)] + [Description("")] + // ReSharper disable MemberCanBePrivate.Global + public int SeparatorMaxLength { get; set; } + // ReSharper restore MemberCanBePrivate.Global + + [Category("Text output")] + [DefaultValue('-')] + [Description("")] + // ReSharper disable MemberCanBePrivate.Global + public char SeparatorChar { get; set; } + // ReSharper restore MemberCanBePrivate.Global + + + #endregion + } +} diff --git a/source/AccUnit/Properties/AssemblyInfo.cs b/source/AccUnit/Properties/AssemblyInfo.cs index 2ea2cd7..90e6cf6 100644 --- a/source/AccUnit/Properties/AssemblyInfo.cs +++ b/source/AccUnit/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("access-codelib.net")] [assembly: AssemblyProduct("AccUnit")] -[assembly: AssemblyCopyright("Copyright © 2024")] +[assembly: AssemblyCopyright("© 2010-2024")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -31,5 +31,5 @@ // Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, // indem Sie "*" wie unten gezeigt eingeben: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.9.9.0")] -[assembly: AssemblyFileVersion("0.9.9.0")] +[assembly: AssemblyVersion("0.9.10.0")] +[assembly: AssemblyFileVersion("0.9.10.0")] diff --git a/source/AccUnit/Tools/UserSettings.cs b/source/AccUnit/Tools/UserSettings.cs new file mode 100644 index 0000000..447683f --- /dev/null +++ b/source/AccUnit/Tools/UserSettings.cs @@ -0,0 +1,111 @@ +using AccessCodeLib.AccUnit.Properties; +using AccessCodeLib.AccUnit.Tools.Templates; +using AccessCodeLib.Common.Tools.Logging; +using System; + +namespace AccessCodeLib.AccUnit.Tools +{ + public class UserSettings + { + #region Static members + + /// + /// Unloads the previously loaded instance provided via property Current. + /// This method is mainly needed to support testing the singleton implementation in property Current. + /// + public static void UnloadCurrent() + { + _current = null; + } + + private static UserSettings _current; + public static UserSettings Current + { + get + { + if (_current == null) + { + _current = new UserSettings(); + _current.Load(); + } + return _current; + } + set + { + _current = value ?? throw new ArgumentNullException(); + } + } + + #endregion + + private UserSettings() + { + } + + public UserSettings Clone() + { + var clone = new UserSettings + { + TemplateFolder = TemplateFolder, + TestTemplates = TestTemplates, + UserDefinedTemplates = UserDefinedTemplates, + TestMethodTemplate = TestMethodTemplate + }; + return clone; + } + + #region Load/Save + + private void Load() + { + using (new BlockLogger()) + { + TemplateFolder = Settings.Default.TemplateFolder; + TestMethodTemplate = GetTestMethodTemplate(); + TestTemplates = new TestTemplateCollection(); + UserDefinedTemplates = new TestTemplateCollection(TestTemplates.UserDefinedTemplates); + } + } + + private static string GetTestMethodTemplate() + { + var savedTemplate = Settings.Default.TestMethodTemplate; + return !string.IsNullOrEmpty(savedTemplate) ? savedTemplate : Resources.DefaultTestMethodTemplate; + } + + public void Save() + { + using (new BlockLogger()) + { + Settings.Default.TestMethodTemplate = TestMethodTemplate; + Settings.Default.TemplateFolder = TemplateFolder; + Settings.Default.Save(); + UserDefinedTemplates.Save(); + TestTemplates = new TestTemplateCollection(); + } + } + + #endregion + + #region Setting Properties + + private string _templateFolder; + public string TemplateFolder + { + get + { + return _templateFolder; + } + set + { + _templateFolder = value.TrimEnd('\\', ' ').TrimStart(); + } + } + + public TestTemplateCollection TestTemplates { get; private set; } + public TestTemplateCollection UserDefinedTemplates { get; private set; } + public string TestMethodTemplate { get; set; } + + #endregion + } +} diff --git a/source/Common/Common.VBIDETools/Commandbar/VbeCommandBarAdapter.cs b/source/Common/Common.VBIDETools/Commandbar/VbeCommandBarAdapter.cs index 3b8a293..8df5198 100644 --- a/source/Common/Common.VBIDETools/Commandbar/VbeCommandBarAdapter.cs +++ b/source/Common/Common.VBIDETools/Commandbar/VbeCommandBarAdapter.cs @@ -3,6 +3,7 @@ using Microsoft.Vbe.Interop; using System; using System.Collections.Generic; +using System.Runtime.InteropServices; namespace AccessCodeLib.Common.VBIDETools.Commandbar { @@ -15,7 +16,7 @@ public VbeCommandBarAdapter(VBE vbe) VBE = vbe; } - public VBE VBE { get; } + public VBE VBE { get; private set; } public CommandBar MenuBar { @@ -61,12 +62,10 @@ private CommandBar GetCommandBar(int index) return foundControl.Index; } } - // ReSharper disable EmptyGeneralCatchClause catch { // Don't mind if the control could not be found. } - // ReSharper restore EmptyGeneralCatchClause return null; } @@ -114,17 +113,18 @@ protected virtual void Dispose(bool disposing) using (new BlockLogger()) { - DisposeUnManagedResources(); - + DisposeUnmanagedResources(); _disposed = true; } } - private void DisposeUnManagedResources() + private void DisposeUnmanagedResources() { using (new BlockLogger()) { - + Marshal.ReleaseComObject(VBE); + VBE = null; + // issue #77: (http://accunit.access-codelib.net/bugs/view.php?id=77) return; /* diff --git a/source/Common/Common.VBIDETools/InvocationHelper.cs b/source/Common/Common.VBIDETools/InvocationHelper.cs index b6b4129..25d2647 100644 --- a/source/Common/Common.VBIDETools/InvocationHelper.cs +++ b/source/Common/Common.VBIDETools/InvocationHelper.cs @@ -45,17 +45,22 @@ protected virtual void Dispose(bool disposing) try { - _target = null; + if (_target != null) + { + //Marshal.ReleaseComObject(_target); // --> RCW error ... Why? + _target = null; + } } catch (Exception ex) { Logger.Log(ex.Message); } - // GC-Bereinigung wegen unmanaged res: + // GC clean up (instead of Marshal.ReleaseComObject) GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); + GC.WaitForPendingFinalizers(); _disposed = true; } diff --git a/source/Common/Common.VBIDETools/OfficeApplicationHelper.cs b/source/Common/Common.VBIDETools/OfficeApplicationHelper.cs index 0592b05..b10ae06 100644 --- a/source/Common/Common.VBIDETools/OfficeApplicationHelper.cs +++ b/source/Common/Common.VBIDETools/OfficeApplicationHelper.cs @@ -3,6 +3,7 @@ using Microsoft.Vbe.Interop; using System; using System.Linq; +using System.Runtime.InteropServices; namespace AccessCodeLib.Common.VBIDETools { @@ -137,8 +138,12 @@ protected virtual void Dispose(bool disposing) } } - _application = null; - + if (_application != null) + { + Marshal.ReleaseComObject(_application); + _application = null; + } + } catch (Exception ex) { @@ -146,10 +151,12 @@ protected virtual void Dispose(bool disposing) } // GC-Bereinigung wegen unmanaged res: + /* GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); - + GC.WaitForPendingFinalizers(); + */ _disposed = true; } diff --git a/source/Common/Common.VBIDETools/Properties/AssemblyInfo.cs b/source/Common/Common.VBIDETools/Properties/AssemblyInfo.cs index 9b7983c..8bf0bd9 100644 --- a/source/Common/Common.VBIDETools/Properties/AssemblyInfo.cs +++ b/source/Common/Common.VBIDETools/Properties/AssemblyInfo.cs @@ -28,5 +28,5 @@ // Build Number // Revision // -[assembly: AssemblyVersion("0.9.17.0")] -[assembly: AssemblyFileVersion("0.9.17.0")] +[assembly: AssemblyVersion("0.9.18.0")] +[assembly: AssemblyFileVersion("0.9.18.0")] diff --git a/vbe-add-In/AccUnit.VbeAddIn/About/AboutDialog.xaml b/vbe-add-In/AccUnit.VbeAddIn/About/AboutDialog.xaml new file mode 100644 index 0000000..11aee8f --- /dev/null +++ b/vbe-add-In/AccUnit.VbeAddIn/About/AboutDialog.xaml @@ -0,0 +1,62 @@ + + + + + + + + + diff --git a/vbe-add-In/AccUnit.VbeAddIn/About/AboutDialog.xaml.cs b/vbe-add-In/AccUnit.VbeAddIn/About/AboutDialog.xaml.cs new file mode 100644 index 0000000..d7383e4 --- /dev/null +++ b/vbe-add-In/AccUnit.VbeAddIn/About/AboutDialog.xaml.cs @@ -0,0 +1,12 @@ +using System.Windows; + +namespace AccessCodeLib.AccUnit.VbeAddIn.About +{ + public partial class AboutDialog : Window + { + public AboutDialog() + { + InitializeComponent(); + } + } +} diff --git a/vbe-add-In/AccUnit.VbeAddIn/About/AboutViewModel.cs b/vbe-add-In/AccUnit.VbeAddIn/About/AboutViewModel.cs new file mode 100644 index 0000000..7f578f9 --- /dev/null +++ b/vbe-add-In/AccUnit.VbeAddIn/About/AboutViewModel.cs @@ -0,0 +1,82 @@ +using AccessCodeLib.AccUnit.Configuration; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Windows.Input; + +namespace AccessCodeLib.AccUnit.VbeAddIn.About +{ + public class AboutViewModel + { + public ICommand NavigateCommand { get; } + + public string AddInVersion => AddInManager.FileVersion; + public string FrameworkVersion => AccUnitInfo.FileVersion; + public string AddInCopyright => AddInManager.Copyright; + public string FrameworkCopyright => AccUnitInfo.Copyright; + public string Copyright => AddInCopyright.CompareTo(FrameworkCopyright) >= 0 + ? AddInManager.Copyright : FrameworkCopyright; + + + public AboutViewModel() + { + NavigateCommand = new RelayCommand(Navigate); + Contributors = new List + { + new Contributor("Josef Pötzl"), + new Contributor("Paul Rohorzka"), + new Contributor("Sten Schmidt") + }; + } + + private void Navigate(string url) + { + if (Uri.TryCreate(url, UriKind.Absolute, out var uri)) + { + Process.Start(new ProcessStartInfo(uri.AbsoluteUri) { UseShellExecute = true }); + } + } + + public IEnumerable Contributors { get; } + + } + + public class RelayCommand : ICommand + { + private readonly Action _execute; + private readonly Predicate _canExecute; + + public RelayCommand(Action execute, Predicate canExecute = null) + { + _execute = execute ?? throw new ArgumentNullException(nameof(execute)); + _canExecute = canExecute; + } + + public bool CanExecute(object parameter) + { + return _canExecute == null || _canExecute((T)parameter); + } + + public void Execute(object parameter) + { + _execute((T)parameter); + } + + public event EventHandler CanExecuteChanged + { + add => CommandManager.RequerySuggested += value; + remove => CommandManager.RequerySuggested -= value; + } + } + + public class Contributor + { + public Contributor(string name) + { + Name = name; + } + + public string Name { get; } + } + +} diff --git a/vbe-add-In/AccUnit.VbeAddIn/AccessCodeLib.AccUnit.VbeAddIn.csproj b/vbe-add-In/AccUnit.VbeAddIn/AccessCodeLib.AccUnit.VbeAddIn.csproj index a3bb8af..ce539f0 100644 --- a/vbe-add-In/AccUnit.VbeAddIn/AccessCodeLib.AccUnit.VbeAddIn.csproj +++ b/vbe-add-In/AccUnit.VbeAddIn/AccessCodeLib.AccUnit.VbeAddIn.csproj @@ -92,6 +92,7 @@ + @@ -106,6 +107,10 @@ + + AboutDialog.xaml + + @@ -135,6 +140,10 @@ + + + Component + CheckableTreeView.xaml @@ -223,6 +232,13 @@ + + + Form + + + UserSettingDialog.cs + @@ -280,11 +296,21 @@ VbeCommandbars.Designer.cs Designer + + UserSettingDialog.cs + + + UserSettingDialog.cs + + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/vbe-add-In/AccUnit.VbeAddIn/AddInManager.cs b/vbe-add-In/AccUnit.VbeAddIn/AddInManager.cs index cd3b485..ff330f8 100644 --- a/vbe-add-In/AccUnit.VbeAddIn/AddInManager.cs +++ b/vbe-add-In/AccUnit.VbeAddIn/AddInManager.cs @@ -10,6 +10,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Reflection; +using System.Runtime.InteropServices; using Timer = System.Windows.Forms.Timer; namespace AccessCodeLib.AccUnit.VbeAddIn @@ -17,7 +18,7 @@ namespace AccessCodeLib.AccUnit.VbeAddIn internal class AddInManager : IDisposable { private AddIn _addIn; - private Timer _startupTimer; + //private Timer _startupTimer; private OfficeApplicationHelper _officeApplicationHelper; private readonly VbeIntegrationManager _vbeIntegrationManager = new VbeIntegrationManager(); @@ -27,20 +28,18 @@ internal class AddInManager : IDisposable private readonly TestStarter _testStarter = new TestStarter(); private readonly TestExplorerManager _testExplorerManager; + private readonly DialogManager _dialogManager = new DialogManager(); /* private readonly TagListManager _tagListManager = new TagListManager(); - private readonly DialogManager _dialogManager = new DialogManager(); + private readonly TestTemplateGenerator _testTemplateGenerator = new TestTemplateGenerator(); private AccSpecCommandBarAdapterClient _accSpecCommandBarAdapterClient; private AccSpecManager _accSpecManager; - */ - //private VbaProgrammingTools _vbaProgrammingTools; - public AddInManager(AddIn addIn) { using (new BlockLogger()) @@ -50,12 +49,6 @@ public AddInManager(AddIn addIn) /* _tagListManager.AddIn = addIn; _testListAndResultManager.AddIn = addIn; - - - if (Settings.Default.VbaProgrammingToolsEnabled) - { - _vbaProgrammingTools = new VbaProgrammingTools(); - } */ InitOfficeApplicationHelper(); @@ -130,12 +123,11 @@ private void InitCommandBarsAdapter() _commandBarsAdapter.AddClient(_testStarter); _commandBarsAdapter.AddClient(_vbeIntegrationManager); _commandBarsAdapter.AddClient(_testExplorerManager); + _commandBarsAdapter.AddClient(_dialogManager); /* _commandBarsAdapter.AddClient(_tagListManager); _commandBarsAdapter.AddClient(_testTemplateGenerator); - - _commandBarsAdapter.AddClient(_dialogManager); */ /* @@ -143,25 +135,10 @@ private void InitCommandBarsAdapter() { _commandBarsAdapter.AddClient(_accSpecCommandBarAdapterClient); } - - if (_vbaProgrammingTools != null) - { - AddVbaProgrammingToolsToCommandBar(); - } */ } } - /* - private void AddVbaProgrammingToolsToCommandBar() - { - using (new BlockLogger()) - { - _commandBarsAdapter.AddClient(_vbaProgrammingTools); - } - } - */ - private void InitTestSuiteManager() { using (new BlockLogger()) @@ -289,29 +266,15 @@ private void InitOfficeApplicationHelper(object hostApplication = null) { using (new BlockLogger()) { + // Note: if load RubberDuck, an instance of Access stay in memory after close _officeApplicationHelper = HostApplicationTools.GetOfficeApplicationHelper(VBE, ref hostApplication); _vbeIntegrationManager.OfficeApplicationHelper = _officeApplicationHelper; _testSuiteManager.OfficeApplicationHelper = _officeApplicationHelper; - - /* - if (_vbaProgrammingTools != null) - { - InitVbaProgrammingTools(_officeApplicationHelper); - } - */ } } #endregion - /* - private void InitVbaProgrammingTools(OfficeApplicationHelper officeApplicationHelper) - { - using (new BlockLogger()) - { - _vbaProgrammingTools.OfficeApplicationHelper = officeApplicationHelper; - } - } - */ + #region ad VbeWindow private void InitVbeWindows() @@ -355,6 +318,7 @@ private void InitStartUpTimer(int interval, bool start) } */ + /* private void DisposeStartUpTimer() { if (_startupTimer == null) @@ -399,6 +363,7 @@ void StartupTimerTick(object sender, EventArgs e) //_testListAndResultManager.AddTestClassListToTestListAndResultWindow(); DisposeStartUpTimer(); } + */ #endregion @@ -413,6 +378,15 @@ public static string FileVersion } } + public static string Copyright + { + get + { + var version = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location); + return version.LegalCopyright; + } + } + private VBE VBE => AddIn.VBE; private AddIn AddIn => _addIn; @@ -442,76 +416,56 @@ protected virtual void Dispose(bool disposing) try { - DisposeUnManagedResources(); + DisposeUnmanagedResources(); } catch (Exception ex) { Logger.Log(ex); } - GC.Collect(); - GC.WaitForPendingFinalizers(); - GC.Collect(); - _disposed = true; } } - private void DisposeUnManagedResources() + private void DisposeUnmanagedResources() { - _addIn = null; + if (_addIn != null) + { + Marshal.ReleaseComObject(_addIn); + _addIn = null; + } } private void DisposeManagedResources() { using (new BlockLogger()) { - try - { - DisposeStartUpTimer(); - DisposeVbaProgrammingTools(); - - _testStarter.Dispose(); - - //_testTemplateGenerator.Dispose(); - - _vbeIntegrationManager.Dispose(); - - try - { - _commandBarsAdapter.Dispose(); - } - catch (Exception ex) - { - Logger.Log(ex); - } - - _testSuiteManager.Dispose(); + //DisposeStartUpTimer(); + //_testTemplateGenerator.Dispose(); - DisposeAddInManagerBridge(); + DisposeManagedResource(_testStarter); + DisposeManagedResource(_testExplorerManager); + DisposeManagedResource(_vbeIntegrationManager); + DisposeManagedResource(_commandBarsAdapter); + DisposeManagedResource(_testSuiteManager); - } - catch (Exception ex) - { - Logger.Log(ex); - } + DisposeAddInManagerBridge(); - try - { - _officeApplicationHelper.Dispose(); - _officeApplicationHelper = null; - } - catch (Exception ex) - { - Logger.Log(ex); - } + DisposeManagedResource(_officeApplicationHelper); + _officeApplicationHelper = null; } } - private void DisposeVbaProgrammingTools() + private void DisposeManagedResource(IDisposable disposable) { - //_vbaProgrammingTools?.Dispose(); - //_vbaProgrammingTools = null; + try + { + disposable.Dispose(); + } + catch (Exception ex) + { + Logger.Log(ex); + } } private void DisposeAddInManagerBridge() @@ -537,6 +491,8 @@ private void RemoveEventHandler(AddInManagerBridge addInManagerBridge) { addInManagerBridge.TestSuiteRequest -= AddInBridgeTestSuiteRequest; addInManagerBridge.HostApplicationInitialized -= AddInBridgeHostApplicationInitialized; + addInManagerBridge.ConstraintBuilderRequest -= AddInBridgeConstraintBuilderRequest; + addInManagerBridge.AssertRequest -= AddInBridgeAssertRequest; } public void Dispose() diff --git a/vbe-add-In/AccUnit.VbeAddIn/Connect.cs b/vbe-add-In/AccUnit.VbeAddIn/Connect.cs index 76819bc..000c725 100644 --- a/vbe-add-In/AccUnit.VbeAddIn/Connect.cs +++ b/vbe-add-In/AccUnit.VbeAddIn/Connect.cs @@ -131,7 +131,10 @@ public void OnBeginShutdown(ref Array custom) { try { - _addInInstance.Object = null; + if (!_disposed) + { + Dispose(); + } } catch (Exception ex) { @@ -176,6 +179,15 @@ protected virtual void Dispose(bool disposing) return; } + try + { + _addInInstance.Object = null; + } + catch (Exception ex) + { + Logger.Log(ex); + } + if (disposing) { Logger.Log("disposing == true"); @@ -187,11 +199,19 @@ protected virtual void Dispose(bool disposing) } } - _addInInstance = null; - + if (_addInInstance != null) + { + Logger.Log("Start Marshal.ReleaseComObject(_addInInstance) ..."); + Marshal.ReleaseComObject(_addInInstance); + _addInInstance = null; + } + + /* GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); + GC.WaitForPendingFinalizers(); + */ _disposed = true; diff --git a/vbe-add-In/AccUnit.VbeAddIn/DialogManager.cs b/vbe-add-In/AccUnit.VbeAddIn/DialogManager.cs new file mode 100644 index 0000000..d58da4a --- /dev/null +++ b/vbe-add-In/AccUnit.VbeAddIn/DialogManager.cs @@ -0,0 +1,89 @@ +using System; +using System.Windows.Forms; +using AccessCodeLib.AccUnit.VbeAddIn.About; +using AccessCodeLib.Common.Tools.Logging; +using AccessCodeLib.Common.VBIDETools.Commandbar; +using Microsoft.Office.Core; + +namespace AccessCodeLib.AccUnit.VbeAddIn +{ + class DialogManager : ICommandBarsAdapterClient + { + + public event EventHandler RefreshTestTemplates; + + private static void ShowAboutDialog() + { + var aboutForm = new AboutDialog(); + aboutForm.ShowDialog(); + } + + #region ICommandBarsAdapterClient support + + public void SubscribeToCommandBarAdapter(VbeCommandBarAdapter commandBarAdapter) + { + using (new BlockLogger()) + { + if (!(commandBarAdapter is AccUnitCommandBarAdapter accUnitCommandBarAdapter)) return; + + var popUp = accUnitCommandBarAdapter.AccUnitSubMenu; + CreateCommandBarItems(commandBarAdapter, popUp); + } + } + + private void CreateCommandBarItems(VbeCommandBarAdapter commandBarAdapter, CommandBarPopup popUp) + { + var buttonData = new CommandbarButtonData + { + Caption = Resources.VbeCommandbars.ToolsUserSettingFormCommandbarButtonCaption, + Description = string.Empty, + FaceId = 222, + BeginGroup = true + }; + commandBarAdapter.AddCommandBarButton(popUp, buttonData, AccUnitMenuItemsShowUserSettingForm); + + buttonData = new CommandbarButtonData + { + Caption = Resources.VbeCommandbars.ToolsAboutCommandbarButtonCaption, + Description = string.Empty, + FaceId = 487, + BeginGroup = true + }; + commandBarAdapter.AddCommandBarButton(popUp, buttonData, AccUnitMenuItemsShowAboutForm); + } + + static void AccUnitMenuItemsShowAboutForm(CommandBarButton ctrl, ref bool cancelDefault) + { + ShowAboutDialog(); + } + + void AccUnitMenuItemsShowUserSettingForm(CommandBarButton ctrl, ref bool cancelDefault) + { + try + { + /* + var dialog = new SettingsWindow(new SettingsViewModel()); + dialog.ShowDialog(); + */ + + using (var settingDialog = new UserSettingDialog()) + { + settingDialog.Settings = UserSettings.Current.Clone(); + if (settingDialog.ShowDialog() == DialogResult.OK) + { + UserSettings.Current = settingDialog.Settings as UserSettings; + UserSettings.Current?.Save(); + RefreshTestTemplates?.Invoke(this, null); + } + } + } + catch (Exception ex) + { + UITools.ShowException(ex); + } + } + + #endregion + + } +} diff --git a/vbe-add-In/AccUnit.VbeAddIn/Properties/AssemblyInfo.cs b/vbe-add-In/AccUnit.VbeAddIn/Properties/AssemblyInfo.cs index a57c307..94a6212 100644 --- a/vbe-add-In/AccUnit.VbeAddIn/Properties/AssemblyInfo.cs +++ b/vbe-add-In/AccUnit.VbeAddIn/Properties/AssemblyInfo.cs @@ -9,7 +9,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("access-codelib.net")] [assembly: AssemblyProduct("AccUnit VBE Add-in")] -[assembly: AssemblyCopyright("Copyright © 2024")] +[assembly: AssemblyCopyright("© 2010-2024")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -31,5 +31,5 @@ // Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, // indem Sie "*" wie unten gezeigt eingeben: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.9.1.0")] -[assembly: AssemblyFileVersion("0.9.1.0")] +[assembly: AssemblyVersion("0.9.2.0")] +[assembly: AssemblyFileVersion("0.9.2.0")] diff --git a/vbe-add-In/AccUnit.VbeAddIn/SimpleLinkLabel.cs b/vbe-add-In/AccUnit.VbeAddIn/SimpleLinkLabel.cs new file mode 100644 index 0000000..d989dac --- /dev/null +++ b/vbe-add-In/AccUnit.VbeAddIn/SimpleLinkLabel.cs @@ -0,0 +1,30 @@ +using System.Diagnostics; +using System.Windows.Forms; + +namespace AccessCodeLib.AccUnit.VbeAddIn +{ + public class SimpleLinkLabel : LinkLabel + { + public override string Text + { + get { return base.Text; } + set + { + base.Text = value; + var url = base.Text; + Links.Clear(); + Links.Add(0, url.Length, url); + } + } + + protected override void OnLinkClicked(LinkLabelLinkClickedEventArgs e) + { + base.OnLinkClicked(e); + var psi = new ProcessStartInfo { + UseShellExecute = true, + FileName = e.Link.LinkData.ToString() + }; + Process.Start(psi); + } + } +} \ No newline at end of file diff --git a/vbe-add-In/AccUnit.VbeAddIn/TestExplorer/TestExplorerManager.cs b/vbe-add-In/AccUnit.VbeAddIn/TestExplorer/TestExplorerManager.cs index 352c994..a90cf51 100644 --- a/vbe-add-In/AccUnit.VbeAddIn/TestExplorer/TestExplorerManager.cs +++ b/vbe-add-In/AccUnit.VbeAddIn/TestExplorer/TestExplorerManager.cs @@ -7,7 +7,7 @@ namespace AccessCodeLib.AccUnit.VbeAddIn.TestExplorer { - internal class TestExplorerManager : ITestResultReporter, ICommandBarsAdapterClient + internal class TestExplorerManager : ITestResultReporter, ICommandBarsAdapterClient, IDisposable { private readonly VbeUserControl _vbeUserControl; private readonly TestExplorerViewModel _viewModel; @@ -143,5 +143,49 @@ private void FillTestsFromVbProject() } #endregion + + #region IDisposable Support + + bool _disposed; + + protected virtual void Dispose(bool disposing) + { + if (_disposed) return; + + if (disposing) + { + DisposeManagedResources(); + } + + DisposeUnmanagedResources(); + _disposed = true; + } + + private void DisposeUnmanagedResources() + { + _testResultCollector = null; + } + + private void DisposeManagedResources() + { + _vbeUserControl.Dispose(); + } + + public void Dispose() + { + using (new BlockLogger()) + { + Dispose(true); + GC.SuppressFinalize(this); + } + } + + ~TestExplorerManager() + { + Dispose(false); + } + + #endregion + } } diff --git a/vbe-add-In/AccUnit.VbeAddIn/UserSettingDialog.Designer.cs b/vbe-add-In/AccUnit.VbeAddIn/UserSettingDialog.Designer.cs new file mode 100644 index 0000000..8fb37ce --- /dev/null +++ b/vbe-add-In/AccUnit.VbeAddIn/UserSettingDialog.Designer.cs @@ -0,0 +1,75 @@ +namespace AccessCodeLib.AccUnit.VbeAddIn +{ + partial class UserSettingDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(UserSettingDialog)); + this.SettingPropertyGrid = new System.Windows.Forms.PropertyGrid(); + this.OkBtn = new System.Windows.Forms.Button(); + this.CancelBtn = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // SettingPropertyGrid + // + resources.ApplyResources(this.SettingPropertyGrid, "SettingPropertyGrid"); + this.SettingPropertyGrid.Name = "SettingPropertyGrid"; + // + // OkBtn + // + resources.ApplyResources(this.OkBtn, "OkBtn"); + this.OkBtn.DialogResult = System.Windows.Forms.DialogResult.OK; + this.OkBtn.Name = "OkBtn"; + this.OkBtn.UseVisualStyleBackColor = true; + // + // CancelBtn + // + resources.ApplyResources(this.CancelBtn, "CancelBtn"); + this.CancelBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel; + this.CancelBtn.Name = "CancelBtn"; + this.CancelBtn.UseVisualStyleBackColor = true; + // + // UserSettingDialog + // + this.AcceptButton = this.OkBtn; + resources.ApplyResources(this, "$this"); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.CancelBtn); + this.Controls.Add(this.OkBtn); + this.Controls.Add(this.SettingPropertyGrid); + this.Name = "UserSettingDialog"; + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.PropertyGrid SettingPropertyGrid; + protected System.Windows.Forms.Button CancelBtn; + private System.Windows.Forms.Button OkBtn; + } +} \ No newline at end of file diff --git a/vbe-add-In/AccUnit.VbeAddIn/UserSettingDialog.cs b/vbe-add-In/AccUnit.VbeAddIn/UserSettingDialog.cs new file mode 100644 index 0000000..dbb8020 --- /dev/null +++ b/vbe-add-In/AccUnit.VbeAddIn/UserSettingDialog.cs @@ -0,0 +1,26 @@ +using System.Windows.Forms; + +namespace AccessCodeLib.AccUnit.VbeAddIn +{ + public partial class UserSettingDialog : Form + { + public UserSettingDialog() + { + InitializeComponent(); + Icon = UITools.ConvertBitmapToIcon(Resources.Icons.settings); + } + + public object Settings + { + get + { + return SettingPropertyGrid.SelectedObject; + } + set + { + SettingPropertyGrid.SelectedObject = value; + } + } + + } +} diff --git a/vbe-add-In/AccUnit.VbeAddIn/UserSettingDialog.de.resx b/vbe-add-In/AccUnit.VbeAddIn/UserSettingDialog.de.resx new file mode 100644 index 0000000..b85b4eb --- /dev/null +++ b/vbe-add-In/AccUnit.VbeAddIn/UserSettingDialog.de.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + &Abbrechen + + + AccUnit Einstellungen + + \ No newline at end of file diff --git a/vbe-add-In/AccUnit.VbeAddIn/UserSettingDialog.resx b/vbe-add-In/AccUnit.VbeAddIn/UserSettingDialog.resx new file mode 100644 index 0000000..93a3395 --- /dev/null +++ b/vbe-add-In/AccUnit.VbeAddIn/UserSettingDialog.resx @@ -0,0 +1,228 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + Top, Bottom, Left, Right + + + + 0, 0 + + + 561, 449 + + + + 0 + + + SettingPropertyGrid + + + System.Windows.Forms.PropertyGrid, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 2 + + + Bottom, Left + + + 15, 465 + + + 114, 27 + + + 1 + + + &OK + + + OkBtn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 1 + + + Bottom, Right + + + 433, 465 + + + 114, 27 + + + 2 + + + &Cancel + + + CancelBtn + + + System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 0 + + + True + + + 7, 15 + + + GrowAndShrink + + + 561, 505 + + + Segoe UI, 9pt + + + CenterParent + + + AccUnit Settings + + + UserSettingDialog + + + System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/vbe-add-In/AccUnit.VbeAddIn/UserSettings.cs b/vbe-add-In/AccUnit.VbeAddIn/UserSettings.cs new file mode 100644 index 0000000..d93c51f --- /dev/null +++ b/vbe-add-In/AccUnit.VbeAddIn/UserSettings.cs @@ -0,0 +1,181 @@ +using AccessCodeLib.AccUnit.Tools.Templates; +using AccessCodeLib.Common.Tools.Logging; +using System; +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Drawing.Design; + +namespace AccessCodeLib.AccUnit.VbeAddIn +{ + public class UserSettings + { + #region Static members + + /// + /// Unloads the previously loaded instance provided via property Current. + /// This method is mainly needed to support testing the singleton implementation in property Current. + /// + public static void UnloadCurrent() + { + _current = null; + AccUnit.UserSettings.UnloadCurrent(); + Tools.UserSettings.UnloadCurrent(); + } + + private static UserSettings _current; + public static UserSettings Current + { + get + { + if (_current == null) + { + _current = new UserSettings(); + _current.Load(); + } + return _current; + } + set + { + _current = value ?? throw new ArgumentNullException(); + } + } + + #endregion + + private AccUnit.UserSettings _testSuiteUserSettings; + private Tools.UserSettings _toolsUserSettings; + //private AccSpec.Integration.UserSettings _accSpecUserSettings; + + private UserSettings() + { + } + + public UserSettings Clone() + { + using (new BlockLogger()) + { + var clone = new UserSettings + { + _testSuiteUserSettings = AccUnit.UserSettings.Current.Clone(), + _toolsUserSettings = Tools.UserSettings.Current.Clone(), + //_accSpecUserSettings = AccSpec.Integration.UserSettings.Current.Clone(), + RestoreVbeWindowsStateOnLoad = RestoreVbeWindowsStateOnLoad, + TestClassNameFormat = Properties.Settings.Default.TestClassNameFormat + }; + return clone; + } + } + + #region Load/Save + + private void Load() + { + using (new BlockLogger()) + { + _testSuiteUserSettings = AccUnit.UserSettings.Current.Clone(); + _toolsUserSettings = Tools.UserSettings.Current.Clone(); + //_accSpecUserSettings = AccSpec.Integration.UserSettings.Current.Clone(); + RestoreVbeWindowsStateOnLoad = Properties.Settings.Default.RestoreVbeWindowsStateOnLoad; + TestClassNameFormat = Properties.Settings.Default.TestClassNameFormat; + } + } + + public void Save() + { + AccUnit.UserSettings.Current = _testSuiteUserSettings; + AccUnit.UserSettings.Current.Save(); + Tools.UserSettings.Current = _toolsUserSettings; + Tools.UserSettings.Current.Save(); + /* + * AccSpec.Integration.UserSettings.Current = _accSpecUserSettings; + AccSpec.Integration.UserSettings.Current.Save(); + */ + Properties.Settings.Default.RestoreVbeWindowsStateOnLoad = RestoreVbeWindowsStateOnLoad; + Properties.Settings.Default.TestClassNameFormat = TestClassNameFormat; + } + + #endregion + + #region Setting Properties + + [Category("Add-in")] + [DefaultValue("%ModuleUnderTest%Tests")] + [Description("Naming convention for test classes. Example: %ModuleUnderTest%Tests")] + public string TestClassNameFormat { get; set; } + + [Category("Add-in")] + [DefaultValue(false)] + [Description("Save last state of treeview window on unload and restore window on load (if visible)")] + // ReSharper disable MemberCanBePrivate.Global + public bool RestoreVbeWindowsStateOnLoad { get; set; } + // ReSharper restore MemberCanBePrivate.Global + + #region Tools + + [Category("Import/Export")] + [DefaultValue(@"%APPFOLDER%\Tests\%APPNAME%")] + [Description("Import and export folder for test classes\n%APPFOLDER% ... Path to current mdb/accdb\n%APPNAME% ... Filename of mdb/accdb")] + public string ImportExportFolder + { + get { return _testSuiteUserSettings.ImportExportFolder; } + set { _testSuiteUserSettings.ImportExportFolder = value.TrimEnd('\\', ' ').TrimStart(); } + } + + [Category("Templates")] + [DefaultValue(@"%APPDATA%\AccessCodeLib\AccUnit\Templates")] + [Description("Location of template files")] + public string TemplateFolder + { + get { return _toolsUserSettings.TemplateFolder; } + set { _toolsUserSettings.TemplateFolder = value.TrimEnd('\\', ' ').TrimStart(); } + } + + [Browsable(false)] + public TestTemplateCollection TestTemplates + { + get + { + using (new BlockLogger()) + { + return _toolsUserSettings.TestTemplates; + } + } + } + + [Category("Templates")] + [Description("Collection of test class templates")] + public TestTemplateCollection UserDefinedTemplates + { + get + { + using (new BlockLogger()) + { + return _toolsUserSettings.UserDefinedTemplates; + } + } + } + + [Category("Templates")] + [Description("Template for test methods")] + [DefaultValue(@"Public Sub {MethodUnderTest}_{StateUnderTest}_{ExpectedBehaviour}({Params}) + ' Arrange + Err.Raise vbObjectError, ""{MethodUnderTest}_{StateUnderTest}_{ExpectedBehaviour}"", ""Test not implemented"" + Const Expected As Variant = ""expected value"" + Dim Actual As Variant + ' Act + Actual = ""actual value"" + ' Assert + Assert.That Actual, Iz.EqualTo(Expected) +End Sub")] + [Editor(typeof(MultilineStringEditor), typeof(UITypeEditor))] + public string TestMethodTemplate + { + get { return _toolsUserSettings.TestMethodTemplate; } + set { _toolsUserSettings.TestMethodTemplate = value; } + } + + #endregion + + #endregion + } +} diff --git a/vbe-add-In/lib/VbeUserControlHost/AccessCodeLib.Common.VbeUserControlHost.dll b/vbe-add-In/lib/VbeUserControlHost/AccessCodeLib.Common.VbeUserControlHost.dll index 50a8b80..4aa530d 100644 Binary files a/vbe-add-In/lib/VbeUserControlHost/AccessCodeLib.Common.VbeUserControlHost.dll and b/vbe-add-In/lib/VbeUserControlHost/AccessCodeLib.Common.VbeUserControlHost.dll differ