Skip to content

Commit

Permalink
Merge pull request #57 from baSSiLL/auto-close-checked
Browse files Browse the repository at this point in the history
Auto close for checked components
  • Loading branch information
dblock committed Nov 14, 2013
2 parents 3ac3f32 + a14b8b5 commit 68bc195
Show file tree
Hide file tree
Showing 10 changed files with 234 additions and 43 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ Features
Bugs
----

* [#41](https://github.com/dblock/dotnetinstaller/pull/41): Fix: When an uninstall successfully completes, pop `uninstallcompletemessage` message box instead of `installcompletemessage` - [@montrowe](https://github.com/montrowe).
* [#41](https://github.com/dblock/dotnetinstaller/pull/41) - Fix: When an uninstall successfully completes, pop `uninstallcompletemessage` message box instead of `installcompletemessage` - [@montrowe](https://github.com/montrowe).
* [#18](https://github.com/dblock/dotnetinstaller/issues/18) - Installer should auto close when all checked components are installed - [@baSSiLL](https://github.com/baSSiLL).

Misc
--------
Expand Down
135 changes: 127 additions & 8 deletions UnitTests/dotNetInstallerUnitTests/AutoCloseUnitTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,20 @@ namespace dotNetInstallerUnitTests
public class AutoCloseUnitTests
{
[Test]
public void TestAutoCloseIfInstalledWithComponentInstallSuccess()
public void TestAutoClosesAfterInstallWhenComponentInstallSucceeds()
{
Console.WriteLine("TestAutoCloseIfInstalledWithComponentInstallSuccess");
Console.WriteLine("TestAutoClosesAfterInstallWhenComponentInstallSucceeds");

//configuration with a component that will run and succeed and so dni will auto close
// configuration with a component that will run and succeed and so dni will auto close

// marker that makes installed check succeeed after installation
// marker that makes installed check succeed after installation
string markerFilename = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());

ConfigFile configFile = new ConfigFile();
SetupConfiguration setupConfiguration = new SetupConfiguration();
setupConfiguration.auto_start = true;
setupConfiguration.auto_close_if_installed = true;
setupConfiguration.installation_completed = null;
configFile.Children.Add(setupConfiguration);

// dummy component
Expand All @@ -45,24 +46,28 @@ public void TestAutoCloseIfInstalledWithComponentInstallSuccess()
Console.WriteLine("Writing '{0}'", configFilename);
configFile.SaveAs(configFilename);

dotNetInstallerExeUtils.RunOptions options = new dotNetInstallerExeUtils.RunOptions(configFilename);
options.quiet = false;

// will auto close since all components installed successfully
Assert.AreEqual(0, dotNetInstallerExeUtils.Run(configFilename));
Assert.AreEqual(0, dotNetInstallerExeUtils.Run(options, TimeSpan.FromSeconds(3)));

File.Delete(configFilename);
File.Delete(markerFilename);
}

[Test]
public void TestAutoCloseIfInstalledWithComponentInstallFailure()
public void TestNotAutoClosesAfterInstallWhenComponentInstallFails()
{
Console.WriteLine("TestAutoCloseIfInstalledWithComponentInstallFailure");
Console.WriteLine("TestNotAutoClosesAfterInstallWhenComponentInstallFails");

//configuration with a component that will run and fail and so dni will not auto close
// configuration with a component that will run and fail and so dni will not auto close

ConfigFile configFile = new ConfigFile();
SetupConfiguration setupConfiguration = new SetupConfiguration();
setupConfiguration.auto_start = true;
setupConfiguration.auto_close_if_installed = true;
setupConfiguration.installation_completed = null;
setupConfiguration.failed_exec_command_continue = string.Empty;
configFile.Children.Add(setupConfiguration);

Expand Down Expand Up @@ -95,5 +100,119 @@ public void TestAutoCloseIfInstalledWithComponentInstallFailure()

File.Delete(configFilename);
}

[Test]
public void TestAutoClosesBeforeInstallWhenComponentIsAlreadyInstalled()
{
Console.WriteLine("TestAutoClosesBeforeInstallWhenComponentIsAlreadyInstalled");

// configuration with a component that is already installed and so dni will auto close

// marker that makes installed check succeed before installation
string markerFilename = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
File.Create(markerFilename).Close();

ConfigFile configFile = new ConfigFile();
SetupConfiguration setupConfiguration = new SetupConfiguration();
setupConfiguration.auto_start = true;
setupConfiguration.auto_close_if_installed = true;
setupConfiguration.installation_completed = null;
setupConfiguration.installation_none = null;
setupConfiguration.supports_uninstall = false; // prevent switching to uninstall
configFile.Children.Add(setupConfiguration);

// dummy component
ComponentCmd component = new ComponentCmd();
setupConfiguration.Children.Add(component);
component.required_install = true;
component.supports_install = true;
component.command = string.Format("cmd.exe /C dir > \"{0}\"", markerFilename);

InstalledCheckFile check = new InstalledCheckFile();
check.filename = markerFilename;
check.comparison = installcheckfile_comparison.exists;
component.Children.Add(check);

string configFilename = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".xml");
Console.WriteLine("Writing '{0}'", configFilename);
configFile.SaveAs(configFilename);

dotNetInstallerExeUtils.RunOptions options = new dotNetInstallerExeUtils.RunOptions(configFilename);
options.quiet = false;

// will auto close since all components are already installed
Assert.AreEqual(0, dotNetInstallerExeUtils.Run(options, TimeSpan.FromSeconds(3)));

File.Delete(configFilename);
File.Delete(markerFilename);
}

[Test]
public void TestAutoClosesAfterInstallWhenCheckedComponentsInstallSucceeds()
{
Console.WriteLine("TestAutoClosesAfterInstallWhenCheckedComponentsInstallSucceeds");

// configuration with two selected components and one unselected component
// selected components will run and succeed, and so dni will auto close

// marker that makes installed check succeed after installation
string markerFilename1 = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
string markerFilename2 = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());

ConfigFile configFile = new ConfigFile();
SetupConfiguration setupConfiguration = new SetupConfiguration();
setupConfiguration.auto_start = true;
setupConfiguration.auto_close_if_installed = true;
setupConfiguration.installation_completed = null;
configFile.Children.Add(setupConfiguration);

// required and selected component
ComponentCmd component1 = new ComponentCmd();
setupConfiguration.Children.Add(component1);
component1.required_install = true;
component1.selected_install = true;
component1.supports_install = true;
component1.command = string.Format("cmd.exe /C dir > \"{0}\"", markerFilename1);

InstalledCheckFile check1 = new InstalledCheckFile();
check1.filename = markerFilename1;
check1.comparison = installcheckfile_comparison.exists;
component1.Children.Add(check1);

// optional and selected component
ComponentCmd component2 = new ComponentCmd();
setupConfiguration.Children.Add(component2);
component2.required_install = false;
component2.selected_install = true;
component2.supports_install = true;
component2.command = string.Format("cmd.exe /C dir > \"{0}\"", markerFilename2);

InstalledCheckFile check2 = new InstalledCheckFile();
check2.filename = markerFilename2;
check2.comparison = installcheckfile_comparison.exists;
component2.Children.Add(check2);

// optional and unselected component
ComponentCmd component3 = new ComponentCmd();
setupConfiguration.Children.Add(component3);
component3.required_install = false;
component3.selected_install = false;
component3.supports_install = true;
component3.command = "cmd.exe /C exit /b 1";

string configFilename = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".xml");
Console.WriteLine("Writing '{0}'", configFilename);
configFile.SaveAs(configFilename);

dotNetInstallerExeUtils.RunOptions options = new dotNetInstallerExeUtils.RunOptions(configFilename);
options.quiet = false;

// will auto close since all checked components were installed
Assert.AreEqual(0, dotNetInstallerExeUtils.Run(options, TimeSpan.FromSeconds(6)));

File.Delete(configFilename);
File.Delete(markerFilename1);
File.Delete(markerFilename2);
}
}
}
28 changes: 27 additions & 1 deletion UnitTests/dotNetUnitTestsRunner/dotNetInstallerExeUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,35 @@ public static int Run(string configFile)
}

public static int Run(RunOptions options)
{
return Run(options, new TimeSpan(-1));
}

/// <summary>
/// Runs the installer and waits till its exit for a specified timeout.
/// </summary>
/// <param name="options">Run options.</param>
/// <param name="timeout">Timeout. Negative values mean "no timeout".</param>
/// <returns>Exit code of the installer process.</returns>
/// <exception cref="TimeoutException">
/// Timeout exceeded while waiting for the installer process to exit.
/// </exception>
public static int Run(RunOptions options, TimeSpan timeout)
{
Process p = Detach(options);
p.WaitForExit();
if (timeout < TimeSpan.Zero)
{
p.WaitForExit();
}
else
{
if (!p.WaitForExit((int)timeout.TotalMilliseconds))
{
p.Kill();
p.WaitForExit();
throw new TimeoutException();
}
}
return p.ExitCode;
}

Expand Down
2 changes: 1 addition & 1 deletion dotNetInstaller/ComponentsList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ void CComponentsList::OnLButtonDblClk(UINT nFlags, CPoint point)
Exec(component);
if (m_pExecuteCallback)
{
m_pExecuteCallback->LoadComponentsList();
m_pExecuteCallback->LoadComponentsList(false);
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions dotNetInstaller/dotNetInstallerDlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,10 +255,10 @@ void CdotNetInstallerDlg::OnBnClickedInstall()
}
}

// returns true if all components have been installed
ComponentsStatus CdotNetInstallerDlg::LoadComponentsList()
// returns install state of the components
ComponentsStatus CdotNetInstallerDlg::LoadComponentsList(bool autoSetChecked)
{
ComponentsStatus rc = InstallerUI::LoadComponentsList();
ComponentsStatus rc = InstallerUI::LoadComponentsList(autoSetChecked);
InstallConfiguration * pConfiguration = reinterpret_cast<InstallConfiguration *>(get(m_configuration));
CHECK_BOOL(pConfiguration != NULL, L"Invalid configuration");
m_ListBoxComponents.Load(pConfiguration);
Expand Down
2 changes: 1 addition & 1 deletion dotNetInstaller/dotNetInstallerDlg.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class CdotNetInstallerDlg : public CDialog, public IExecuteCallback, public Inst
CStatic m_PictureBox;
CStatic m_lblOperatingSystem;
afx_msg void OnBnClickedInstall();
ComponentsStatus LoadComponentsList();
ComponentsStatus LoadComponentsList(bool autoSetChecked);
CHyperlinkStatic m_InfoLink;
afx_msg void OnDestroy();
afx_msg void OnBnClickedCancel();
Expand Down
7 changes: 7 additions & 0 deletions dotNetInstallerLib/ComponentStatus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
ComponentsStatus::ComponentsStatus()
: m_all_required(true)
, m_all_optional(true)
, m_all_checked(true)
{

}
Expand All @@ -17,6 +18,7 @@ ComponentsStatus& ComponentsStatus::operator=(const ComponentsStatus& s)
{
m_all_required = s.all_required();
m_all_optional = s.all_optional();
m_all_checked = s.all_checked();
return * this;
}

Expand All @@ -29,3 +31,8 @@ void ComponentsStatus::add_optional(bool value)
{
m_all_optional &= value;
}

void ComponentsStatus::add_checked(bool value)
{
m_all_checked &= value;
}
3 changes: 3 additions & 0 deletions dotNetInstallerLib/ComponentsStatus.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ class ComponentsStatus
private:
bool m_all_required;
bool m_all_optional;
bool m_all_checked;
public:
bool all_required() const { return m_all_required; }
bool all_optional() const { return m_all_optional; }
bool all_checked() const { return m_all_checked; }
bool all() const { return all_required() && all_optional(); }
void add_required(bool value);
void add_optional(bool value);
void add_checked(bool value);
ComponentsStatus();
ComponentsStatus(const ComponentsStatus&);
ComponentsStatus& operator=(const ComponentsStatus&);
Expand Down

0 comments on commit 68bc195

Please sign in to comment.