Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

- refactored unit tests, embedded /data as a resource so the unit test

dl can be run from anywhere (Zac Ruiz)
- helper methods for zip class (contains(), hasRootFolder())  (Zac Ruiz)
- Create a root folder for the zip if it doesn't have one, instead of 
extracting tons of files to c:\program files (Zac 
Ruiz)
  • Loading branch information...
commit a8d3853fe7649f81d867b3324bf93f98c4398eec 1 parent 921db53
@philc authored
View
3  Changelog.txt
@@ -1,5 +1,8 @@
0.5
+- refactored unit tests, embedded /data as a resource so the unit test dl can be run from anywhere (Zac Ruiz)
+- helper methods for zip class (contains(), hasRootFolder()) (Zac Ruiz)
+- Create a root folder for the zip if it doesn't have one, instead of extracting tons of files to c:\program files (Zac Ruiz)
- Bugfix: If there is an error writing our applist back to disk, backup the original file and then restore it so it is not lost (Craig Reynolds)
- Turned on double buffering for the ApplicationListItem control. Makes resizing a little faster.
View
6 InstallPadTest/App.config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+ <appSettings>
+ <add key="sambaPath" value="\\kagero\incoming\test\"/>
+ </appSettings>
+</configuration>
View
55 InstallPadTest/BaseTestFixture.cs
@@ -0,0 +1,55 @@
+//
+// Author: Phil Crosby
+//
+
+// Copyright (C) 2006 Phil Crosby
+// Permission is granted to use, copy, modify, and merge copies
+// of this software for personal use. Permission is not granted
+// to use or change this software for commercial use or commercial
+// redistribution. Permission is not granted to use, modify or
+// distribute this software internally within a corporation.
+
+using System;
+using System.IO;
+
+using NUnit.Framework;
+
+namespace InstallPadTest
+{
+ public class BaseTestFixture
+ {
+ protected readonly string DATA_DIRECTORY = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "data");
+ protected readonly string OUTPUT_DIRECTORY = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "output");
+
+ [TestFixtureSetUp]
+ public void TestFixtureSetUp()
+ {
+ InstallPadTest.ExtractToFile(DATA_DIRECTORY, "data", ".txt");
+ InstallPadTest.ExtractToFile(DATA_DIRECTORY, "data", ".zip");
+
+ Directory.CreateDirectory(OUTPUT_DIRECTORY);
+ }
+
+ [TestFixtureTearDown]
+ public void TestFixtureTearDown()
+ {
+ Directory.Delete(DATA_DIRECTORY, true);
+ Directory.Delete(OUTPUT_DIRECTORY, true);
+ }
+
+ [SetUp]
+ public void SetUp()
+ {
+ }
+
+ [TearDown]
+ public void TearDown()
+ {
+ // clean output directory
+ foreach (string f in Directory.GetFiles(OUTPUT_DIRECTORY))
+ {
+ File.Delete(f);
+ }
+ }
+ }
+}
View
220 InstallPadTest/DownloaderTest.cs
@@ -10,34 +10,37 @@
// distribute this software internally within a corporation.
using System;
-using System.Collections.Generic;
-using System.Text;
using System.IO;
+using System.Text;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Configuration;
+
using NUnit.Framework;
+
using CodeProject.Downloader;
-using System.Diagnostics;
-namespace InstallPadTest
+namespace InstallPadTest
{
[TestFixture]
- public class DownloaderTest
+ public class DownloaderTestFixture : BaseTestFixture
{
- Dictionary<string, long> fileSizes = new Dictionary<string, long>();
- List<string> badUrls = new List<string>();
-
- // Where the test files be
- string dataDirectory = "../../data/";
+ #region Fields and Ctor
+ private List<string> badUrls = new List<string>();
+ private Dictionary<string, long> fileSizes = new Dictionary<string, long>();
- // Used for loading test files from a windows share
- private static readonly string sambaPath = @"\\kagero\incoming\test\";
+ // Used for loading test files from a windows share.
+ private static readonly string sambaPath = ConfigurationManager.AppSettings["sambaPath"];
- private static readonly string firefoxFtpUrl =
- "ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/1.5/win32/en-US/Firefox%20Setup%201.5.exe";
+ private static readonly string firefoxFtpUrl = "ftp://ftp.mozilla.org/pub/mozilla.org/firefox/releases/1.5/win32/en-US/Firefox%20Setup%201.5.exe";
- private string NonEmptyFile;
+ private string NonEmptyFile = string.Empty;
private string malformedUrl = "!@#$%badUrl";
- public DownloaderTest()
+ private FileDownloader cancelTestDownloader;
+ private FileDownloader downloadFtpTestDownloader;
+
+ public DownloaderTestFixture()
{
fileSizes.Add("test1.txt", 0);
fileSizes.Add("test2.txt", 98);
@@ -50,22 +53,26 @@ public DownloaderTest()
badUrls.Add("ftp://ftp.mozilla.org/pub/i-dont-exist");
badUrls.Add("file://c:/doesNotExist.txt");
}
- [SetUp]
- public void SetUp(){
- }
+ #endregion
+ #region Test Download HTTP
[Test]
public void DownloadHttp()
{
FileDownloader downloader = new FileDownloader();
foreach (String s in fileSizes.Keys)
{
- downloader.Download(InstallPadTest.GetDownloadPath(s));
+ downloader.Download(InstallPadTest.GetDownloadPath(s), OUTPUT_DIRECTORY);
+
+ string fi = Path.Combine(OUTPUT_DIRECTORY, s);
// Veryify file exists and is the correct size
- Assert.IsTrue(InstallPadTest.VerifyExistenceAndSize(s, fileSizes[s]));
- }
+ Assert.IsTrue(InstallPadTest.VerifyExistenceAndSize(fi, fileSizes[s]));
+ }
}
+ #endregion
+
+ #region Test Download FTP
[Test]
public void DownloadFtp()
{
@@ -74,41 +81,68 @@ public void DownloadFtp()
// We expect no exceptions
downloadFtpTestDownloader = new FileDownloader();
downloadFtpTestDownloader.ProgressChanged += new DownloadProgressHandler(DownloadFtp_ProgressChanged);
- downloadFtpTestDownloader.Download(firefoxFtpUrl);
+ downloadFtpTestDownloader.Download(firefoxFtpUrl, OUTPUT_DIRECTORY);
+
+ string fi = Path.Combine(OUTPUT_DIRECTORY, Path.GetFileName(new Uri(firefoxFtpUrl).ToString()));
// Ensure the file size is 1KB, meaning we were notified of progress information
// and Cancel worked.
- info = new FileInfo(Path.GetFileName(new Uri(firefoxFtpUrl).ToString()));
+ info = new FileInfo(fi);
Assert.AreEqual(info.Length, 1024);
// Trying (and failing) to resume an ftp source should result
// in the file getting deleted and starting over at 0 KB.
- downloadFtpTestDownloader.Download(firefoxFtpUrl);
- info = new FileInfo(Path.GetFileName(new Uri(firefoxFtpUrl).ToString()));
- Assert.AreEqual(info.Length, 1024);
+ downloadFtpTestDownloader.Download(firefoxFtpUrl, OUTPUT_DIRECTORY);
+ info = new FileInfo(fi);
+ Assert.AreEqual(info.Length, 1024);
}
+ #endregion
+ #region Test Download File
[Test]
public void DownloadFile()
{
FileDownloader downloader = new FileDownloader();
foreach (String s in fileSizes.Keys)
{
- string fileUrl = "file:///" + Path.GetFullPath(dataDirectory + s);
- downloader.Download(fileUrl);
+ string fileUrl = "file:///" + Path.Combine(DATA_DIRECTORY, s);
+
+ downloader.Download(fileUrl, OUTPUT_DIRECTORY);
+
+ string fi = Path.Combine(OUTPUT_DIRECTORY, s);
// Veryify file exists and is the correct size
- Assert.IsTrue(InstallPadTest.VerifyExistenceAndSize(s, fileSizes[s]));
+ Assert.IsTrue(InstallPadTest.VerifyExistenceAndSize(fi, fileSizes[s]));
}
- // Download them from a windows share
- foreach (String s in fileSizes.Keys)
+ }
+ #endregion
+
+ #region Test Download File From Windows Share
+ [Test]
+ public void DownloadFileFromWindowsShare()
+ {
+ FileDownloader downloader = new FileDownloader();
+
+ // Download them from a windows share. We could get a C# MapDrive() function to allow this portion of the
+ // test not to rely on a hardcoded share path.
+ if (Directory.Exists(sambaPath))
{
- string fileUrl = "file:///" + sambaPath + s;
- downloader.Download(fileUrl);
- Assert.IsTrue(InstallPadTest.VerifyExistenceAndSize(s, fileSizes[s]));
+ foreach (String s in fileSizes.Keys)
+ {
+ string fileUrl = "file:///" + sambaPath + s;
+ downloader.Download(fileUrl, OUTPUT_DIRECTORY);
+ string fi = Path.Combine(OUTPUT_DIRECTORY, s);
+ Assert.IsTrue(InstallPadTest.VerifyExistenceAndSize(fi, fileSizes[s]));
+ }
+ }
+ else
+ {
+ Assert.Ignore("Test ignored because share is not mapped or may not exist.");
}
}
+ #endregion
+ #region Test Download Alternate Location
[Test]
public void DownloadFileWithAlternate()
{
@@ -116,9 +150,7 @@ public void DownloadFileWithAlternate()
FileDownloader downloader = new FileDownloader();
foreach (String s in fileSizes.Keys)
{
- string fileUrl = "file:///" + Path.GetFullPath(dataDirectory + s);
- string output = Path.GetFullPath(dataDirectory + "alternate");
- Directory.CreateDirectory(output);
+ string fileUrl = "file:///" + Path.Combine(DATA_DIRECTORY, s);
List<string> urlList = new List<string>();
@@ -126,59 +158,50 @@ public void DownloadFileWithAlternate()
urlList.Add(fileUrl);
urlList.Add("file://somebadpath"+s);
- downloader.Download(urlList,output);
+ downloader.Download(urlList, OUTPUT_DIRECTORY);
- // Veryify file exists and is the correct size
- Assert.IsTrue(InstallPadTest.VerifyExistenceAndSize(Path.Combine(output, s), fileSizes[s]));
+ // Veryify file exists and is the correct size
+ Assert.IsTrue(InstallPadTest.VerifyExistenceAndSize(Path.Combine(OUTPUT_DIRECTORY, s), fileSizes[s]));
}
- // Download them from a windows share
- foreach (String s in fileSizes.Keys)
- {
- string fileUrl = "file:///" + sambaPath + s;
+ }
+ #endregion
- List<string> urlList = new List<string>();
+ #region Test Download Alternate Location From Windows Share
+ [Test]
+ public void DownloadFileWithAlternateFromWindowsShare()
+ {
+ // These download URLs need to be changed
+ FileDownloader downloader = new FileDownloader();
- urlList.Add("file://somebadpath"+s);
- urlList.Add(fileUrl);
- urlList.Add("file://somebadpath"+s);
+ // Download them from a windows share. We could get a C# MapDrive() function to allow this portion of the
+ // test not to rely on a hardcoded SAMBA path.
+ if (Directory.Exists(sambaPath))
+ {
+ foreach (String s in fileSizes.Keys)
+ {
+ string fileUrl = "file:///" + sambaPath + s;
- downloader.Download(urlList);
+ List<string> urlList = new List<string>();
- Assert.IsTrue(InstallPadTest.VerifyExistenceAndSize(s, fileSizes[s]));
- }
- }
+ urlList.Add("file://somebadpath" + s);
+ urlList.Add(fileUrl);
+ urlList.Add("file://somebadpath" + s);
- FileDownloader downloadFtpTestDownloader;
+ downloader.Download(urlList, OUTPUT_DIRECTORY);
- void DownloadFtp_ProgressChanged(object sender, DownloadEventArgs e)
- {
- downloadFtpTestDownloader.Cancel();
- }
+ string fi = Path.Combine(OUTPUT_DIRECTORY, s);
- [Test]
- public void Resume()
- {
- // Create a file, fill with some data, then try and resume.
- File.Delete(NonEmptyFile);
- StreamWriter w = File.CreateText(NonEmptyFile);
- w.Write("222222222");
- w.Close();
- FileDownloader downloader = new FileDownloader();
- downloader.Download(InstallPadTest.GetDownloadPath(NonEmptyFile));
- Assert.IsTrue(InstallPadTest.VerifyExistenceAndSize(NonEmptyFile, fileSizes[NonEmptyFile]));
-
- // Verify that the first 9 bytes of the file are 2's
- TextReader reader = new StreamReader(NonEmptyFile);
- int charactersRead=0;
- while (charactersRead<9){
- char c = (char)reader.Read() ;
- Assert.IsTrue(c == '2');
- charactersRead++;
+ Assert.IsTrue(InstallPadTest.VerifyExistenceAndSize(fi, fileSizes[s]));
+ }
+ }
+ else
+ {
+ Assert.Ignore("Test ignored because share is not mapped or may not exist.");
}
- reader.Close();
-
}
+ #endregion
+ #region Test Download Bad Urls
[Test]
public void BadUrls()
{
@@ -189,7 +212,7 @@ public void BadUrls()
System.Net.WebException webException = null;
try
{
- downloader.Download(badUrl);
+ downloader.Download(badUrl, OUTPUT_DIRECTORY);
}
catch (System.Net.WebException e)
{
@@ -200,8 +223,11 @@ public void BadUrls()
{
Assert.IsNotNull(webException);
}
- }
+ }
}
+ #endregion
+
+ #region Test Download Malformed Urls
[Test]
public void MalformedUrl()
{
@@ -211,7 +237,7 @@ public void MalformedUrl()
try
{
- downloader.Download(malformedUrl);
+ downloader.Download(malformedUrl, OUTPUT_DIRECTORY);
}
catch (ArgumentException e)
{
@@ -223,37 +249,41 @@ public void MalformedUrl()
}
}
+ #endregion
+ #region Test Download Cancel
[Test]
public void Cancel()
{
cancelTestDownloader = new FileDownloader();
- cancelTestDownloader.ProgressChanged += new DownloadProgressHandler(CancelProgressChanged);
- cancelTestDownloader.Download(InstallPadTest.GetDownloadPath("test3.txt"));
+
+ cancelTestDownloader.ProgressChanged += new DownloadProgressHandler(Cancel_ProgressChanged);
+ cancelTestDownloader.Download(InstallPadTest.GetDownloadPath("test3.txt"), OUTPUT_DIRECTORY);
+
+ string fi = Path.Combine(OUTPUT_DIRECTORY, "test3.txt");
+
// Ensure file exists but is not full, since our block size is 1k and we've only downloaded
// one block by this point.
- Assert.IsTrue(File.Exists("test3.txt"));
- FileInfo info = new FileInfo("test3.txt");
+ Assert.IsTrue(File.Exists(fi));
+
+ FileInfo info = new FileInfo(fi);
// If block size is 1K, which it is by default, then info.Length should be 1024
Assert.IsTrue(info.Length != 0);
Assert.IsTrue(info.Length < fileSizes["test3.txt"]);
}
+ #endregion
- FileDownloader cancelTestDownloader;
-
- void CancelProgressChanged(object sender, DownloadEventArgs e)
+ #region Helper Methods
+ private void Cancel_ProgressChanged(object sender, DownloadEventArgs e)
{
cancelTestDownloader.Cancel();
}
- [TearDown]
- public void TearDown()
+ private void DownloadFtp_ProgressChanged(object sender, DownloadEventArgs e)
{
- // Delete all files that we may have downloaded
- foreach (String s in fileSizes.Keys)
- File.Delete(s);
+ downloadFtpTestDownloader.Cancel();
}
-
+ #endregion
}
}
View
61 InstallPadTest/InstallPadTest.cs
@@ -14,14 +14,19 @@
using System.Text;
using System.IO;
using System.Diagnostics;
+using System.Reflection;
+
namespace InstallPadTest
{
class InstallPadTest
{
- public static readonly string TMPDIR="";
-
public static readonly string ONLINETESTPATH = "http://www.philisoft.com/projects/installpad/test/";
+ public static string GetDownloadPath(string file)
+ {
+ return Path.Combine(InstallPadTest.ONLINETESTPATH, file);
+ }
+
/// <summary>
/// Verify existance and size of file, in bytes.
/// </summary>
@@ -40,9 +45,57 @@ public static bool VerifyExistenceAndSize(string filename, long size)
return true;
}
- public static string GetDownloadPath(string file)
+ /// <summary>
+ /// Extract embedded resource to file.
+ /// </summary>
+ /// <param name="Path">Location for output file. If it does not exist we will create it.</param>
+ /// <param name="Namespace">Embedded resources are organized by namespace. Extract only resources in this namespace.</param>
+ /// <param name="Type">Filter for resource type.<example>.config, .xml</example></param>
+ public static void ExtractToFile(string Path, string Namespace, string Type)
{
- return Path.Combine(InstallPadTest.ONLINETESTPATH, file);
+ // Make sure Path is valid
+ if (Directory.Exists(Path) == false)
+ Directory.CreateDirectory(Path);
+
+ // Get handle to executing assembly.
+ Assembly theAssembly = Assembly.GetExecutingAssembly();
+
+ // Retrieve list of embedded resource names.
+ string[] resNames = theAssembly.GetManifestResourceNames();
+
+ // Iterate through the resources.
+ foreach (string s in resNames)
+ {
+ // If they passed a resource type, filter on it.
+ if (Type.Length == 0 || s.EndsWith(Type))
+ {
+ int nsLoc = s.IndexOf(Namespace) + Namespace.Length + 1;
+
+ // Ensure namespace is present within resource name.
+ if (nsLoc < 0) throw new FileNotFoundException("Invalid namespace.");
+
+ string filename = System.IO.Path.Combine(Path, s.Substring(nsLoc));
+
+ // Extract the resource.
+ using (Stream FromStream = theAssembly.GetManifestResourceStream(s))
+ {
+ // Create a new file.
+ using (Stream ToStream = File.Create(filename))
+ {
+ // Copy the resource to the file.
+ BinaryReader br = new BinaryReader(FromStream);
+ BinaryWriter bw = new BinaryWriter(ToStream);
+
+ // TODO: Can this return before reading all the bytes?
+ bw.Write(br.ReadBytes((int)FromStream.Length));
+
+ bw.Flush();
+ bw.Close();
+ br.Close();
+ }
+ }
+ }
+ }
}
}
}
View
19 InstallPadTest/InstallPadTest.csproj
@@ -29,6 +29,10 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
+ <Reference Include="ICSharpCode.SharpZipLib, Version=0.84.0.0, Culture=neutral, PublicKeyToken=1b03e6acf1164f73">
+ <SpecificVersion>False</SpecificVersion>
+ <HintPath>..\lib\ICSharpCode.SharpZipLib.dll</HintPath>
+ </Reference>
<Reference Include="nunit.core, Version=2.2.8.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>lib\nunit.core.dll</HintPath>
@@ -38,13 +42,16 @@
<HintPath>lib\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="System" />
+ <Reference Include="System.configuration" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
+ <Compile Include="BaseTestFixture.cs" />
<Compile Include="DownloaderTest.cs" />
<Compile Include="InstallPadTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="ZipTest.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\InstallPad.csproj">
@@ -52,6 +59,18 @@
<Name>InstallPad</Name>
</ProjectReference>
</ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="data\test1.txt" />
+ <EmbeddedResource Include="data\test2.txt" />
+ <EmbeddedResource Include="data\test3.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="data\test4.zip" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="App.config" />
+ <EmbeddedResource Include="data\test5.zip" />
+ </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
View
94 InstallPadTest/ZipTest.cs
@@ -10,97 +10,71 @@
// distribute this software internally within a corporation.
using System;
-using System.Collections.Generic;
-using System.Text;
using System.IO;
-using NUnit.Framework;
using System.Diagnostics;
+using NUnit.Framework;
+
namespace InstallPadTest
{
[TestFixture]
- public class ZipTest
+ public class ZipTestFixture : BaseTestFixture
{
- Dictionary<string, long> fileSizes = new Dictionary<string, long>();
-
- public ZipTest()
- {
- // fileSizes.Add("test1.txt", 0);
- fileSizes.Add("test2.txt", 98);
- fileSizes.Add("test3.txt", 1747);
- }
-
- [SetUp]
- public void SetUp()
- {
- }
-
- /// <summary>
- ///
- /// </summary>
+ #region Test UnZip
[Test]
- public void UnZip1()
+ public void TestUnZip()
{
string target = "test4.zip";
- string dataDirectory = "../../data/";
- string outputDirectory = "../../data/out/";
- string fileUrl = Path.GetFullPath(dataDirectory + target);
- string destUrl = Path.GetFullPath(outputDirectory);
+ string fileUrl = Path.Combine(DATA_DIRECTORY, target);
try
{
- InstallPad.Zip.Instance.ExtractZip(fileUrl, destUrl);
+ InstallPad.Zip.Instance.ExtractZip(fileUrl, OUTPUT_DIRECTORY);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
- foreach (String s in fileSizes.Keys)
+ foreach (string f in Directory.GetFiles(OUTPUT_DIRECTORY))
{
- fileUrl = "file:///" + Path.GetFullPath(outputDirectory + s);
+ FileInfo fi = new FileInfo(f);
+ FileInfo fr = new FileInfo(Path.Combine(DATA_DIRECTORY, fi.Name));
// Veryify file exists and is the correct size
- Assert.IsTrue(InstallPadTest.VerifyExistenceAndSize(s, fileSizes[s]));
+ Assert.IsTrue(InstallPadTest.VerifyExistenceAndSize(f, fr.Length));
}
}
+ #endregion
- /// <summary>
- ///
- /// </summary>
+ #region Test Zip Contains
[Test]
- public void UnZip2()
+ public void TestZipContains()
{
- string target = "test5.zip";
- string dataDirectory = "../../data/";
- string outputDirectory = "../../data/out2/";
-
- string fileUrl = Path.GetFullPath(dataDirectory + target);
- string destUrl = Path.GetFullPath(outputDirectory);
-
- try
- {
- InstallPad.Zip.Instance.ExtractZip(fileUrl, destUrl);
- }
- catch (Exception ex)
- {
- Console.WriteLine(ex.Message);
- }
-
- foreach (String s in fileSizes.Keys)
- {
- fileUrl = "file:///" + Path.GetFullPath(outputDirectory + @"test\" + s);
-
- // Veryify file exists and is the correct size
- Assert.IsTrue(InstallPadTest.VerifyExistenceAndSize(s, fileSizes[s]));
- }
+ string fileUrl0 = Path.Combine(DATA_DIRECTORY, "test4.zip");
+ string fileUrl1 = Path.Combine(DATA_DIRECTORY, "test5.zip");
+
+ Assert.IsTrue(InstallPad.Zip.Instance.Contains(fileUrl0, "test2.txt") == true);
+ Assert.IsTrue(InstallPad.Zip.Instance.Contains(fileUrl0, "test3.txt") == true);
+ Assert.IsTrue(InstallPad.Zip.Instance.Contains(fileUrl0, "test4.txt") == false);
+ Assert.IsTrue(InstallPad.Zip.Instance.Contains(fileUrl1, "test5") == true);
+ Assert.IsTrue(InstallPad.Zip.Instance.Contains(fileUrl1, "test2.txt") == true);
+ Assert.IsTrue(InstallPad.Zip.Instance.Contains(fileUrl1, "test3.txt") == true);
+ Assert.IsTrue(InstallPad.Zip.Instance.Contains(fileUrl1, "test4.txt") == false);
}
+ #endregion
- [TearDown]
- public void TearDown()
+ #region Test Zip Has Root Folder
+ [Test]
+ public void TestZipHasRootFolder()
{
- }
+ string fileUrl0 = Path.Combine(DATA_DIRECTORY, "test4.zip");
+ string fileUrl1 = Path.Combine(DATA_DIRECTORY, "test5.zip");
+ Assert.IsTrue(InstallPad.Zip.Instance.HasRootFolder(fileUrl0) == false);
+ Assert.IsTrue(InstallPad.Zip.Instance.HasRootFolder(fileUrl1) == true);
+ }
+ #endregion
}
}
View
66 Settings.cs
@@ -1,28 +1,38 @@
-namespace InstallPad.Properties {
-
-
- // This class allows you to handle specific events on the settings class:
- // The SettingChanging event is raised before a setting's value is changed.
- // The PropertyChanged event is raised after a setting's value is changed.
- // The SettingsLoaded event is raised after the setting values are loaded.
- // The SettingsSaving event is raised before the setting values are saved.
- internal sealed partial class Settings {
-
- public Settings() {
- // // To add event handlers for saving and changing settings, uncomment the lines below:
- //
- // this.SettingChanging += this.SettingChangingEventHandler;
- //
- // this.SettingsSaving += this.SettingsSavingEventHandler;
- //
- }
-
- private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) {
- // Add code to handle the SettingChangingEvent event here.
- }
-
- private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) {
- // Add code to handle the SettingsSaving event here.
- }
- }
-}
+//
+// Author: Phil Crosby
+//
+
+// Copyright (C) 2006 Phil Crosby
+// Permission is granted to use, copy, modify, and merge copies
+// of this software for personal use. Permission is not granted
+// to use or change this software for commercial use or commercial
+// redistribution. Permission is not granted to use, modify or
+// distribute this software internally within a corporation.
+
+namespace InstallPad.Properties
+{
+ // This class allows you to handle specific events on the settings class:
+ // The SettingChanging event is raised before a setting's value is changed.
+ // The PropertyChanged event is raised after a setting's value is changed.
+ // The SettingsLoaded event is raised after the setting values are loaded.
+ // The SettingsSaving event is raised before the setting values are saved.
+ internal sealed partial class Settings {
+
+ public Settings() {
+ // // To add event handlers for saving and changing settings, uncomment the lines below:
+ //
+ // this.SettingChanging += this.SettingChangingEventHandler;
+ //
+ // this.SettingsSaving += this.SettingsSavingEventHandler;
+ //
+ }
+
+ private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) {
+ // Add code to handle the SettingChangingEvent event here.
+ }
+
+ private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) {
+ // Add code to handle the SettingsSaving event here.
+ }
+ }
+}
View
1  data/applists/test2.txt
@@ -0,0 +1 @@
+0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456
View
1  data/applists/test3.txt
@@ -0,0 +1 @@
+012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345601234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234560123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345601234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234560123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345601234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234560123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345601234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234560123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345601234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234560123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345601234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234560123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456
View
28 src/ApplicationDialog.cs
@@ -42,7 +42,7 @@ public ApplicationDialog(ApplicationItem item)
this.DownloadLatestVersion = item.Options.DownloadLatestVersion;
this.SilentInstall = item.Options.SilentInstall;
this.InstallerArguments = item.Options.InstallerArguments;
- this.Comment = item.Comment;
+ this.Comment = item.Comment;
this.Checked = item.Options.Checked ;
this.InstallationRoot = item.Options.InstallationRoot;
@@ -51,7 +51,7 @@ public ApplicationDialog(ApplicationItem item)
{
this.InstallationRoot = InstallPadApp.AppList.InstallationOptions.InstallationRoot;
// but preferences overrides applist installation options!
- if (InstallPadApp.Preferences.InstallationRoot != string.Empty)
+ if (InstallPadApp.Preferences.InstallationRoot != string.Empty)
this.InstallationRoot = InstallPadApp.Preferences.InstallationRoot;
}
@@ -155,15 +155,15 @@ public string Comment
{
this.appCommentBox.Text = value;
}
- }
- public bool Checked
- {
- get
- {
- return this.checkedByDefault.Checked;
- }
- set { this.checkedByDefault.Checked = value; }
-
+ }
+ public bool Checked
+ {
+ get
+ {
+ return this.checkedByDefault.Checked;
+ }
+ set { this.checkedByDefault.Checked = value; }
+
}
public bool DownloadLatestVersion
{
@@ -204,12 +204,12 @@ public string InstallationRoot
{
get
{
- //return this.installationRootBox.Text;
+ //return this.installationRootBox.Text;
return null;
}
set
{
- //this.installationRootBox.Text = value;
+ //this.installationRootBox.Text = value;
}
}
@@ -246,7 +246,7 @@ public void ModifyApplicationItemFromDialog(ApplicationItem item)
item.Comment = this.Comment;
item.Options.DownloadLatestVersion = this.DownloadLatestVersion;
item.Options.SilentInstall = this.SilentInstall;
- item.Options.InstallerArguments = this.InstallerArguments;
+ item.Options.InstallerArguments = this.InstallerArguments;
item.Options.Checked = this.Checked;
// Setting InstallationRoot is disabled for now until the rules are decided.
View
680 src/ApplicationListItem.Installation.cs
@@ -1,330 +1,350 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Drawing;
-using System.Data;
-using System.Diagnostics;
-using System.Text;
-using System.Threading;
-using System.Windows.Forms;
-using CodeProject.Downloader;
-using InstallPad;
-
-namespace InstallPad
-{
- public partial class ApplicationListItem
- {
- public enum InstallState
- {
- None, Downloading, Downloaded, Installing, Installed
- }
- InstallState state = InstallState.None;
-
- string installError = null;
-
- public string InstallError
- {
- get { return installError; }
- set { installError = value; }
- }
-
- public InstallState State
- {
- get { return state; }
- set { state = value; }
- }
-
- #region Events we publish
- public event EventHandler FinishedDownloading;
- private void OnFinishedDownloading()
- {
- SetState(InstallState.Downloaded);
-
- if (this.FinishedDownloading != null)
- FinishedDownloading(this, new EventArgs());
-
- if (installAfterDownload)
- InstallApplication();
- }
- public event EventHandler FinishedInstalling;
- private void OnFinishedInstalling()
- {
- // Could be an error condition
- if (installError != null || (this.installProcess != null && this.installProcess.ExitCode != 0))
- {
- SetState(InstallState.Downloaded);
- }
- else
- {
- SetState(InstallState.Installed);
- RunPostInstallationScript();
- }
- if (this.FinishedInstalling != null)
- FinishedInstalling(this, new EventArgs());
- }
- private void OnFinishedUnzipping(bool status)
- {
- if (status)
- {
- SetState(InstallState.Installed);
- RunPostInstallationScript();
- }
- else
- SetState(InstallState.Downloaded);
- }
- #endregion
-
- private void RunPostInstallationScript()
- {
- if (this.application.Options.PostInstallScript == null)
- return;
- try
- {
- //ProcessStartInfo info = new ProcessStartInfo();
- //info.FileName = application.Options.PostInstallScript;
- //Process p = Process.Start(info);
- Process.Start(application.Options.PostInstallScript);
- }
- catch (Exception e)
- {
- this.Invoke(new EventHandler(delegate
- {
- this.installErrorBox.DetailsText =
- String.Format("Error running the post install script {0} : {1}",
- application.Options.PostInstallScript, e.Message);
- this.installErrorBox.Show();
- }));
- }
- }
- void downloader_DownloadComplete(object sender, EventArgs e)
- {
- // Update our appearance, let others know we're finished downloading.
- Debug.WriteLine("download complete.");
- if (this.state != InstallState.Downloading)
- return;
-
- SetState(InstallState.Downloaded);
-
- this.OnFinishedDownloading();
- }
-
- // Determines whether installation should begin after the download
- bool installAfterDownload = false;
-
- public void Download(bool installAfterDownload)
- {
- this.installAfterDownload = installAfterDownload;
- // If we're already downloading this file, ignore this click
- if (this.state == InstallState.Downloaded || this.state == InstallState.Downloading)
- return;
- SetState(InstallState.Downloading);
-
- ThreadPool.QueueUserWorkItem(new WaitCallback(this.AsyncDownload), null);
- }
-
- /// <summary>
- /// Begins an async download
- /// </summary>
- /// <param name="data"></param>
- private void AsyncDownload(object data)
- {
- Debug.WriteLine("starting an async download");
- Exception ex = null;
- try
- {
- // process alternate download locations, build a download list ordered by best location
- List<string> downloadUrlOrderedList = this.application.CreateOrderedUrlList();
-
- // download from one of the sources
- downloader.Download(downloadUrlOrderedList, InstallPadApp.Preferences.DownloadTo);
- }
- catch (System.IO.DirectoryNotFoundException e)
- {
- ex = e;
- }
- catch (Exception e)
- {
- ex = e;
- }
- if (ex != null)
- {
- Debug.WriteLine("async download had error: " + ex.Message);
- this.Invoke(new EventHandler(delegate
- {
- // Show an error
- this.downloadErrorBox.Visible = true;
- this.downloadErrorBox.DetailsText = ex.Message;
- }));
- SetState(InstallState.None);
- }
-
- // Downloader_Complete event will trigger the state change to downloaded
- }
-
- /// <summary>
- /// Installs the application referred to by this app list item.
- /// </summary>
- public void InstallApplication()
- {
- Debug.Assert(this.state == InstallState.Downloaded);
-
- SetState(InstallState.Installing);
-
- if (downloader.DownloadingTo.ToLower().EndsWith(".zip"))
- {
- ThreadPool.QueueUserWorkItem(new WaitCallback(this.AsyncZipInstall), null);
- }
- else
- {
- ThreadPool.QueueUserWorkItem(new WaitCallback(this.AsyncInstall), null);
- }
- }
-
- private static string ArgumentsForSilentInstall(ApplicationItem application)
- {
- // Coding in special rules here for apps. Each of these special rules should be moved
- // to another class, or a seperate file. Make sure there is a space before the command line arguments.
-
- // TODO: externalize this information. Put it in a .ini or .config file accessible by users?
- // Each rule should be on its own line; first, a regex to match the application name, and next to it,
- // the installer arguments that pertain to that app
-
- if (application.FileName.ToLower().EndsWith(".msi"))
- {
- return "/qn";
- }else if (application.FileName.ToLower().Contains("firefox"))
- return "-ms";
- else if (application.FileName.ToLower().Contains("itunessetup"))
- {
- // Args are: /s /v"SILENT_INSTALL=1 ALLUSERS=1 /qb"
- //return "/s /v\"SILENT_INSTALL=1 ALLUSERS=1 /qb\"";
-
- // Above is for the older iTunes. Newer itunes is just an exe that extracts to an msi.
- return "/qn";
- }
- else if (application.FileName.ToLower().Contains("quicktimeinstaller"))
- {
- // QuickTime is just an MSI, like iTunes
- return "/qn";
- }
- else if (application.FileName.ToLower().Contains("spybot"))
- {
- return "/VERYSILENT";
- }
- else if (application.FileName.ToLower().Contains("adberdr"))
- {
- // Adobe Acrobat Reader. Argh adobe...
- return "/S /w /v\"/qb-! /norestart EULA_ACCEPT=YES\"";
- }
- else
- // This will work for most installers - /S for nullsoft installers, and -s for InstallShield
- return "/S -s";
-
- }
-
- private void AsyncZipInstall(object data)
- {
- Exception ex = null;
- try
- {
- string extractTo =null;
- // If the application has an InstallationRoot option set, extract there. Otherwise
- // use the user preference's InstallationRoot
- string appRoot = this.application.Options.InstallationRoot;
- if (appRoot != null && appRoot.Length > 0)
- extractTo = appRoot;
- else
- extractTo = InstallPadApp.Preferences.InstallationRoot;
-
- Zip.Instance.ExtractZip(downloader.DownloadingTo, InstallPadApp.Preferences.InstallationRoot);
- }
- catch (Exception e)
- {
- ex = e;
- }
- if (ex != null)
- {
- // There was an error
- this.installProcess = null;
- this.installError = String.Format("Couldn't unzip {0} : {1}",
- downloader.DownloadingTo, ex.Message);
-
- this.Invoke(new EventHandler(delegate
- {
- // Show an error
- installErrorBox.DetailsText = this.installError;
- installErrorBox.Visible = true;
- }));
- }
- // Done unzipping/installing
- OnFinishedInstalling();
- }
-
- /// <summary>
- /// Begin an async install
- /// </summary>
- private void AsyncInstall(object data)
- {
- Debug.WriteLine("starting async install: ");
- ProcessStartInfo psi = new ProcessStartInfo(downloader.DownloadingTo);
- psi.Arguments = application.Options.InstallerArguments;
- if (application.Options.SilentInstall || InstallPadApp.AppList.InstallationOptions.SilentInstall)
- {
- psi.Arguments = String.Format("{0} {1}", psi.Arguments, ArgumentsForSilentInstall(application));
- }
-
- installProcess = new Process();
-
- installProcess.StartInfo = psi;
- installProcess.EnableRaisingEvents = true;
- installProcess.Exited += new EventHandler(process_Exited);
-
- Exception ex = null;
- try
- {
- installProcess.Start();
- }
- catch (Exception e)
- {
- ex = e;
- }
- if (ex != null)
- {
- // There was an error.
- this.installProcess = null;
- this.installError = String.Format("Couldn't install {0} : {1}", downloader.DownloadingTo, ex.Message);
-
- this.Invoke(new EventHandler(delegate
- {
- // Show an error
- installErrorBox.DetailsText = this.installError;
- installErrorBox.Visible = true;
- }));
-
- // We're done running the installer..
- OnFinishedInstalling();
- }
-
- // OnFinishedInstalling will get called by the process when it exits.
- }
- void downloader_ProgressChanged(object sender, CodeProject.Downloader.DownloadEventArgs e)
- {
- // Sometimes we may get events fired even after we're done downloading.
- // Don't react to them.
- if (this.state != InstallState.Downloading)
- return;
- this.Invoke(new EventHandler(delegate
- {
- if (e.PercentDone <= 100)
- {
- this.progressBar.Value = e.PercentDone;
- UpdateProgressLabel(e);
- }
- }));
- }
- void process_Exited(object sender, EventArgs e)
- {
- OnFinishedInstalling();
- }
- }
-}
+//
+// Author: Phil Crosby
+//
+
+// Copyright (C) 2006 Phil Crosby
+// Permission is granted to use, copy, modify, and merge copies
+// of this software for personal use. Permission is not granted
+// to use or change this software for commercial use or commercial
+// redistribution. Permission is not granted to use, modify or
+// distribute this software internally within a corporation.
+
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Diagnostics;
+using System.Text;
+using System.Threading;
+using System.Windows.Forms;
+using CodeProject.Downloader;
+using InstallPad;
+
+namespace InstallPad
+{
+ public partial class ApplicationListItem
+ {
+ public enum InstallState
+ {
+ None, Downloading, Downloaded, Installing, Installed
+ }
+ InstallState state = InstallState.None;
+
+ string installError = null;
+
+ public string InstallError
+ {
+ get { return installError; }
+ set { installError = value; }
+ }
+
+ public InstallState State
+ {
+ get { return state; }
+ set { state = value; }
+ }
+
+ #region Events we publish
+ public event EventHandler FinishedDownloading;
+ private void OnFinishedDownloading()
+ {
+ SetState(InstallState.Downloaded);
+
+ if (this.FinishedDownloading != null)
+ FinishedDownloading(this, new EventArgs());
+
+ if (installAfterDownload)
+ InstallApplication();
+ }
+ public event EventHandler FinishedInstalling;
+ private void OnFinishedInstalling()
+ {
+ // Could be an error condition
+ if (installError != null || (this.installProcess != null && this.installProcess.ExitCode != 0))
+ {
+ SetState(InstallState.Downloaded);
+ }
+ else
+ {
+ SetState(InstallState.Installed);
+ RunPostInstallationScript();
+ }
+ if (this.FinishedInstalling != null)
+ FinishedInstalling(this, new EventArgs());
+ }
+ private void OnFinishedUnzipping(bool status)
+ {
+ if (status)
+ {
+ SetState(InstallState.Installed);
+ RunPostInstallationScript();
+ }
+ else
+ SetState(InstallState.Downloaded);
+ }
+ #endregion
+
+ private void RunPostInstallationScript()
+ {
+ if (this.application.Options.PostInstallScript == null)
+ return;
+ try
+ {
+ //ProcessStartInfo info = new ProcessStartInfo();
+ //info.FileName = application.Options.PostInstallScript;
+ //Process p = Process.Start(info);
+ Process.Start(application.Options.PostInstallScript);
+ }
+ catch (Exception e)
+ {
+ this.Invoke(new EventHandler(delegate
+ {
+ this.installErrorBox.DetailsText =
+ String.Format("Error running the post install script {0} : {1}",
+ application.Options.PostInstallScript, e.Message);
+ this.installErrorBox.Show();
+ }));
+ }
+ }
+ void downloader_DownloadComplete(object sender, EventArgs e)
+ {
+ // Update our appearance, let others know we're finished downloading.
+ Debug.WriteLine("download complete.");
+ if (this.state != InstallState.Downloading)
+ return;
+
+ SetState(InstallState.Downloaded);
+
+ this.OnFinishedDownloading();
+ }
+
+ // Determines whether installation should begin after the download
+ bool installAfterDownload = false;
+
+ public void Download(bool installAfterDownload)
+ {
+ this.installAfterDownload = installAfterDownload;
+ // If we're already downloading this file, ignore this click
+ if (this.state == InstallState.Downloaded || this.state == InstallState.Downloading)
+ return;
+ SetState(InstallState.Downloading);
+
+ ThreadPool.QueueUserWorkItem(new WaitCallback(this.AsyncDownload), null);
+ }
+
+ /// <summary>
+ /// Begins an async download
+ /// </summary>
+ /// <param name="data"></param>
+ private void AsyncDownload(object data)
+ {
+ Debug.WriteLine("starting an async download");
+ Exception ex = null;
+ try
+ {
+ // process alternate download locations, build a download list ordered by best location
+ List<string> downloadUrlOrderedList = this.application.CreateOrderedUrlList();
+
+ // download from one of the sources
+ downloader.Download(downloadUrlOrderedList, InstallPadApp.Preferences.DownloadTo);
+ }
+ catch (System.IO.DirectoryNotFoundException e)
+ {
+ ex = e;
+ }
+ catch (Exception e)
+ {
+ ex = e;
+ }
+ if (ex != null)
+ {
+ Debug.WriteLine("async download had error: " + ex.Message);
+ this.Invoke(new EventHandler(delegate
+ {
+ // Show an error
+ this.downloadErrorBox.Visible = true;
+ this.downloadErrorBox.DetailsText = ex.Message;
+ }));
+ SetState(InstallState.None);
+ }
+
+ // Downloader_Complete event will trigger the state change to downloaded
+ }
+
+ /// <summary>
+ /// Installs the application referred to by this app list item.
+ /// </summary>
+ public void InstallApplication()
+ {
+ Debug.Assert(this.state == InstallState.Downloaded);
+
+ SetState(InstallState.Installing);
+
+ if (downloader.DownloadingTo.ToLower().EndsWith(".zip"))
+ {
+ ThreadPool.QueueUserWorkItem(new WaitCallback(this.AsyncZipInstall), null);
+ }
+ else
+ {
+ ThreadPool.QueueUserWorkItem(new WaitCallback(this.AsyncInstall), null);
+ }
+ }
+
+ private static string ArgumentsForSilentInstall(ApplicationItem application)
+ {
+ // Coding in special rules here for apps. Each of these special rules should be moved
+ // to another class, or a seperate file. Make sure there is a space before the command line arguments.
+
+ // TODO: externalize this information. Put it in a .ini or .config file accessible by users?
+ // Each rule should be on its own line; first, a regex to match the application name, and next to it,
+ // the installer arguments that pertain to that app
+
+ if (application.FileName.ToLower().EndsWith(".msi"))
+ {
+ return "/qn";
+ }else if (application.FileName.ToLower().Contains("firefox"))
+ return "-ms";
+ else if (application.FileName.ToLower().Contains("itunessetup"))
+ {
+ // Args are: /s /v"SILENT_INSTALL=1 ALLUSERS=1 /qb"
+ //return "/s /v\"SILENT_INSTALL=1 ALLUSERS=1 /qb\"";
+
+ // Above is for the older iTunes. Newer itunes is just an exe that extracts to an msi.
+ return "/qn";
+ }
+ else if (application.FileName.ToLower().Contains("quicktimeinstaller"))
+ {
+ // QuickTime is just an MSI, like iTunes
+ return "/qn";
+ }
+ else if (application.FileName.ToLower().Contains("spybot"))
+ {
+ return "/VERYSILENT";
+ }
+ else if (application.FileName.ToLower().Contains("adberdr"))
+ {
+ // Adobe Acrobat Reader. Argh adobe...
+ return "/S /w /v\"/qb-! /norestart EULA_ACCEPT=YES\"";
+ }
+ else
+ // This will work for most installers - /S for nullsoft installers, and -s for InstallShield
+ return "/S -s";
+
+ }
+
+ private void AsyncZipInstall(object data)
+ {
+ Exception ex = null;
+ try
+ {
+ string extractTo =null;
+ // If the application has an InstallationRoot option set, extract there. Otherwise
+ // use the user preference's InstallationRoot
+ string appRoot = this.application.Options.InstallationRoot;
+ if (appRoot != null && appRoot.Length > 0)
+ extractTo = appRoot;
+ else
+ extractTo = InstallPadApp.Preferences.InstallationRoot;
+
+ // If zip file is not constructed in such a way that it extracts to a single folder, then
+ // extract it into a newly created folder within appRoot or InstallationRoot.
+ if (Zip.Instance.HasRootFolder(downloader.DownloadingTo) == false)
+ {
+ extractTo = Path.Combine(extractTo, Path.GetFileNameWithoutExtension(downloader.DownloadingTo));
+ Directory.CreateDirectory(extractTo);
+ }
+
+ Zip.Instance.ExtractZip(downloader.DownloadingTo, extractTo);
+ }
+ catch (Exception e)
+ {
+ ex = e;
+ }
+ if (ex != null)
+ {
+ // There was an error
+ this.installProcess = null;
+ this.installError = String.Format("Couldn't unzip {0} : {1}",
+ downloader.DownloadingTo, ex.Message);
+
+ this.Invoke(new EventHandler(delegate
+ {
+ // Show an error
+ installErrorBox.DetailsText = this.installError;
+ installErrorBox.Visible = true;
+ }));
+ }
+ // Done unzipping/installing
+ OnFinishedInstalling();
+ }
+
+ /// <summary>
+ /// Begin an async install
+ /// </summary>
+ private void AsyncInstall(object data)
+ {
+ Debug.WriteLine("starting async install: ");
+ ProcessStartInfo psi = new ProcessStartInfo(downloader.DownloadingTo);
+ psi.Arguments = application.Options.InstallerArguments;
+ if (application.Options.SilentInstall || InstallPadApp.AppList.InstallationOptions.SilentInstall)
+ {
+ psi.Arguments = String.Format("{0} {1}", psi.Arguments, ArgumentsForSilentInstall(application));
+ }
+
+ installProcess = new Process();
+
+ installProcess.StartInfo = psi;
+ installProcess.EnableRaisingEvents = true;
+ installProcess.Exited += new EventHandler(process_Exited);
+
+ Exception ex = null;
+ try
+ {
+ installProcess.Start();
+ }
+ catch (Exception e)
+ {
+ ex = e;
+ }
+ if (ex != null)
+ {
+ // There was an error.
+ this.installProcess = null;
+ this.installError = String.Format("Couldn't install {0} : {1}", downloader.DownloadingTo, ex.Message);
+
+ this.Invoke(new EventHandler(delegate
+ {
+ // Show an error
+ installErrorBox.DetailsText = this.installError;
+ installErrorBox.Visible = true;
+ }));
+
+ // We're done running the installer..
+ OnFinishedInstalling();
+ }
+
+ // OnFinishedInstalling will get called by the process when it exits.
+ }
+ void downloader_ProgressChanged(object sender, CodeProject.Downloader.DownloadEventArgs e)
+ {
+ // Sometimes we may get events fired even after we're done downloading.
+ // Don't react to them.
+ if (this.state != InstallState.Downloading)
+ return;
+ this.Invoke(new EventHandler(delegate
+ {
+ if (e.PercentDone <= 100)
+ {
+ this.progressBar.Value = e.PercentDone;
+ UpdateProgressLabel(e);
+ }
+ }));
+ }
+ void process_Exited(object sender, EventArgs e)
+ {
+ OnFinishedInstalling();
+ }
+ }
+}
View
739 src/ControlList.cs
@@ -1,365 +1,376 @@
-using System;
-using System.Diagnostics;
-using System.Collections;
-using System.ComponentModel;
-using System.Drawing;
-using System.Data;
-using System.Text;
-using System.Windows.Forms;
-
-namespace InstallPad
-{
- #region ScrollPanel
- /// <summary>
- /// An autoscrollable panel used by ControlList to host the
- /// TableLayoutPanel. Essentially adds a scrollbar to TableLayout
- /// </summary>
- class ScrollPanel : ScrollableControl
- {
- Label label;
- public ScrollPanel()
- { this.AutoScroll = true ;
-
- // Label acts as a place holder, it will reside next to the tablepanel
- label = new Label();
- label.Width = 1;
- label.Height = 10;
- this.Controls.Add(label);
- }
-
- public int MinimumHeight
- {
- set
- {
- this.label.Height = value;
- }
- get
- {
- return this.label.Height;
- }
- }
- }
- #endregion
-
- /// <summary>
- /// A control list shows controls in a scrollable list with alternating colors.
- /// </summary>
- public partial class ControlList : UserControl
- {
- #region Coloring
- static Color alternatingColor;
- static Color highlightColor;
-
- static ControlList()
- {
- alternatingColor = Color.FromArgb(241, 241, 241);
-
- // The highlight is a little bit darker than the alternating
- highlightColor = Color.FromArgb(
- alternatingColor.R - 12, alternatingColor.G - 12, alternatingColor.B);
- }
- #endregion
-
- public event MouseEventHandler ListItemClicked;
- public ControlList()
- {
- InitializeComponent();
- //this.DoubleBuffered = true;
- }
-
- private ScrollPanel scrollPanel;
- private TableLayoutPanel tableLayout;
-
- // Entry highlighted when a context menu is shown
- private Control highlightedEntry = null;
-
- private void ControlList_Load(object sender, EventArgs e)
- {
- // Build a scrollable control and add a table layout to it.
- this.tableLayout = new TableLayoutPanel();
-
- this.scrollPanel=new ScrollPanel();
- scrollPanel.Size = this.Size;
-
- scrollPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
- | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
-
- this.Controls.Add(scrollPanel);
- this.scrollPanel.Controls.Add(this.tableLayout);
-
- this.tableLayout.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top)
- | System.Windows.Forms.AnchorStyles.Left)
- | System.Windows.Forms.AnchorStyles.Right)));
- // Don't anchor to the bottom; if you do, the table control will be too big and won't scroll right.
- //| System.Windows.Forms.AnchorStyles.Bottom));
-
- this.tableLayout.ColumnCount = 1;
- this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
- this.tableLayout.Location = new System.Drawing.Point(0, 0);
- this.tableLayout.Margin = new System.Windows.Forms.Padding(0);
- this.tableLayout.Name = "tableLayout";
- this.tableLayout.RowCount = 1;
- this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 149F));
- this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 149F));
- this.tableLayout.Size = scrollPanel.Size;
- this.tableLayout.TabIndex = 2;
-
- foreach (RowStyle style in this.tableLayout.RowStyles)
- style.SizeType = SizeType.Absolute;
-
- this.ContextMenu = new ContextMenu();
-
- UpdateTableHeight();
- }
-
- private void OnListItemClicked(object sender, MouseEventArgs e)
- {
- if (ListItemClicked != null)
- ListItemClicked(sender, e);
- }
-
- /// <summary>
- /// Find a control at the given screen position, in absolute coordinates.
- /// </summary>
- /// <param name="p"></param>
- /// <returns></returns>
- public Control ControlAtAbsolutePosition(Point p)
- {
- foreach (Control c in this.ListItems)
- {
- // Using absolute screen coordinates, because if we use coords relative to a control,
- // scrolling the control can mess that up.
- Rectangle bounds = new Rectangle(PointToClient(c.Bounds.Location), c.Bounds.Size);
- Point loc = Interop.UpperLeftCornerOfWindow(c.Handle);
- bounds = new Rectangle(loc, c.Bounds.Size);
- if (bounds.Contains(p))
- return c;
- }
- return null;
- }
-
- public ControlCollection ListItems
- {
- get
- {
- return this.tableLayout.Controls;
- }
- }
-
- public void ClearListItems()
- {
- this.tableLayout.Controls.Clear();
- this.tableLayout.RowCount = 1;
- UpdateTableHeight();
- }
-
- /// <summary>
- /// Update the heights of the tablet layout and scroll panel controls
- /// </summary>
- private void UpdateTableHeight()
- {
- int controlsCount = tableLayout.Controls.Count;
- int controlHeight = (controlsCount > 0) ? tableLayout.Controls[0].Height : 0;
- this.tableLayout.MinimumSize = new Size(this.tableLayout.MinimumSize.Width, controlsCount*controlHeight);
- this.tableLayout.Height = controlHeight*controlsCount;
- this.scrollPanel.MinimumHeight = this.tableLayout.Height;
- }
-
- public void RemoveControl(Control control)
- {
- if (this.tableLayout.Controls.Contains(control)){
- int rowOfOldControl = this.tableLayout.GetRow(control);
- this.tableLayout.Controls.Remove(control);
-
- // Update minimum heights
- Size oldMinSize = this.tableLayout.MinimumSize;
- foreach (RowStyle style in this.tableLayout.RowStyles)
- {
- style.SizeType = SizeType.Absolute;
- style.Height = control.Height;
- }
- // Removing an entry leaves a hole in the cell positions of the table entries.
- // Shift everyone up into that hole.
- ShiftRowsUp(rowOfOldControl + 1);
-
- this.tableLayout.RowCount--;
-
- UpdateTableHeight();
-
- AlternateColorsOfEntries();
- }
- }
- /// <summary>
- /// All rows at 'row' will be shifted down one.
- /// </summary>
- /// <param name="row"></param>
- private void ShiftRowsDown(int row)
- {
- for (int i = this.tableLayout.RowCount - 1; i >= row; i-- )
- {
- Control c = this.tableLayout.GetControlFromPosition(0, i);
- if (c!=null)
- this.tableLayout.SetRow(c, i + 1);
- }
- }
- /// <summary>
- /// All rows at 'row' will be shifted down one.
- /// </summary>
- /// <param name="row"></param>
- private void ShiftRowsUp(int row)
- {
- for (int i=row;i<this.tableLayout.RowCount-1;i++)
- {
- Control c = this.tableLayout.GetControlFromPosition(0, i);
- this.tableLayout.SetRow(c, i - 1);
- }
- }
- /// <summary>
- /// Add many controls at once. Improves drawing performance slightly.
- /// </summary>
- /// <param name="controls"></param>
- public void AddAll(IEnumerable controls)
- {
- foreach (Control control in controls)
- {
- FormatAndAddControl(control);
- }
- foreach (RowStyle style in this.tableLayout.RowStyles)
- {
- style.SizeType = SizeType.Absolute;
- style.Height = this.tableLayout.Controls[0].Height;
- }
- UpdateTableHeight();
- AlternateColorsOfEntries();
- }
-
- /// <summary>
- /// When a control is added, we need to add it to the TableView, adjust
- /// its width, listen to its visibility, and update our appearance.
- /// </summary>
- /// <param name="control"></param>
- public void AddControl(Control control)
- {
- // -1 is the end of the list
- AddControl(control, -1);
- }
- public void AddControl(Control control, int position)
- {
- FormatAndAddControl(control, position);
-
- // Set all row styles to be the same height. Neglecting to this will lead
- // to some oddly shaped rows.
- foreach (RowStyle style in this.tableLayout.RowStyles)
- {
- style.SizeType = SizeType.Absolute;
- style.Height = control.Height;
- }
-
- // Toggle the colors from white to light gray
- AlternateColorsOfEntries();
-
- UpdateTableHeight();
- }
- public int IndexOfListItem(Control control)
- {
- if (control == null)
- return -1;
-
- TableLayoutPanelCellPosition pos = this.tableLayout.GetCellPosition(control);
- return pos.Row;
- }
-
- /// <summary>
- /// Utility method to get a control read and stick it at the end of the table layout
- /// </summary>
- /// <param name="control"></param>
- private void FormatAndAddControl(Control control)
- {
- // -1 is the end of the list
- FormatAndAddControl(control, -1);
- }
- private void FormatAndAddControl(Control control, int position)
- {
- control.Width = this.Width;
- control.Anchor = AnchorStyles.Left | AnchorStyles.Right;
-
- // If one of the controls we're showing gets hidden, we have to update our appearance.
- control.VisibleChanged += new EventHandler(control_VisibleChanged);
-
- this.tableLayout.RowCount++;
-
- // If they did not provide a position, insert at the end.
- // Insert new control before the last row of the table; the last row is of size zero
- // and always empty, because it fills the rest of the space when resized.
- if (position == -1)
- position = this.tableLayout.RowCount - 2;
- else
- {
- ShiftRowsDown(position);
- }
-
- this.tableLayout.Controls.Add(control, 0, position);
-
- control.MouseClick += new MouseEventHandler(OnListItemClicked);
- }
-
- void control_VisibleChanged(object sender, EventArgs e)
- {
- // When one of the panels gets hidden, have to update the the colors of the other
- // panels so that they alternate
- AlternateColorsOfEntries();
-
- // Shouldn't we update the minimum height of the table here, making it smaller
- // if a control is hidden?
- UpdateTableHeight();
- }
-
- /// <summary>
- /// Alternates colors of entries between gray and transparent.
- /// </summary>
- protected void AlternateColorsOfEntries()
- {
- foreach (Control control in this.tableLayout.Controls)
- {
- // Only count those that are visible
- if (!control.Visible)
- continue;
-
- Color targetColor;
- // Rows that are divisble by two are colored
- if (this.tableLayout.GetRow(control) % 2 == 0)
- targetColor = Color.Transparent;
- else
- targetColor=alternatingColor;
-
- if (control.BackColor != targetColor)
- control.BackColor = targetColor;
- }
- }
-
- public void Highlight(Control c)
- {
- if (c != null)
- {
- c.BackColor = highlightColor;
- highlightedEntry = c;
- }
- }
- public void Unhighlight(Control c)
- {
- // TODO: unhighlight one at a time
- AlternateColorsOfEntries();
- highlightedEntry = null;
- }
-
- #region Properties
- public Control HighlightedEntry
- {
- get { return highlightedEntry; }
- set { highlightedEntry = value; }
- }
-
- #endregion
- }
+//
+// Author: Phil Crosby
+//
+
+// Copyright (C) 2006 Phil Crosby
+// Permission is granted to use, copy, modify, and merge copies
+// of this software for personal use. Permission is not granted
+// to use or change this software for commercial use or commercial
+// redistribution. Permission is not granted to use, modify or
+// distribute this software internally within a corporation.
+
+using System;
+using System.Diagnostics;
+using System.Collections;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Text;
+using System.Windows.Forms;
+
+namespace InstallPad
+{
+ #region ScrollPanel
+ /// <summary>
+ /// An autoscrollable panel used by ControlList to host the
+ /// TableLayoutPanel. Essentially adds a scrollbar to TableLayout
+ /// </summary>
+ class ScrollPanel : ScrollableControl
+ {
+ Label label;
+ public ScrollPanel()
+ { this.AutoScroll = true ;
+
+ // Label acts as a place holder, it will reside next to the tablepanel
+ label = new Label();
+ label.Width = 1;
+ label.Height = 10;
+ this.Controls.Add(label);
+ }
+
+ public int MinimumHeight
+ {
+ set
+ {
+ this.label.Height = value;
+ }
+ get
+ {
+ return this.label.Height;
+ }
+ }
+ }
+ #endregion
+
+ /// <summary>
+ /// A control list shows controls in a scrollable list with alternating colors.
+ /// </summary>
+ public partial class ControlList : UserControl
+ {
+ #region Coloring
+ static Color alternatingColor;
+ static Color highlightColor;
+
+ static ControlList()
+ {
+ alternatingColor = Color.FromArgb(241, 241, 241);
+
+ // The highlight is a little bit darker than the alternating
+ highlightColor = Color.FromArgb(
+ alternatingColor.R - 12, alternatingColor.G - 12, alternatingColor.B);
+ }
+ #endregion
+
+ public event MouseEventHandler ListItemClicked;
+ public ControlList()
+ {
+ InitializeComponent();
+ //this.DoubleBuffered = true;
+ }
+
+ private ScrollPanel scrollPanel;
+ private TableLayoutPanel tableLayout;
+
+ // Entry highlighted when a context menu is shown
+ private Control highlightedEntry = null;
+
+ private void ControlList_Load(object sender, EventArgs e)
+ {
+ // Build a scrollable control and add a table layout to it.
+ this.tableLayout = new TableLayoutPanel();
+
+ this.scrollPanel=new ScrollPanel();
+ scrollPanel.Size = this.Size;
+
+ scrollPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+
+ this.Controls.Add(scrollPanel);
+ this.scrollPanel.Controls.Add(this.tableLayout);
+
+ this.tableLayout.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ // Don't anchor to the bottom; if you do, the table control will be too big and won't scroll right.
+ //| System.Windows.Forms.AnchorStyles.Bottom));
+
+ this.tableLayout.ColumnCount = 1;
+ this.tableLayout.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
+ this.tableLayout.Location = new System.Drawing.Point(0, 0);
+ this.tableLayout.Margin = new System.Windows.Forms.Padding(0);
+ this.tableLayout.Name = "tableLayout";
+ this.tableLayout.RowCount = 1;
+ this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 149F));
+ this.tableLayout.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 149F));
+ this.tableLayout.Size = scrollPanel.Size;
+ this.tableLayout.TabIndex = 2;
+
+ foreach (RowStyle style in this.tableLayout.RowStyles)
+ style.SizeType = SizeType.Absolute;
+
+ this.ContextMenu = new ContextMenu();
+
+ UpdateTableHeight();
+ }
+
+ private void OnListItemClicked(object sender, MouseEventArgs e)
+ {
+ if (ListItemClicked != null)
+ ListItemClicked(sender, e);
+ }
+
+ /// <summary>
+ /// Find a control at the given screen position, in absolute coordinates.
+ /// </summary>
+ /// <param name="p"></param>
+ /// <returns></returns>
+ public Control ControlAtAbsolutePosition(Point p)
+ {
+ foreach (Control c in this.ListItems)
+ {
+ // Using absolute screen coordinates, because if we use coords relative to a control,
+ // scrolling the control can mess that up.
+ Rectangle bounds = new Rectangle(PointToClient(c.Bounds.Location), c.Bounds.Size);
+ Point loc = Interop.UpperLeftCornerOfWindow(c.Handle);
+ bounds = new Rectangle(loc, c.Bounds.Size);
+ if (bounds.Contains(p))
+ return c;
+ }
+ return null;
+ }
+
+ public ControlCollection ListItems
+ {
+ get
+ {
+ return this.tableLayout.Controls;
+ }
+ }
+
+ public void ClearListItems()
+ {
+ this.tableLayout.Controls.Clear();
+ this.tableLayout.RowCount = 1;
+ UpdateTableHeight();
+ }
+
+ /// <summary>
+ /// Update the heights of the tablet layout and scroll panel controls
+ /// </summary>
+ private void UpdateTableHeight()
+ {
+ int controlsCount = tableLayout.Controls.Count;
+ int controlHeight = (controlsCount > 0) ? tableLayout.Controls[0].Height : 0;
+ this.tableLayout.MinimumSize = new Size(this.tableLayout.MinimumSize.Width, controlsCount*controlHeight);
+ this.tableLayout.Height = controlHeight*controlsCount;
+ this.scrollPanel.MinimumHeight = this.tableLayout.Height;
+ }
+
+ public void RemoveControl(Control control)
+ {
+ if (this.tableLayout.Controls.Contains(control)){
+ int rowOfOldControl = this.tableLayout.GetRow(control);
+ this.tableLayout.Controls.Remove(control);
+
+ // Update minimum heights
+ Size oldMinSize = this.tableLayout.MinimumSize;
+ foreach (RowStyle style in this.tableLayout.RowStyles)
+ {
+ style.SizeType = SizeType.Absolute;
+ style.Height = control.Height;
+ }
+ // Removing an entry leaves a hole in the cell positions of the table entries.
+ // Shift everyone up into that hole.
+ ShiftRowsUp(rowOfOldControl + 1);
+
+ this.tableLayout.RowCount--;
+
+ UpdateTableHeight();
+
+ AlternateColorsOfEntries();
+ }
+ }
+ /// <summary>
+ /// All rows at 'row' will be shifted down one.
+ /// </summary>
+ /// <param name="row"></param>
+ private void ShiftRowsDown(int row)
+ {
+ for (int i = this.tableLayout.RowCount - 1; i >= row; i-- )
+ {
+ Control c = this.tableLayout.GetControlFromPosition(0, i);
+ if (c!=null)
+ this.tableLayout.SetRow(c, i + 1);
+ }
+ }
+ /// <summary>
+ /// All rows at 'row' will be shifted down one.
+ /// </summary>
+ /// <param name="row"></param>
+ private void ShiftRowsUp(int row)
+ {
+ for (int i=row;i<this.tableLayout.RowCount-1;i++)
+ {
+ Control c = this.tableLayout.GetControlFromPosition(0, i);
+ this.tableLayout.SetRow(c, i - 1);
+ }
+ }
+ /// <summary>
+ /// Add many controls at once. Improves drawing performance slightly.
+ /// </summary>
+ /// <param name="controls"></param>
+ public void AddAll(IEnumerable controls)
+ {
+ foreach (Control control in controls)
+ {
+ FormatAndAddControl(control);
+ }
+ foreach (RowStyle style in this.tableLayout.RowStyles)
+ {
+ style.SizeType = SizeType.Absolute;
+ style.Height = this.tableLayout.Controls[0].Height;
+ }
+ UpdateTableHeight();
+ AlternateColorsOfEntries();
+ }
+
+ /// <summary>
+ /// When a control is added, we need to add it to the TableView, adjust
+ /// its width, listen to its visibility, and update our appearance.
+ /// </summary>
+ /// <param name="control"></param>
+ public void AddControl(Control control)
+ {
+ // -1 is the end of the list
+ AddControl(control, -1);
+ }
+ public void AddControl(Control control, int position)
+ {
+ FormatAndAddControl(control, position);
+
+ // Set all row styles to be the same height. Neglecting to this will lead
+ // to some oddly shaped rows.
+ foreach (RowStyle style in this.tableLayout.RowStyles)
+ {
+ style.SizeType = SizeType.Absolute;
+ style.Height = control.Height;
+ }
+
+ // Toggle the colors from white to light gray
+ AlternateColorsOfEntries();
+
+ UpdateTableHeight();
+ }
+ public int IndexOfListItem(Control control)
+ {
+ if (control == null)
+ return -1;
+
+ TableLayoutPanelCellPosition pos = this.tableLayout.GetCellPosition(control);
+ return pos.Row;
+ }
+
+ /// <summary>
+ /// Utility method to get a control read and stick it at the end of the table layout
+ /// </summary>
+ /// <param name="control"></param>
+ private void FormatAndAddControl(Control control)
+ {
+ // -1 is the end of the list
+ FormatAndAddControl(control, -1);
+ }
+ private void FormatAndAddControl(Control control, int position)
+ {
+ control.Width = this.Width;
+ control.Anchor = AnchorStyles.Left | AnchorStyles.Right;
+
+ // If one of the controls we're showing gets hidden, we have to update our appearance.
+ control.VisibleChanged += new EventHandler(control_VisibleChanged);
+
+ this.tableLayout.RowCount++;
+
+ // If they did not provide a position, insert at the end.
+ // Insert new control before the last row of the table; the last row is of size zero
+ // and always empty, because it fills the rest of the space when resized.
+ if (position == -1)
+ position = this.tableLayout.RowCount - 2;
+ else
+ {
+ ShiftRowsDown(position);
+ }
+
+ this.tableLayout.Controls.Add(control, 0, position);
+
+ control.MouseClick += new MouseEventHandler(OnListItemClicked);
+ }
+
+ void control_VisibleChanged(object sender, EventArgs e)
+ {
+ // When one of the panels gets hidden, have to update the the colors of the other
+ // panels so that they alternate
+ AlternateColorsOfEntries();
+
+ // Shouldn't we update the minimum height of the table here, making it smaller
+ // if a control is hidden?
+ UpdateTableHeight();
+ }
+
+ /// <summary>
+ /// Alternates colors of entries between gray and transparent.
+ /// </summary>
+ protected void AlternateColorsOfEntries()
+ {
+ foreach (Control control in this.tableLayout.Controls)
+ {
+ // Only count those that are visible
+ if (!control.Visible)
+ continue;
+
+ Color targetColor;
+ // Rows that are divisble by two are colored
+ if (this.tableLayout.GetRow(control) % 2 == 0)
+ targetColor = Color.Transparent;
+ else
+ targetColor=alternatingColor;
+
+ if (control.BackColor != targetColor)
+ control.BackColor = targetColor;
+ }
+ }
+
+ public void Highlight(Control c)
+ {
+ if (c != null)
+ {
+ c.BackColor = highlightColor;
+ highlightedEntry = c;
+ }
+ }
+ public void Unhighlight(Control c)
+ {
+ // TODO: unhighlight one at a time
+ AlternateColorsOfEntries();
+ highlightedEntry = null;
+ }
+
+ #region Properties
+ public Control HighlightedEntry
+ {
+ get { return highlightedEntry; }
+ set { highlightedEntry = value; }
+ }
+
+ #endregion
+ }
}
View
191 src/InstallPadApp.cs
</
@@ -1,97 +1,96 @@
-//
-// Author: Phil Crosby
-// Author: Zac Ruiz
-//
-
-// Copyright (C) 2006 Phil Crosby
-// Permission is granted to use, copy, modify, and merge copies
-// of this software for personal use. Permission is not granted
-// to use or change this software for commercial use or commercial
-// redistribution. Permission is not granted to use, modify or
-// distribute this software internally within a corporation.
-
-using System;
-using System.IO;
-using System.Text;
-using System.Reflection;
-
-
-namespace InstallPad
-{
- /// <summary>
- /// Application wide resources
- /// </summary>
- partial class InstallPadApp
- {
- #region Fields and Ctor
- private static string appListFile = "applist.xml";
- private static ApplicationList appList = null;
- private static Preferences preferences = new Preferences();
-
- static InstallPadApp()
- {
- if (Preferences.AppListFile != string.Empty)
- appListFile = Preferences.AppListFile;
- }
- #endregion
-
- #region Accessors
- /// <summary>
- /// The loaded application list.
- /// </summary>
- public static ApplicationList AppList
- {
- get { return InstallPadApp.appList; }
- set { InstallPadApp.appList = value; }
- }
-
- /// <summary>
- /// Location to store application data.
- /// </summary>
- public static string ApplicationDataPath
- {
- get
- {
- return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"InstallPad");
- }
- }
-
- /// <summary>
- /// Full path of file to cache WinForm config data.
- /// </summary>
- public static string ConfigFilePath
- {
- get
- {
- return System.IO.Path.Combine(ApplicationDataPath, @"ui.xml");
- }
- }
-
- /// <summary>
- /// Full path of application configuration file.
- /// </summary>
- public static string AppConfigFilePath
- {
- get
- {
- return System.IO.Path.Combine(ApplicationDataPath, @"InstallPad.exe.config");
- }
- }
-
- /// <summary>
- /// File containing application list.
- /// </summary>
- public static string AppListFile
- {
- get
- {
- return appListFile;
- }
- set
- {
- appListFile = value;
- }
- }
- #endregion
- }
+//
+// Author: Phil Crosby
+// Author: Zac Ruiz
+//
+
+// Copyright (C) 2006 Phil Crosby
+// Permission is granted to use, copy, modify, and merge copies
+// of this software for personal use. Permission is not granted
+// to use or change this software for commercial use or commercial
+// redistribution. Permission is not granted to use, modify or
+// distribute this software internally within a corporation.
+
+using System;
+using System.IO;
+using System.Text;
+using System.Reflection;
+
+namespace InstallPad
+{
+ /// <summary>
+ /// Application wide resources
+ /// </summary>
+ partial class InstallPadApp
+ {
+ #region Fields and Ctor
+ private static string appListFile = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "applist.xml");
+ private static ApplicationList appList = null;
+ private static Preferences preferences = new Preferences();
+
+ static InstallPadApp()
+ {
+ if (Preferences.AppListFile != string.Empty)
+ appListFile = Preferences.AppListFile;
+ }
+ #endregion
+
+ #region Accessors
+ /// <summary>
+ /// The loaded application list.
+ /// </summary>
+ public static ApplicationList AppList
+ {
+ get { return InstallPadApp.appList; }
+ set { InstallPadApp.appList = value; }
+ }
+
+ /// <summary>
+ /// Location to store application data.
+ /// </summary>
+ public static string ApplicationDataPath
+ {
+ get
+ {
+ return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"InstallPad");
+ }
+ }
+
+ /// <summary>
+ /// Full path of file to cache WinForm config data.
+ /// </summary>
+ public static string ConfigFilePath
+ {
+ get
+ {
+ return System.IO.Path.Combine(ApplicationDataPath, @"ui.xml");
+ }
+ }
+
+ /// <summary>
+ /// Full path of application configuration file.
+ /// </summary>
+ public static string AppConfigFilePath
+ {
+ get
+ {
+ return System.IO.Path.Combine(ApplicationDataPath, @"InstallPad.exe.config");
+ }
+ }