Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
Hefaistos68 committed Aug 31, 2023
2 parents d9f40e8 + 41d43fc commit 6bab4b6
Show file tree
Hide file tree
Showing 14 changed files with 885 additions and 543 deletions.
1 change: 0 additions & 1 deletion BackgroundLaunch/BackgroundLaunch.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\VCLXshared\VSLXshared.csproj" />
<ProjectReference Include="..\VSLXshared\VSLXshared.csproj" />
</ItemGroup>

Expand Down
2 changes: 1 addition & 1 deletion BackgroundLaunch/Runner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public Runner(LaunchInfo item)
if ((item.ItemType == ItemTypeEnum.Solution) || (item.ItemType == ItemTypeEnum.Project))
{
startInfo.FileName = this.launchInfo.Target;
startInfo.Arguments = item.Path;
startInfo.Arguments = "\"" + item.Path + "\"";
if (!string.IsNullOrEmpty(item.Commands))
{
startInfo.Arguments += " " + item.Commands;
Expand Down
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ Doing so manually is most often a tedious and time consuming process.
Also, as of late, the "Start Window" of Visual Studio is not the most helpful, besides its inherent limitations of managing its recently used list.

## Working Features

- Importing from folders
- Importing from any Visual Studio version and profile
- Support for VS 2017, 2019 and 2022
Expand All @@ -51,6 +50,16 @@ Also, as of late, the "Start Window" of Visual Studio is not the most helpful, b
- Support for dark mode
- Support for non-Windows environments

## How to use
First either import your whole recent list from VS by using the toolbar button with the VS symbol, or import from folder directly with the folder-up-arrow toolbar button. You can also drag solutions or projects from the explorer directly into it.

After you have at least one SoP in the list, you can start it by pressing enter on the selected item or double clicking it. When you double click on a folder/group then the whole folder will be launched, each item in its own VS instance as defined in the items settings.

As expected, you can use drag and drop to order items, alt+enter to open the items settings, del to delete an item, etc. Remember that the settings of a folder/group item are applied before all items. This means that when you set a folder to execute as admin, all the contained SoPs will run as admin too.
You can set for each SoP which (installed) version of Visual Studio you want to open it with. Recomended version is shown for each as it is defined in the solution file.
There are also context menus that you can invoke with right clicking on an item.


![SoP Settings](https://github.com/Hefaistos68/VSLauncherX/blob/master/docs/Settings-sample.jpg)


1 change: 1 addition & 0 deletions VSLXshared/DataModel/VsFolder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ public VsItemList Items
/// <summary>
/// Gets or sets a value indicating whether this folder is expanded
/// </summary>
[JsonIgnore]
public bool Expanded { get; set; }

/// <summary>
Expand Down
26 changes: 26 additions & 0 deletions VSLXshared/Helpers/FileHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace VSLXshared.Helpers
{
public static class FileHelper
{
public static readonly string ExecutablesFilterString = "Executable files (*.exe)|*.exe|" +
"Batch files (*.bat)|*.bat|" +
"Command files (*.cmd)|*.cmd|" +
"PowerShell files (*.ps1)|*.ps1|" +
"All files (*.*)|*.*";

public static readonly string SolutionFilterString = "Solutions (*.sln)|*.sln|" +
"C# Projects (*.csproj)|*.csproj|" +
"F# Projects (*.fsproj)|*.fsproj|" +
"TS/JS Projects (*.esproj, *.tsproj)|*.esproj|" +
"Cxx Projects (*.vcxproj)|*.vcxproj|" +
"All files (*.*)|*.*";


}
}
36 changes: 36 additions & 0 deletions VSLauncherX/Controls/TextBoxEx.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 56 additions & 0 deletions VSLauncherX/Controls/TextBoxEx.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace VSLauncher.Controls
{
/// <summary>
/// The text box ex.
/// </summary>
public partial class TextBoxEx : TextBox
{
private readonly Label lblXButton;

/// <summary>
/// Gets or sets a value indicating whether show clear button.
/// </summary>
public bool ShowClearButton { get; set; } = true;

/// <summary>
/// Initializes a new instance of the <see cref="TextBoxEx"/> class.
/// </summary>
public TextBoxEx()
{
InitializeComponent();

this.Resize += PositionX;
this.TextChanged += ShowHideX;

this.lblXButton = new Label()
{
Location = new Point(100, 0),
AutoSize = true,
Text = " x ",
ForeColor = Color.Gray,
Visible = false,
Font = new Font("Tahoma", this.Font.Size * 0.9F),
// BorderStyle = BorderStyle.FixedSingle,
Cursor = Cursors.Arrow
};

Controls.Add(lblXButton);
this.lblXButton.Click += (ss, ee) => { ((Label)ss).Visible = false; this.Text = string.Empty; };
this.lblXButton.BringToFront();
}

private void ShowHideX(object sender, EventArgs e) => this.lblXButton.Visible = this.ShowClearButton && !string.IsNullOrEmpty(Text);

private void PositionX(object sender, EventArgs e) => this.lblXButton.Location = new Point(this.Width - this.lblXButton.Width - 3, ((Height - this.lblXButton.Height) / 2) - 3);
}
}
120 changes: 120 additions & 0 deletions VSLauncherX/Controls/TextBoxEx.resx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
12 changes: 4 additions & 8 deletions VSLauncherX/Forms/dlgBeforeAfter.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
using VSLauncher.DataModel;

using VSLXshared.Helpers;

namespace VSLauncher
{
/// <summary>
/// The dlg before after.
/// </summary>
public partial class dlgBeforeAfter : Form
{
private readonly string executablesFilterString = "Executable files (*.exe)|*.exe|" +
"Batch files (*.bat)|*.bat|" +
"Command files (*.cmd)|*.cmd|" +
"PowerShell files (*.ps1)|*.ps1|" +
"All files (*.*)|*.*";

/// <summary>
/// Initializes a new instance of the <see cref="dlgAddFolder"/> class.
/// </summary>
Expand Down Expand Up @@ -56,7 +52,7 @@ private void btnSelectAfter_Click(object sender, EventArgs e)
{
using (OpenFileDialog openFileDialog = new OpenFileDialog())
{
openFileDialog.Filter = executablesFilterString;
openFileDialog.Filter = FileHelper.ExecutablesFilterString;
openFileDialog.FilterIndex = 1;
openFileDialog.RestoreDirectory = true;

Expand All @@ -78,7 +74,7 @@ private void btnSelectBefore_Click(object sender, EventArgs e)
{
using (OpenFileDialog openFileDialog = new OpenFileDialog())
{
openFileDialog.Filter = executablesFilterString;
openFileDialog.Filter = FileHelper.ExecutablesFilterString;
openFileDialog.FilterIndex = 1;
openFileDialog.RestoreDirectory = true;

Expand Down
11 changes: 3 additions & 8 deletions VSLauncherX/Forms/dlgExecuteVisualStudio.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,15 @@
using VSLauncher.DataModel;
using VSLauncher.Forms;

using VSLXshared.Helpers;

namespace VSLauncher
{
/// <summary>
/// The dlg new instance.
/// </summary>
public partial class dlgExecuteVisualStudio : Form
{
private readonly string solutionFilterString = "Solutions (*.sln)|*.sln|" +
"C# Projects (*.csproj)|*.csproj" +
"F# Projects (*.fsproj)|*.fsproj" +
"TS/JS Projects (*.esproj, *.tsproj)|*.esproj" +
"Cxx Projects (*.vcxproj)|*.vcxproj" +
"All files (*.*)|*.*";

private VsItem? currentItem;

/// <summary>
Expand Down Expand Up @@ -165,7 +160,7 @@ private void btnSelectFolder_Click(object sender, EventArgs e)
// let the user select a folder through the system dialog
using (OpenFileDialog openFileDialog = new())
{
openFileDialog.Filter = solutionFilterString;
openFileDialog.Filter = FileHelper.SolutionFilterString;
openFileDialog.FilterIndex = 1;
openFileDialog.CheckFileExists = true;
openFileDialog.Multiselect = false;
Expand Down
24 changes: 23 additions & 1 deletion VSLauncherX/Helpers/ColumnHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,29 @@ internal static CheckState GetCheckState(object rowObject)
break;

case ItemTypeEnum.Folder:
desc = $"Contains {f.ContainedSolutionsCount()} solution{((f.ContainedSolutionsCount() != 1) ? 's' : "")}";
{
var so = f.ContainedSolutionsCount();
var pr = f.ContainedProjectsCount();
desc = "Contains ";
if(pr > 0)
{
desc += $"{pr} project{((pr != 1) ? 's' : "")}";
}

if(so > 0)
{
if (pr > 0)
{
desc += " and ";
}
desc += $"{so} solution{((so != 1) ? 's' : "")}";
}

if(pr == 0 && so == 0)
{
desc += "nothing yet";
}
}
break;

default:
Expand Down
Loading

0 comments on commit 6bab4b6

Please sign in to comment.