diff --git a/.vscode/format-report.json b/.vscode/format-report.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/.vscode/format-report.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..dae7fe8 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,19 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + }, + { + "type": "node", + "request": "launch", + "name": "node Launch Current Opened File", + "program": "${file}" + } + ] +} \ No newline at end of file diff --git a/.vscode/mklink.md b/.vscode/mklink.md new file mode 100644 index 0000000..d4f23be --- /dev/null +++ b/.vscode/mklink.md @@ -0,0 +1,31 @@ +--- +type: "note" +created: "2023-10-20T03:53:13.742Z" +updated: "2023-10-20T04:00:37.259Z" +--- + +# mklink + +```bash +mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.kanbn" "D:\5-Other-Small\Kanban\File-Folder-Helper" +``` + +```bash +mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.kanbn" "D:\5-Other-Small\Kanban\File-Folder-Helper" +``` + +```bash +del "L:\DevOps\Mesa_FI\File-Folder-Helper\.extensions-vscode" +del "L:\DevOps\Mesa_FI\File-Folder-Helper\.extensions-vscode-oss" +del "L:\DevOps\Mesa_FI\File-Folder-Helper\.extensions-vscode-insiders" +mkdir "C:\Users\phares\.vscode\extensions\ifx.type-script-helper-1.111.0\net8.0\win-x64\publish" +mkdir "C:\Users\phares\.vscode-oss\extensions\ifx.type-script-helper-1.111.0\net8.0\win-x64\publish" +mkdir "C:\Users\phares\.vscode-insiders\extensions\ifx.type-script-helper-1.111.0\net8.0\win-x64\publish" +mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.extensions-vscode" "C:\Users\phares\.vscode\extensions\ifx.type-script-helper-1.111.0" +mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.extensions-vscode-oss" "C:\Users\phares\.vscode-oss\extensions\ifx.type-script-helper-1.111.0" +mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.extensions-vscode-insiders" "C:\Users\phares\.vscode-insiders\extensions\ifx.type-script-helper-1.111.0" +``` + +```bash Thu Jul 18 2024 13:47:40 GMT-0700 (Mountain Standard Time) +mklink /J "L:\DevOps\Mesa_FI\File-Folder-Helper\.vscode\.UserSecrets" "C:\Users\phares\AppData\Roaming\Microsoft\UserSecrets\8da397d4-13ec-4576-9722-3c79cad25563" +``` diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..0243f6a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,20 @@ +{ + "[markdown]": { + "editor.wordWrap": "off" + }, + "cSpell.words": [ + "Amstrad", + "doesnt", + "dont", + "Doubleclick", + "Finalizers", + "harddrive", + "propval", + "propvals", + "refrences", + "SETTINGSROOT", + "subdirs", + "subfolders", + "treeview" + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..05517a6 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,163 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "User Secrets Init", + "command": "dotnet", + "type": "process", + "args": [ + "user-secrets", + "-p", + "${workspaceFolder}/Snap2HTML.sln", + "init" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "User Secrets Set", + "command": "dotnet", + "type": "process", + "args": [ + "user-secrets", + "-p", + "${workspaceFolder}/Snap2HTML.sln", + "set", + "_UserSecretsId", + "0c43f9aa-96e9-4298-967c-ed069d79e262" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "Format", + "command": "dotnet", + "type": "process", + "args": [ + "format", + "--report", + ".vscode", + "--verbosity", + "detailed", + "--severity", + "warn" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "Format-Whitespaces", + "command": "dotnet", + "type": "process", + "args": [ + "format", + "whitespace" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "-r", + "win-x64", + "${workspaceFolder}/Snap2HTML.sln", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "build Linux", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "-r", + "linux-x64", + "${workspaceFolder}/Snap2HTML.sln", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/Snap2HTML.sln", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "--project", + "${workspaceFolder}/Snap2HTML.sln" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "Publish AOT", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "-r", + "win-x64", + "-c", + "Release", + "-p:PublishAot=true", + "${workspaceFolder}/Snap2HTML.sln", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "Publish AOT Linux", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "-r", + "linux-x64", + "-c", + "Release", + "-p:PublishAot=true", + "${workspaceFolder}/Snap2HTML.sln", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "MSBuild for EAF Deployment Packages", + "command": "C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/MSBuild/Current/Bin/MSBuild.exe", + "type": "process", + "args": [ + "/target:Build", + "/restore:True", + "/p:RestoreSources=https://artifactory.intra.infineon.com/artifactory/api/nuget/ngt-fi-package-main-vir/%3Bhttps://tfs.intra.infineon.com/tfs/FactoryIntegration/_packaging/EAF/nuget/v3/index.json%3Bhttps://tfs.intra.infineon.com/tfs/FactoryIntegration/_packaging/EAF%40Local/nuget/v3/index.json%3Bhttps://api.nuget.org/v3/index.json", + "/detailedsummary", + "/consoleloggerparameters:PerformanceSummary;ErrorsOnly;", + "/property:Configuration=Debug;TargetFrameworkVersion=v4.8", + "Snap2HTML.sln" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "Jest", + "type": "shell", + "command": "npx jest", + "problemMatcher": [] + } + ] +} \ No newline at end of file diff --git a/Snap2HTML/CommandLine.cs b/Snap2HTML/CommandLine.cs index 1aacf2b..ae909a2 100644 --- a/Snap2HTML/CommandLine.cs +++ b/Snap2HTML/CommandLine.cs @@ -118,9 +118,9 @@ namespace CommandLine.Utility //Because of the split index 0 will be a empty string string valuesWithoutQuotes = RemoveMatchingQuotes(parts[2]); - // MOD: Don't split on commas + // MOD: Don't split on commas //AddListValues(parts[1], valuesWithoutQuotes.Split(',')); - Add( parts[1], valuesWithoutQuotes ); + Add(parts[1], valuesWithoutQuotes); break; } } diff --git a/Snap2HTML/Models.cs b/Snap2HTML/Models.cs index 7febb8c..0aec6f8 100644 --- a/Snap2HTML/Models.cs +++ b/Snap2HTML/Models.cs @@ -5,91 +5,91 @@ using System.Text; namespace Snap2HTML { - public class SnapSettings - { - public string rootFolder { get; set; } - public string title { get; set; } - public string outputFile { get; set; } - public bool skipHiddenItems { get; set; } - public bool skipSystemItems { get; set; } - public bool openInBrowser { get; set; } - public bool linkFiles { get; set; } - public string linkRoot { get; set; } + public class SnapSettings + { + public string rootFolder { get; set; } + public string title { get; set; } + public string outputFile { get; set; } + public bool skipHiddenItems { get; set; } + public bool skipSystemItems { get; set; } + public bool openInBrowser { get; set; } + public bool linkFiles { get; set; } + public string linkRoot { get; set; } - public SnapSettings() - { - this.skipHiddenItems = true; - this.skipSystemItems = true; - this.openInBrowser = false; - this.linkFiles = false; - this.linkRoot = ""; - } - } + public SnapSettings() + { + this.skipHiddenItems = true; + this.skipSystemItems = true; + this.openInBrowser = false; + this.linkFiles = false; + this.linkRoot = ""; + } + } - public class SnappedFile - { - public SnappedFile( string name ) - { - this.Name = name; - this.Properties = new Dictionary(); - } + public class SnappedFile + { + public SnappedFile(string name) + { + this.Name = name; + this.Properties = new Dictionary(); + } - public string Name { get; set; } - public Dictionary Properties { get; set; } + public string Name { get; set; } + public Dictionary Properties { get; set; } - public string GetProp( string key ) - { - if( this.Properties.ContainsKey( key ) ) - return this.Properties[key]; - else - return ""; - } + public string GetProp(string key) + { + if (this.Properties.ContainsKey(key)) + return this.Properties[key]; + else + return ""; + } - } + } - public class SnappedFolder - { - public SnappedFolder( string name, string path ) - { - this.Name = name; - this.Path = path; - this.Properties = new Dictionary(); - this.Files = new List(); - } + public class SnappedFolder + { + public SnappedFolder(string name, string path) + { + this.Name = name; + this.Path = path; + this.Properties = new Dictionary(); + this.Files = new List(); + } - public string Name { get; set; } - public string Path { get; set; } - public Dictionary Properties { get; set; } - public List Files { get; set; } + public string Name { get; set; } + public string Path { get; set; } + public Dictionary Properties { get; set; } + public List Files { get; set; } - public string GetFullPath() - { - string path; + public string GetFullPath() + { + string path; - if( this.Path.EndsWith( @"\" ) ) - path = this.Path + this.Name; - else - path = this.Path + @"\" + this.Name; + if (this.Path.EndsWith(@"\")) + path = this.Path + this.Name; + else + path = this.Path + @"\" + this.Name; - if( path.EndsWith( @"\" ) ) // remove trailing backslash - { - if(!Utils.IsWildcardMatch( @"?:\", path, false )) // except for drive letters - { - path = path.Remove( path.Length - 1 ); - } - - } + if (path.EndsWith(@"\")) // remove trailing backslash + { + if (!Utils.IsWildcardMatch(@"?:\", path, false)) // except for drive letters + { + path = path.Remove(path.Length - 1); + } - return path; - } + } - public string GetProp( string key ) - { - if( this.Properties.ContainsKey( key ) ) - return this.Properties[key]; - else - return ""; - } - } + return path; + } + + public string GetProp(string key) + { + if (this.Properties.ContainsKey(key)) + return this.Properties[key]; + else + return ""; + } + } } diff --git a/Snap2HTML/PortableSettingsProvider.cs b/Snap2HTML/PortableSettingsProvider.cs index da0f760..7066d9d 100644 --- a/Snap2HTML/PortableSettingsProvider.cs +++ b/Snap2HTML/PortableSettingsProvider.cs @@ -4,198 +4,240 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Text; +using System.Collections.Specialized; using System.Configuration; using System.Configuration.Provider; -using System.Windows.Forms; -using System.Collections.Specialized; -using Microsoft.Win32; -using System.Xml; using System.IO; - -public class PortableSettingsProvider : SettingsProvider { - - const string SETTINGSROOT = "Settings"; - //XML Root Node +using System.Text; +using System.Windows.Forms; +using System.Xml; +using Microsoft.Win32; - public override void Initialize(string name, NameValueCollection col) { - base.Initialize(this.ApplicationName, col); - } - - public override string ApplicationName { - get { - if (Application.ProductName.Trim().Length > 0) { - return Application.ProductName; - } - else { - FileInfo fi = new FileInfo(Application.ExecutablePath); - return fi.Name.Substring(0, fi.Name.Length - fi.Extension.Length); - } +public class PortableSettingsProvider : SettingsProvider +{ + + const string SETTINGSROOT = "Settings"; + //XML Root Node + + public override void Initialize(string name, NameValueCollection col) + { + base.Initialize(this.ApplicationName, col); } - set { } - //Do nothing - } - - public override string Name { - get { return "PortableSettingsProvider"; } - } - public virtual string GetAppSettingsPath() { - //Used to determine where to store the settings - System.IO.FileInfo fi = new System.IO.FileInfo(Application.ExecutablePath); - return fi.DirectoryName; - } - - public virtual string GetAppSettingsFilename() { - //Used to determine the filename to store the settings - return ApplicationName + ".settings"; - } - - public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection propvals) { - //Iterate through the settings to be stored - //Only dirty settings are included in propvals, and only ones relevant to this provider - foreach (SettingsPropertyValue propval in propvals) { - SetValue(propval); - } - - try { - SettingsXML.Save(Path.Combine(GetAppSettingsPath(), GetAppSettingsFilename())); - } - catch (Exception ex) { - } - //Ignore if cant save, device been ejected - } - - public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection props) { - //Create new collection of values - SettingsPropertyValueCollection values = new SettingsPropertyValueCollection(); - - //Iterate through the settings to be retrieved - foreach (SettingsProperty setting in props) { - - SettingsPropertyValue value = new SettingsPropertyValue(setting); - value.IsDirty = false; - value.SerializedValue = GetValue(setting); - values.Add(value); - } - return values; - } - - private XmlDocument _settingsXML = null; - - private XmlDocument SettingsXML { - get { - //If we dont hold an xml document, try opening one. - //If it doesnt exist then create a new one ready. - if (_settingsXML == null) { - _settingsXML = new XmlDocument(); - - try { - _settingsXML.Load(Path.Combine(GetAppSettingsPath(), GetAppSettingsFilename())); + + public override string ApplicationName + { + get + { + if (Application.ProductName.Trim().Length > 0) + { + return Application.ProductName; + } + else + { + FileInfo fi = new FileInfo(Application.ExecutablePath); + return fi.Name.Substring(0, fi.Name.Length - fi.Extension.Length); + } } - catch (Exception ex) { - //Create new document - XmlDeclaration dec = _settingsXML.CreateXmlDeclaration("1.0", "utf-8", string.Empty); - _settingsXML.AppendChild(dec); - - XmlNode nodeRoot = default(XmlNode); - - nodeRoot = _settingsXML.CreateNode(XmlNodeType.Element, SETTINGSROOT, ""); - _settingsXML.AppendChild(nodeRoot); + set { } + //Do nothing + } + + public override string Name + { + get { return "PortableSettingsProvider"; } + } + public virtual string GetAppSettingsPath() + { + //Used to determine where to store the settings + System.IO.FileInfo fi = new System.IO.FileInfo(Application.ExecutablePath); + return fi.DirectoryName; + } + + public virtual string GetAppSettingsFilename() + { + //Used to determine the filename to store the settings + return ApplicationName + ".settings"; + } + + public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection propvals) + { + //Iterate through the settings to be stored + //Only dirty settings are included in propvals, and only ones relevant to this provider + foreach (SettingsPropertyValue propval in propvals) + { + SetValue(propval); } - } - - return _settingsXML; - } - } - - private string GetValue(SettingsProperty setting) { - string ret = ""; - - try { - if (IsRoaming(setting)) { - ret = SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + setting.Name).InnerText; - } - else { - ret = SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + Environment.MachineName + "/" + setting.Name).InnerText; - } - } - - catch (Exception ex) { - if ((setting.DefaultValue != null)) { - ret = setting.DefaultValue.ToString(); - } - else { - ret = ""; - } - } - - return ret; - } - - private void SetValue(SettingsPropertyValue propVal) { - - XmlElement MachineNode = default(XmlElement); - XmlElement SettingNode = default(XmlElement); - - //Determine if the setting is roaming. - //If roaming then the value is stored as an element under the root - //Otherwise it is stored under a machine name node - try { - if (IsRoaming(propVal.Property)) { - SettingNode = (XmlElement)SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + propVal.Name); - } - else { - SettingNode = (XmlElement)SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + Environment.MachineName + "/" + propVal.Name); - } - } - catch (Exception ex) { - SettingNode = null; - } - - //Check to see if the node exists, if so then set its new value - if ((SettingNode != null)) { - SettingNode.InnerText = propVal.SerializedValue.ToString(); - } - else { - if (IsRoaming(propVal.Property)) { - //Store the value as an element of the Settings Root Node - SettingNode = SettingsXML.CreateElement(propVal.Name); - SettingNode.InnerText = propVal.SerializedValue.ToString(); - SettingsXML.SelectSingleNode(SETTINGSROOT).AppendChild(SettingNode); - } - else { - //Its machine specific, store as an element of the machine name node, - //creating a new machine name node if one doesnt exist. - try { - - MachineNode = (XmlElement)SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + Environment.MachineName); + + try + { + SettingsXML.Save(Path.Combine(GetAppSettingsPath(), GetAppSettingsFilename())); } - catch (Exception ex) { - MachineNode = SettingsXML.CreateElement(Environment.MachineName); - SettingsXML.SelectSingleNode(SETTINGSROOT).AppendChild(MachineNode); + catch (Exception) + { } - - if (MachineNode == null) { - MachineNode = SettingsXML.CreateElement(Environment.MachineName); - SettingsXML.SelectSingleNode(SETTINGSROOT).AppendChild(MachineNode); + //Ignore if cant save, device been ejected + } + + public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection props) + { + //Create new collection of values + SettingsPropertyValueCollection values = new SettingsPropertyValueCollection(); + + //Iterate through the settings to be retrieved + foreach (SettingsProperty setting in props) + { + + SettingsPropertyValue value = new SettingsPropertyValue(setting); + value.IsDirty = false; + value.SerializedValue = GetValue(setting); + values.Add(value); } - - SettingNode = SettingsXML.CreateElement(propVal.Name); - SettingNode.InnerText = propVal.SerializedValue.ToString(); - MachineNode.AppendChild(SettingNode); - } + return values; } - } - - private bool IsRoaming(SettingsProperty prop) { - //Determine if the setting is marked as Roaming - foreach (DictionaryEntry d in prop.Attributes) { - Attribute a = (Attribute)d.Value; - if (a is System.Configuration.SettingsManageabilityAttribute) { - return true; - } + + private XmlDocument _settingsXML = null; + + private XmlDocument SettingsXML + { + get + { + //If we dont hold an xml document, try opening one. + //If it doesnt exist then create a new one ready. + if (_settingsXML == null) + { + _settingsXML = new XmlDocument(); + + try + { + _settingsXML.Load(Path.Combine(GetAppSettingsPath(), GetAppSettingsFilename())); + } + catch (Exception) + { + //Create new document + XmlDeclaration dec = _settingsXML.CreateXmlDeclaration("1.0", "utf-8", string.Empty); + _settingsXML.AppendChild(dec); + + XmlNode nodeRoot = default(XmlNode); + + nodeRoot = _settingsXML.CreateNode(XmlNodeType.Element, SETTINGSROOT, ""); + _settingsXML.AppendChild(nodeRoot); + } + } + + return _settingsXML; + } + } + + private string GetValue(SettingsProperty setting) + { + string ret = ""; + + try + { + if (IsRoaming(setting)) + { + ret = SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + setting.Name).InnerText; + } + else + { + ret = SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + Environment.MachineName + "/" + setting.Name).InnerText; + } + } + + catch (Exception) + { + if ((setting.DefaultValue != null)) + { + ret = setting.DefaultValue.ToString(); + } + else + { + ret = ""; + } + } + + return ret; + } + + private void SetValue(SettingsPropertyValue propVal) + { + + XmlElement MachineNode = default(XmlElement); + XmlElement SettingNode = default(XmlElement); + + //Determine if the setting is roaming. + //If roaming then the value is stored as an element under the root + //Otherwise it is stored under a machine name node + try + { + if (IsRoaming(propVal.Property)) + { + SettingNode = (XmlElement)SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + propVal.Name); + } + else + { + SettingNode = (XmlElement)SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + Environment.MachineName + "/" + propVal.Name); + } + } + catch (Exception) + { + SettingNode = null; + } + + //Check to see if the node exists, if so then set its new value + if ((SettingNode != null)) + { + SettingNode.InnerText = propVal.SerializedValue.ToString(); + } + else + { + if (IsRoaming(propVal.Property)) + { + //Store the value as an element of the Settings Root Node + SettingNode = SettingsXML.CreateElement(propVal.Name); + SettingNode.InnerText = propVal.SerializedValue.ToString(); + SettingsXML.SelectSingleNode(SETTINGSROOT).AppendChild(SettingNode); + } + else + { + //Its machine specific, store as an element of the machine name node, + //creating a new machine name node if one doesnt exist. + try + { + + MachineNode = (XmlElement)SettingsXML.SelectSingleNode(SETTINGSROOT + "/" + Environment.MachineName); + } + catch (Exception) + { + MachineNode = SettingsXML.CreateElement(Environment.MachineName); + SettingsXML.SelectSingleNode(SETTINGSROOT).AppendChild(MachineNode); + } + + if (MachineNode == null) + { + MachineNode = SettingsXML.CreateElement(Environment.MachineName); + SettingsXML.SelectSingleNode(SETTINGSROOT).AppendChild(MachineNode); + } + + SettingNode = SettingsXML.CreateElement(propVal.Name); + SettingNode.InnerText = propVal.SerializedValue.ToString(); + MachineNode.AppendChild(SettingNode); + } + } + } + + private bool IsRoaming(SettingsProperty prop) + { + //Determine if the setting is marked as Roaming + foreach (DictionaryEntry d in prop.Attributes) + { + Attribute a = (Attribute)d.Value; + if (a is System.Configuration.SettingsManageabilityAttribute) + { + return true; + } + } + return false; } - return false; - } } - + diff --git a/Snap2HTML/Properties/AssemblyInfo.cs b/Snap2HTML/Properties/AssemblyInfo.cs index 2acc4b7..3e68488 100644 --- a/Snap2HTML/Properties/AssemblyInfo.cs +++ b/Snap2HTML/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("RL Vision")] [assembly: AssemblyProduct("Snap2HTML")] -[assembly: AssemblyCopyright( "Copyright © RL Vision 2011-2020" )] +[assembly: AssemblyCopyright("Copyright © RL Vision 2011-2020")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion( "2.14.0.0" )] -[assembly: AssemblyFileVersion( "2.14.0.0" )] +[assembly: AssemblyVersion("2.14.0.0")] +[assembly: AssemblyFileVersion("2.14.0.0")] diff --git a/Snap2HTML/ReadMe.txt b/Snap2HTML/ReadMe.txt index a6fdbae..81dd1ef 100644 --- a/Snap2HTML/ReadMe.txt +++ b/Snap2HTML/ReadMe.txt @@ -233,7 +233,7 @@ Fixed a threading issue that caused the program to hang on some systems v2.12 (2020-04-29) - Reduced memory consumsion when generating HTML + Reduced memory consumption when generating HTML Parent folder link [..] is now sticky Reworked command line code to fix issues in 2.11 A few small tweaks too diff --git a/Snap2HTML/Settings.cs b/Snap2HTML/Settings.cs index 8279e96..b2eae50 100644 --- a/Snap2HTML/Settings.cs +++ b/Snap2HTML/Settings.cs @@ -1,36 +1,37 @@ -namespace Snap2HTML.Properties { +namespace Snap2HTML.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; - // + 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; + // - this.SettingsLoaded += this.SettingsLoadedEventHandler; - } + this.SettingsLoaded += this.SettingsLoadedEventHandler; + } - private void SettingChangingEventHandler( object sender, System.Configuration.SettingChangingEventArgs e ) - { - // Add code to handle the SettingChangingEvent event here. - } + 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. - System.Console.WriteLine( "Settings Saving..." ); - } - private void SettingsLoadedEventHandler( object sender, System.Configuration.SettingsLoadedEventArgs e ) - { - System.Console.WriteLine( "Settings Loaded..." ); - } - } + private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) + { + // Add code to handle the SettingsSaving event here. + System.Console.WriteLine("Settings Saving..."); + } + private void SettingsLoadedEventHandler(object sender, System.Configuration.SettingsLoadedEventArgs e) + { + System.Console.WriteLine("Settings Loaded..."); + } + } } diff --git a/Snap2HTML/Utils.cs b/Snap2HTML/Utils.cs index 797715d..fd33dfe 100644 --- a/Snap2HTML/Utils.cs +++ b/Snap2HTML/Utils.cs @@ -11,80 +11,80 @@ using System.Diagnostics; namespace Snap2HTML { - class Utils - { - // Hack to sort folders correctly even if they have spaces/periods in them - public static List SortDirList( List lstDirs ) - { - for( int n = 0; n < lstDirs.Count; n++ ) - { - lstDirs[n] = lstDirs[n].Replace( " ", "1|1" ); - lstDirs[n] = lstDirs[n].Replace( ".", "2|2" ); - } - lstDirs.Sort(); - for( int n = 0; n < lstDirs.Count; n++ ) - { - lstDirs[n] = lstDirs[n].Replace( "1|1", " " ); - lstDirs[n] = lstDirs[n].Replace( "2|2", "." ); - } - return lstDirs; - } + class Utils + { + // Hack to sort folders correctly even if they have spaces/periods in them + public static List SortDirList(List lstDirs) + { + for (int n = 0; n < lstDirs.Count; n++) + { + lstDirs[n] = lstDirs[n].Replace(" ", "1|1"); + lstDirs[n] = lstDirs[n].Replace(".", "2|2"); + } + lstDirs.Sort(); + for (int n = 0; n < lstDirs.Count; n++) + { + lstDirs[n] = lstDirs[n].Replace("1|1", " "); + lstDirs[n] = lstDirs[n].Replace("2|2", "."); + } + return lstDirs; + } - // Replaces characters that may appear in filenames/paths that have special meaning to JavaScript - // Info on u2028/u2029: https://en.wikipedia.org/wiki/Newline#Unicode - public static string MakeCleanJsString( string s ) - { - return s.Replace( "\\", "\\\\" ) - .Replace( "&", "&" ) - .Replace( "\u2028", "" ) - .Replace( "\u2029", "" ) - .Replace( "\u0004", "" ); - } + // Replaces characters that may appear in filenames/paths that have special meaning to JavaScript + // Info on u2028/u2029: https://en.wikipedia.org/wiki/Newline#Unicode + public static string MakeCleanJsString(string s) + { + return s.Replace("\\", "\\\\") + .Replace("&", "&") + .Replace("\u2028", "") + .Replace("\u2029", "") + .Replace("\u0004", ""); + } - // Test string for matches against a wildcard pattern. Use ? and * as wildcards. (Wrapper around RegEx) - public static bool IsWildcardMatch( String wildcard, String text, bool casesensitive ) - { - System.Text.StringBuilder sb = new System.Text.StringBuilder( wildcard.Length + 10 ); - sb.Append( "^" ); - for( int i = 0; i < wildcard.Length; i++ ) - { - char c = wildcard[i]; - switch( c ) - { - case '*': - sb.Append( ".*" ); - break; - case '?': - sb.Append( "." ); - break; - default: - sb.Append( System.Text.RegularExpressions.Regex.Escape( wildcard[i].ToString() ) ); - break; - } - } - sb.Append( "$" ); - System.Text.RegularExpressions.Regex regex; - if( casesensitive ) - regex = new System.Text.RegularExpressions.Regex( sb.ToString(), System.Text.RegularExpressions.RegexOptions.None ); - else - regex = new System.Text.RegularExpressions.Regex( sb.ToString(), System.Text.RegularExpressions.RegexOptions.IgnoreCase ); + // Test string for matches against a wildcard pattern. Use ? and * as wildcards. (Wrapper around RegEx) + public static bool IsWildcardMatch(String wildcard, String text, bool casesensitive) + { + System.Text.StringBuilder sb = new System.Text.StringBuilder(wildcard.Length + 10); + sb.Append("^"); + for (int i = 0; i < wildcard.Length; i++) + { + char c = wildcard[i]; + switch (c) + { + case '*': + sb.Append(".*"); + break; + case '?': + sb.Append("."); + break; + default: + sb.Append(System.Text.RegularExpressions.Regex.Escape(wildcard[i].ToString())); + break; + } + } + sb.Append("$"); + System.Text.RegularExpressions.Regex regex; + if (casesensitive) + regex = new System.Text.RegularExpressions.Regex(sb.ToString(), System.Text.RegularExpressions.RegexOptions.None); + else + regex = new System.Text.RegularExpressions.Regex(sb.ToString(), System.Text.RegularExpressions.RegexOptions.IgnoreCase); - return regex.IsMatch( text ); - } + return regex.IsMatch(text); + } - public static int ToUnixTimestamp( DateTime value ) - { - return (int)Math.Truncate( ( value.ToUniversalTime().Subtract( new DateTime( 1970, 1, 1 ) ) ).TotalSeconds ); - } + public static int ToUnixTimestamp(DateTime value) + { + return (int)Math.Truncate((value.ToUniversalTime().Subtract(new DateTime(1970, 1, 1))).TotalSeconds); + } - public static long ParseLong(string s) - { - long num; - if( Int64.TryParse( s, out num ) ) - { - return num; - } - return 0; - } - } + public static long ParseLong(string s) + { + long num; + if (Int64.TryParse(s, out num)) + { + return num; + } + return 0; + } + } } diff --git a/Snap2HTML/frmMain.cs b/Snap2HTML/frmMain.cs index 5fa2b15..20f01ad 100644 --- a/Snap2HTML/frmMain.cs +++ b/Snap2HTML/frmMain.cs @@ -11,250 +11,250 @@ namespace Snap2HTML { public partial class frmMain : Form { - private bool initDone = false; - private bool runningAutomated = false; + private bool initDone = false; + private bool runningAutomated = false; public frmMain() { InitializeComponent(); } - private void frmMain_Load( object sender, EventArgs e ) - { - this.Text = Application.ProductName + " (Press F1 for Help)"; - labelAboutVersion.Text = "version " + Application.ProductVersion.Split( '.' )[0] + "." + Application.ProductVersion.Split( '.' )[1]; + private void frmMain_Load(object sender, EventArgs e) + { + this.Text = Application.ProductName + " (Press F1 for Help)"; + labelAboutVersion.Text = "version " + Application.ProductVersion.Split('.')[0] + "." + Application.ProductVersion.Split('.')[1]; - // initialize some settings - int left = Snap2HTML.Properties.Settings.Default.WindowLeft; - int top = Snap2HTML.Properties.Settings.Default.WindowTop; - if( left >= 0 ) this.Left = left; - if( top >= 0 ) this.Top = top; + // initialize some settings + int left = Snap2HTML.Properties.Settings.Default.WindowLeft; + int top = Snap2HTML.Properties.Settings.Default.WindowTop; + if (left >= 0) this.Left = left; + if (top >= 0) this.Top = top; - if( System.IO.Directory.Exists( txtRoot.Text ) ) - { - SetRootPath( txtRoot.Text , true); - } - else - { - SetRootPath( "" , false ); - } + if (System.IO.Directory.Exists(txtRoot.Text)) + { + SetRootPath(txtRoot.Text, true); + } + else + { + SetRootPath("", false); + } - txtLinkRoot.Enabled = chkLinkFiles.Checked; + txtLinkRoot.Enabled = chkLinkFiles.Checked; - // setup drag & drop handlers - tabPage1.DragDrop += DragDropHandler; - tabPage1.DragEnter += DragEnterHandler; - tabPage1.AllowDrop = true; - foreach( Control cnt in tabPage1.Controls ) - { - cnt.DragDrop += DragDropHandler; - cnt.DragEnter += DragEnterHandler; - cnt.AllowDrop = true; - } + // setup drag & drop handlers + tabPage1.DragDrop += DragDropHandler; + tabPage1.DragEnter += DragEnterHandler; + tabPage1.AllowDrop = true; + foreach (Control cnt in tabPage1.Controls) + { + cnt.DragDrop += DragDropHandler; + cnt.DragEnter += DragEnterHandler; + cnt.AllowDrop = true; + } - Opacity = 0; // for silent mode + Opacity = 0; // for silent mode - initDone = true; - } + initDone = true; + } - private void frmMain_Shown( object sender, EventArgs e ) + private void frmMain_Shown(object sender, EventArgs e) { // parse command line var commandLine = Environment.CommandLine; - commandLine = commandLine.Replace( "-output:", "-outfile:" ); // correct wrong parameter to avoid confusion + commandLine = commandLine.Replace("-output:", "-outfile:"); // correct wrong parameter to avoid confusion var splitCommandLine = Arguments.SplitCommandLine(commandLine); var arguments = new Arguments(splitCommandLine); // first test for single argument (ie path only) - if( splitCommandLine.Length == 2 && !arguments.Exists( "path" ) ) - { - if( System.IO.Directory.Exists( splitCommandLine[1] ) ) - { - SetRootPath( splitCommandLine[1] ); - } - } - - var settings = new SnapSettings(); - if( arguments.Exists( "path" ) && arguments.Exists( "outfile" ) ) + if (splitCommandLine.Length == 2 && !arguments.Exists("path")) { - this.runningAutomated = true; + if (System.IO.Directory.Exists(splitCommandLine[1])) + { + SetRootPath(splitCommandLine[1]); + } + } - settings.rootFolder = arguments.Single( "path" ); - settings.outputFile = arguments.Single( "outfile" ); + var settings = new SnapSettings(); + if (arguments.Exists("path") && arguments.Exists("outfile")) + { + this.runningAutomated = true; - // First validate paths - if( !System.IO.Directory.Exists( settings.rootFolder ) ) - { - if( !arguments.Exists( "silent" ) ) - { - MessageBox.Show( "Input path does not exist: " + settings.rootFolder, "Automation Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); - } - Application.Exit(); - } - if( !System.IO.Directory.Exists( System.IO.Path.GetDirectoryName(settings.outputFile) ) ) - { - if( !arguments.Exists( "silent" ) ) - { - MessageBox.Show( "Output path does not exist: " + System.IO.Path.GetDirectoryName( settings.outputFile ), "Automation Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); - } - Application.Exit(); - } + settings.rootFolder = arguments.Single("path"); + settings.outputFile = arguments.Single("outfile"); - // Rest of settings + // First validate paths + if (!System.IO.Directory.Exists(settings.rootFolder)) + { + if (!arguments.Exists("silent")) + { + MessageBox.Show("Input path does not exist: " + settings.rootFolder, "Automation Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + Application.Exit(); + } + if (!System.IO.Directory.Exists(System.IO.Path.GetDirectoryName(settings.outputFile))) + { + if (!arguments.Exists("silent")) + { + MessageBox.Show("Output path does not exist: " + System.IO.Path.GetDirectoryName(settings.outputFile), "Automation Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + Application.Exit(); + } - settings.skipHiddenItems = !arguments.Exists( "hidden" ); - settings.skipSystemItems = !arguments.Exists( "system" ); - settings.openInBrowser = false; - - settings.linkFiles = false; - if( arguments.Exists( "link" ) ) - { - settings.linkFiles = true; - settings.linkRoot = arguments.Single( "link" ); - } + // Rest of settings - settings.title = "Snapshot of " + settings.rootFolder; - if( arguments.Exists( "title" ) ) - { - settings.title = arguments.Single( "title" ); - } + settings.skipHiddenItems = !arguments.Exists("hidden"); + settings.skipSystemItems = !arguments.Exists("system"); + settings.openInBrowser = false; + + settings.linkFiles = false; + if (arguments.Exists("link")) + { + settings.linkFiles = true; + settings.linkRoot = arguments.Single("link"); + } + + settings.title = "Snapshot of " + settings.rootFolder; + if (arguments.Exists("title")) + { + settings.title = arguments.Single("title"); + } } - // keep window hidden in silent mode - if( arguments.IsTrue( "silent" ) && this.runningAutomated ) - { - Visible = false; - } - else - { - Opacity = 100; - } + // keep window hidden in silent mode + if (arguments.IsTrue("silent") && this.runningAutomated) + { + Visible = false; + } + else + { + Opacity = 100; + } - if( this.runningAutomated ) - { - StartProcessing( settings ); - } + if (this.runningAutomated) + { + StartProcessing(settings); + } } - private void frmMain_FormClosing( object sender, FormClosingEventArgs e ) - { - if( backgroundWorker.IsBusy ) e.Cancel = true; - - if( !this.runningAutomated ) // don't save settings when automated through command line - { - Snap2HTML.Properties.Settings.Default.WindowLeft = this.Left; - Snap2HTML.Properties.Settings.Default.WindowTop = this.Top; - Snap2HTML.Properties.Settings.Default.Save(); - } - } - - private void cmdBrowse_Click(object sender, EventArgs e) + private void frmMain_FormClosing(object sender, FormClosingEventArgs e) { - folderBrowserDialog1.RootFolder = Environment.SpecialFolder.Desktop; // this makes it possible to select network paths too - folderBrowserDialog1.SelectedPath = txtRoot.Text; + if (backgroundWorker.IsBusy) e.Cancel = true; + + if (!this.runningAutomated) // don't save settings when automated through command line + { + Snap2HTML.Properties.Settings.Default.WindowLeft = this.Left; + Snap2HTML.Properties.Settings.Default.WindowTop = this.Top; + Snap2HTML.Properties.Settings.Default.Save(); + } + } + + private void cmdBrowse_Click(object sender, EventArgs e) + { + folderBrowserDialog1.RootFolder = Environment.SpecialFolder.Desktop; // this makes it possible to select network paths too + folderBrowserDialog1.SelectedPath = txtRoot.Text; if (folderBrowserDialog1.ShowDialog() == DialogResult.OK) - { - try - { - SetRootPath( folderBrowserDialog1.SelectedPath ); - } - catch( System.Exception ex ) - { - MessageBox.Show( "Could not select folder:\n\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); - SetRootPath( "", false ); - } + { + try + { + SetRootPath(folderBrowserDialog1.SelectedPath); + } + catch (System.Exception ex) + { + MessageBox.Show("Could not select folder:\n\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + SetRootPath("", false); + } } } private void cmdCreate_Click(object sender, EventArgs e) - { - // ask for output file - string fileName = new System.IO.DirectoryInfo( txtRoot.Text + @"\" ).Name; - char[] invalid = System.IO.Path.GetInvalidFileNameChars(); - for (int i = 0; i < invalid.Length; i++) - { - fileName = fileName.Replace(invalid[i].ToString(), ""); - } + { + // ask for output file + string fileName = new System.IO.DirectoryInfo(txtRoot.Text + @"\").Name; + char[] invalid = System.IO.Path.GetInvalidFileNameChars(); + for (int i = 0; i < invalid.Length; i++) + { + fileName = fileName.Replace(invalid[i].ToString(), ""); + } saveFileDialog1.DefaultExt = "html"; - if( !fileName.ToLower().EndsWith( ".html" ) ) fileName += ".html"; - saveFileDialog1.FileName = fileName; - saveFileDialog1.Filter = "HTML files (*.html)|*.html|All files (*.*)|*.*"; + if (!fileName.ToLower().EndsWith(".html")) fileName += ".html"; + saveFileDialog1.FileName = fileName; + saveFileDialog1.Filter = "HTML files (*.html)|*.html|All files (*.*)|*.*"; saveFileDialog1.InitialDirectory = System.IO.Path.GetDirectoryName(txtRoot.Text); - saveFileDialog1.CheckPathExists = true; + saveFileDialog1.CheckPathExists = true; if (saveFileDialog1.ShowDialog() != DialogResult.OK) return; - if( !saveFileDialog1.FileName.ToLower().EndsWith( ".html" ) ) saveFileDialog1.FileName += ".html"; + if (!saveFileDialog1.FileName.ToLower().EndsWith(".html")) saveFileDialog1.FileName += ".html"; - // begin generating html - var settings = new SnapSettings() - { - rootFolder = txtRoot.Text, - title = txtTitle.Text, - outputFile = saveFileDialog1.FileName, - skipHiddenItems = !chkHidden.Checked, - skipSystemItems = !chkSystem.Checked, - openInBrowser = chkOpenOutput.Checked, - linkFiles = chkLinkFiles.Checked, - linkRoot = txtLinkRoot.Text, - }; - StartProcessing(settings); - } + // begin generating html + var settings = new SnapSettings() + { + rootFolder = txtRoot.Text, + title = txtTitle.Text, + outputFile = saveFileDialog1.FileName, + skipHiddenItems = !chkHidden.Checked, + skipSystemItems = !chkSystem.Checked, + openInBrowser = chkOpenOutput.Checked, + linkFiles = chkLinkFiles.Checked, + linkRoot = txtLinkRoot.Text, + }; + StartProcessing(settings); + } - private void StartProcessing(SnapSettings settings) - { - // ensure source path format - settings.rootFolder = System.IO.Path.GetFullPath( settings.rootFolder ); - if( settings.rootFolder.EndsWith( @"\" ) ) settings.rootFolder = settings.rootFolder.Substring( 0, settings.rootFolder.Length - 1 ); - if( Utils.IsWildcardMatch( "?:", settings.rootFolder, false ) ) settings.rootFolder += @"\"; // add backslash to path if only letter and colon eg "c:" + private void StartProcessing(SnapSettings settings) + { + // ensure source path format + settings.rootFolder = System.IO.Path.GetFullPath(settings.rootFolder); + if (settings.rootFolder.EndsWith(@"\")) settings.rootFolder = settings.rootFolder.Substring(0, settings.rootFolder.Length - 1); + if (Utils.IsWildcardMatch("?:", settings.rootFolder, false)) settings.rootFolder += @"\"; // add backslash to path if only letter and colon eg "c:" - // add slash or backslash to end of link (in cases where it is clear that we we can) - if( settings.linkFiles ) - { - if( !settings.linkRoot.EndsWith( @"/" ) ) - { - if( settings.linkRoot.ToLower().StartsWith( @"http" ) ) // web site - { - settings.linkRoot += @"/"; - } - if( Utils.IsWildcardMatch( "?:*", settings.linkRoot, false ) ) // local disk - { - settings.linkRoot += @"\"; - } - if( settings.linkRoot.StartsWith( @"\\" ) ) // unc path - { - settings.linkRoot += @"\"; - } - } - } + // add slash or backslash to end of link (in cases where it is clear that we we can) + if (settings.linkFiles) + { + if (!settings.linkRoot.EndsWith(@"/")) + { + if (settings.linkRoot.ToLower().StartsWith(@"http")) // web site + { + settings.linkRoot += @"/"; + } + if (Utils.IsWildcardMatch("?:*", settings.linkRoot, false)) // local disk + { + settings.linkRoot += @"\"; + } + if (settings.linkRoot.StartsWith(@"\\")) // unc path + { + settings.linkRoot += @"\"; + } + } + } - Cursor.Current = Cursors.WaitCursor; - this.Text = "Snap2HTML (Working... Press Escape to Cancel)"; - tabControl1.Enabled = false; - backgroundWorker.RunWorkerAsync( argument: settings ); - } + Cursor.Current = Cursors.WaitCursor; + this.Text = "Snap2HTML (Working... Press Escape to Cancel)"; + tabControl1.Enabled = false; + backgroundWorker.RunWorkerAsync(argument: settings); + } - private void backgroundWorker_ProgressChanged( object sender, ProgressChangedEventArgs e ) - { - toolStripStatusLabel1.Text = e.UserState.ToString(); - } + private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) + { + toolStripStatusLabel1.Text = e.UserState.ToString(); + } - private void backgroundWorker_RunWorkerCompleted( object sender, RunWorkerCompletedEventArgs e ) - { - GC.Collect(); - GC.WaitForPendingFinalizers(); + private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) + { + GC.Collect(); + GC.WaitForPendingFinalizers(); - Cursor.Current = Cursors.Default; - tabControl1.Enabled = true; - this.Text = "Snap2HTML"; + Cursor.Current = Cursors.Default; + tabControl1.Enabled = true; + this.Text = "Snap2HTML"; - // Quit when finished if automated via command line - if( this.runningAutomated ) - { - Application.Exit(); - } - } + // Quit when finished if automated via command line + if (this.runningAutomated) + { + Application.Exit(); + } + } private void chkLinkFiles_CheckedChanged(object sender, EventArgs e) { @@ -264,101 +264,101 @@ namespace Snap2HTML txtLinkRoot.Enabled = false; } - // Link Label handlers - private void linkLabel1_LinkClicked( object sender, LinkLabelLinkClickedEventArgs e ) - { - System.Diagnostics.Process.Start( @"http://www.rlvision.com" ); - } - private void linkLabel3_LinkClicked( object sender, LinkLabelLinkClickedEventArgs e ) - { - System.Diagnostics.Process.Start( @"https://rlvision.com/exif/about.php" ); - } - private void linkLabel2_LinkClicked( object sender, LinkLabelLinkClickedEventArgs e ) - { - System.Diagnostics.Process.Start( @"http://www.rlvision.com/flashren/about.php" ); - } - private void linkLabel4_LinkClicked( object sender, LinkLabelLinkClickedEventArgs e ) - { - System.Diagnostics.Process.Start( "notepad.exe", System.IO.Path.GetDirectoryName( Application.ExecutablePath ) + "\\template.html" ); - } - private void linkLabel5_LinkClicked( object sender, LinkLabelLinkClickedEventArgs e ) - { - System.Diagnostics.Process.Start( @"http://www.rlvision.com/contact.php" ); - } - private void pictureBoxDonate_Click( object sender, EventArgs e ) - { - System.Diagnostics.Process.Start( @"https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=U3E4HE8HMY9Q4&item_name=Snap2HTML¤cy_code=USD&source=url" ); - } + // Link Label handlers + private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + System.Diagnostics.Process.Start(@"http://www.rlvision.com"); + } + private void linkLabel3_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + System.Diagnostics.Process.Start(@"https://rlvision.com/exif/about.php"); + } + private void linkLabel2_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + System.Diagnostics.Process.Start(@"http://www.rlvision.com/flashren/about.php"); + } + private void linkLabel4_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + System.Diagnostics.Process.Start("notepad.exe", System.IO.Path.GetDirectoryName(Application.ExecutablePath) + "\\template.html"); + } + private void linkLabel5_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + System.Diagnostics.Process.Start(@"http://www.rlvision.com/contact.php"); + } + private void pictureBoxDonate_Click(object sender, EventArgs e) + { + System.Diagnostics.Process.Start(@"https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=U3E4HE8HMY9Q4&item_name=Snap2HTML¤cy_code=USD&source=url"); + } - // Drag & Drop handlers - private void DragEnterHandler( object sender, DragEventArgs e ) - { - if( e.Data.GetDataPresent( DataFormats.FileDrop ) ) - { - e.Effect = DragDropEffects.Copy; - } - else - { - e.Effect = DragDropEffects.None; - } - } - private void DragDropHandler( object sender, DragEventArgs e ) - { - if( e.Data.GetDataPresent( DataFormats.FileDrop ) ) - { - string[] files = (string[])e.Data.GetData( DataFormats.FileDrop ); - if( files.Length == 1 && System.IO.Directory.Exists( files[0] ) ) - { - SetRootPath( files[0] ); - } - } - } + // Drag & Drop handlers + private void DragEnterHandler(object sender, DragEventArgs e) + { + if (e.Data.GetDataPresent(DataFormats.FileDrop)) + { + e.Effect = DragDropEffects.Copy; + } + else + { + e.Effect = DragDropEffects.None; + } + } + private void DragDropHandler(object sender, DragEventArgs e) + { + if (e.Data.GetDataPresent(DataFormats.FileDrop)) + { + string[] files = (string[])e.Data.GetData(DataFormats.FileDrop); + if (files.Length == 1 && System.IO.Directory.Exists(files[0])) + { + SetRootPath(files[0]); + } + } + } - // Escape to cancel - private void frmMain_KeyUp( object sender, KeyEventArgs e ) - { - if( backgroundWorker.IsBusy ) - { - if( e.KeyCode == Keys.Escape ) - { - backgroundWorker.CancelAsync(); - } - } - else - { - if( e.KeyCode == Keys.F1 ) - { - System.Diagnostics.Process.Start( System.IO.Path.GetDirectoryName( Application.ExecutablePath ) + "\\ReadMe.txt" ); - } - } - } + // Escape to cancel + private void frmMain_KeyUp(object sender, KeyEventArgs e) + { + if (backgroundWorker.IsBusy) + { + if (e.KeyCode == Keys.Escape) + { + backgroundWorker.CancelAsync(); + } + } + else + { + if (e.KeyCode == Keys.F1) + { + System.Diagnostics.Process.Start(System.IO.Path.GetDirectoryName(Application.ExecutablePath) + "\\ReadMe.txt"); + } + } + } - // Sets the root path input box and makes related gui parts ready to use - private void SetRootPath( string path, bool pathIsValid = true ) - { - if( pathIsValid ) - { - txtRoot.Text = path; - cmdCreate.Enabled = true; - toolStripStatusLabel1.Text = ""; - if( initDone ) - { - txtLinkRoot.Text = txtRoot.Text; - txtTitle.Text = "Snapshot of " + txtRoot.Text; - } - } - else - { - txtRoot.Text = ""; - cmdCreate.Enabled = false; - toolStripStatusLabel1.Text = ""; - if( initDone ) - { - txtLinkRoot.Text = txtRoot.Text; - txtTitle.Text = ""; - } - } - } + // Sets the root path input box and makes related gui parts ready to use + private void SetRootPath(string path, bool pathIsValid = true) + { + if (pathIsValid) + { + txtRoot.Text = path; + cmdCreate.Enabled = true; + toolStripStatusLabel1.Text = ""; + if (initDone) + { + txtLinkRoot.Text = txtRoot.Text; + txtTitle.Text = "Snapshot of " + txtRoot.Text; + } + } + else + { + txtRoot.Text = ""; + cmdCreate.Enabled = false; + toolStripStatusLabel1.Text = ""; + if (initDone) + { + txtLinkRoot.Text = txtRoot.Text; + txtTitle.Text = ""; + } + } + } } } diff --git a/Snap2HTML/frmMain_BackgroundWorker.cs b/Snap2HTML/frmMain_BackgroundWorker.cs index 41d24cb..62234c6 100644 --- a/Snap2HTML/frmMain_BackgroundWorker.cs +++ b/Snap2HTML/frmMain_BackgroundWorker.cs @@ -2,433 +2,433 @@ using System.Collections.Generic; using System.ComponentModel; using System.Data; +using System.Diagnostics; using System.Drawing; +using System.IO; using System.Text; using System.Windows.Forms; using CommandLine.Utility; -using System.IO; -using System.Diagnostics; namespace Snap2HTML { - public partial class frmMain : Form - { - // This runs on a separate thread from the GUI - private void backgroundWorker_DoWork( object sender, DoWorkEventArgs e ) - { - var settings = (SnapSettings)e.Argument; - - // Get files & folders - var content = GetContent( settings, backgroundWorker ); - if( backgroundWorker.CancellationPending ) - { - backgroundWorker.ReportProgress( 0, "User cancelled" ); - return; - } - if( content == null ) - { - backgroundWorker.ReportProgress( 0, "Error reading source" ); - return; - } - - // Calculate some stats - int totDirs = 0; - int totFiles = 0; - long totSize = 0; - foreach( var folder in content ) - { - totDirs++; - foreach( var file in folder.Files ) - { - totFiles++; - totSize += Utils.ParseLong( file.GetProp( "Size" ) ); - } - } - - // Let's generate the output - - backgroundWorker.ReportProgress( 0, "Generating HTML file..." ); - - // Read template - var sbTemplate = new StringBuilder(); - try - { - using( System.IO.StreamReader reader = new System.IO.StreamReader( System.IO.Path.GetDirectoryName( Application.ExecutablePath ) + System.IO.Path.DirectorySeparatorChar + "template.html", Encoding.UTF8 ) ) - { - sbTemplate.Append(reader.ReadToEnd()); - } - } - catch( System.Exception ex ) - { - MessageBox.Show( "Failed to open 'Template.html' for reading:\n\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); - backgroundWorker.ReportProgress( 0, "An error occurred..." ); - return; - } - - // Build HTML - sbTemplate.Replace( "[TITLE]", settings.title ); - sbTemplate.Replace( "[APP LINK]", "http://www.rlvision.com" ); - sbTemplate.Replace( "[APP NAME]", Application.ProductName ); - sbTemplate.Replace( "[APP VER]", Application.ProductVersion.Split( '.' )[0] + "." + Application.ProductVersion.Split( '.' )[1] ); - sbTemplate.Replace( "[GEN TIME]", DateTime.Now.ToString( "t" ) ); - sbTemplate.Replace( "[GEN DATE]", DateTime.Now.ToString( "d" ) ); - sbTemplate.Replace( "[NUM FILES]", totFiles.ToString() ); - sbTemplate.Replace( "[NUM DIRS]", totDirs.ToString() ); - sbTemplate.Replace( "[TOT SIZE]", totSize.ToString() ); - if( settings.linkFiles ) - { - sbTemplate.Replace( "[LINK FILES]", "true" ); - sbTemplate.Replace( "[LINK ROOT]", settings.linkRoot.Replace( @"\", "/" ) ); - sbTemplate.Replace( "[SOURCE ROOT]", settings.rootFolder.Replace( @"\", "/" ) ); - - string link_root = settings.linkRoot.Replace( @"\", "/" ); - if( Utils.IsWildcardMatch( @"?:/*", link_root, false ) ) // "file://" is needed in the browser if path begins with drive letter, else it should not be used - { - sbTemplate.Replace( "[LINK PROTOCOL]", @"file://" ); - } - else if( link_root.StartsWith( "//" ) ) // for UNC paths e.g. \\server\path - { - sbTemplate.Replace( "[LINK PROTOCOL]", @"file://///" ); - } - else - { - sbTemplate.Replace( "[LINK PROTOCOL]", "" ); - } - - } - else - { - sbTemplate.Replace( "[LINK FILES]", "false" ); - sbTemplate.Replace( "[LINK PROTOCOL]", "" ); - sbTemplate.Replace( "[LINK ROOT]", "" ); - sbTemplate.Replace( "[SOURCE ROOT]", settings.rootFolder.Replace( @"\", "/" ) ); - } - - // Write output file - try - { - using( System.IO.StreamWriter writer = new System.IO.StreamWriter( settings.outputFile, false, Encoding.UTF8 ) ) - { - writer.AutoFlush = true; - - var template = sbTemplate.ToString(); - var startOfData = template.IndexOf( "[DIR DATA]" ); - - writer.Write(template.Substring(0, startOfData)); - - BuildJavascriptContentArray( content, 0, writer, backgroundWorker ); - - if( backgroundWorker.CancellationPending ) - { - backgroundWorker.ReportProgress( 0, "User cancelled" ); - return; - } - - writer.Write( template.Substring( startOfData + 10) ); - } - - sbTemplate = null; - - if( settings.openInBrowser ) - { - System.Diagnostics.Process.Start( settings.outputFile ); - } - } - catch( Exception ex ) - { - MessageBox.Show( "Failed to open file for writing:\n\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error ); - backgroundWorker.ReportProgress( 0, "An error occurred..." ); - return; - } - - // Ready! - Cursor.Current = Cursors.Default; - backgroundWorker.ReportProgress( 100, "Ready!" ); - } - - - // --- Helper functions (must be static to avoid thread problems) --- - - private static List GetContent( SnapSettings settings, BackgroundWorker bgWorker ) - { - var stopwatch = new Stopwatch(); - stopwatch.Start(); - - var result = new List(); - - // Get all folders - var dirs = new List(); - dirs.Insert( 0, settings.rootFolder ); - DirSearch( settings.rootFolder, dirs, settings.skipHiddenItems, settings.skipSystemItems, stopwatch, bgWorker ); - dirs = Utils.SortDirList( dirs ); - - if( bgWorker.CancellationPending ) - { - return null; - } - - var totFiles = 0; - - stopwatch.Restart(); - - try - { - string modified_date; - string created_date; - - // Parse each folder - for( int d = 0; d < dirs.Count; d++ ) - { - // Get folder properties - var dirName = dirs[d]; - var currentDir = new SnappedFolder( Path.GetFileName( dirName ), Path.GetDirectoryName( dirName ) ); - if( dirName == Path.GetPathRoot( dirName ) ) - { - currentDir = new SnappedFolder( "", dirName ); - } - - modified_date = ""; - created_date = ""; - try - { - modified_date = Utils.ToUnixTimestamp( System.IO.Directory.GetLastWriteTime( dirName ).ToLocalTime() ).ToString(); - created_date = Utils.ToUnixTimestamp( System.IO.Directory.GetCreationTime( dirName ).ToLocalTime() ).ToString(); - } - catch( Exception ex ) - { - Console.WriteLine( "{0} Exception caught.", ex ); - } - currentDir.Properties.Add( "Modified", modified_date ); - currentDir.Properties.Add( "Created", created_date ); - - // Get files in folder - List files; - try - { - files = new List( System.IO.Directory.GetFiles( dirName, "*.*", System.IO.SearchOption.TopDirectoryOnly ) ); - } - catch( Exception ex ) - { - Console.WriteLine( "{0} Exception caught.", ex ); - result.Add( currentDir ); - continue; - } - files.Sort(); - - // Get file properties - foreach( string sFile in files ) - { - totFiles++; - if(stopwatch.ElapsedMilliseconds >= 50) - { - bgWorker.ReportProgress( 0, "Reading files... " + totFiles + " (" + sFile + ")" ); - stopwatch.Restart(); - } - - if( bgWorker.CancellationPending ) - { - return null; - } - - var currentFile = new SnappedFile( Path.GetFileName( sFile ) ); - try - { - System.IO.FileInfo fi = new System.IO.FileInfo( sFile ); - var isHidden = ( fi.Attributes & System.IO.FileAttributes.Hidden ) == System.IO.FileAttributes.Hidden; - var isSystem = ( fi.Attributes & System.IO.FileAttributes.System ) == System.IO.FileAttributes.System; - - if( ( isHidden && settings.skipHiddenItems ) || ( isSystem && settings.skipSystemItems ) ) - { - continue; - } - - currentFile.Properties.Add( "Size", fi.Length.ToString() ); - - modified_date = "-"; - created_date = "-"; - try - { - modified_date = Utils.ToUnixTimestamp( fi.LastWriteTime.ToLocalTime() ).ToString(); - created_date = Utils.ToUnixTimestamp( fi.CreationTime.ToLocalTime() ).ToString(); - } - catch( Exception ex ) - { - Console.WriteLine( "{0} Exception caught.", ex ); - } - - currentFile.Properties.Add( "Modified", modified_date ); - currentFile.Properties.Add( "Created", created_date ); - - } - catch( Exception ex ) - { - Console.WriteLine( "{0} Exception caught.", ex ); - } - - currentDir.Files.Add( currentFile ); - } - - result.Add( currentDir ); - } - } - catch( System.Exception ex ) - { - Console.WriteLine( "{0} exception caught: {1}", ex, ex.Message ); - } - - return result; - } - - // Recursive function to get all folders and subfolders of given path path - private static void DirSearch( string sDir, List lstDirs, bool skipHidden, bool skipSystem, Stopwatch stopwatch, BackgroundWorker backgroundWorker ) - { - if( backgroundWorker.CancellationPending ) return; - - try - { - foreach( string d in System.IO.Directory.GetDirectories( sDir ) ) - { - bool includeThisFolder = true; - - //if( d.ToUpper().EndsWith( "SYSTEM VOLUME INFORMATION" ) ) includeThisFolder = false; - - // exclude folders that have the system or hidden attr set (if required) - if( skipHidden || skipSystem ) - { - var attr = new DirectoryInfo( d ).Attributes; - - if( skipHidden ) - { - if( ( attr & FileAttributes.Hidden ) == FileAttributes.Hidden ) - { - includeThisFolder = false; - } - } - - if( skipSystem ) - { - if( ( attr & FileAttributes.System ) == FileAttributes.System ) - { - includeThisFolder = false; - } - } - } - - - if( includeThisFolder ) - { - lstDirs.Add( d ); - - if( stopwatch.ElapsedMilliseconds >= 50 ) - { - backgroundWorker.ReportProgress( 0, "Getting folders... " + lstDirs.Count + " (" + d + ")" ); - stopwatch.Restart(); - } - - DirSearch( d, lstDirs, skipHidden, skipSystem, stopwatch, backgroundWorker ); - } - } - } - catch( System.Exception ex ) - { - Console.WriteLine( "ERROR in DirSearch():" + ex.Message ); - } - } - - private static void BuildJavascriptContentArray( List content, int startIndex, StreamWriter writer, BackgroundWorker bgWorker ) - { - // Data format: - // Each index in "dirs" array is an array representing a directory: - // First item in array: "directory path*always 0*directory modified date" - // Note that forward slashes are used instead of (Windows style) backslashes - // Then, for each each file in the directory: "filename*size of file*file modified date" - // Second to last item in array tells the total size of directory content - // Last item in array refrences IDs to all subdirectories of this dir (if any). - // ID is the item index in dirs array. - // Note: Modified date is in UNIX format - - var lineBreakSymbol = ""; // Could be set to \n to make the html output more readable, at the expense of increased size - - // Assign an ID to each folder. This is equal to the index in the JS data array - var dirIndexes = new Dictionary(); - for( var i = 0; i < content.Count; i++ ) - { - dirIndexes.Add( content[i].GetFullPath(), ( i + startIndex ).ToString() ); - } - - // Build a lookup table with subfolder IDs for each folder - var subdirs = new Dictionary>(); - foreach( var dir in content ) - { - // add all folders as keys - subdirs.Add( dir.GetFullPath(), new List() ); - } - if( !subdirs.ContainsKey( content[0].Path ) && content[0].Name != "" ) - { - // ensure that root folder is not missed missed - subdirs.Add( content[0].Path, new List() ); - } - foreach( var dir in content ) - { - if( dir.Name != "" ) - { - try - { - // for each folder, add its index to its parent folder list of subdirs - subdirs[dir.Path].Add( dirIndexes[dir.GetFullPath()] ); - } - catch( Exception ex ) - { - // orphan file or folder? - } - } - } - - // Generate the data array - var result = new StringBuilder(); - foreach( var currentDir in content ) - { - result.Append( "D.p([" + lineBreakSymbol ); - - var sDirWithForwardSlash = currentDir.GetFullPath().Replace( @"\", "/" ); - result.Append( "\"" ).Append( Utils.MakeCleanJsString( sDirWithForwardSlash ) ).Append( "*" ).Append( "0" ).Append( "*" ).Append( currentDir.GetProp( "Modified" ) ).Append( "\"," + lineBreakSymbol ); - - long dirSize = 0; - - foreach( var currentFile in currentDir.Files ) - { - result.Append( "\"" ).Append( Utils.MakeCleanJsString( currentFile.Name ) ).Append( "*" ).Append( currentFile.GetProp( "Size" ) ).Append( "*" ).Append( currentFile.GetProp( "Modified" ) ).Append( "\"," + lineBreakSymbol ); - dirSize += Utils.ParseLong( currentFile.GetProp( "Size" ) ); - } - - // Add total dir size - result.Append( "" ).Append( dirSize ).Append( "," + lineBreakSymbol ); - - // Add reference to subdirs - result.Append( "\"" ).Append( String.Join( "*", subdirs[currentDir.GetFullPath()].ToArray() ) ).Append( "\"" + lineBreakSymbol ); - - // Finalize - result.Append( "])" ); - result.Append( "\n" ); - - // Write result in chunks to limit memory consumtion - if( result.Length > 10240 ) - { - writer.Write( result.ToString() ); - result.Clear(); - } - - if( bgWorker.CancellationPending ) - { - return; - } - } - - writer.Write( result.ToString() ); - - return; - } - - } + public partial class frmMain : Form + { + // This runs on a separate thread from the GUI + private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) + { + var settings = (SnapSettings)e.Argument; + + // Get files & folders + var content = GetContent(settings, backgroundWorker); + if (backgroundWorker.CancellationPending) + { + backgroundWorker.ReportProgress(0, "User cancelled"); + return; + } + if (content == null) + { + backgroundWorker.ReportProgress(0, "Error reading source"); + return; + } + + // Calculate some stats + int totDirs = 0; + int totFiles = 0; + long totSize = 0; + foreach (var folder in content) + { + totDirs++; + foreach (var file in folder.Files) + { + totFiles++; + totSize += Utils.ParseLong(file.GetProp("Size")); + } + } + + // Let's generate the output + + backgroundWorker.ReportProgress(0, "Generating HTML file..."); + + // Read template + var sbTemplate = new StringBuilder(); + try + { + using (System.IO.StreamReader reader = new System.IO.StreamReader(System.IO.Path.GetDirectoryName(Application.ExecutablePath) + System.IO.Path.DirectorySeparatorChar + "template.html", Encoding.UTF8)) + { + sbTemplate.Append(reader.ReadToEnd()); + } + } + catch (System.Exception ex) + { + MessageBox.Show("Failed to open 'Template.html' for reading:\n\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + backgroundWorker.ReportProgress(0, "An error occurred..."); + return; + } + + // Build HTML + sbTemplate.Replace("[TITLE]", settings.title); + sbTemplate.Replace("[APP LINK]", "http://www.rlvision.com"); + sbTemplate.Replace("[APP NAME]", Application.ProductName); + sbTemplate.Replace("[APP VER]", Application.ProductVersion.Split('.')[0] + "." + Application.ProductVersion.Split('.')[1]); + sbTemplate.Replace("[GEN TIME]", DateTime.Now.ToString("t")); + sbTemplate.Replace("[GEN DATE]", DateTime.Now.ToString("d")); + sbTemplate.Replace("[NUM FILES]", totFiles.ToString()); + sbTemplate.Replace("[NUM DIRS]", totDirs.ToString()); + sbTemplate.Replace("[TOT SIZE]", totSize.ToString()); + if (settings.linkFiles) + { + sbTemplate.Replace("[LINK FILES]", "true"); + sbTemplate.Replace("[LINK ROOT]", settings.linkRoot.Replace(@"\", "/")); + sbTemplate.Replace("[SOURCE ROOT]", settings.rootFolder.Replace(@"\", "/")); + + string link_root = settings.linkRoot.Replace(@"\", "/"); + if (Utils.IsWildcardMatch(@"?:/*", link_root, false)) // "file://" is needed in the browser if path begins with drive letter, else it should not be used + { + sbTemplate.Replace("[LINK PROTOCOL]", @"file://"); + } + else if (link_root.StartsWith("//")) // for UNC paths e.g. \\server\path + { + sbTemplate.Replace("[LINK PROTOCOL]", @"file://///"); + } + else + { + sbTemplate.Replace("[LINK PROTOCOL]", ""); + } + + } + else + { + sbTemplate.Replace("[LINK FILES]", "false"); + sbTemplate.Replace("[LINK PROTOCOL]", ""); + sbTemplate.Replace("[LINK ROOT]", ""); + sbTemplate.Replace("[SOURCE ROOT]", settings.rootFolder.Replace(@"\", "/")); + } + + // Write output file + try + { + using (System.IO.StreamWriter writer = new System.IO.StreamWriter(settings.outputFile, false, Encoding.UTF8)) + { + writer.AutoFlush = true; + + var template = sbTemplate.ToString(); + var startOfData = template.IndexOf("[DIR DATA]"); + + writer.Write(template.Substring(0, startOfData)); + + BuildJavascriptContentArray(content, 0, writer, backgroundWorker); + + if (backgroundWorker.CancellationPending) + { + backgroundWorker.ReportProgress(0, "User cancelled"); + return; + } + + writer.Write(template.Substring(startOfData + 10)); + } + + sbTemplate = null; + + if (settings.openInBrowser) + { + System.Diagnostics.Process.Start(settings.outputFile); + } + } + catch (Exception ex) + { + MessageBox.Show("Failed to open file for writing:\n\n" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); + backgroundWorker.ReportProgress(0, "An error occurred..."); + return; + } + + // Ready! + Cursor.Current = Cursors.Default; + backgroundWorker.ReportProgress(100, "Ready!"); + } + + + // --- Helper functions (must be static to avoid thread problems) --- + + private static List GetContent(SnapSettings settings, BackgroundWorker bgWorker) + { + var stopwatch = new Stopwatch(); + stopwatch.Start(); + + var result = new List(); + + // Get all folders + var dirs = new List(); + dirs.Insert(0, settings.rootFolder); + DirSearch(settings.rootFolder, dirs, settings.skipHiddenItems, settings.skipSystemItems, stopwatch, bgWorker); + dirs = Utils.SortDirList(dirs); + + if (bgWorker.CancellationPending) + { + return null; + } + + var totFiles = 0; + + stopwatch.Restart(); + + try + { + string modified_date; + string created_date; + + // Parse each folder + for (int d = 0; d < dirs.Count; d++) + { + // Get folder properties + var dirName = dirs[d]; + var currentDir = new SnappedFolder(Path.GetFileName(dirName), Path.GetDirectoryName(dirName)); + if (dirName == Path.GetPathRoot(dirName)) + { + currentDir = new SnappedFolder("", dirName); + } + + modified_date = ""; + created_date = ""; + try + { + modified_date = Utils.ToUnixTimestamp(System.IO.Directory.GetLastWriteTime(dirName).ToLocalTime()).ToString(); + created_date = Utils.ToUnixTimestamp(System.IO.Directory.GetCreationTime(dirName).ToLocalTime()).ToString(); + } + catch (Exception ex) + { + Console.WriteLine("{0} Exception caught.", ex); + } + currentDir.Properties.Add("Modified", modified_date); + currentDir.Properties.Add("Created", created_date); + + // Get files in folder + List files; + try + { + files = new List(System.IO.Directory.GetFiles(dirName, "*.*", System.IO.SearchOption.TopDirectoryOnly)); + } + catch (Exception ex) + { + Console.WriteLine("{0} Exception caught.", ex); + result.Add(currentDir); + continue; + } + files.Sort(); + + // Get file properties + foreach (string sFile in files) + { + totFiles++; + if (stopwatch.ElapsedMilliseconds >= 50) + { + bgWorker.ReportProgress(0, "Reading files... " + totFiles + " (" + sFile + ")"); + stopwatch.Restart(); + } + + if (bgWorker.CancellationPending) + { + return null; + } + + var currentFile = new SnappedFile(Path.GetFileName(sFile)); + try + { + System.IO.FileInfo fi = new System.IO.FileInfo(sFile); + var isHidden = (fi.Attributes & System.IO.FileAttributes.Hidden) == System.IO.FileAttributes.Hidden; + var isSystem = (fi.Attributes & System.IO.FileAttributes.System) == System.IO.FileAttributes.System; + + if ((isHidden && settings.skipHiddenItems) || (isSystem && settings.skipSystemItems)) + { + continue; + } + + currentFile.Properties.Add("Size", fi.Length.ToString()); + + modified_date = "-"; + created_date = "-"; + try + { + modified_date = Utils.ToUnixTimestamp(fi.LastWriteTime.ToLocalTime()).ToString(); + created_date = Utils.ToUnixTimestamp(fi.CreationTime.ToLocalTime()).ToString(); + } + catch (Exception ex) + { + Console.WriteLine("{0} Exception caught.", ex); + } + + currentFile.Properties.Add("Modified", modified_date); + currentFile.Properties.Add("Created", created_date); + + } + catch (Exception ex) + { + Console.WriteLine("{0} Exception caught.", ex); + } + + currentDir.Files.Add(currentFile); + } + + result.Add(currentDir); + } + } + catch (System.Exception ex) + { + Console.WriteLine("{0} exception caught: {1}", ex, ex.Message); + } + + return result; + } + + // Recursive function to get all folders and subfolders of given path path + private static void DirSearch(string sDir, List lstDirs, bool skipHidden, bool skipSystem, Stopwatch stopwatch, BackgroundWorker backgroundWorker) + { + if (backgroundWorker.CancellationPending) return; + + try + { + foreach (string d in System.IO.Directory.GetDirectories(sDir)) + { + bool includeThisFolder = true; + + //if( d.ToUpper().EndsWith( "SYSTEM VOLUME INFORMATION" ) ) includeThisFolder = false; + + // exclude folders that have the system or hidden attr set (if required) + if (skipHidden || skipSystem) + { + var attr = new DirectoryInfo(d).Attributes; + + if (skipHidden) + { + if ((attr & FileAttributes.Hidden) == FileAttributes.Hidden) + { + includeThisFolder = false; + } + } + + if (skipSystem) + { + if ((attr & FileAttributes.System) == FileAttributes.System) + { + includeThisFolder = false; + } + } + } + + + if (includeThisFolder) + { + lstDirs.Add(d); + + if (stopwatch.ElapsedMilliseconds >= 50) + { + backgroundWorker.ReportProgress(0, "Getting folders... " + lstDirs.Count + " (" + d + ")"); + stopwatch.Restart(); + } + + DirSearch(d, lstDirs, skipHidden, skipSystem, stopwatch, backgroundWorker); + } + } + } + catch (System.Exception ex) + { + Console.WriteLine("ERROR in DirSearch():" + ex.Message); + } + } + + private static void BuildJavascriptContentArray(List content, int startIndex, StreamWriter writer, BackgroundWorker bgWorker) + { + // Data format: + // Each index in "dirs" array is an array representing a directory: + // First item in array: "directory path*always 0*directory modified date" + // Note that forward slashes are used instead of (Windows style) backslashes + // Then, for each each file in the directory: "filename*size of file*file modified date" + // Second to last item in array tells the total size of directory content + // Last item in array refrences IDs to all subdirectories of this dir (if any). + // ID is the item index in dirs array. + // Note: Modified date is in UNIX format + + var lineBreakSymbol = ""; // Could be set to \n to make the html output more readable, at the expense of increased size + + // Assign an ID to each folder. This is equal to the index in the JS data array + var dirIndexes = new Dictionary(); + for (var i = 0; i < content.Count; i++) + { + dirIndexes.Add(content[i].GetFullPath(), (i + startIndex).ToString()); + } + + // Build a lookup table with subfolder IDs for each folder + var subdirs = new Dictionary>(); + foreach (var dir in content) + { + // add all folders as keys + subdirs.Add(dir.GetFullPath(), new List()); + } + if (!subdirs.ContainsKey(content[0].Path) && content[0].Name != "") + { + // ensure that root folder is not missed missed + subdirs.Add(content[0].Path, new List()); + } + foreach (var dir in content) + { + if (dir.Name != "") + { + try + { + // for each folder, add its index to its parent folder list of subdirs + subdirs[dir.Path].Add(dirIndexes[dir.GetFullPath()]); + } + catch (Exception) + { + // orphan file or folder? + } + } + } + + // Generate the data array + var result = new StringBuilder(); + foreach (var currentDir in content) + { + result.Append("D.p([" + lineBreakSymbol); + + var sDirWithForwardSlash = currentDir.GetFullPath().Replace(@"\", "/"); + result.Append("\"").Append(Utils.MakeCleanJsString(sDirWithForwardSlash)).Append("*").Append("0").Append("*").Append(currentDir.GetProp("Modified")).Append("\"," + lineBreakSymbol); + + long dirSize = 0; + + foreach (var currentFile in currentDir.Files) + { + result.Append("\"").Append(Utils.MakeCleanJsString(currentFile.Name)).Append("*").Append(currentFile.GetProp("Size")).Append("*").Append(currentFile.GetProp("Modified")).Append("\"," + lineBreakSymbol); + dirSize += Utils.ParseLong(currentFile.GetProp("Size")); + } + + // Add total dir size + result.Append("").Append(dirSize).Append("," + lineBreakSymbol); + + // Add reference to subdirs + result.Append("\"").Append(String.Join("*", subdirs[currentDir.GetFullPath()].ToArray())).Append("\"" + lineBreakSymbol); + + // Finalize + result.Append("])"); + result.Append("\n"); + + // Write result in chunks to limit memory consumption + if (result.Length > 10240) + { + writer.Write(result.ToString()); + result.Clear(); + } + + if (bgWorker.CancellationPending) + { + return; + } + } + + writer.Write(result.ToString()); + + return; + } + + } }