diff --git a/ShortPATH.sln b/ShortPATH.sln new file mode 100644 index 0000000..7ab0b6d --- /dev/null +++ b/ShortPATH.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27703.2042 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShortPATH", "ShortPATH\ShortPATH.csproj", "{A63270E0-85CD-4201-94A8-54802601CF7E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A63270E0-85CD-4201-94A8-54802601CF7E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A63270E0-85CD-4201-94A8-54802601CF7E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A63270E0-85CD-4201-94A8-54802601CF7E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A63270E0-85CD-4201-94A8-54802601CF7E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {54087D54-133B-4375-A6E1-C589CE3FDCD7} + EndGlobalSection +EndGlobal diff --git a/ShortPATH/App.config b/ShortPATH/App.config new file mode 100644 index 0000000..731f6de --- /dev/null +++ b/ShortPATH/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/ShortPATH/Form1.Designer.cs b/ShortPATH/Form1.Designer.cs new file mode 100644 index 0000000..63b3865 --- /dev/null +++ b/ShortPATH/Form1.Designer.cs @@ -0,0 +1,184 @@ +namespace ShortPATH +{ + partial class Form1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.listBox1 = new System.Windows.Forms.ListBox(); + this.button1 = new System.Windows.Forms.Button(); + this.textBox1 = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.textBox2 = new System.Windows.Forms.TextBox(); + this.button2 = new System.Windows.Forms.Button(); + this.button3 = new System.Windows.Forms.Button(); + this.button4 = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // listBox1 + // + this.listBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.listBox1.Font = new System.Drawing.Font("Calibri", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.listBox1.FormattingEnabled = true; + this.listBox1.ItemHeight = 14; + this.listBox1.Location = new System.Drawing.Point(10, 12); + this.listBox1.Name = "listBox1"; + this.listBox1.Size = new System.Drawing.Size(132, 130); + this.listBox1.TabIndex = 0; + this.listBox1.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged); + // + // button1 + // + this.button1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.button1.Location = new System.Drawing.Point(10, 154); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(132, 38); + this.button1.TabIndex = 1; + this.button1.Text = "Add"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // textBox1 + // + this.textBox1.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.textBox1.Enabled = false; + this.textBox1.Font = new System.Drawing.Font("Calibri", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.textBox1.Location = new System.Drawing.Point(152, 36); + this.textBox1.Name = "textBox1"; + this.textBox1.Size = new System.Drawing.Size(321, 22); + this.textBox1.TabIndex = 2; + this.textBox1.KeyUp += new System.Windows.Forms.KeyEventHandler(this.textBox1_KeyUp); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Font = new System.Drawing.Font("Calibri", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label1.Location = new System.Drawing.Point(154, 17); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(54, 14); + this.label1.TabIndex = 3; + this.label1.Text = "Shortcut:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Font = new System.Drawing.Font("Calibri", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label2.Location = new System.Drawing.Point(154, 75); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(45, 14); + this.label2.TabIndex = 5; + this.label2.Text = "Folder:"; + // + // textBox2 + // + this.textBox2.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.textBox2.Enabled = false; + this.textBox2.Font = new System.Drawing.Font("Calibri", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.textBox2.Location = new System.Drawing.Point(152, 94); + this.textBox2.Name = "textBox2"; + this.textBox2.Size = new System.Drawing.Size(285, 22); + this.textBox2.TabIndex = 4; + this.textBox2.KeyUp += new System.Windows.Forms.KeyEventHandler(this.textBox2_KeyUp); + // + // button2 + // + this.button2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.button2.Enabled = false; + this.button2.Location = new System.Drawing.Point(443, 93); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(30, 24); + this.button2.TabIndex = 6; + this.button2.Text = "..."; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // button3 + // + this.button3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.button3.Enabled = false; + this.button3.Location = new System.Drawing.Point(341, 154); + this.button3.Name = "button3"; + this.button3.Size = new System.Drawing.Size(132, 38); + this.button3.TabIndex = 7; + this.button3.Text = "Save"; + this.button3.UseVisualStyleBackColor = true; + this.button3.Click += new System.EventHandler(this.button3_Click); + // + // button4 + // + this.button4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.button4.Enabled = false; + this.button4.Location = new System.Drawing.Point(203, 154); + this.button4.Name = "button4"; + this.button4.Size = new System.Drawing.Size(132, 38); + this.button4.TabIndex = 8; + this.button4.Text = "Remove"; + this.button4.UseVisualStyleBackColor = true; + this.button4.Click += new System.EventHandler(this.button4_Click); + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(484, 201); + this.Controls.Add(this.button4); + this.Controls.Add(this.button3); + this.Controls.Add(this.button2); + this.Controls.Add(this.label2); + this.Controls.Add(this.textBox2); + this.Controls.Add(this.label1); + this.Controls.Add(this.textBox1); + this.Controls.Add(this.button1); + this.Controls.Add(this.listBox1); + this.MinimumSize = new System.Drawing.Size(450, 230); + this.Name = "Form1"; + this.ShowIcon = false; + this.Text = "ShortPATH"; + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.ListBox listBox1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.TextBox textBox1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox textBox2; + private System.Windows.Forms.Button button2; + private System.Windows.Forms.Button button3; + private System.Windows.Forms.Button button4; + } +} + diff --git a/ShortPATH/Form1.cs b/ShortPATH/Form1.cs new file mode 100644 index 0000000..6d8e681 --- /dev/null +++ b/ShortPATH/Form1.cs @@ -0,0 +1,490 @@ +using Microsoft.Win32; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text.RegularExpressions; +using System.Windows.Forms; + +namespace ShortPATH +{ + public partial class Form1 : Form + { + private Boolean FirstRun = false; + private Boolean PATHUpdated = false; + + private string AppTitle = "ShortPATH"; + private string DefaultNewShortcutIdentifier = "new_shortcut"; + private List CommandFileExtensions = new List() { "exe", "bat", "cmd", "msi" }; + + private string DirectoryPath; + + private List shortcuts; + + const int HWND_BROADCAST = 0xffff; + const uint WM_SETTINGCHANGE = 0x001a; + + [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] + static extern bool SendNotifyMessage(IntPtr hWnd, uint Msg, + UIntPtr wParam, string lParam); + + public Form1() + { + InitializeComponent(); + + DirectoryPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\" + AppTitle; + + // See if we can access (or create & access) the application directory in AppData + if (!CheckAppData()) + { + MessageBox.Show("Failed to load application data directory.", AppTitle, MessageBoxButtons.OK, MessageBoxIcon.Error); + System.Environment.Exit(0); + } + + // See if the application directory is in the PATH environment variable (or add & check) + if (!CheckPATH()) + { + MessageBox.Show("Failed add shortcut directory to PATH environment variable.", AppTitle, MessageBoxButtons.OK, MessageBoxIcon.Error); + System.Environment.Exit(0); + } + + // See if we can load any Shortcuts + if (!LoadShortcuts() || !LoadShortcutList()) + { + MessageBox.Show("Failed to load shortcuts.", AppTitle, MessageBoxButtons.OK, MessageBoxIcon.Error); + System.Environment.Exit(0); + } + + Console.WriteLine(AppTitle + " loaded"); + } + + // Check if we can access (or create & access) the application directory in AppData + public Boolean CheckAppData() + { + try + { + // If the application directory exists we're done here + if (Directory.Exists(DirectoryPath)) + { + return true; + } + + // Create the directory + DirectoryInfo di = Directory.CreateDirectory(DirectoryPath); + + // No exception means the directory has been created + Console.WriteLine("Directory created: " + DirectoryPath); + + // This mostly indicates a firstrun so we can show an informative message later + FirstRun = true; + + return true; + } + catch (Exception exception) + { + Console.WriteLine("The process failed: {0}", exception.ToString()); + } + + return false; + } + + // Check if the application directory is in the PATH environment variable (or add & check) + public Boolean CheckPATH(Boolean addToPATH = true) + { + // Store into CURRENT_USER for easy portability + string registeryKey = "HKEY_CURRENT_USER\\Environment"; + string registeryValue = "Path"; + + try + { + + // Get current paths from registery + string pathVariable = (string) Registry.GetValue(registeryKey, registeryValue, ""); + string[] paths = pathVariable.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); + + // A list to remember all current directory paths in the current PATH variable if we must edit it + List pathList = new List(); + + // See if our directory is present + foreach (string path in paths) + { + pathList.Add(path); + + if (path == DirectoryPath) { + return true; + } + } + + // addToPATH will be false if this is our second try to add the path + if(addToPATH == false) { + return false; + } + + // Add our directory to the PATH variable list + pathList.Add(DirectoryPath); + + // Set the new registry value + pathVariable = String.Join(";", pathList); + Registry.SetValue(registeryKey, registeryValue, pathVariable); + Console.WriteLine("PATH updated: " + pathVariable); + + // Signal the environment so the new PATH is used (not accurate) + SendNotifyMessage((IntPtr)HWND_BROADCAST, WM_SETTINGCHANGE, (UIntPtr)0, "Environment"); + + // Show a nice message to explain things + MessageBox.Show( + "The PATH Environment variable of this user account has been updated. " + + "You will have to sign out and sign in again before changes are reflected. " + + "After that changes to the shortcuts will update instantly.", + AppTitle, + MessageBoxButtons.OK, + MessageBoxIcon.Information + ); + + // If the PATH was updated we can make the messagebox when a file is saved context-aware + PATHUpdated = true; + + // Double check the PATH + return CheckPATH(false); + } + catch (Exception exception) + { + Console.WriteLine("The process failed: {0}", exception.ToString()); + } + + return false; + } + + // Load all Shortcuts into a List + private Boolean LoadShortcuts() + { + shortcuts = new List(); + + DirectoryInfo dir = new DirectoryInfo(DirectoryPath); + FileInfo[] Files = dir.GetFiles("*.bat"); + + foreach (FileInfo file in Files) + { + string name = Path.GetFileNameWithoutExtension(file.Name); + shortcuts.Add(new Shortcut(DirectoryPath, name)); + } + + return true; + } + + // Load the Shortcut List into the ListBox + public Boolean LoadShortcutList(string selectedItem = null) + { + try + { + // Update Data source + listBox1.DataSource = null; + listBox1.DataSource = shortcuts; + listBox1.DisplayMember = "Identifier"; + listBox1.ValueMember = "Folder"; + + // Check if we need to select an item + if(selectedItem == null) + { + listBox1.SelectedIndex = -1; + } else + { + // Get index in ListBox by string + int index = listBox1.FindString(selectedItem); + + // Select it if it's found + if (index != -1) + { + listBox1.SetSelected(index, true); + } + } + + return true; + } + catch (Exception exception) { + Console.WriteLine("The process failed: {0}", exception.ToString()); + } + + return false; + } + + // Load the right panel when the listbox updates + private void listBox1_SelectedIndexChanged(object sender, EventArgs e) + { + // The index of the listbox matches the index in the list of Shortcuts + int index = listBox1.SelectedIndex; + + // If nothing selected reset the right panel + if (index == -1) + { + textBox1.Text = ""; + textBox1.Enabled = false; + + textBox2.Text = ""; + textBox2.Enabled = false; + + button2.Enabled = false; + button3.Enabled = false; + button4.Enabled = false; + + } else + { + // Load the shortcut into the right panel + try + { + Shortcut shortcut = shortcuts.ElementAt(index); + + textBox1.Text = shortcut.Identifier; + textBox1.Enabled = true; + + textBox2.Text = shortcut.Folder; + textBox2.Enabled = true; + + button2.Enabled = true; + button3.Enabled = true; + button4.Enabled = true; + + } catch (Exception exception){ + Console.WriteLine("The process failed: {0}", exception.ToString()); + } + + } + + + } + + // Save + private void button3_Click(object sender, EventArgs e) + { + // Check for filled in fields + if (textBox1.Text == "" || textBox2.Text == "") + { + MessageBox.Show("Both the shortcut identifier and folder should be filled in.", + AppTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); + return; + } + + // Check for a valid filename + if (!IsValidFilename(textBox1.Text)) + { + MessageBox.Show("Invalid shortcut identifier. It should be able to be saved as a file", + AppTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); + return; + } + + // Check for a valid directory path + if (!IsValidDirectoryPath(textBox2.Text)) + { + MessageBox.Show("Invalid folder path", AppTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); + return; + } + + // The index of the listbox matches the index in the list of Shortcuts + int index = listBox1.SelectedIndex; + + if (index != -1) + { + // Get the Shortcut from the list and update its properties, temporary Shortcuts are also stored in the list + Shortcut shortcut = shortcuts.ElementAt(index); + + // Make sure the Shortcut does not exist yet by checking the ListBox + if(shortcut.Identifier != textBox1.Text) + { + if (listBox1.FindString(textBox1.Text) != -1) + { + MessageBox.Show("This shortcut identifier is already in use.", AppTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); + return; + } + } + + // Check if the command is already in use (second parameter is the ignored Shortcut identifier) + if (CommandExistsInPATH(textBox1.Text, shortcut.Identifier)) + { + MessageBox.Show("The command \"" + textBox1.Text + "\" is already in use by the environment.", + AppTitle, MessageBoxButtons.OK, MessageBoxIcon.Exclamation); + return; + } + + // Shortcut object properties + shortcut.Identifier = textBox1.Text; + shortcut.Folder = textBox2.Text; + shortcut.SaveFile(); + + // Reload everything + LoadShortcuts(); + LoadShortcutList(); + + // On the first run we'll show a messagebox for more information + if (FirstRun) + { + // When the PATH is updated as well we'll show this context-aware messagebox + if (PATHUpdated) + { + MessageBox.Show( + "When you sign out and back in again, you will be able to run commands directly in the chosen folder by running: " + + "\"" + shortcut.Identifier + " \". ", + AppTitle, MessageBoxButtons.OK, MessageBoxIcon.Information); + } else + { + MessageBox.Show("You can now run commands directly in the chosen folder by running: " + + "\"" + shortcut.Identifier + " \". ", + AppTitle, MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + // Next saves shouldn't annoy the user + FirstRun = false; + PATHUpdated = false; + } + } + } + + // Add + private void button1_Click(object sender, EventArgs e) + { + // Reload shortcuts to remove any non saved shortcuts + LoadShortcuts(); + + // Check for the default new shortcut string and get the next available one if it already exists + string shortcutIdentifier = DefaultNewShortcutIdentifier; + if (listBox1.FindString(shortcutIdentifier) != -1) + { + int nextNumber = 2; + + // While we've not found the next identifier + while (shortcutIdentifier == DefaultNewShortcutIdentifier) + { + string nextShortcutIdentifier = DefaultNewShortcutIdentifier + nextNumber.ToString(); + + // If the next identifier is not yet in the list we'll leave the while loop by updating the identifier we'll use + if(listBox1.FindString(nextShortcutIdentifier) == -1) + { + shortcutIdentifier = nextShortcutIdentifier; + } else + { + nextNumber++; + } + } + } + + // Add a shortcut to the list and show it in the right panel. It is not saved yet at this point + shortcuts.Add(new Shortcut(DirectoryPath, shortcutIdentifier)); + LoadShortcutList(shortcutIdentifier); + + // Select the shortcut text + textBox1.Select(); + } + + // Remove + private void button4_Click(object sender, EventArgs e) + { + // The index of the listbox matches the index in the list of Shortcuts + int index = listBox1.SelectedIndex; + + if (index != -1) + { + // Select Shortcut and delete it + Shortcut shortcut = shortcuts.ElementAt(index); + shortcut.Delete(); + + // Reload everything + LoadShortcuts(); + LoadShortcutList(); + } + } + + // Browse folder + private void button2_Click(object sender, EventArgs e) + { + using (var fbd = new FolderBrowserDialog()) + { + DialogResult result = fbd.ShowDialog(); + + if (result == DialogResult.OK && !string.IsNullOrWhiteSpace(fbd.SelectedPath)) + { + textBox2.Text = fbd.SelectedPath; + } + } + } + + // Simulate a Save button click when we press enter in the field + private void textBox1_KeyUp(object sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.Enter) + { + button3_Click(this, new EventArgs()); + } + } + + // Simulate a Save button click when we press enter in the field + private void textBox2_KeyUp(object sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.Enter) + { + button3_Click(this, new EventArgs()); + } + } + + // Check if a string is a valid filename + bool IsValidFilename(string testName) + { + // https://stackoverflow.com/a/62855/5865844 + Regex containsABadCharacter = new Regex("[" + + Regex.Escape(new string(System.IO.Path.GetInvalidFileNameChars())) + "]"); + if (containsABadCharacter.IsMatch(testName)) { return false; }; + + return true; + } + + // Check if a string is a valid directory path + private bool IsValidDirectoryPath(string path, bool exactPath = true) + { + // https://stackoverflow.com/a/48820213/5865844 + bool isValid = true; + + try { + string fullPath = Path.GetFullPath(path); + + if (exactPath){ + string root = Path.GetPathRoot(path); + isValid = string.IsNullOrEmpty(root.Trim(new char[] { '\\', '/' })) == false; + } else { + isValid = Path.IsPathRooted(path); + } + } catch (Exception ex) { + isValid = false; + } + + return isValid; + } + + // Check if the given string can already be used as a command + private bool CommandExistsInPATH(string possibleCommand, string ignoredIdentifier = null) + { + string PATH = System.Environment.GetEnvironmentVariable("PATH"); + string[] paths = PATH.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); + + // See if our directory is present + foreach (string path in paths) + { + string currentDirectoryPath = path.Trim(new[] { '\\', '/' }); + + if(currentDirectoryPath != DirectoryPath) + { + // https://stackoverflow.com/a/50856314/5865844 + //foreach (var fileExtension in new[] { "exe", "bat", "cmd", "msi" }) + foreach (var fileExtension in CommandFileExtensions) + { + string filePath = currentDirectoryPath + "\\" + possibleCommand + "." + fileExtension; + if (File.Exists(filePath)) + { + return true; + } + } + } + } + + return false; + } + } +} diff --git a/ShortPATH/Form1.resx b/ShortPATH/Form1.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/ShortPATH/Form1.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ShortPATH/Program.cs b/ShortPATH/Program.cs new file mode 100644 index 0000000..5f467fa --- /dev/null +++ b/ShortPATH/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace ShortPATH +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new Form1()); + } + } +} diff --git a/ShortPATH/Properties/AssemblyInfo.cs b/ShortPATH/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..e2e8a5b --- /dev/null +++ b/ShortPATH/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ShortPATH")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("yanikore")] +[assembly: AssemblyProduct("ShortPATH")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("a63270e0-85cd-4201-94a8-54802601cf7e")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// 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("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ShortPATH/Properties/Resources.Designer.cs b/ShortPATH/Properties/Resources.Designer.cs new file mode 100644 index 0000000..240b7e5 --- /dev/null +++ b/ShortPATH/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace ShortPATH.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ShortPATH.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/ShortPATH/Properties/Resources.resx b/ShortPATH/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/ShortPATH/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ShortPATH/Properties/Settings.Designer.cs b/ShortPATH/Properties/Settings.Designer.cs new file mode 100644 index 0000000..de473a3 --- /dev/null +++ b/ShortPATH/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace ShortPATH.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/ShortPATH/Properties/Settings.settings b/ShortPATH/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/ShortPATH/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/ShortPATH/ShortPATH.csproj b/ShortPATH/ShortPATH.csproj new file mode 100644 index 0000000..e36d8c6 --- /dev/null +++ b/ShortPATH/ShortPATH.csproj @@ -0,0 +1,83 @@ + + + + + Debug + AnyCPU + {A63270E0-85CD-4201-94A8-54802601CF7E} + WinExe + ShortPATH + ShortPATH + v4.6.1 + 512 + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + Form + + + Form1.cs + + + + + Form1.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + \ No newline at end of file diff --git a/ShortPATH/Shortcut.cs b/ShortPATH/Shortcut.cs new file mode 100644 index 0000000..44f5fc3 --- /dev/null +++ b/ShortPATH/Shortcut.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; + +namespace ShortPATH +{ + class Shortcut + { + private string DirectoryPath; + + private string FilePath; + + public string Identifier { get; set; } + + public string Folder { get; set; } + + private string FileContents = "@echo off\r\n" + + "SET org_dir=%cd%\r\n" + + "cd /d \"{folder}\"\r\n" + + "%*\r\n" + + "cd /d \"%org_dir%\""; + + public Shortcut(string directoryPath, string identifier = null) + { + DirectoryPath = directoryPath; + + if(identifier != null) + { + Identifier = identifier; + FilePath = GetFilePath(identifier); + LoadFile(); + } + } + + private Boolean LoadFile() + { + if (File.Exists(FilePath)) + { + string contents = null; + + try + { + using (StreamReader streamReader = new StreamReader(FilePath, Encoding.UTF8)) + { + contents = streamReader.ReadToEnd(); + } + + } catch(Exception exception) + { + Console.WriteLine("The process failed: {0}", exception.ToString()); + } + + if (!String.IsNullOrEmpty(contents)) + { + Regex regex = new Regex("cd /d \"(.+?)\""); + Match match = regex.Match(contents); + + if (match.Success) + { + string folder = match.Groups[1].ToString(); + + if (!String.IsNullOrEmpty(folder)) + { + Folder = folder.Replace("\\\\", "\\"); + + return true; + } + } + } + } + + return false; + } + + public void SaveFile() + { + string outputFile = GetFilePath(Identifier); + + // If the identifier has changed we should remove the old file + if (outputFile != FilePath) { + File.Delete(FilePath); + } + + string contents = FileContents.Replace("{folder}", Folder.Replace("\\", "\\\\")); + + File.WriteAllText(outputFile, contents); + + FilePath = outputFile; + } + + public void Delete() + { + if (File.Exists(FilePath)) + { + File.Delete(FilePath); + } + } + + private string GetFilePath(string identifier) + { + return DirectoryPath + "\\" + identifier + ".bat"; + } + + public override string ToString() { + return Identifier; + } + } +}