diff --git a/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/Form1.cs b/Form1.cs
deleted file mode 100755
index 74b2085..0000000
--- a/Form1.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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 JumpListTest
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/Form1.cs b/Form1.cs
deleted file mode 100755
index 74b2085..0000000
--- a/Form1.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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 JumpListTest
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/JumpListTest.csproj b/JumpListTest.csproj
deleted file mode 100755
index 9ad6f29..0000000
--- a/JumpListTest.csproj
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
- WinExe
- JumpListTest
- JumpListTest
- v4.7.2
- 512
- true
- true
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Form
-
-
- 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/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/Form1.cs b/Form1.cs
deleted file mode 100755
index 74b2085..0000000
--- a/Form1.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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 JumpListTest
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/JumpListTest.csproj b/JumpListTest.csproj
deleted file mode 100755
index 9ad6f29..0000000
--- a/JumpListTest.csproj
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
- WinExe
- JumpListTest
- JumpListTest
- v4.7.2
- 512
- true
- true
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Form
-
-
- 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/JumpListTest.sln b/JumpListTest.sln
deleted file mode 100755
index ad79cd7..0000000
--- a/JumpListTest.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30114.105
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListTest", "JumpListTest.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
- EndGlobalSection
-EndGlobal
diff --git a/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/Form1.cs b/Form1.cs
deleted file mode 100755
index 74b2085..0000000
--- a/Form1.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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 JumpListTest
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/JumpListTest.csproj b/JumpListTest.csproj
deleted file mode 100755
index 9ad6f29..0000000
--- a/JumpListTest.csproj
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
- WinExe
- JumpListTest
- JumpListTest
- v4.7.2
- 512
- true
- true
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Form
-
-
- 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/JumpListTest.sln b/JumpListTest.sln
deleted file mode 100755
index ad79cd7..0000000
--- a/JumpListTest.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30114.105
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListTest", "JumpListTest.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
- EndGlobalSection
-EndGlobal
diff --git a/JumpListUtil.sln b/JumpListUtil.sln
new file mode 100755
index 0000000..c91e4de
--- /dev/null
+++ b/JumpListUtil.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
+ EndGlobalSection
+EndGlobal
diff --git a/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/Form1.cs b/Form1.cs
deleted file mode 100755
index 74b2085..0000000
--- a/Form1.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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 JumpListTest
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/JumpListTest.csproj b/JumpListTest.csproj
deleted file mode 100755
index 9ad6f29..0000000
--- a/JumpListTest.csproj
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
- WinExe
- JumpListTest
- JumpListTest
- v4.7.2
- 512
- true
- true
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Form
-
-
- 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/JumpListTest.sln b/JumpListTest.sln
deleted file mode 100755
index ad79cd7..0000000
--- a/JumpListTest.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30114.105
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListTest", "JumpListTest.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
- EndGlobalSection
-EndGlobal
diff --git a/JumpListUtil.sln b/JumpListUtil.sln
new file mode 100755
index 0000000..c91e4de
--- /dev/null
+++ b/JumpListUtil.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
+ EndGlobalSection
+EndGlobal
diff --git a/JumpListUtil/App.config b/JumpListUtil/App.config
new file mode 100755
index 0000000..de2fc4c
--- /dev/null
+++ b/JumpListUtil/App.config
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/Form1.cs b/Form1.cs
deleted file mode 100755
index 74b2085..0000000
--- a/Form1.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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 JumpListTest
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/JumpListTest.csproj b/JumpListTest.csproj
deleted file mode 100755
index 9ad6f29..0000000
--- a/JumpListTest.csproj
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
- WinExe
- JumpListTest
- JumpListTest
- v4.7.2
- 512
- true
- true
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Form
-
-
- 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/JumpListTest.sln b/JumpListTest.sln
deleted file mode 100755
index ad79cd7..0000000
--- a/JumpListTest.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30114.105
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListTest", "JumpListTest.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
- EndGlobalSection
-EndGlobal
diff --git a/JumpListUtil.sln b/JumpListUtil.sln
new file mode 100755
index 0000000..c91e4de
--- /dev/null
+++ b/JumpListUtil.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
+ EndGlobalSection
+EndGlobal
diff --git a/JumpListUtil/App.config b/JumpListUtil/App.config
new file mode 100755
index 0000000..de2fc4c
--- /dev/null
+++ b/JumpListUtil/App.config
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj
new file mode 100755
index 0000000..5f31de9
--- /dev/null
+++ b/JumpListUtil/JumpListUtil.csproj
@@ -0,0 +1,106 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
+ WinExe
+ JumpListUtil
+ JumpListUtil
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
+
+
+
+
+ ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+
+ ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
+
+
+
+ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\packages\System.Text.Encodings.Web.4.7.1\lib\net461\System.Text.Encodings.Web.dll
+
+
+ ..\packages\System.Text.Json.4.7.2\lib\net461\System.Text.Json.dll
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+
+ ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/Form1.cs b/Form1.cs
deleted file mode 100755
index 74b2085..0000000
--- a/Form1.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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 JumpListTest
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/JumpListTest.csproj b/JumpListTest.csproj
deleted file mode 100755
index 9ad6f29..0000000
--- a/JumpListTest.csproj
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
- WinExe
- JumpListTest
- JumpListTest
- v4.7.2
- 512
- true
- true
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Form
-
-
- 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/JumpListTest.sln b/JumpListTest.sln
deleted file mode 100755
index ad79cd7..0000000
--- a/JumpListTest.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30114.105
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListTest", "JumpListTest.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
- EndGlobalSection
-EndGlobal
diff --git a/JumpListUtil.sln b/JumpListUtil.sln
new file mode 100755
index 0000000..c91e4de
--- /dev/null
+++ b/JumpListUtil.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
+ EndGlobalSection
+EndGlobal
diff --git a/JumpListUtil/App.config b/JumpListUtil/App.config
new file mode 100755
index 0000000..de2fc4c
--- /dev/null
+++ b/JumpListUtil/App.config
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj
new file mode 100755
index 0000000..5f31de9
--- /dev/null
+++ b/JumpListUtil/JumpListUtil.csproj
@@ -0,0 +1,106 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
+ WinExe
+ JumpListUtil
+ JumpListUtil
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
+
+
+
+
+ ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+
+ ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
+
+
+
+ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\packages\System.Text.Encodings.Web.4.7.1\lib\net461\System.Text.Encodings.Web.dll
+
+
+ ..\packages\System.Text.Json.4.7.2\lib\net461\System.Text.Json.dll
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+
+ ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/Program.cs b/JumpListUtil/Program.cs
new file mode 100755
index 0000000..a13d723
--- /dev/null
+++ b/JumpListUtil/Program.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text.Json;
+using System.Threading;
+using System.Windows.Forms;
+using System.Windows.Shell;
+
+namespace JumpListUtil
+{
+ public class Entry
+ {
+ public string Target { get; set; }
+ public string Icon { get; set; }
+ public int IconIndex { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ }
+ static class Program
+ {
+ [DllImport("shell32.dll", SetLastError = true)]
+ static extern void SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr)] string AppID);
+
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ System.Windows.Application wpfApp = new System.Windows.Application();
+ string thisProgram = Process.GetCurrentProcess().MainModule.FileName;
+
+ // parse all arguments
+ string shortcutsFile = "shortcuts.json";
+ string appUserModelId = "Microsoft.WindowsTerminal_8wekyb3d8bbwe!App";
+ int startIndex = 0;
+ bool onlyRefreshJumpList = false;
+
+ int i = 0;
+ string[] args = Environment.GetCommandLineArgs();
+ bool ParseFlag(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length > 2)
+ {
+ args[i] = "-" + args[i].Substring(2);
+ i--;
+ }
+ return true;
+ }
+ else if (args[i] == "--" + longName)
+ {
+ return true;
+ }
+ return false;
+ }
+ string ParseArg(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length == 2)
+ {
+ i++;
+ return args[i];
+ }
+ else
+ {
+ return args[i].Substring(2);
+ }
+ }
+ else if (args[i].IndexOf("--" + longName + "=") == 0)
+ {
+ return args[i].Substring(longName.Length + 3);
+ }
+ return null;
+ }
+
+ string val = null;
+ for (i = 1; i < args.Length; i++)
+ {
+ if ((val = ParseArg('s', "shortcuts")) != null)
+ {
+ shortcutsFile = val;
+ }
+ else if ((val = ParseArg('i', "startIndex")) != null)
+ {
+ startIndex = int.Parse(val);
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if (ParseFlag('r', "refresh"))
+ {
+ onlyRefreshJumpList = true;
+ }
+ }
+
+ SetCurrentProcessExplicitAppUserModelID(appUserModelId);
+
+ List jumpItems = new List();
+
+ Entry[] entries = null;
+
+ try
+ {
+ string shortcutJson = "";
+ using (FileStream input = File.OpenRead(shortcutsFile))
+ {
+ shortcutJson = new StreamReader(input).ReadToEnd();
+ }
+
+
+ entries = (Entry[])JsonSerializer.Deserialize(shortcutJson, typeof(Entry[]), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true, ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true });
+ }
+ catch (Exception e)
+ {
+ MessageBox.Show("Failed to load shortcut entries: " + e);
+ }
+
+ if (entries != null)
+ {
+ foreach (Entry entry in entries)
+ {
+ JumpTask task = new JumpTask();
+ task.ApplicationPath = entry.Target;
+ task.Description = entry.Description;
+ task.Title = entry.Name;
+ task.IconResourcePath = entry.Icon;
+ task.IconResourceIndex = entry.IconIndex;
+
+ jumpItems.Add(task);
+ }
+
+ jumpItems.Insert(0, new JumpTask
+ {
+ Title = "Refresh",
+ Description = "Refreshes the Jump List",
+ ApplicationPath = thisProgram,
+ WorkingDirectory = Environment.CurrentDirectory,
+ IconResourcePath = Environment.ExpandEnvironmentVariables("%systemroot%\\system32\\imageres.dll"),
+ IconResourceIndex = 228,
+ Arguments = "-r"
+ });
+
+ JumpList.SetJumpList(wpfApp, new JumpList(jumpItems, false, false));
+
+ if (!onlyRefreshJumpList)
+ {
+ if (startIndex >= 0 && startIndex < entries.Length)
+ {
+ Entry start = entries[startIndex];
+ Process p = Process.Start(new ProcessStartInfo
+ {
+ FileName = start.Target,
+ UseShellExecute = true
+ });
+ }
+ else
+ {
+ MessageBox.Show("Shortcut index " + startIndex + " is outside the range of valid entries (" + entries.Length + " entries)");
+ }
+ }
+ }
+
+ //Application.EnableVisualStyles();
+ //Application.SetCompatibleTextRenderingDefault(false);
+ //Application.Run();
+ }
+ }
+}
diff --git a/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/Form1.cs b/Form1.cs
deleted file mode 100755
index 74b2085..0000000
--- a/Form1.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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 JumpListTest
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/JumpListTest.csproj b/JumpListTest.csproj
deleted file mode 100755
index 9ad6f29..0000000
--- a/JumpListTest.csproj
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
- WinExe
- JumpListTest
- JumpListTest
- v4.7.2
- 512
- true
- true
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Form
-
-
- 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/JumpListTest.sln b/JumpListTest.sln
deleted file mode 100755
index ad79cd7..0000000
--- a/JumpListTest.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30114.105
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListTest", "JumpListTest.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
- EndGlobalSection
-EndGlobal
diff --git a/JumpListUtil.sln b/JumpListUtil.sln
new file mode 100755
index 0000000..c91e4de
--- /dev/null
+++ b/JumpListUtil.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
+ EndGlobalSection
+EndGlobal
diff --git a/JumpListUtil/App.config b/JumpListUtil/App.config
new file mode 100755
index 0000000..de2fc4c
--- /dev/null
+++ b/JumpListUtil/App.config
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj
new file mode 100755
index 0000000..5f31de9
--- /dev/null
+++ b/JumpListUtil/JumpListUtil.csproj
@@ -0,0 +1,106 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
+ WinExe
+ JumpListUtil
+ JumpListUtil
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
+
+
+
+
+ ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+
+ ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
+
+
+
+ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\packages\System.Text.Encodings.Web.4.7.1\lib\net461\System.Text.Encodings.Web.dll
+
+
+ ..\packages\System.Text.Json.4.7.2\lib\net461\System.Text.Json.dll
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+
+ ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/Program.cs b/JumpListUtil/Program.cs
new file mode 100755
index 0000000..a13d723
--- /dev/null
+++ b/JumpListUtil/Program.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text.Json;
+using System.Threading;
+using System.Windows.Forms;
+using System.Windows.Shell;
+
+namespace JumpListUtil
+{
+ public class Entry
+ {
+ public string Target { get; set; }
+ public string Icon { get; set; }
+ public int IconIndex { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ }
+ static class Program
+ {
+ [DllImport("shell32.dll", SetLastError = true)]
+ static extern void SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr)] string AppID);
+
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ System.Windows.Application wpfApp = new System.Windows.Application();
+ string thisProgram = Process.GetCurrentProcess().MainModule.FileName;
+
+ // parse all arguments
+ string shortcutsFile = "shortcuts.json";
+ string appUserModelId = "Microsoft.WindowsTerminal_8wekyb3d8bbwe!App";
+ int startIndex = 0;
+ bool onlyRefreshJumpList = false;
+
+ int i = 0;
+ string[] args = Environment.GetCommandLineArgs();
+ bool ParseFlag(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length > 2)
+ {
+ args[i] = "-" + args[i].Substring(2);
+ i--;
+ }
+ return true;
+ }
+ else if (args[i] == "--" + longName)
+ {
+ return true;
+ }
+ return false;
+ }
+ string ParseArg(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length == 2)
+ {
+ i++;
+ return args[i];
+ }
+ else
+ {
+ return args[i].Substring(2);
+ }
+ }
+ else if (args[i].IndexOf("--" + longName + "=") == 0)
+ {
+ return args[i].Substring(longName.Length + 3);
+ }
+ return null;
+ }
+
+ string val = null;
+ for (i = 1; i < args.Length; i++)
+ {
+ if ((val = ParseArg('s', "shortcuts")) != null)
+ {
+ shortcutsFile = val;
+ }
+ else if ((val = ParseArg('i', "startIndex")) != null)
+ {
+ startIndex = int.Parse(val);
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if (ParseFlag('r', "refresh"))
+ {
+ onlyRefreshJumpList = true;
+ }
+ }
+
+ SetCurrentProcessExplicitAppUserModelID(appUserModelId);
+
+ List jumpItems = new List();
+
+ Entry[] entries = null;
+
+ try
+ {
+ string shortcutJson = "";
+ using (FileStream input = File.OpenRead(shortcutsFile))
+ {
+ shortcutJson = new StreamReader(input).ReadToEnd();
+ }
+
+
+ entries = (Entry[])JsonSerializer.Deserialize(shortcutJson, typeof(Entry[]), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true, ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true });
+ }
+ catch (Exception e)
+ {
+ MessageBox.Show("Failed to load shortcut entries: " + e);
+ }
+
+ if (entries != null)
+ {
+ foreach (Entry entry in entries)
+ {
+ JumpTask task = new JumpTask();
+ task.ApplicationPath = entry.Target;
+ task.Description = entry.Description;
+ task.Title = entry.Name;
+ task.IconResourcePath = entry.Icon;
+ task.IconResourceIndex = entry.IconIndex;
+
+ jumpItems.Add(task);
+ }
+
+ jumpItems.Insert(0, new JumpTask
+ {
+ Title = "Refresh",
+ Description = "Refreshes the Jump List",
+ ApplicationPath = thisProgram,
+ WorkingDirectory = Environment.CurrentDirectory,
+ IconResourcePath = Environment.ExpandEnvironmentVariables("%systemroot%\\system32\\imageres.dll"),
+ IconResourceIndex = 228,
+ Arguments = "-r"
+ });
+
+ JumpList.SetJumpList(wpfApp, new JumpList(jumpItems, false, false));
+
+ if (!onlyRefreshJumpList)
+ {
+ if (startIndex >= 0 && startIndex < entries.Length)
+ {
+ Entry start = entries[startIndex];
+ Process p = Process.Start(new ProcessStartInfo
+ {
+ FileName = start.Target,
+ UseShellExecute = true
+ });
+ }
+ else
+ {
+ MessageBox.Show("Shortcut index " + startIndex + " is outside the range of valid entries (" + entries.Length + " entries)");
+ }
+ }
+ }
+
+ //Application.EnableVisualStyles();
+ //Application.SetCompatibleTextRenderingDefault(false);
+ //Application.Run();
+ }
+ }
+}
diff --git a/JumpListUtil/Properties/AssemblyInfo.cs b/JumpListUtil/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..e929884
--- /dev/null
+++ b/JumpListUtil/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("JumpListUtil")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("JumpListUtil")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
+
+// 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/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/Form1.cs b/Form1.cs
deleted file mode 100755
index 74b2085..0000000
--- a/Form1.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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 JumpListTest
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/JumpListTest.csproj b/JumpListTest.csproj
deleted file mode 100755
index 9ad6f29..0000000
--- a/JumpListTest.csproj
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
- WinExe
- JumpListTest
- JumpListTest
- v4.7.2
- 512
- true
- true
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Form
-
-
- 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/JumpListTest.sln b/JumpListTest.sln
deleted file mode 100755
index ad79cd7..0000000
--- a/JumpListTest.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30114.105
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListTest", "JumpListTest.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
- EndGlobalSection
-EndGlobal
diff --git a/JumpListUtil.sln b/JumpListUtil.sln
new file mode 100755
index 0000000..c91e4de
--- /dev/null
+++ b/JumpListUtil.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
+ EndGlobalSection
+EndGlobal
diff --git a/JumpListUtil/App.config b/JumpListUtil/App.config
new file mode 100755
index 0000000..de2fc4c
--- /dev/null
+++ b/JumpListUtil/App.config
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj
new file mode 100755
index 0000000..5f31de9
--- /dev/null
+++ b/JumpListUtil/JumpListUtil.csproj
@@ -0,0 +1,106 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
+ WinExe
+ JumpListUtil
+ JumpListUtil
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
+
+
+
+
+ ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+
+ ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
+
+
+
+ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\packages\System.Text.Encodings.Web.4.7.1\lib\net461\System.Text.Encodings.Web.dll
+
+
+ ..\packages\System.Text.Json.4.7.2\lib\net461\System.Text.Json.dll
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+
+ ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/Program.cs b/JumpListUtil/Program.cs
new file mode 100755
index 0000000..a13d723
--- /dev/null
+++ b/JumpListUtil/Program.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text.Json;
+using System.Threading;
+using System.Windows.Forms;
+using System.Windows.Shell;
+
+namespace JumpListUtil
+{
+ public class Entry
+ {
+ public string Target { get; set; }
+ public string Icon { get; set; }
+ public int IconIndex { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ }
+ static class Program
+ {
+ [DllImport("shell32.dll", SetLastError = true)]
+ static extern void SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr)] string AppID);
+
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ System.Windows.Application wpfApp = new System.Windows.Application();
+ string thisProgram = Process.GetCurrentProcess().MainModule.FileName;
+
+ // parse all arguments
+ string shortcutsFile = "shortcuts.json";
+ string appUserModelId = "Microsoft.WindowsTerminal_8wekyb3d8bbwe!App";
+ int startIndex = 0;
+ bool onlyRefreshJumpList = false;
+
+ int i = 0;
+ string[] args = Environment.GetCommandLineArgs();
+ bool ParseFlag(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length > 2)
+ {
+ args[i] = "-" + args[i].Substring(2);
+ i--;
+ }
+ return true;
+ }
+ else if (args[i] == "--" + longName)
+ {
+ return true;
+ }
+ return false;
+ }
+ string ParseArg(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length == 2)
+ {
+ i++;
+ return args[i];
+ }
+ else
+ {
+ return args[i].Substring(2);
+ }
+ }
+ else if (args[i].IndexOf("--" + longName + "=") == 0)
+ {
+ return args[i].Substring(longName.Length + 3);
+ }
+ return null;
+ }
+
+ string val = null;
+ for (i = 1; i < args.Length; i++)
+ {
+ if ((val = ParseArg('s', "shortcuts")) != null)
+ {
+ shortcutsFile = val;
+ }
+ else if ((val = ParseArg('i', "startIndex")) != null)
+ {
+ startIndex = int.Parse(val);
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if (ParseFlag('r', "refresh"))
+ {
+ onlyRefreshJumpList = true;
+ }
+ }
+
+ SetCurrentProcessExplicitAppUserModelID(appUserModelId);
+
+ List jumpItems = new List();
+
+ Entry[] entries = null;
+
+ try
+ {
+ string shortcutJson = "";
+ using (FileStream input = File.OpenRead(shortcutsFile))
+ {
+ shortcutJson = new StreamReader(input).ReadToEnd();
+ }
+
+
+ entries = (Entry[])JsonSerializer.Deserialize(shortcutJson, typeof(Entry[]), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true, ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true });
+ }
+ catch (Exception e)
+ {
+ MessageBox.Show("Failed to load shortcut entries: " + e);
+ }
+
+ if (entries != null)
+ {
+ foreach (Entry entry in entries)
+ {
+ JumpTask task = new JumpTask();
+ task.ApplicationPath = entry.Target;
+ task.Description = entry.Description;
+ task.Title = entry.Name;
+ task.IconResourcePath = entry.Icon;
+ task.IconResourceIndex = entry.IconIndex;
+
+ jumpItems.Add(task);
+ }
+
+ jumpItems.Insert(0, new JumpTask
+ {
+ Title = "Refresh",
+ Description = "Refreshes the Jump List",
+ ApplicationPath = thisProgram,
+ WorkingDirectory = Environment.CurrentDirectory,
+ IconResourcePath = Environment.ExpandEnvironmentVariables("%systemroot%\\system32\\imageres.dll"),
+ IconResourceIndex = 228,
+ Arguments = "-r"
+ });
+
+ JumpList.SetJumpList(wpfApp, new JumpList(jumpItems, false, false));
+
+ if (!onlyRefreshJumpList)
+ {
+ if (startIndex >= 0 && startIndex < entries.Length)
+ {
+ Entry start = entries[startIndex];
+ Process p = Process.Start(new ProcessStartInfo
+ {
+ FileName = start.Target,
+ UseShellExecute = true
+ });
+ }
+ else
+ {
+ MessageBox.Show("Shortcut index " + startIndex + " is outside the range of valid entries (" + entries.Length + " entries)");
+ }
+ }
+ }
+
+ //Application.EnableVisualStyles();
+ //Application.SetCompatibleTextRenderingDefault(false);
+ //Application.Run();
+ }
+ }
+}
diff --git a/JumpListUtil/Properties/AssemblyInfo.cs b/JumpListUtil/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..e929884
--- /dev/null
+++ b/JumpListUtil/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("JumpListUtil")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("JumpListUtil")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
+
+// 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/JumpListUtil/Properties/Resources.Designer.cs b/JumpListUtil/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..ed070d5
--- /dev/null
+++ b/JumpListUtil/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+ using System;
+
+
+ ///
+ /// 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", "16.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 (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("JumpListUtil.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/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/Form1.cs b/Form1.cs
deleted file mode 100755
index 74b2085..0000000
--- a/Form1.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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 JumpListTest
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/JumpListTest.csproj b/JumpListTest.csproj
deleted file mode 100755
index 9ad6f29..0000000
--- a/JumpListTest.csproj
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
- WinExe
- JumpListTest
- JumpListTest
- v4.7.2
- 512
- true
- true
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Form
-
-
- 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/JumpListTest.sln b/JumpListTest.sln
deleted file mode 100755
index ad79cd7..0000000
--- a/JumpListTest.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30114.105
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListTest", "JumpListTest.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
- EndGlobalSection
-EndGlobal
diff --git a/JumpListUtil.sln b/JumpListUtil.sln
new file mode 100755
index 0000000..c91e4de
--- /dev/null
+++ b/JumpListUtil.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
+ EndGlobalSection
+EndGlobal
diff --git a/JumpListUtil/App.config b/JumpListUtil/App.config
new file mode 100755
index 0000000..de2fc4c
--- /dev/null
+++ b/JumpListUtil/App.config
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj
new file mode 100755
index 0000000..5f31de9
--- /dev/null
+++ b/JumpListUtil/JumpListUtil.csproj
@@ -0,0 +1,106 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
+ WinExe
+ JumpListUtil
+ JumpListUtil
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
+
+
+
+
+ ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+
+ ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
+
+
+
+ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\packages\System.Text.Encodings.Web.4.7.1\lib\net461\System.Text.Encodings.Web.dll
+
+
+ ..\packages\System.Text.Json.4.7.2\lib\net461\System.Text.Json.dll
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+
+ ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/Program.cs b/JumpListUtil/Program.cs
new file mode 100755
index 0000000..a13d723
--- /dev/null
+++ b/JumpListUtil/Program.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text.Json;
+using System.Threading;
+using System.Windows.Forms;
+using System.Windows.Shell;
+
+namespace JumpListUtil
+{
+ public class Entry
+ {
+ public string Target { get; set; }
+ public string Icon { get; set; }
+ public int IconIndex { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ }
+ static class Program
+ {
+ [DllImport("shell32.dll", SetLastError = true)]
+ static extern void SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr)] string AppID);
+
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ System.Windows.Application wpfApp = new System.Windows.Application();
+ string thisProgram = Process.GetCurrentProcess().MainModule.FileName;
+
+ // parse all arguments
+ string shortcutsFile = "shortcuts.json";
+ string appUserModelId = "Microsoft.WindowsTerminal_8wekyb3d8bbwe!App";
+ int startIndex = 0;
+ bool onlyRefreshJumpList = false;
+
+ int i = 0;
+ string[] args = Environment.GetCommandLineArgs();
+ bool ParseFlag(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length > 2)
+ {
+ args[i] = "-" + args[i].Substring(2);
+ i--;
+ }
+ return true;
+ }
+ else if (args[i] == "--" + longName)
+ {
+ return true;
+ }
+ return false;
+ }
+ string ParseArg(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length == 2)
+ {
+ i++;
+ return args[i];
+ }
+ else
+ {
+ return args[i].Substring(2);
+ }
+ }
+ else if (args[i].IndexOf("--" + longName + "=") == 0)
+ {
+ return args[i].Substring(longName.Length + 3);
+ }
+ return null;
+ }
+
+ string val = null;
+ for (i = 1; i < args.Length; i++)
+ {
+ if ((val = ParseArg('s', "shortcuts")) != null)
+ {
+ shortcutsFile = val;
+ }
+ else if ((val = ParseArg('i', "startIndex")) != null)
+ {
+ startIndex = int.Parse(val);
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if (ParseFlag('r', "refresh"))
+ {
+ onlyRefreshJumpList = true;
+ }
+ }
+
+ SetCurrentProcessExplicitAppUserModelID(appUserModelId);
+
+ List jumpItems = new List();
+
+ Entry[] entries = null;
+
+ try
+ {
+ string shortcutJson = "";
+ using (FileStream input = File.OpenRead(shortcutsFile))
+ {
+ shortcutJson = new StreamReader(input).ReadToEnd();
+ }
+
+
+ entries = (Entry[])JsonSerializer.Deserialize(shortcutJson, typeof(Entry[]), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true, ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true });
+ }
+ catch (Exception e)
+ {
+ MessageBox.Show("Failed to load shortcut entries: " + e);
+ }
+
+ if (entries != null)
+ {
+ foreach (Entry entry in entries)
+ {
+ JumpTask task = new JumpTask();
+ task.ApplicationPath = entry.Target;
+ task.Description = entry.Description;
+ task.Title = entry.Name;
+ task.IconResourcePath = entry.Icon;
+ task.IconResourceIndex = entry.IconIndex;
+
+ jumpItems.Add(task);
+ }
+
+ jumpItems.Insert(0, new JumpTask
+ {
+ Title = "Refresh",
+ Description = "Refreshes the Jump List",
+ ApplicationPath = thisProgram,
+ WorkingDirectory = Environment.CurrentDirectory,
+ IconResourcePath = Environment.ExpandEnvironmentVariables("%systemroot%\\system32\\imageres.dll"),
+ IconResourceIndex = 228,
+ Arguments = "-r"
+ });
+
+ JumpList.SetJumpList(wpfApp, new JumpList(jumpItems, false, false));
+
+ if (!onlyRefreshJumpList)
+ {
+ if (startIndex >= 0 && startIndex < entries.Length)
+ {
+ Entry start = entries[startIndex];
+ Process p = Process.Start(new ProcessStartInfo
+ {
+ FileName = start.Target,
+ UseShellExecute = true
+ });
+ }
+ else
+ {
+ MessageBox.Show("Shortcut index " + startIndex + " is outside the range of valid entries (" + entries.Length + " entries)");
+ }
+ }
+ }
+
+ //Application.EnableVisualStyles();
+ //Application.SetCompatibleTextRenderingDefault(false);
+ //Application.Run();
+ }
+ }
+}
diff --git a/JumpListUtil/Properties/AssemblyInfo.cs b/JumpListUtil/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..e929884
--- /dev/null
+++ b/JumpListUtil/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("JumpListUtil")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("JumpListUtil")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
+
+// 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/JumpListUtil/Properties/Resources.Designer.cs b/JumpListUtil/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..ed070d5
--- /dev/null
+++ b/JumpListUtil/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+ using System;
+
+
+ ///
+ /// 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", "16.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 (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("JumpListUtil.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/JumpListUtil/Properties/Resources.resx b/JumpListUtil/Properties/Resources.resx
new file mode 100755
index 0000000..ffecec8
--- /dev/null
+++ b/JumpListUtil/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/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/Form1.cs b/Form1.cs
deleted file mode 100755
index 74b2085..0000000
--- a/Form1.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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 JumpListTest
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/JumpListTest.csproj b/JumpListTest.csproj
deleted file mode 100755
index 9ad6f29..0000000
--- a/JumpListTest.csproj
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
- WinExe
- JumpListTest
- JumpListTest
- v4.7.2
- 512
- true
- true
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Form
-
-
- 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/JumpListTest.sln b/JumpListTest.sln
deleted file mode 100755
index ad79cd7..0000000
--- a/JumpListTest.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30114.105
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListTest", "JumpListTest.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
- EndGlobalSection
-EndGlobal
diff --git a/JumpListUtil.sln b/JumpListUtil.sln
new file mode 100755
index 0000000..c91e4de
--- /dev/null
+++ b/JumpListUtil.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
+ EndGlobalSection
+EndGlobal
diff --git a/JumpListUtil/App.config b/JumpListUtil/App.config
new file mode 100755
index 0000000..de2fc4c
--- /dev/null
+++ b/JumpListUtil/App.config
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj
new file mode 100755
index 0000000..5f31de9
--- /dev/null
+++ b/JumpListUtil/JumpListUtil.csproj
@@ -0,0 +1,106 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
+ WinExe
+ JumpListUtil
+ JumpListUtil
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
+
+
+
+
+ ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+
+ ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
+
+
+
+ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\packages\System.Text.Encodings.Web.4.7.1\lib\net461\System.Text.Encodings.Web.dll
+
+
+ ..\packages\System.Text.Json.4.7.2\lib\net461\System.Text.Json.dll
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+
+ ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/Program.cs b/JumpListUtil/Program.cs
new file mode 100755
index 0000000..a13d723
--- /dev/null
+++ b/JumpListUtil/Program.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text.Json;
+using System.Threading;
+using System.Windows.Forms;
+using System.Windows.Shell;
+
+namespace JumpListUtil
+{
+ public class Entry
+ {
+ public string Target { get; set; }
+ public string Icon { get; set; }
+ public int IconIndex { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ }
+ static class Program
+ {
+ [DllImport("shell32.dll", SetLastError = true)]
+ static extern void SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr)] string AppID);
+
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ System.Windows.Application wpfApp = new System.Windows.Application();
+ string thisProgram = Process.GetCurrentProcess().MainModule.FileName;
+
+ // parse all arguments
+ string shortcutsFile = "shortcuts.json";
+ string appUserModelId = "Microsoft.WindowsTerminal_8wekyb3d8bbwe!App";
+ int startIndex = 0;
+ bool onlyRefreshJumpList = false;
+
+ int i = 0;
+ string[] args = Environment.GetCommandLineArgs();
+ bool ParseFlag(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length > 2)
+ {
+ args[i] = "-" + args[i].Substring(2);
+ i--;
+ }
+ return true;
+ }
+ else if (args[i] == "--" + longName)
+ {
+ return true;
+ }
+ return false;
+ }
+ string ParseArg(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length == 2)
+ {
+ i++;
+ return args[i];
+ }
+ else
+ {
+ return args[i].Substring(2);
+ }
+ }
+ else if (args[i].IndexOf("--" + longName + "=") == 0)
+ {
+ return args[i].Substring(longName.Length + 3);
+ }
+ return null;
+ }
+
+ string val = null;
+ for (i = 1; i < args.Length; i++)
+ {
+ if ((val = ParseArg('s', "shortcuts")) != null)
+ {
+ shortcutsFile = val;
+ }
+ else if ((val = ParseArg('i', "startIndex")) != null)
+ {
+ startIndex = int.Parse(val);
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if (ParseFlag('r', "refresh"))
+ {
+ onlyRefreshJumpList = true;
+ }
+ }
+
+ SetCurrentProcessExplicitAppUserModelID(appUserModelId);
+
+ List jumpItems = new List();
+
+ Entry[] entries = null;
+
+ try
+ {
+ string shortcutJson = "";
+ using (FileStream input = File.OpenRead(shortcutsFile))
+ {
+ shortcutJson = new StreamReader(input).ReadToEnd();
+ }
+
+
+ entries = (Entry[])JsonSerializer.Deserialize(shortcutJson, typeof(Entry[]), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true, ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true });
+ }
+ catch (Exception e)
+ {
+ MessageBox.Show("Failed to load shortcut entries: " + e);
+ }
+
+ if (entries != null)
+ {
+ foreach (Entry entry in entries)
+ {
+ JumpTask task = new JumpTask();
+ task.ApplicationPath = entry.Target;
+ task.Description = entry.Description;
+ task.Title = entry.Name;
+ task.IconResourcePath = entry.Icon;
+ task.IconResourceIndex = entry.IconIndex;
+
+ jumpItems.Add(task);
+ }
+
+ jumpItems.Insert(0, new JumpTask
+ {
+ Title = "Refresh",
+ Description = "Refreshes the Jump List",
+ ApplicationPath = thisProgram,
+ WorkingDirectory = Environment.CurrentDirectory,
+ IconResourcePath = Environment.ExpandEnvironmentVariables("%systemroot%\\system32\\imageres.dll"),
+ IconResourceIndex = 228,
+ Arguments = "-r"
+ });
+
+ JumpList.SetJumpList(wpfApp, new JumpList(jumpItems, false, false));
+
+ if (!onlyRefreshJumpList)
+ {
+ if (startIndex >= 0 && startIndex < entries.Length)
+ {
+ Entry start = entries[startIndex];
+ Process p = Process.Start(new ProcessStartInfo
+ {
+ FileName = start.Target,
+ UseShellExecute = true
+ });
+ }
+ else
+ {
+ MessageBox.Show("Shortcut index " + startIndex + " is outside the range of valid entries (" + entries.Length + " entries)");
+ }
+ }
+ }
+
+ //Application.EnableVisualStyles();
+ //Application.SetCompatibleTextRenderingDefault(false);
+ //Application.Run();
+ }
+ }
+}
diff --git a/JumpListUtil/Properties/AssemblyInfo.cs b/JumpListUtil/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..e929884
--- /dev/null
+++ b/JumpListUtil/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("JumpListUtil")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("JumpListUtil")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
+
+// 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/JumpListUtil/Properties/Resources.Designer.cs b/JumpListUtil/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..ed070d5
--- /dev/null
+++ b/JumpListUtil/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+ using System;
+
+
+ ///
+ /// 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", "16.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 (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("JumpListUtil.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/JumpListUtil/Properties/Resources.resx b/JumpListUtil/Properties/Resources.resx
new file mode 100755
index 0000000..ffecec8
--- /dev/null
+++ b/JumpListUtil/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/JumpListUtil/Properties/Settings.Designer.cs b/JumpListUtil/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..8593114
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.6.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/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/Form1.cs b/Form1.cs
deleted file mode 100755
index 74b2085..0000000
--- a/Form1.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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 JumpListTest
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/JumpListTest.csproj b/JumpListTest.csproj
deleted file mode 100755
index 9ad6f29..0000000
--- a/JumpListTest.csproj
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
- WinExe
- JumpListTest
- JumpListTest
- v4.7.2
- 512
- true
- true
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Form
-
-
- 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/JumpListTest.sln b/JumpListTest.sln
deleted file mode 100755
index ad79cd7..0000000
--- a/JumpListTest.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30114.105
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListTest", "JumpListTest.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
- EndGlobalSection
-EndGlobal
diff --git a/JumpListUtil.sln b/JumpListUtil.sln
new file mode 100755
index 0000000..c91e4de
--- /dev/null
+++ b/JumpListUtil.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
+ EndGlobalSection
+EndGlobal
diff --git a/JumpListUtil/App.config b/JumpListUtil/App.config
new file mode 100755
index 0000000..de2fc4c
--- /dev/null
+++ b/JumpListUtil/App.config
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj
new file mode 100755
index 0000000..5f31de9
--- /dev/null
+++ b/JumpListUtil/JumpListUtil.csproj
@@ -0,0 +1,106 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
+ WinExe
+ JumpListUtil
+ JumpListUtil
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
+
+
+
+
+ ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+
+ ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
+
+
+
+ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\packages\System.Text.Encodings.Web.4.7.1\lib\net461\System.Text.Encodings.Web.dll
+
+
+ ..\packages\System.Text.Json.4.7.2\lib\net461\System.Text.Json.dll
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+
+ ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/Program.cs b/JumpListUtil/Program.cs
new file mode 100755
index 0000000..a13d723
--- /dev/null
+++ b/JumpListUtil/Program.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text.Json;
+using System.Threading;
+using System.Windows.Forms;
+using System.Windows.Shell;
+
+namespace JumpListUtil
+{
+ public class Entry
+ {
+ public string Target { get; set; }
+ public string Icon { get; set; }
+ public int IconIndex { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ }
+ static class Program
+ {
+ [DllImport("shell32.dll", SetLastError = true)]
+ static extern void SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr)] string AppID);
+
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ System.Windows.Application wpfApp = new System.Windows.Application();
+ string thisProgram = Process.GetCurrentProcess().MainModule.FileName;
+
+ // parse all arguments
+ string shortcutsFile = "shortcuts.json";
+ string appUserModelId = "Microsoft.WindowsTerminal_8wekyb3d8bbwe!App";
+ int startIndex = 0;
+ bool onlyRefreshJumpList = false;
+
+ int i = 0;
+ string[] args = Environment.GetCommandLineArgs();
+ bool ParseFlag(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length > 2)
+ {
+ args[i] = "-" + args[i].Substring(2);
+ i--;
+ }
+ return true;
+ }
+ else if (args[i] == "--" + longName)
+ {
+ return true;
+ }
+ return false;
+ }
+ string ParseArg(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length == 2)
+ {
+ i++;
+ return args[i];
+ }
+ else
+ {
+ return args[i].Substring(2);
+ }
+ }
+ else if (args[i].IndexOf("--" + longName + "=") == 0)
+ {
+ return args[i].Substring(longName.Length + 3);
+ }
+ return null;
+ }
+
+ string val = null;
+ for (i = 1; i < args.Length; i++)
+ {
+ if ((val = ParseArg('s', "shortcuts")) != null)
+ {
+ shortcutsFile = val;
+ }
+ else if ((val = ParseArg('i', "startIndex")) != null)
+ {
+ startIndex = int.Parse(val);
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if (ParseFlag('r', "refresh"))
+ {
+ onlyRefreshJumpList = true;
+ }
+ }
+
+ SetCurrentProcessExplicitAppUserModelID(appUserModelId);
+
+ List jumpItems = new List();
+
+ Entry[] entries = null;
+
+ try
+ {
+ string shortcutJson = "";
+ using (FileStream input = File.OpenRead(shortcutsFile))
+ {
+ shortcutJson = new StreamReader(input).ReadToEnd();
+ }
+
+
+ entries = (Entry[])JsonSerializer.Deserialize(shortcutJson, typeof(Entry[]), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true, ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true });
+ }
+ catch (Exception e)
+ {
+ MessageBox.Show("Failed to load shortcut entries: " + e);
+ }
+
+ if (entries != null)
+ {
+ foreach (Entry entry in entries)
+ {
+ JumpTask task = new JumpTask();
+ task.ApplicationPath = entry.Target;
+ task.Description = entry.Description;
+ task.Title = entry.Name;
+ task.IconResourcePath = entry.Icon;
+ task.IconResourceIndex = entry.IconIndex;
+
+ jumpItems.Add(task);
+ }
+
+ jumpItems.Insert(0, new JumpTask
+ {
+ Title = "Refresh",
+ Description = "Refreshes the Jump List",
+ ApplicationPath = thisProgram,
+ WorkingDirectory = Environment.CurrentDirectory,
+ IconResourcePath = Environment.ExpandEnvironmentVariables("%systemroot%\\system32\\imageres.dll"),
+ IconResourceIndex = 228,
+ Arguments = "-r"
+ });
+
+ JumpList.SetJumpList(wpfApp, new JumpList(jumpItems, false, false));
+
+ if (!onlyRefreshJumpList)
+ {
+ if (startIndex >= 0 && startIndex < entries.Length)
+ {
+ Entry start = entries[startIndex];
+ Process p = Process.Start(new ProcessStartInfo
+ {
+ FileName = start.Target,
+ UseShellExecute = true
+ });
+ }
+ else
+ {
+ MessageBox.Show("Shortcut index " + startIndex + " is outside the range of valid entries (" + entries.Length + " entries)");
+ }
+ }
+ }
+
+ //Application.EnableVisualStyles();
+ //Application.SetCompatibleTextRenderingDefault(false);
+ //Application.Run();
+ }
+ }
+}
diff --git a/JumpListUtil/Properties/AssemblyInfo.cs b/JumpListUtil/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..e929884
--- /dev/null
+++ b/JumpListUtil/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("JumpListUtil")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("JumpListUtil")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
+
+// 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/JumpListUtil/Properties/Resources.Designer.cs b/JumpListUtil/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..ed070d5
--- /dev/null
+++ b/JumpListUtil/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+ using System;
+
+
+ ///
+ /// 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", "16.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 (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("JumpListUtil.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/JumpListUtil/Properties/Resources.resx b/JumpListUtil/Properties/Resources.resx
new file mode 100755
index 0000000..ffecec8
--- /dev/null
+++ b/JumpListUtil/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/JumpListUtil/Properties/Settings.Designer.cs b/JumpListUtil/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..8593114
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.6.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/JumpListUtil/Properties/Settings.settings b/JumpListUtil/Properties/Settings.settings
new file mode 100755
index 0000000..abf36c5
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/Form1.cs b/Form1.cs
deleted file mode 100755
index 74b2085..0000000
--- a/Form1.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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 JumpListTest
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/JumpListTest.csproj b/JumpListTest.csproj
deleted file mode 100755
index 9ad6f29..0000000
--- a/JumpListTest.csproj
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
- WinExe
- JumpListTest
- JumpListTest
- v4.7.2
- 512
- true
- true
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Form
-
-
- 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/JumpListTest.sln b/JumpListTest.sln
deleted file mode 100755
index ad79cd7..0000000
--- a/JumpListTest.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30114.105
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListTest", "JumpListTest.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
- EndGlobalSection
-EndGlobal
diff --git a/JumpListUtil.sln b/JumpListUtil.sln
new file mode 100755
index 0000000..c91e4de
--- /dev/null
+++ b/JumpListUtil.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
+ EndGlobalSection
+EndGlobal
diff --git a/JumpListUtil/App.config b/JumpListUtil/App.config
new file mode 100755
index 0000000..de2fc4c
--- /dev/null
+++ b/JumpListUtil/App.config
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj
new file mode 100755
index 0000000..5f31de9
--- /dev/null
+++ b/JumpListUtil/JumpListUtil.csproj
@@ -0,0 +1,106 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
+ WinExe
+ JumpListUtil
+ JumpListUtil
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
+
+
+
+
+ ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+
+ ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
+
+
+
+ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\packages\System.Text.Encodings.Web.4.7.1\lib\net461\System.Text.Encodings.Web.dll
+
+
+ ..\packages\System.Text.Json.4.7.2\lib\net461\System.Text.Json.dll
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+
+ ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/Program.cs b/JumpListUtil/Program.cs
new file mode 100755
index 0000000..a13d723
--- /dev/null
+++ b/JumpListUtil/Program.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text.Json;
+using System.Threading;
+using System.Windows.Forms;
+using System.Windows.Shell;
+
+namespace JumpListUtil
+{
+ public class Entry
+ {
+ public string Target { get; set; }
+ public string Icon { get; set; }
+ public int IconIndex { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ }
+ static class Program
+ {
+ [DllImport("shell32.dll", SetLastError = true)]
+ static extern void SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr)] string AppID);
+
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ System.Windows.Application wpfApp = new System.Windows.Application();
+ string thisProgram = Process.GetCurrentProcess().MainModule.FileName;
+
+ // parse all arguments
+ string shortcutsFile = "shortcuts.json";
+ string appUserModelId = "Microsoft.WindowsTerminal_8wekyb3d8bbwe!App";
+ int startIndex = 0;
+ bool onlyRefreshJumpList = false;
+
+ int i = 0;
+ string[] args = Environment.GetCommandLineArgs();
+ bool ParseFlag(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length > 2)
+ {
+ args[i] = "-" + args[i].Substring(2);
+ i--;
+ }
+ return true;
+ }
+ else if (args[i] == "--" + longName)
+ {
+ return true;
+ }
+ return false;
+ }
+ string ParseArg(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length == 2)
+ {
+ i++;
+ return args[i];
+ }
+ else
+ {
+ return args[i].Substring(2);
+ }
+ }
+ else if (args[i].IndexOf("--" + longName + "=") == 0)
+ {
+ return args[i].Substring(longName.Length + 3);
+ }
+ return null;
+ }
+
+ string val = null;
+ for (i = 1; i < args.Length; i++)
+ {
+ if ((val = ParseArg('s', "shortcuts")) != null)
+ {
+ shortcutsFile = val;
+ }
+ else if ((val = ParseArg('i', "startIndex")) != null)
+ {
+ startIndex = int.Parse(val);
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if (ParseFlag('r', "refresh"))
+ {
+ onlyRefreshJumpList = true;
+ }
+ }
+
+ SetCurrentProcessExplicitAppUserModelID(appUserModelId);
+
+ List jumpItems = new List();
+
+ Entry[] entries = null;
+
+ try
+ {
+ string shortcutJson = "";
+ using (FileStream input = File.OpenRead(shortcutsFile))
+ {
+ shortcutJson = new StreamReader(input).ReadToEnd();
+ }
+
+
+ entries = (Entry[])JsonSerializer.Deserialize(shortcutJson, typeof(Entry[]), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true, ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true });
+ }
+ catch (Exception e)
+ {
+ MessageBox.Show("Failed to load shortcut entries: " + e);
+ }
+
+ if (entries != null)
+ {
+ foreach (Entry entry in entries)
+ {
+ JumpTask task = new JumpTask();
+ task.ApplicationPath = entry.Target;
+ task.Description = entry.Description;
+ task.Title = entry.Name;
+ task.IconResourcePath = entry.Icon;
+ task.IconResourceIndex = entry.IconIndex;
+
+ jumpItems.Add(task);
+ }
+
+ jumpItems.Insert(0, new JumpTask
+ {
+ Title = "Refresh",
+ Description = "Refreshes the Jump List",
+ ApplicationPath = thisProgram,
+ WorkingDirectory = Environment.CurrentDirectory,
+ IconResourcePath = Environment.ExpandEnvironmentVariables("%systemroot%\\system32\\imageres.dll"),
+ IconResourceIndex = 228,
+ Arguments = "-r"
+ });
+
+ JumpList.SetJumpList(wpfApp, new JumpList(jumpItems, false, false));
+
+ if (!onlyRefreshJumpList)
+ {
+ if (startIndex >= 0 && startIndex < entries.Length)
+ {
+ Entry start = entries[startIndex];
+ Process p = Process.Start(new ProcessStartInfo
+ {
+ FileName = start.Target,
+ UseShellExecute = true
+ });
+ }
+ else
+ {
+ MessageBox.Show("Shortcut index " + startIndex + " is outside the range of valid entries (" + entries.Length + " entries)");
+ }
+ }
+ }
+
+ //Application.EnableVisualStyles();
+ //Application.SetCompatibleTextRenderingDefault(false);
+ //Application.Run();
+ }
+ }
+}
diff --git a/JumpListUtil/Properties/AssemblyInfo.cs b/JumpListUtil/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..e929884
--- /dev/null
+++ b/JumpListUtil/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("JumpListUtil")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("JumpListUtil")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
+
+// 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/JumpListUtil/Properties/Resources.Designer.cs b/JumpListUtil/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..ed070d5
--- /dev/null
+++ b/JumpListUtil/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+ using System;
+
+
+ ///
+ /// 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", "16.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 (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("JumpListUtil.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/JumpListUtil/Properties/Resources.resx b/JumpListUtil/Properties/Resources.resx
new file mode 100755
index 0000000..ffecec8
--- /dev/null
+++ b/JumpListUtil/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/JumpListUtil/Properties/Settings.Designer.cs b/JumpListUtil/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..8593114
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.6.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/JumpListUtil/Properties/Settings.settings b/JumpListUtil/Properties/Settings.settings
new file mode 100755
index 0000000..abf36c5
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs
new file mode 100755
index 0000000..6d13f4e
--- /dev/null
+++ b/JumpListUtil/ShellLink.cs
@@ -0,0 +1,486 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using System.Text;
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+/****************************************************************************
+ * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/
+ ***************************************************************************/
+
+namespace ShellLinkPlus
+{
+ // Modified from http://smdn.jp/programming/tips/createlnk/
+ // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects
+ // /Creating_and_Modifying_Shortcuts/article.asp
+ // Partly based on Sending toast notifications from desktop apps sample
+ public class ShellLink : IDisposable
+ {
+ #region Win32 and COM
+
+ // IShellLink Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("000214F9-0000-0000-C000-000000000046")]
+ private interface IShellLinkW
+ {
+ uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile,
+ int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags);
+ uint GetIDList(out IntPtr ppidl);
+ uint SetIDList(IntPtr pidl);
+ uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName,
+ int cchMaxName);
+ uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
+ uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir,
+ int cchMaxPath);
+ uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
+ uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs,
+ int cchMaxPath);
+ uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
+ uint GetHotKey(out ushort pwHotkey);
+ uint SetHotKey(ushort wHotKey);
+ uint GetShowCmd(out int piShowCmd);
+ uint SetShowCmd(int iShowCmd);
+ uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath,
+ int cchIconPath, out int piIcon);
+ uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
+ uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel,
+ uint dwReserved);
+ uint Resolve(IntPtr hwnd, uint fFlags);
+ uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
+ }
+
+ // ShellLink CoClass (ShellLink object)
+ [ComImport,
+ ClassInterface(ClassInterfaceType.None),
+ Guid("00021401-0000-0000-C000-000000000046")]
+ private class CShellLink { }
+
+ // WIN32_FIND_DATAW Structure
+ [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]
+ private struct WIN32_FIND_DATAW
+ {
+ public uint dwFileAttributes;
+ public ComTypes.FILETIME ftCreationTime;
+ public ComTypes.FILETIME ftLastAccessTime;
+ public ComTypes.FILETIME ftLastWriteTime;
+ public uint nFileSizeHigh;
+ public uint nFileSizeLow;
+ public uint dwReserved0;
+ public uint dwReserved1;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
+ public string cFileName;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
+ public string cAlternateFileName;
+ }
+
+ // IPropertyStore Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")]
+ private interface IPropertyStore
+ {
+ uint GetCount([Out] out uint cProps);
+ uint GetAt([In] uint iProp, out PropertyKey pkey);
+ uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv);
+ uint SetValue([In] ref PropertyKey key, [In] PropVariant pv);
+ uint Commit();
+ }
+
+ // PropertyKey Structure
+ // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ private struct PropertyKey
+ {
+ #region Fields
+
+ private Guid formatId; // Unique GUID for property
+ private Int32 propertyId; // Property identifier (PID)
+
+ #endregion
+
+ #region Public Properties
+
+ public Guid FormatId
+ {
+ get
+ {
+ return formatId;
+ }
+ }
+
+ public Int32 PropertyId
+ {
+ get
+ {
+ return propertyId;
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropertyKey(Guid formatId, Int32 propertyId)
+ {
+ this.formatId = formatId;
+ this.propertyId = propertyId;
+ }
+
+ public PropertyKey(string formatId, Int32 propertyId)
+ {
+ this.formatId = new Guid(formatId);
+ this.propertyId = propertyId;
+ }
+
+ #endregion
+ }
+
+ // PropVariant Class (only for string value)
+ // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1
+ // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11
+ // /interop-with-propvariants-in-net.aspx
+ [StructLayout(LayoutKind.Explicit)]
+ private sealed class PropVariant : IDisposable
+ {
+ #region Fields
+
+ [FieldOffset(0)]
+ ushort valueType; // Value type
+
+ // [FieldOffset(2)]
+ // ushort wReserved1; // Reserved field
+ // [FieldOffset(4)]
+ // ushort wReserved2; // Reserved field
+ // [FieldOffset(6)]
+ // ushort wReserved3; // Reserved field
+
+ [FieldOffset(8)]
+ IntPtr ptr; // Value
+
+ #endregion
+
+ #region Public Properties
+
+ // Value type (System.Runtime.InteropServices.VarEnum)
+ public VarEnum VarType
+ {
+ get { return (VarEnum)valueType; }
+ set { valueType = (ushort)value; }
+ }
+
+ // Whether value is empty or null
+ public bool IsNullOrEmpty
+ {
+ get
+ {
+ return (valueType == (ushort)VarEnum.VT_EMPTY ||
+ valueType == (ushort)VarEnum.VT_NULL);
+ }
+ }
+
+ // Value (only for string value)
+ public string Value
+ {
+ get
+ {
+ return Marshal.PtrToStringUni(ptr);
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropVariant()
+ { }
+
+ // Construct with string value
+ public PropVariant(string value)
+ {
+ if (value == null)
+ throw new ArgumentException("Failed to set value.");
+
+ valueType = (ushort)VarEnum.VT_LPWSTR;
+ ptr = Marshal.StringToCoTaskMemUni(value);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~PropVariant()
+ {
+ Dispose();
+ }
+
+ public void Dispose()
+ {
+ PropVariantClear(this);
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+ }
+
+ [DllImport("Ole32.dll", PreserveSig = false)]
+ private extern static void PropVariantClear([In, Out] PropVariant pvar);
+
+ #endregion
+
+ #region Fields
+
+ private IShellLinkW shellLinkW = null;
+
+ // Name = System.AppUserModel.ID
+ // ShellPKey = PKEY_AppUserModel_ID
+ // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3
+ // PropID = 5
+ // Type = String (VT_LPWSTR)
+ private readonly PropertyKey AppUserModelIDKey =
+ new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5);
+
+ private const int MAX_PATH = 260;
+ private const int INFOTIPSIZE = 1024;
+
+ private const int STGM_READ = 0x00000000; // STGM constants
+ private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags
+
+ #endregion
+
+ #region Private Properties (Interfaces)
+
+ private IPersistFile PersistFile
+ {
+ get
+ {
+ IPersistFile PersistFile = shellLinkW as IPersistFile;
+
+ if (PersistFile == null)
+ throw new COMException("Failed to create IPersistFile.");
+ else
+ return PersistFile;
+ }
+ }
+
+ private IPropertyStore PropertyStore
+ {
+ get
+ {
+ IPropertyStore PropertyStore = shellLinkW as IPropertyStore;
+
+ if (PropertyStore == null)
+ throw new COMException("Failed to create IPropertyStore.");
+ else
+ return PropertyStore;
+ }
+ }
+
+ #endregion
+
+ #region Public Properties (Minimal)
+
+ // Path of loaded shortcut file
+ public string ShortcutFile
+ {
+ get
+ {
+ string shortcutFile;
+
+ PersistFile.GetCurFile(out shortcutFile);
+
+ return shortcutFile;
+ }
+ }
+
+ // Path of target file
+ public string TargetPath
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder targetPath = new StringBuilder(MAX_PATH);
+
+ WIN32_FIND_DATAW data = new WIN32_FIND_DATAW();
+
+ VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data,
+ SLGP_UNCPRIORITY));
+
+ return targetPath.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetPath(value));
+ }
+ }
+
+ public string Arguments
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder arguments = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity));
+
+ return arguments.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetArguments(value));
+ }
+ }
+
+ public string Description
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder description = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity));
+
+ return description.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetDescription(value));
+ }
+ }
+
+ public Tuple IconLocation
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder icon = new StringBuilder(INFOTIPSIZE);
+
+ int index;
+ VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index));
+
+ return new Tuple(icon.ToString(), index);
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2));
+ }
+ }
+
+ // AppUserModelID to be used for Windows 7 or later.
+ public string AppUserModelID
+ {
+ get
+ {
+ using (PropVariant pv = new PropVariant())
+ {
+ VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv));
+
+ if (pv.Value == null)
+ return "Null";
+ else
+ return pv.Value;
+ }
+ }
+ set
+ {
+ using (PropVariant pv = new PropVariant(value))
+ {
+ VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv));
+ VerifySucceeded(PropertyStore.Commit());
+ }
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public ShellLink()
+ : this(null)
+ { }
+
+ // Construct with loading shortcut file.
+ public ShellLink(string file)
+ {
+ try
+ {
+ shellLinkW = (IShellLinkW)new CShellLink();
+ }
+ catch
+ {
+ throw new COMException("Failed to create ShellLink object.");
+ }
+
+ if (file != null)
+ Load(file);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~ShellLink()
+ {
+ Dispose(false);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (shellLinkW != null)
+ {
+ // Release all references.
+ Marshal.FinalReleaseComObject(shellLinkW);
+ shellLinkW = null;
+ }
+ }
+
+ #endregion
+
+ #region Methods
+
+ // Save shortcut file.
+ public void Save()
+ {
+ string file = ShortcutFile;
+
+ if (file == null)
+ throw new InvalidOperationException("File name is not given.");
+ else
+ Save(file);
+ }
+
+ public void Save(string file)
+ {
+ if (file == null)
+ throw new ArgumentNullException("File name is required.");
+ else
+ PersistFile.Save(file, true);
+ }
+
+ // Load shortcut file.
+ public void Load(string file)
+ {
+ if (!File.Exists(file))
+ throw new FileNotFoundException("File is not found.", file);
+ else
+ PersistFile.Load(file, STGM_READ);
+ }
+
+ // Verify if operation succeeded.
+ public static void VerifySucceeded(uint hresult)
+ {
+ if (hresult > 1)
+ throw new InvalidOperationException("Failed with HRESULT: " +
+ hresult.ToString("X"));
+ }
+
+ #endregion
+ }
+}
diff --git a/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/Form1.cs b/Form1.cs
deleted file mode 100755
index 74b2085..0000000
--- a/Form1.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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 JumpListTest
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/JumpListTest.csproj b/JumpListTest.csproj
deleted file mode 100755
index 9ad6f29..0000000
--- a/JumpListTest.csproj
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
- WinExe
- JumpListTest
- JumpListTest
- v4.7.2
- 512
- true
- true
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Form
-
-
- 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/JumpListTest.sln b/JumpListTest.sln
deleted file mode 100755
index ad79cd7..0000000
--- a/JumpListTest.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30114.105
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListTest", "JumpListTest.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
- EndGlobalSection
-EndGlobal
diff --git a/JumpListUtil.sln b/JumpListUtil.sln
new file mode 100755
index 0000000..c91e4de
--- /dev/null
+++ b/JumpListUtil.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
+ EndGlobalSection
+EndGlobal
diff --git a/JumpListUtil/App.config b/JumpListUtil/App.config
new file mode 100755
index 0000000..de2fc4c
--- /dev/null
+++ b/JumpListUtil/App.config
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj
new file mode 100755
index 0000000..5f31de9
--- /dev/null
+++ b/JumpListUtil/JumpListUtil.csproj
@@ -0,0 +1,106 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
+ WinExe
+ JumpListUtil
+ JumpListUtil
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
+
+
+
+
+ ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+
+ ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
+
+
+
+ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\packages\System.Text.Encodings.Web.4.7.1\lib\net461\System.Text.Encodings.Web.dll
+
+
+ ..\packages\System.Text.Json.4.7.2\lib\net461\System.Text.Json.dll
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+
+ ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/Program.cs b/JumpListUtil/Program.cs
new file mode 100755
index 0000000..a13d723
--- /dev/null
+++ b/JumpListUtil/Program.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text.Json;
+using System.Threading;
+using System.Windows.Forms;
+using System.Windows.Shell;
+
+namespace JumpListUtil
+{
+ public class Entry
+ {
+ public string Target { get; set; }
+ public string Icon { get; set; }
+ public int IconIndex { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ }
+ static class Program
+ {
+ [DllImport("shell32.dll", SetLastError = true)]
+ static extern void SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr)] string AppID);
+
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ System.Windows.Application wpfApp = new System.Windows.Application();
+ string thisProgram = Process.GetCurrentProcess().MainModule.FileName;
+
+ // parse all arguments
+ string shortcutsFile = "shortcuts.json";
+ string appUserModelId = "Microsoft.WindowsTerminal_8wekyb3d8bbwe!App";
+ int startIndex = 0;
+ bool onlyRefreshJumpList = false;
+
+ int i = 0;
+ string[] args = Environment.GetCommandLineArgs();
+ bool ParseFlag(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length > 2)
+ {
+ args[i] = "-" + args[i].Substring(2);
+ i--;
+ }
+ return true;
+ }
+ else if (args[i] == "--" + longName)
+ {
+ return true;
+ }
+ return false;
+ }
+ string ParseArg(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length == 2)
+ {
+ i++;
+ return args[i];
+ }
+ else
+ {
+ return args[i].Substring(2);
+ }
+ }
+ else if (args[i].IndexOf("--" + longName + "=") == 0)
+ {
+ return args[i].Substring(longName.Length + 3);
+ }
+ return null;
+ }
+
+ string val = null;
+ for (i = 1; i < args.Length; i++)
+ {
+ if ((val = ParseArg('s', "shortcuts")) != null)
+ {
+ shortcutsFile = val;
+ }
+ else if ((val = ParseArg('i', "startIndex")) != null)
+ {
+ startIndex = int.Parse(val);
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if (ParseFlag('r', "refresh"))
+ {
+ onlyRefreshJumpList = true;
+ }
+ }
+
+ SetCurrentProcessExplicitAppUserModelID(appUserModelId);
+
+ List jumpItems = new List();
+
+ Entry[] entries = null;
+
+ try
+ {
+ string shortcutJson = "";
+ using (FileStream input = File.OpenRead(shortcutsFile))
+ {
+ shortcutJson = new StreamReader(input).ReadToEnd();
+ }
+
+
+ entries = (Entry[])JsonSerializer.Deserialize(shortcutJson, typeof(Entry[]), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true, ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true });
+ }
+ catch (Exception e)
+ {
+ MessageBox.Show("Failed to load shortcut entries: " + e);
+ }
+
+ if (entries != null)
+ {
+ foreach (Entry entry in entries)
+ {
+ JumpTask task = new JumpTask();
+ task.ApplicationPath = entry.Target;
+ task.Description = entry.Description;
+ task.Title = entry.Name;
+ task.IconResourcePath = entry.Icon;
+ task.IconResourceIndex = entry.IconIndex;
+
+ jumpItems.Add(task);
+ }
+
+ jumpItems.Insert(0, new JumpTask
+ {
+ Title = "Refresh",
+ Description = "Refreshes the Jump List",
+ ApplicationPath = thisProgram,
+ WorkingDirectory = Environment.CurrentDirectory,
+ IconResourcePath = Environment.ExpandEnvironmentVariables("%systemroot%\\system32\\imageres.dll"),
+ IconResourceIndex = 228,
+ Arguments = "-r"
+ });
+
+ JumpList.SetJumpList(wpfApp, new JumpList(jumpItems, false, false));
+
+ if (!onlyRefreshJumpList)
+ {
+ if (startIndex >= 0 && startIndex < entries.Length)
+ {
+ Entry start = entries[startIndex];
+ Process p = Process.Start(new ProcessStartInfo
+ {
+ FileName = start.Target,
+ UseShellExecute = true
+ });
+ }
+ else
+ {
+ MessageBox.Show("Shortcut index " + startIndex + " is outside the range of valid entries (" + entries.Length + " entries)");
+ }
+ }
+ }
+
+ //Application.EnableVisualStyles();
+ //Application.SetCompatibleTextRenderingDefault(false);
+ //Application.Run();
+ }
+ }
+}
diff --git a/JumpListUtil/Properties/AssemblyInfo.cs b/JumpListUtil/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..e929884
--- /dev/null
+++ b/JumpListUtil/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("JumpListUtil")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("JumpListUtil")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
+
+// 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/JumpListUtil/Properties/Resources.Designer.cs b/JumpListUtil/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..ed070d5
--- /dev/null
+++ b/JumpListUtil/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+ using System;
+
+
+ ///
+ /// 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", "16.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 (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("JumpListUtil.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/JumpListUtil/Properties/Resources.resx b/JumpListUtil/Properties/Resources.resx
new file mode 100755
index 0000000..ffecec8
--- /dev/null
+++ b/JumpListUtil/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/JumpListUtil/Properties/Settings.Designer.cs b/JumpListUtil/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..8593114
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.6.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/JumpListUtil/Properties/Settings.settings b/JumpListUtil/Properties/Settings.settings
new file mode 100755
index 0000000..abf36c5
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs
new file mode 100755
index 0000000..6d13f4e
--- /dev/null
+++ b/JumpListUtil/ShellLink.cs
@@ -0,0 +1,486 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using System.Text;
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+/****************************************************************************
+ * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/
+ ***************************************************************************/
+
+namespace ShellLinkPlus
+{
+ // Modified from http://smdn.jp/programming/tips/createlnk/
+ // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects
+ // /Creating_and_Modifying_Shortcuts/article.asp
+ // Partly based on Sending toast notifications from desktop apps sample
+ public class ShellLink : IDisposable
+ {
+ #region Win32 and COM
+
+ // IShellLink Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("000214F9-0000-0000-C000-000000000046")]
+ private interface IShellLinkW
+ {
+ uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile,
+ int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags);
+ uint GetIDList(out IntPtr ppidl);
+ uint SetIDList(IntPtr pidl);
+ uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName,
+ int cchMaxName);
+ uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
+ uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir,
+ int cchMaxPath);
+ uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
+ uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs,
+ int cchMaxPath);
+ uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
+ uint GetHotKey(out ushort pwHotkey);
+ uint SetHotKey(ushort wHotKey);
+ uint GetShowCmd(out int piShowCmd);
+ uint SetShowCmd(int iShowCmd);
+ uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath,
+ int cchIconPath, out int piIcon);
+ uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
+ uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel,
+ uint dwReserved);
+ uint Resolve(IntPtr hwnd, uint fFlags);
+ uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
+ }
+
+ // ShellLink CoClass (ShellLink object)
+ [ComImport,
+ ClassInterface(ClassInterfaceType.None),
+ Guid("00021401-0000-0000-C000-000000000046")]
+ private class CShellLink { }
+
+ // WIN32_FIND_DATAW Structure
+ [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]
+ private struct WIN32_FIND_DATAW
+ {
+ public uint dwFileAttributes;
+ public ComTypes.FILETIME ftCreationTime;
+ public ComTypes.FILETIME ftLastAccessTime;
+ public ComTypes.FILETIME ftLastWriteTime;
+ public uint nFileSizeHigh;
+ public uint nFileSizeLow;
+ public uint dwReserved0;
+ public uint dwReserved1;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
+ public string cFileName;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
+ public string cAlternateFileName;
+ }
+
+ // IPropertyStore Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")]
+ private interface IPropertyStore
+ {
+ uint GetCount([Out] out uint cProps);
+ uint GetAt([In] uint iProp, out PropertyKey pkey);
+ uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv);
+ uint SetValue([In] ref PropertyKey key, [In] PropVariant pv);
+ uint Commit();
+ }
+
+ // PropertyKey Structure
+ // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ private struct PropertyKey
+ {
+ #region Fields
+
+ private Guid formatId; // Unique GUID for property
+ private Int32 propertyId; // Property identifier (PID)
+
+ #endregion
+
+ #region Public Properties
+
+ public Guid FormatId
+ {
+ get
+ {
+ return formatId;
+ }
+ }
+
+ public Int32 PropertyId
+ {
+ get
+ {
+ return propertyId;
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropertyKey(Guid formatId, Int32 propertyId)
+ {
+ this.formatId = formatId;
+ this.propertyId = propertyId;
+ }
+
+ public PropertyKey(string formatId, Int32 propertyId)
+ {
+ this.formatId = new Guid(formatId);
+ this.propertyId = propertyId;
+ }
+
+ #endregion
+ }
+
+ // PropVariant Class (only for string value)
+ // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1
+ // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11
+ // /interop-with-propvariants-in-net.aspx
+ [StructLayout(LayoutKind.Explicit)]
+ private sealed class PropVariant : IDisposable
+ {
+ #region Fields
+
+ [FieldOffset(0)]
+ ushort valueType; // Value type
+
+ // [FieldOffset(2)]
+ // ushort wReserved1; // Reserved field
+ // [FieldOffset(4)]
+ // ushort wReserved2; // Reserved field
+ // [FieldOffset(6)]
+ // ushort wReserved3; // Reserved field
+
+ [FieldOffset(8)]
+ IntPtr ptr; // Value
+
+ #endregion
+
+ #region Public Properties
+
+ // Value type (System.Runtime.InteropServices.VarEnum)
+ public VarEnum VarType
+ {
+ get { return (VarEnum)valueType; }
+ set { valueType = (ushort)value; }
+ }
+
+ // Whether value is empty or null
+ public bool IsNullOrEmpty
+ {
+ get
+ {
+ return (valueType == (ushort)VarEnum.VT_EMPTY ||
+ valueType == (ushort)VarEnum.VT_NULL);
+ }
+ }
+
+ // Value (only for string value)
+ public string Value
+ {
+ get
+ {
+ return Marshal.PtrToStringUni(ptr);
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropVariant()
+ { }
+
+ // Construct with string value
+ public PropVariant(string value)
+ {
+ if (value == null)
+ throw new ArgumentException("Failed to set value.");
+
+ valueType = (ushort)VarEnum.VT_LPWSTR;
+ ptr = Marshal.StringToCoTaskMemUni(value);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~PropVariant()
+ {
+ Dispose();
+ }
+
+ public void Dispose()
+ {
+ PropVariantClear(this);
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+ }
+
+ [DllImport("Ole32.dll", PreserveSig = false)]
+ private extern static void PropVariantClear([In, Out] PropVariant pvar);
+
+ #endregion
+
+ #region Fields
+
+ private IShellLinkW shellLinkW = null;
+
+ // Name = System.AppUserModel.ID
+ // ShellPKey = PKEY_AppUserModel_ID
+ // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3
+ // PropID = 5
+ // Type = String (VT_LPWSTR)
+ private readonly PropertyKey AppUserModelIDKey =
+ new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5);
+
+ private const int MAX_PATH = 260;
+ private const int INFOTIPSIZE = 1024;
+
+ private const int STGM_READ = 0x00000000; // STGM constants
+ private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags
+
+ #endregion
+
+ #region Private Properties (Interfaces)
+
+ private IPersistFile PersistFile
+ {
+ get
+ {
+ IPersistFile PersistFile = shellLinkW as IPersistFile;
+
+ if (PersistFile == null)
+ throw new COMException("Failed to create IPersistFile.");
+ else
+ return PersistFile;
+ }
+ }
+
+ private IPropertyStore PropertyStore
+ {
+ get
+ {
+ IPropertyStore PropertyStore = shellLinkW as IPropertyStore;
+
+ if (PropertyStore == null)
+ throw new COMException("Failed to create IPropertyStore.");
+ else
+ return PropertyStore;
+ }
+ }
+
+ #endregion
+
+ #region Public Properties (Minimal)
+
+ // Path of loaded shortcut file
+ public string ShortcutFile
+ {
+ get
+ {
+ string shortcutFile;
+
+ PersistFile.GetCurFile(out shortcutFile);
+
+ return shortcutFile;
+ }
+ }
+
+ // Path of target file
+ public string TargetPath
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder targetPath = new StringBuilder(MAX_PATH);
+
+ WIN32_FIND_DATAW data = new WIN32_FIND_DATAW();
+
+ VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data,
+ SLGP_UNCPRIORITY));
+
+ return targetPath.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetPath(value));
+ }
+ }
+
+ public string Arguments
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder arguments = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity));
+
+ return arguments.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetArguments(value));
+ }
+ }
+
+ public string Description
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder description = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity));
+
+ return description.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetDescription(value));
+ }
+ }
+
+ public Tuple IconLocation
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder icon = new StringBuilder(INFOTIPSIZE);
+
+ int index;
+ VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index));
+
+ return new Tuple(icon.ToString(), index);
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2));
+ }
+ }
+
+ // AppUserModelID to be used for Windows 7 or later.
+ public string AppUserModelID
+ {
+ get
+ {
+ using (PropVariant pv = new PropVariant())
+ {
+ VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv));
+
+ if (pv.Value == null)
+ return "Null";
+ else
+ return pv.Value;
+ }
+ }
+ set
+ {
+ using (PropVariant pv = new PropVariant(value))
+ {
+ VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv));
+ VerifySucceeded(PropertyStore.Commit());
+ }
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public ShellLink()
+ : this(null)
+ { }
+
+ // Construct with loading shortcut file.
+ public ShellLink(string file)
+ {
+ try
+ {
+ shellLinkW = (IShellLinkW)new CShellLink();
+ }
+ catch
+ {
+ throw new COMException("Failed to create ShellLink object.");
+ }
+
+ if (file != null)
+ Load(file);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~ShellLink()
+ {
+ Dispose(false);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (shellLinkW != null)
+ {
+ // Release all references.
+ Marshal.FinalReleaseComObject(shellLinkW);
+ shellLinkW = null;
+ }
+ }
+
+ #endregion
+
+ #region Methods
+
+ // Save shortcut file.
+ public void Save()
+ {
+ string file = ShortcutFile;
+
+ if (file == null)
+ throw new InvalidOperationException("File name is not given.");
+ else
+ Save(file);
+ }
+
+ public void Save(string file)
+ {
+ if (file == null)
+ throw new ArgumentNullException("File name is required.");
+ else
+ PersistFile.Save(file, true);
+ }
+
+ // Load shortcut file.
+ public void Load(string file)
+ {
+ if (!File.Exists(file))
+ throw new FileNotFoundException("File is not found.", file);
+ else
+ PersistFile.Load(file, STGM_READ);
+ }
+
+ // Verify if operation succeeded.
+ public static void VerifySucceeded(uint hresult)
+ {
+ if (hresult > 1)
+ throw new InvalidOperationException("Failed with HRESULT: " +
+ hresult.ToString("X"));
+ }
+
+ #endregion
+ }
+}
diff --git a/JumpListUtil/packages.config b/JumpListUtil/packages.config
new file mode 100755
index 0000000..abb0b89
--- /dev/null
+++ b/JumpListUtil/packages.config
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/Form1.cs b/Form1.cs
deleted file mode 100755
index 74b2085..0000000
--- a/Form1.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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 JumpListTest
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/JumpListTest.csproj b/JumpListTest.csproj
deleted file mode 100755
index 9ad6f29..0000000
--- a/JumpListTest.csproj
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
- WinExe
- JumpListTest
- JumpListTest
- v4.7.2
- 512
- true
- true
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Form
-
-
- 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/JumpListTest.sln b/JumpListTest.sln
deleted file mode 100755
index ad79cd7..0000000
--- a/JumpListTest.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30114.105
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListTest", "JumpListTest.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
- EndGlobalSection
-EndGlobal
diff --git a/JumpListUtil.sln b/JumpListUtil.sln
new file mode 100755
index 0000000..c91e4de
--- /dev/null
+++ b/JumpListUtil.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
+ EndGlobalSection
+EndGlobal
diff --git a/JumpListUtil/App.config b/JumpListUtil/App.config
new file mode 100755
index 0000000..de2fc4c
--- /dev/null
+++ b/JumpListUtil/App.config
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj
new file mode 100755
index 0000000..5f31de9
--- /dev/null
+++ b/JumpListUtil/JumpListUtil.csproj
@@ -0,0 +1,106 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
+ WinExe
+ JumpListUtil
+ JumpListUtil
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
+
+
+
+
+ ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+
+ ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
+
+
+
+ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\packages\System.Text.Encodings.Web.4.7.1\lib\net461\System.Text.Encodings.Web.dll
+
+
+ ..\packages\System.Text.Json.4.7.2\lib\net461\System.Text.Json.dll
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+
+ ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/Program.cs b/JumpListUtil/Program.cs
new file mode 100755
index 0000000..a13d723
--- /dev/null
+++ b/JumpListUtil/Program.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text.Json;
+using System.Threading;
+using System.Windows.Forms;
+using System.Windows.Shell;
+
+namespace JumpListUtil
+{
+ public class Entry
+ {
+ public string Target { get; set; }
+ public string Icon { get; set; }
+ public int IconIndex { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ }
+ static class Program
+ {
+ [DllImport("shell32.dll", SetLastError = true)]
+ static extern void SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr)] string AppID);
+
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ System.Windows.Application wpfApp = new System.Windows.Application();
+ string thisProgram = Process.GetCurrentProcess().MainModule.FileName;
+
+ // parse all arguments
+ string shortcutsFile = "shortcuts.json";
+ string appUserModelId = "Microsoft.WindowsTerminal_8wekyb3d8bbwe!App";
+ int startIndex = 0;
+ bool onlyRefreshJumpList = false;
+
+ int i = 0;
+ string[] args = Environment.GetCommandLineArgs();
+ bool ParseFlag(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length > 2)
+ {
+ args[i] = "-" + args[i].Substring(2);
+ i--;
+ }
+ return true;
+ }
+ else if (args[i] == "--" + longName)
+ {
+ return true;
+ }
+ return false;
+ }
+ string ParseArg(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length == 2)
+ {
+ i++;
+ return args[i];
+ }
+ else
+ {
+ return args[i].Substring(2);
+ }
+ }
+ else if (args[i].IndexOf("--" + longName + "=") == 0)
+ {
+ return args[i].Substring(longName.Length + 3);
+ }
+ return null;
+ }
+
+ string val = null;
+ for (i = 1; i < args.Length; i++)
+ {
+ if ((val = ParseArg('s', "shortcuts")) != null)
+ {
+ shortcutsFile = val;
+ }
+ else if ((val = ParseArg('i', "startIndex")) != null)
+ {
+ startIndex = int.Parse(val);
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if (ParseFlag('r', "refresh"))
+ {
+ onlyRefreshJumpList = true;
+ }
+ }
+
+ SetCurrentProcessExplicitAppUserModelID(appUserModelId);
+
+ List jumpItems = new List();
+
+ Entry[] entries = null;
+
+ try
+ {
+ string shortcutJson = "";
+ using (FileStream input = File.OpenRead(shortcutsFile))
+ {
+ shortcutJson = new StreamReader(input).ReadToEnd();
+ }
+
+
+ entries = (Entry[])JsonSerializer.Deserialize(shortcutJson, typeof(Entry[]), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true, ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true });
+ }
+ catch (Exception e)
+ {
+ MessageBox.Show("Failed to load shortcut entries: " + e);
+ }
+
+ if (entries != null)
+ {
+ foreach (Entry entry in entries)
+ {
+ JumpTask task = new JumpTask();
+ task.ApplicationPath = entry.Target;
+ task.Description = entry.Description;
+ task.Title = entry.Name;
+ task.IconResourcePath = entry.Icon;
+ task.IconResourceIndex = entry.IconIndex;
+
+ jumpItems.Add(task);
+ }
+
+ jumpItems.Insert(0, new JumpTask
+ {
+ Title = "Refresh",
+ Description = "Refreshes the Jump List",
+ ApplicationPath = thisProgram,
+ WorkingDirectory = Environment.CurrentDirectory,
+ IconResourcePath = Environment.ExpandEnvironmentVariables("%systemroot%\\system32\\imageres.dll"),
+ IconResourceIndex = 228,
+ Arguments = "-r"
+ });
+
+ JumpList.SetJumpList(wpfApp, new JumpList(jumpItems, false, false));
+
+ if (!onlyRefreshJumpList)
+ {
+ if (startIndex >= 0 && startIndex < entries.Length)
+ {
+ Entry start = entries[startIndex];
+ Process p = Process.Start(new ProcessStartInfo
+ {
+ FileName = start.Target,
+ UseShellExecute = true
+ });
+ }
+ else
+ {
+ MessageBox.Show("Shortcut index " + startIndex + " is outside the range of valid entries (" + entries.Length + " entries)");
+ }
+ }
+ }
+
+ //Application.EnableVisualStyles();
+ //Application.SetCompatibleTextRenderingDefault(false);
+ //Application.Run();
+ }
+ }
+}
diff --git a/JumpListUtil/Properties/AssemblyInfo.cs b/JumpListUtil/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..e929884
--- /dev/null
+++ b/JumpListUtil/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("JumpListUtil")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("JumpListUtil")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
+
+// 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/JumpListUtil/Properties/Resources.Designer.cs b/JumpListUtil/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..ed070d5
--- /dev/null
+++ b/JumpListUtil/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+ using System;
+
+
+ ///
+ /// 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", "16.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 (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("JumpListUtil.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/JumpListUtil/Properties/Resources.resx b/JumpListUtil/Properties/Resources.resx
new file mode 100755
index 0000000..ffecec8
--- /dev/null
+++ b/JumpListUtil/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/JumpListUtil/Properties/Settings.Designer.cs b/JumpListUtil/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..8593114
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.6.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/JumpListUtil/Properties/Settings.settings b/JumpListUtil/Properties/Settings.settings
new file mode 100755
index 0000000..abf36c5
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs
new file mode 100755
index 0000000..6d13f4e
--- /dev/null
+++ b/JumpListUtil/ShellLink.cs
@@ -0,0 +1,486 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using System.Text;
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+/****************************************************************************
+ * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/
+ ***************************************************************************/
+
+namespace ShellLinkPlus
+{
+ // Modified from http://smdn.jp/programming/tips/createlnk/
+ // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects
+ // /Creating_and_Modifying_Shortcuts/article.asp
+ // Partly based on Sending toast notifications from desktop apps sample
+ public class ShellLink : IDisposable
+ {
+ #region Win32 and COM
+
+ // IShellLink Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("000214F9-0000-0000-C000-000000000046")]
+ private interface IShellLinkW
+ {
+ uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile,
+ int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags);
+ uint GetIDList(out IntPtr ppidl);
+ uint SetIDList(IntPtr pidl);
+ uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName,
+ int cchMaxName);
+ uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
+ uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir,
+ int cchMaxPath);
+ uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
+ uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs,
+ int cchMaxPath);
+ uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
+ uint GetHotKey(out ushort pwHotkey);
+ uint SetHotKey(ushort wHotKey);
+ uint GetShowCmd(out int piShowCmd);
+ uint SetShowCmd(int iShowCmd);
+ uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath,
+ int cchIconPath, out int piIcon);
+ uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
+ uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel,
+ uint dwReserved);
+ uint Resolve(IntPtr hwnd, uint fFlags);
+ uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
+ }
+
+ // ShellLink CoClass (ShellLink object)
+ [ComImport,
+ ClassInterface(ClassInterfaceType.None),
+ Guid("00021401-0000-0000-C000-000000000046")]
+ private class CShellLink { }
+
+ // WIN32_FIND_DATAW Structure
+ [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]
+ private struct WIN32_FIND_DATAW
+ {
+ public uint dwFileAttributes;
+ public ComTypes.FILETIME ftCreationTime;
+ public ComTypes.FILETIME ftLastAccessTime;
+ public ComTypes.FILETIME ftLastWriteTime;
+ public uint nFileSizeHigh;
+ public uint nFileSizeLow;
+ public uint dwReserved0;
+ public uint dwReserved1;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
+ public string cFileName;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
+ public string cAlternateFileName;
+ }
+
+ // IPropertyStore Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")]
+ private interface IPropertyStore
+ {
+ uint GetCount([Out] out uint cProps);
+ uint GetAt([In] uint iProp, out PropertyKey pkey);
+ uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv);
+ uint SetValue([In] ref PropertyKey key, [In] PropVariant pv);
+ uint Commit();
+ }
+
+ // PropertyKey Structure
+ // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ private struct PropertyKey
+ {
+ #region Fields
+
+ private Guid formatId; // Unique GUID for property
+ private Int32 propertyId; // Property identifier (PID)
+
+ #endregion
+
+ #region Public Properties
+
+ public Guid FormatId
+ {
+ get
+ {
+ return formatId;
+ }
+ }
+
+ public Int32 PropertyId
+ {
+ get
+ {
+ return propertyId;
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropertyKey(Guid formatId, Int32 propertyId)
+ {
+ this.formatId = formatId;
+ this.propertyId = propertyId;
+ }
+
+ public PropertyKey(string formatId, Int32 propertyId)
+ {
+ this.formatId = new Guid(formatId);
+ this.propertyId = propertyId;
+ }
+
+ #endregion
+ }
+
+ // PropVariant Class (only for string value)
+ // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1
+ // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11
+ // /interop-with-propvariants-in-net.aspx
+ [StructLayout(LayoutKind.Explicit)]
+ private sealed class PropVariant : IDisposable
+ {
+ #region Fields
+
+ [FieldOffset(0)]
+ ushort valueType; // Value type
+
+ // [FieldOffset(2)]
+ // ushort wReserved1; // Reserved field
+ // [FieldOffset(4)]
+ // ushort wReserved2; // Reserved field
+ // [FieldOffset(6)]
+ // ushort wReserved3; // Reserved field
+
+ [FieldOffset(8)]
+ IntPtr ptr; // Value
+
+ #endregion
+
+ #region Public Properties
+
+ // Value type (System.Runtime.InteropServices.VarEnum)
+ public VarEnum VarType
+ {
+ get { return (VarEnum)valueType; }
+ set { valueType = (ushort)value; }
+ }
+
+ // Whether value is empty or null
+ public bool IsNullOrEmpty
+ {
+ get
+ {
+ return (valueType == (ushort)VarEnum.VT_EMPTY ||
+ valueType == (ushort)VarEnum.VT_NULL);
+ }
+ }
+
+ // Value (only for string value)
+ public string Value
+ {
+ get
+ {
+ return Marshal.PtrToStringUni(ptr);
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropVariant()
+ { }
+
+ // Construct with string value
+ public PropVariant(string value)
+ {
+ if (value == null)
+ throw new ArgumentException("Failed to set value.");
+
+ valueType = (ushort)VarEnum.VT_LPWSTR;
+ ptr = Marshal.StringToCoTaskMemUni(value);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~PropVariant()
+ {
+ Dispose();
+ }
+
+ public void Dispose()
+ {
+ PropVariantClear(this);
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+ }
+
+ [DllImport("Ole32.dll", PreserveSig = false)]
+ private extern static void PropVariantClear([In, Out] PropVariant pvar);
+
+ #endregion
+
+ #region Fields
+
+ private IShellLinkW shellLinkW = null;
+
+ // Name = System.AppUserModel.ID
+ // ShellPKey = PKEY_AppUserModel_ID
+ // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3
+ // PropID = 5
+ // Type = String (VT_LPWSTR)
+ private readonly PropertyKey AppUserModelIDKey =
+ new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5);
+
+ private const int MAX_PATH = 260;
+ private const int INFOTIPSIZE = 1024;
+
+ private const int STGM_READ = 0x00000000; // STGM constants
+ private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags
+
+ #endregion
+
+ #region Private Properties (Interfaces)
+
+ private IPersistFile PersistFile
+ {
+ get
+ {
+ IPersistFile PersistFile = shellLinkW as IPersistFile;
+
+ if (PersistFile == null)
+ throw new COMException("Failed to create IPersistFile.");
+ else
+ return PersistFile;
+ }
+ }
+
+ private IPropertyStore PropertyStore
+ {
+ get
+ {
+ IPropertyStore PropertyStore = shellLinkW as IPropertyStore;
+
+ if (PropertyStore == null)
+ throw new COMException("Failed to create IPropertyStore.");
+ else
+ return PropertyStore;
+ }
+ }
+
+ #endregion
+
+ #region Public Properties (Minimal)
+
+ // Path of loaded shortcut file
+ public string ShortcutFile
+ {
+ get
+ {
+ string shortcutFile;
+
+ PersistFile.GetCurFile(out shortcutFile);
+
+ return shortcutFile;
+ }
+ }
+
+ // Path of target file
+ public string TargetPath
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder targetPath = new StringBuilder(MAX_PATH);
+
+ WIN32_FIND_DATAW data = new WIN32_FIND_DATAW();
+
+ VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data,
+ SLGP_UNCPRIORITY));
+
+ return targetPath.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetPath(value));
+ }
+ }
+
+ public string Arguments
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder arguments = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity));
+
+ return arguments.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetArguments(value));
+ }
+ }
+
+ public string Description
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder description = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity));
+
+ return description.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetDescription(value));
+ }
+ }
+
+ public Tuple IconLocation
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder icon = new StringBuilder(INFOTIPSIZE);
+
+ int index;
+ VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index));
+
+ return new Tuple(icon.ToString(), index);
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2));
+ }
+ }
+
+ // AppUserModelID to be used for Windows 7 or later.
+ public string AppUserModelID
+ {
+ get
+ {
+ using (PropVariant pv = new PropVariant())
+ {
+ VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv));
+
+ if (pv.Value == null)
+ return "Null";
+ else
+ return pv.Value;
+ }
+ }
+ set
+ {
+ using (PropVariant pv = new PropVariant(value))
+ {
+ VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv));
+ VerifySucceeded(PropertyStore.Commit());
+ }
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public ShellLink()
+ : this(null)
+ { }
+
+ // Construct with loading shortcut file.
+ public ShellLink(string file)
+ {
+ try
+ {
+ shellLinkW = (IShellLinkW)new CShellLink();
+ }
+ catch
+ {
+ throw new COMException("Failed to create ShellLink object.");
+ }
+
+ if (file != null)
+ Load(file);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~ShellLink()
+ {
+ Dispose(false);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (shellLinkW != null)
+ {
+ // Release all references.
+ Marshal.FinalReleaseComObject(shellLinkW);
+ shellLinkW = null;
+ }
+ }
+
+ #endregion
+
+ #region Methods
+
+ // Save shortcut file.
+ public void Save()
+ {
+ string file = ShortcutFile;
+
+ if (file == null)
+ throw new InvalidOperationException("File name is not given.");
+ else
+ Save(file);
+ }
+
+ public void Save(string file)
+ {
+ if (file == null)
+ throw new ArgumentNullException("File name is required.");
+ else
+ PersistFile.Save(file, true);
+ }
+
+ // Load shortcut file.
+ public void Load(string file)
+ {
+ if (!File.Exists(file))
+ throw new FileNotFoundException("File is not found.", file);
+ else
+ PersistFile.Load(file, STGM_READ);
+ }
+
+ // Verify if operation succeeded.
+ public static void VerifySucceeded(uint hresult)
+ {
+ if (hresult > 1)
+ throw new InvalidOperationException("Failed with HRESULT: " +
+ hresult.ToString("X"));
+ }
+
+ #endregion
+ }
+}
diff --git a/JumpListUtil/packages.config b/JumpListUtil/packages.config
new file mode 100755
index 0000000..abb0b89
--- /dev/null
+++ b/JumpListUtil/packages.config
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Program.cs b/Program.cs
deleted file mode 100755
index 17420a8..0000000
--- a/Program.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-using System.Windows.Shell;
-
-namespace JumpListTest
-{
- static class Program
- {
- ///
- /// The main entry point for the application.
- ///
- [STAThread]
- static void Main()
- {
- System.Windows.Application wpfApp = new System.Windows.Application();
- JumpTask task = new JumpTask();
- task.ApplicationPath = "wt.exe";
- task.Description = "Work Terminal";
- task.Title = "Terminal";
- JumpList.SetJumpList(wpfApp, new JumpList(new List { task }, false, false));
-
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- Application.Run();
-
-
- }
- }
-}
diff --git a/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/Form1.cs b/Form1.cs
deleted file mode 100755
index 74b2085..0000000
--- a/Form1.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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 JumpListTest
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/JumpListTest.csproj b/JumpListTest.csproj
deleted file mode 100755
index 9ad6f29..0000000
--- a/JumpListTest.csproj
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
- WinExe
- JumpListTest
- JumpListTest
- v4.7.2
- 512
- true
- true
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Form
-
-
- 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/JumpListTest.sln b/JumpListTest.sln
deleted file mode 100755
index ad79cd7..0000000
--- a/JumpListTest.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30114.105
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListTest", "JumpListTest.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
- EndGlobalSection
-EndGlobal
diff --git a/JumpListUtil.sln b/JumpListUtil.sln
new file mode 100755
index 0000000..c91e4de
--- /dev/null
+++ b/JumpListUtil.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
+ EndGlobalSection
+EndGlobal
diff --git a/JumpListUtil/App.config b/JumpListUtil/App.config
new file mode 100755
index 0000000..de2fc4c
--- /dev/null
+++ b/JumpListUtil/App.config
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj
new file mode 100755
index 0000000..5f31de9
--- /dev/null
+++ b/JumpListUtil/JumpListUtil.csproj
@@ -0,0 +1,106 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
+ WinExe
+ JumpListUtil
+ JumpListUtil
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
+
+
+
+
+ ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+
+ ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
+
+
+
+ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\packages\System.Text.Encodings.Web.4.7.1\lib\net461\System.Text.Encodings.Web.dll
+
+
+ ..\packages\System.Text.Json.4.7.2\lib\net461\System.Text.Json.dll
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+
+ ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/Program.cs b/JumpListUtil/Program.cs
new file mode 100755
index 0000000..a13d723
--- /dev/null
+++ b/JumpListUtil/Program.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text.Json;
+using System.Threading;
+using System.Windows.Forms;
+using System.Windows.Shell;
+
+namespace JumpListUtil
+{
+ public class Entry
+ {
+ public string Target { get; set; }
+ public string Icon { get; set; }
+ public int IconIndex { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ }
+ static class Program
+ {
+ [DllImport("shell32.dll", SetLastError = true)]
+ static extern void SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr)] string AppID);
+
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ System.Windows.Application wpfApp = new System.Windows.Application();
+ string thisProgram = Process.GetCurrentProcess().MainModule.FileName;
+
+ // parse all arguments
+ string shortcutsFile = "shortcuts.json";
+ string appUserModelId = "Microsoft.WindowsTerminal_8wekyb3d8bbwe!App";
+ int startIndex = 0;
+ bool onlyRefreshJumpList = false;
+
+ int i = 0;
+ string[] args = Environment.GetCommandLineArgs();
+ bool ParseFlag(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length > 2)
+ {
+ args[i] = "-" + args[i].Substring(2);
+ i--;
+ }
+ return true;
+ }
+ else if (args[i] == "--" + longName)
+ {
+ return true;
+ }
+ return false;
+ }
+ string ParseArg(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length == 2)
+ {
+ i++;
+ return args[i];
+ }
+ else
+ {
+ return args[i].Substring(2);
+ }
+ }
+ else if (args[i].IndexOf("--" + longName + "=") == 0)
+ {
+ return args[i].Substring(longName.Length + 3);
+ }
+ return null;
+ }
+
+ string val = null;
+ for (i = 1; i < args.Length; i++)
+ {
+ if ((val = ParseArg('s', "shortcuts")) != null)
+ {
+ shortcutsFile = val;
+ }
+ else if ((val = ParseArg('i', "startIndex")) != null)
+ {
+ startIndex = int.Parse(val);
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if (ParseFlag('r', "refresh"))
+ {
+ onlyRefreshJumpList = true;
+ }
+ }
+
+ SetCurrentProcessExplicitAppUserModelID(appUserModelId);
+
+ List jumpItems = new List();
+
+ Entry[] entries = null;
+
+ try
+ {
+ string shortcutJson = "";
+ using (FileStream input = File.OpenRead(shortcutsFile))
+ {
+ shortcutJson = new StreamReader(input).ReadToEnd();
+ }
+
+
+ entries = (Entry[])JsonSerializer.Deserialize(shortcutJson, typeof(Entry[]), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true, ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true });
+ }
+ catch (Exception e)
+ {
+ MessageBox.Show("Failed to load shortcut entries: " + e);
+ }
+
+ if (entries != null)
+ {
+ foreach (Entry entry in entries)
+ {
+ JumpTask task = new JumpTask();
+ task.ApplicationPath = entry.Target;
+ task.Description = entry.Description;
+ task.Title = entry.Name;
+ task.IconResourcePath = entry.Icon;
+ task.IconResourceIndex = entry.IconIndex;
+
+ jumpItems.Add(task);
+ }
+
+ jumpItems.Insert(0, new JumpTask
+ {
+ Title = "Refresh",
+ Description = "Refreshes the Jump List",
+ ApplicationPath = thisProgram,
+ WorkingDirectory = Environment.CurrentDirectory,
+ IconResourcePath = Environment.ExpandEnvironmentVariables("%systemroot%\\system32\\imageres.dll"),
+ IconResourceIndex = 228,
+ Arguments = "-r"
+ });
+
+ JumpList.SetJumpList(wpfApp, new JumpList(jumpItems, false, false));
+
+ if (!onlyRefreshJumpList)
+ {
+ if (startIndex >= 0 && startIndex < entries.Length)
+ {
+ Entry start = entries[startIndex];
+ Process p = Process.Start(new ProcessStartInfo
+ {
+ FileName = start.Target,
+ UseShellExecute = true
+ });
+ }
+ else
+ {
+ MessageBox.Show("Shortcut index " + startIndex + " is outside the range of valid entries (" + entries.Length + " entries)");
+ }
+ }
+ }
+
+ //Application.EnableVisualStyles();
+ //Application.SetCompatibleTextRenderingDefault(false);
+ //Application.Run();
+ }
+ }
+}
diff --git a/JumpListUtil/Properties/AssemblyInfo.cs b/JumpListUtil/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..e929884
--- /dev/null
+++ b/JumpListUtil/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("JumpListUtil")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("JumpListUtil")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
+
+// 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/JumpListUtil/Properties/Resources.Designer.cs b/JumpListUtil/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..ed070d5
--- /dev/null
+++ b/JumpListUtil/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+ using System;
+
+
+ ///
+ /// 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", "16.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 (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("JumpListUtil.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/JumpListUtil/Properties/Resources.resx b/JumpListUtil/Properties/Resources.resx
new file mode 100755
index 0000000..ffecec8
--- /dev/null
+++ b/JumpListUtil/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/JumpListUtil/Properties/Settings.Designer.cs b/JumpListUtil/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..8593114
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.6.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/JumpListUtil/Properties/Settings.settings b/JumpListUtil/Properties/Settings.settings
new file mode 100755
index 0000000..abf36c5
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs
new file mode 100755
index 0000000..6d13f4e
--- /dev/null
+++ b/JumpListUtil/ShellLink.cs
@@ -0,0 +1,486 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using System.Text;
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+/****************************************************************************
+ * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/
+ ***************************************************************************/
+
+namespace ShellLinkPlus
+{
+ // Modified from http://smdn.jp/programming/tips/createlnk/
+ // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects
+ // /Creating_and_Modifying_Shortcuts/article.asp
+ // Partly based on Sending toast notifications from desktop apps sample
+ public class ShellLink : IDisposable
+ {
+ #region Win32 and COM
+
+ // IShellLink Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("000214F9-0000-0000-C000-000000000046")]
+ private interface IShellLinkW
+ {
+ uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile,
+ int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags);
+ uint GetIDList(out IntPtr ppidl);
+ uint SetIDList(IntPtr pidl);
+ uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName,
+ int cchMaxName);
+ uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
+ uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir,
+ int cchMaxPath);
+ uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
+ uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs,
+ int cchMaxPath);
+ uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
+ uint GetHotKey(out ushort pwHotkey);
+ uint SetHotKey(ushort wHotKey);
+ uint GetShowCmd(out int piShowCmd);
+ uint SetShowCmd(int iShowCmd);
+ uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath,
+ int cchIconPath, out int piIcon);
+ uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
+ uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel,
+ uint dwReserved);
+ uint Resolve(IntPtr hwnd, uint fFlags);
+ uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
+ }
+
+ // ShellLink CoClass (ShellLink object)
+ [ComImport,
+ ClassInterface(ClassInterfaceType.None),
+ Guid("00021401-0000-0000-C000-000000000046")]
+ private class CShellLink { }
+
+ // WIN32_FIND_DATAW Structure
+ [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]
+ private struct WIN32_FIND_DATAW
+ {
+ public uint dwFileAttributes;
+ public ComTypes.FILETIME ftCreationTime;
+ public ComTypes.FILETIME ftLastAccessTime;
+ public ComTypes.FILETIME ftLastWriteTime;
+ public uint nFileSizeHigh;
+ public uint nFileSizeLow;
+ public uint dwReserved0;
+ public uint dwReserved1;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
+ public string cFileName;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
+ public string cAlternateFileName;
+ }
+
+ // IPropertyStore Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")]
+ private interface IPropertyStore
+ {
+ uint GetCount([Out] out uint cProps);
+ uint GetAt([In] uint iProp, out PropertyKey pkey);
+ uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv);
+ uint SetValue([In] ref PropertyKey key, [In] PropVariant pv);
+ uint Commit();
+ }
+
+ // PropertyKey Structure
+ // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ private struct PropertyKey
+ {
+ #region Fields
+
+ private Guid formatId; // Unique GUID for property
+ private Int32 propertyId; // Property identifier (PID)
+
+ #endregion
+
+ #region Public Properties
+
+ public Guid FormatId
+ {
+ get
+ {
+ return formatId;
+ }
+ }
+
+ public Int32 PropertyId
+ {
+ get
+ {
+ return propertyId;
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropertyKey(Guid formatId, Int32 propertyId)
+ {
+ this.formatId = formatId;
+ this.propertyId = propertyId;
+ }
+
+ public PropertyKey(string formatId, Int32 propertyId)
+ {
+ this.formatId = new Guid(formatId);
+ this.propertyId = propertyId;
+ }
+
+ #endregion
+ }
+
+ // PropVariant Class (only for string value)
+ // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1
+ // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11
+ // /interop-with-propvariants-in-net.aspx
+ [StructLayout(LayoutKind.Explicit)]
+ private sealed class PropVariant : IDisposable
+ {
+ #region Fields
+
+ [FieldOffset(0)]
+ ushort valueType; // Value type
+
+ // [FieldOffset(2)]
+ // ushort wReserved1; // Reserved field
+ // [FieldOffset(4)]
+ // ushort wReserved2; // Reserved field
+ // [FieldOffset(6)]
+ // ushort wReserved3; // Reserved field
+
+ [FieldOffset(8)]
+ IntPtr ptr; // Value
+
+ #endregion
+
+ #region Public Properties
+
+ // Value type (System.Runtime.InteropServices.VarEnum)
+ public VarEnum VarType
+ {
+ get { return (VarEnum)valueType; }
+ set { valueType = (ushort)value; }
+ }
+
+ // Whether value is empty or null
+ public bool IsNullOrEmpty
+ {
+ get
+ {
+ return (valueType == (ushort)VarEnum.VT_EMPTY ||
+ valueType == (ushort)VarEnum.VT_NULL);
+ }
+ }
+
+ // Value (only for string value)
+ public string Value
+ {
+ get
+ {
+ return Marshal.PtrToStringUni(ptr);
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropVariant()
+ { }
+
+ // Construct with string value
+ public PropVariant(string value)
+ {
+ if (value == null)
+ throw new ArgumentException("Failed to set value.");
+
+ valueType = (ushort)VarEnum.VT_LPWSTR;
+ ptr = Marshal.StringToCoTaskMemUni(value);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~PropVariant()
+ {
+ Dispose();
+ }
+
+ public void Dispose()
+ {
+ PropVariantClear(this);
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+ }
+
+ [DllImport("Ole32.dll", PreserveSig = false)]
+ private extern static void PropVariantClear([In, Out] PropVariant pvar);
+
+ #endregion
+
+ #region Fields
+
+ private IShellLinkW shellLinkW = null;
+
+ // Name = System.AppUserModel.ID
+ // ShellPKey = PKEY_AppUserModel_ID
+ // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3
+ // PropID = 5
+ // Type = String (VT_LPWSTR)
+ private readonly PropertyKey AppUserModelIDKey =
+ new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5);
+
+ private const int MAX_PATH = 260;
+ private const int INFOTIPSIZE = 1024;
+
+ private const int STGM_READ = 0x00000000; // STGM constants
+ private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags
+
+ #endregion
+
+ #region Private Properties (Interfaces)
+
+ private IPersistFile PersistFile
+ {
+ get
+ {
+ IPersistFile PersistFile = shellLinkW as IPersistFile;
+
+ if (PersistFile == null)
+ throw new COMException("Failed to create IPersistFile.");
+ else
+ return PersistFile;
+ }
+ }
+
+ private IPropertyStore PropertyStore
+ {
+ get
+ {
+ IPropertyStore PropertyStore = shellLinkW as IPropertyStore;
+
+ if (PropertyStore == null)
+ throw new COMException("Failed to create IPropertyStore.");
+ else
+ return PropertyStore;
+ }
+ }
+
+ #endregion
+
+ #region Public Properties (Minimal)
+
+ // Path of loaded shortcut file
+ public string ShortcutFile
+ {
+ get
+ {
+ string shortcutFile;
+
+ PersistFile.GetCurFile(out shortcutFile);
+
+ return shortcutFile;
+ }
+ }
+
+ // Path of target file
+ public string TargetPath
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder targetPath = new StringBuilder(MAX_PATH);
+
+ WIN32_FIND_DATAW data = new WIN32_FIND_DATAW();
+
+ VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data,
+ SLGP_UNCPRIORITY));
+
+ return targetPath.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetPath(value));
+ }
+ }
+
+ public string Arguments
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder arguments = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity));
+
+ return arguments.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetArguments(value));
+ }
+ }
+
+ public string Description
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder description = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity));
+
+ return description.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetDescription(value));
+ }
+ }
+
+ public Tuple IconLocation
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder icon = new StringBuilder(INFOTIPSIZE);
+
+ int index;
+ VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index));
+
+ return new Tuple(icon.ToString(), index);
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2));
+ }
+ }
+
+ // AppUserModelID to be used for Windows 7 or later.
+ public string AppUserModelID
+ {
+ get
+ {
+ using (PropVariant pv = new PropVariant())
+ {
+ VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv));
+
+ if (pv.Value == null)
+ return "Null";
+ else
+ return pv.Value;
+ }
+ }
+ set
+ {
+ using (PropVariant pv = new PropVariant(value))
+ {
+ VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv));
+ VerifySucceeded(PropertyStore.Commit());
+ }
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public ShellLink()
+ : this(null)
+ { }
+
+ // Construct with loading shortcut file.
+ public ShellLink(string file)
+ {
+ try
+ {
+ shellLinkW = (IShellLinkW)new CShellLink();
+ }
+ catch
+ {
+ throw new COMException("Failed to create ShellLink object.");
+ }
+
+ if (file != null)
+ Load(file);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~ShellLink()
+ {
+ Dispose(false);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (shellLinkW != null)
+ {
+ // Release all references.
+ Marshal.FinalReleaseComObject(shellLinkW);
+ shellLinkW = null;
+ }
+ }
+
+ #endregion
+
+ #region Methods
+
+ // Save shortcut file.
+ public void Save()
+ {
+ string file = ShortcutFile;
+
+ if (file == null)
+ throw new InvalidOperationException("File name is not given.");
+ else
+ Save(file);
+ }
+
+ public void Save(string file)
+ {
+ if (file == null)
+ throw new ArgumentNullException("File name is required.");
+ else
+ PersistFile.Save(file, true);
+ }
+
+ // Load shortcut file.
+ public void Load(string file)
+ {
+ if (!File.Exists(file))
+ throw new FileNotFoundException("File is not found.", file);
+ else
+ PersistFile.Load(file, STGM_READ);
+ }
+
+ // Verify if operation succeeded.
+ public static void VerifySucceeded(uint hresult)
+ {
+ if (hresult > 1)
+ throw new InvalidOperationException("Failed with HRESULT: " +
+ hresult.ToString("X"));
+ }
+
+ #endregion
+ }
+}
diff --git a/JumpListUtil/packages.config b/JumpListUtil/packages.config
new file mode 100755
index 0000000..abb0b89
--- /dev/null
+++ b/JumpListUtil/packages.config
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Program.cs b/Program.cs
deleted file mode 100755
index 17420a8..0000000
--- a/Program.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-using System.Windows.Shell;
-
-namespace JumpListTest
-{
- static class Program
- {
- ///
- /// The main entry point for the application.
- ///
- [STAThread]
- static void Main()
- {
- System.Windows.Application wpfApp = new System.Windows.Application();
- JumpTask task = new JumpTask();
- task.ApplicationPath = "wt.exe";
- task.Description = "Work Terminal";
- task.Title = "Terminal";
- JumpList.SetJumpList(wpfApp, new JumpList(new List { task }, false, false));
-
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- Application.Run();
-
-
- }
- }
-}
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
deleted file mode 100755
index 1b650b3..0000000
--- a/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-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("JumpListTest")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("JumpListTest")]
-[assembly: AssemblyCopyright("Copyright © 2020")]
-[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
-
-// 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/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/Form1.cs b/Form1.cs
deleted file mode 100755
index 74b2085..0000000
--- a/Form1.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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 JumpListTest
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/JumpListTest.csproj b/JumpListTest.csproj
deleted file mode 100755
index 9ad6f29..0000000
--- a/JumpListTest.csproj
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
- WinExe
- JumpListTest
- JumpListTest
- v4.7.2
- 512
- true
- true
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Form
-
-
- 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/JumpListTest.sln b/JumpListTest.sln
deleted file mode 100755
index ad79cd7..0000000
--- a/JumpListTest.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30114.105
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListTest", "JumpListTest.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
- EndGlobalSection
-EndGlobal
diff --git a/JumpListUtil.sln b/JumpListUtil.sln
new file mode 100755
index 0000000..c91e4de
--- /dev/null
+++ b/JumpListUtil.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
+ EndGlobalSection
+EndGlobal
diff --git a/JumpListUtil/App.config b/JumpListUtil/App.config
new file mode 100755
index 0000000..de2fc4c
--- /dev/null
+++ b/JumpListUtil/App.config
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj
new file mode 100755
index 0000000..5f31de9
--- /dev/null
+++ b/JumpListUtil/JumpListUtil.csproj
@@ -0,0 +1,106 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
+ WinExe
+ JumpListUtil
+ JumpListUtil
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
+
+
+
+
+ ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+
+ ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
+
+
+
+ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\packages\System.Text.Encodings.Web.4.7.1\lib\net461\System.Text.Encodings.Web.dll
+
+
+ ..\packages\System.Text.Json.4.7.2\lib\net461\System.Text.Json.dll
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+
+ ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/Program.cs b/JumpListUtil/Program.cs
new file mode 100755
index 0000000..a13d723
--- /dev/null
+++ b/JumpListUtil/Program.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text.Json;
+using System.Threading;
+using System.Windows.Forms;
+using System.Windows.Shell;
+
+namespace JumpListUtil
+{
+ public class Entry
+ {
+ public string Target { get; set; }
+ public string Icon { get; set; }
+ public int IconIndex { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ }
+ static class Program
+ {
+ [DllImport("shell32.dll", SetLastError = true)]
+ static extern void SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr)] string AppID);
+
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ System.Windows.Application wpfApp = new System.Windows.Application();
+ string thisProgram = Process.GetCurrentProcess().MainModule.FileName;
+
+ // parse all arguments
+ string shortcutsFile = "shortcuts.json";
+ string appUserModelId = "Microsoft.WindowsTerminal_8wekyb3d8bbwe!App";
+ int startIndex = 0;
+ bool onlyRefreshJumpList = false;
+
+ int i = 0;
+ string[] args = Environment.GetCommandLineArgs();
+ bool ParseFlag(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length > 2)
+ {
+ args[i] = "-" + args[i].Substring(2);
+ i--;
+ }
+ return true;
+ }
+ else if (args[i] == "--" + longName)
+ {
+ return true;
+ }
+ return false;
+ }
+ string ParseArg(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length == 2)
+ {
+ i++;
+ return args[i];
+ }
+ else
+ {
+ return args[i].Substring(2);
+ }
+ }
+ else if (args[i].IndexOf("--" + longName + "=") == 0)
+ {
+ return args[i].Substring(longName.Length + 3);
+ }
+ return null;
+ }
+
+ string val = null;
+ for (i = 1; i < args.Length; i++)
+ {
+ if ((val = ParseArg('s', "shortcuts")) != null)
+ {
+ shortcutsFile = val;
+ }
+ else if ((val = ParseArg('i', "startIndex")) != null)
+ {
+ startIndex = int.Parse(val);
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if (ParseFlag('r', "refresh"))
+ {
+ onlyRefreshJumpList = true;
+ }
+ }
+
+ SetCurrentProcessExplicitAppUserModelID(appUserModelId);
+
+ List jumpItems = new List();
+
+ Entry[] entries = null;
+
+ try
+ {
+ string shortcutJson = "";
+ using (FileStream input = File.OpenRead(shortcutsFile))
+ {
+ shortcutJson = new StreamReader(input).ReadToEnd();
+ }
+
+
+ entries = (Entry[])JsonSerializer.Deserialize(shortcutJson, typeof(Entry[]), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true, ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true });
+ }
+ catch (Exception e)
+ {
+ MessageBox.Show("Failed to load shortcut entries: " + e);
+ }
+
+ if (entries != null)
+ {
+ foreach (Entry entry in entries)
+ {
+ JumpTask task = new JumpTask();
+ task.ApplicationPath = entry.Target;
+ task.Description = entry.Description;
+ task.Title = entry.Name;
+ task.IconResourcePath = entry.Icon;
+ task.IconResourceIndex = entry.IconIndex;
+
+ jumpItems.Add(task);
+ }
+
+ jumpItems.Insert(0, new JumpTask
+ {
+ Title = "Refresh",
+ Description = "Refreshes the Jump List",
+ ApplicationPath = thisProgram,
+ WorkingDirectory = Environment.CurrentDirectory,
+ IconResourcePath = Environment.ExpandEnvironmentVariables("%systemroot%\\system32\\imageres.dll"),
+ IconResourceIndex = 228,
+ Arguments = "-r"
+ });
+
+ JumpList.SetJumpList(wpfApp, new JumpList(jumpItems, false, false));
+
+ if (!onlyRefreshJumpList)
+ {
+ if (startIndex >= 0 && startIndex < entries.Length)
+ {
+ Entry start = entries[startIndex];
+ Process p = Process.Start(new ProcessStartInfo
+ {
+ FileName = start.Target,
+ UseShellExecute = true
+ });
+ }
+ else
+ {
+ MessageBox.Show("Shortcut index " + startIndex + " is outside the range of valid entries (" + entries.Length + " entries)");
+ }
+ }
+ }
+
+ //Application.EnableVisualStyles();
+ //Application.SetCompatibleTextRenderingDefault(false);
+ //Application.Run();
+ }
+ }
+}
diff --git a/JumpListUtil/Properties/AssemblyInfo.cs b/JumpListUtil/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..e929884
--- /dev/null
+++ b/JumpListUtil/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("JumpListUtil")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("JumpListUtil")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
+
+// 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/JumpListUtil/Properties/Resources.Designer.cs b/JumpListUtil/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..ed070d5
--- /dev/null
+++ b/JumpListUtil/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+ using System;
+
+
+ ///
+ /// 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", "16.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 (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("JumpListUtil.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/JumpListUtil/Properties/Resources.resx b/JumpListUtil/Properties/Resources.resx
new file mode 100755
index 0000000..ffecec8
--- /dev/null
+++ b/JumpListUtil/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/JumpListUtil/Properties/Settings.Designer.cs b/JumpListUtil/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..8593114
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.6.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/JumpListUtil/Properties/Settings.settings b/JumpListUtil/Properties/Settings.settings
new file mode 100755
index 0000000..abf36c5
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs
new file mode 100755
index 0000000..6d13f4e
--- /dev/null
+++ b/JumpListUtil/ShellLink.cs
@@ -0,0 +1,486 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using System.Text;
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+/****************************************************************************
+ * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/
+ ***************************************************************************/
+
+namespace ShellLinkPlus
+{
+ // Modified from http://smdn.jp/programming/tips/createlnk/
+ // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects
+ // /Creating_and_Modifying_Shortcuts/article.asp
+ // Partly based on Sending toast notifications from desktop apps sample
+ public class ShellLink : IDisposable
+ {
+ #region Win32 and COM
+
+ // IShellLink Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("000214F9-0000-0000-C000-000000000046")]
+ private interface IShellLinkW
+ {
+ uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile,
+ int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags);
+ uint GetIDList(out IntPtr ppidl);
+ uint SetIDList(IntPtr pidl);
+ uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName,
+ int cchMaxName);
+ uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
+ uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir,
+ int cchMaxPath);
+ uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
+ uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs,
+ int cchMaxPath);
+ uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
+ uint GetHotKey(out ushort pwHotkey);
+ uint SetHotKey(ushort wHotKey);
+ uint GetShowCmd(out int piShowCmd);
+ uint SetShowCmd(int iShowCmd);
+ uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath,
+ int cchIconPath, out int piIcon);
+ uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
+ uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel,
+ uint dwReserved);
+ uint Resolve(IntPtr hwnd, uint fFlags);
+ uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
+ }
+
+ // ShellLink CoClass (ShellLink object)
+ [ComImport,
+ ClassInterface(ClassInterfaceType.None),
+ Guid("00021401-0000-0000-C000-000000000046")]
+ private class CShellLink { }
+
+ // WIN32_FIND_DATAW Structure
+ [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]
+ private struct WIN32_FIND_DATAW
+ {
+ public uint dwFileAttributes;
+ public ComTypes.FILETIME ftCreationTime;
+ public ComTypes.FILETIME ftLastAccessTime;
+ public ComTypes.FILETIME ftLastWriteTime;
+ public uint nFileSizeHigh;
+ public uint nFileSizeLow;
+ public uint dwReserved0;
+ public uint dwReserved1;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
+ public string cFileName;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
+ public string cAlternateFileName;
+ }
+
+ // IPropertyStore Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")]
+ private interface IPropertyStore
+ {
+ uint GetCount([Out] out uint cProps);
+ uint GetAt([In] uint iProp, out PropertyKey pkey);
+ uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv);
+ uint SetValue([In] ref PropertyKey key, [In] PropVariant pv);
+ uint Commit();
+ }
+
+ // PropertyKey Structure
+ // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ private struct PropertyKey
+ {
+ #region Fields
+
+ private Guid formatId; // Unique GUID for property
+ private Int32 propertyId; // Property identifier (PID)
+
+ #endregion
+
+ #region Public Properties
+
+ public Guid FormatId
+ {
+ get
+ {
+ return formatId;
+ }
+ }
+
+ public Int32 PropertyId
+ {
+ get
+ {
+ return propertyId;
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropertyKey(Guid formatId, Int32 propertyId)
+ {
+ this.formatId = formatId;
+ this.propertyId = propertyId;
+ }
+
+ public PropertyKey(string formatId, Int32 propertyId)
+ {
+ this.formatId = new Guid(formatId);
+ this.propertyId = propertyId;
+ }
+
+ #endregion
+ }
+
+ // PropVariant Class (only for string value)
+ // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1
+ // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11
+ // /interop-with-propvariants-in-net.aspx
+ [StructLayout(LayoutKind.Explicit)]
+ private sealed class PropVariant : IDisposable
+ {
+ #region Fields
+
+ [FieldOffset(0)]
+ ushort valueType; // Value type
+
+ // [FieldOffset(2)]
+ // ushort wReserved1; // Reserved field
+ // [FieldOffset(4)]
+ // ushort wReserved2; // Reserved field
+ // [FieldOffset(6)]
+ // ushort wReserved3; // Reserved field
+
+ [FieldOffset(8)]
+ IntPtr ptr; // Value
+
+ #endregion
+
+ #region Public Properties
+
+ // Value type (System.Runtime.InteropServices.VarEnum)
+ public VarEnum VarType
+ {
+ get { return (VarEnum)valueType; }
+ set { valueType = (ushort)value; }
+ }
+
+ // Whether value is empty or null
+ public bool IsNullOrEmpty
+ {
+ get
+ {
+ return (valueType == (ushort)VarEnum.VT_EMPTY ||
+ valueType == (ushort)VarEnum.VT_NULL);
+ }
+ }
+
+ // Value (only for string value)
+ public string Value
+ {
+ get
+ {
+ return Marshal.PtrToStringUni(ptr);
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropVariant()
+ { }
+
+ // Construct with string value
+ public PropVariant(string value)
+ {
+ if (value == null)
+ throw new ArgumentException("Failed to set value.");
+
+ valueType = (ushort)VarEnum.VT_LPWSTR;
+ ptr = Marshal.StringToCoTaskMemUni(value);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~PropVariant()
+ {
+ Dispose();
+ }
+
+ public void Dispose()
+ {
+ PropVariantClear(this);
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+ }
+
+ [DllImport("Ole32.dll", PreserveSig = false)]
+ private extern static void PropVariantClear([In, Out] PropVariant pvar);
+
+ #endregion
+
+ #region Fields
+
+ private IShellLinkW shellLinkW = null;
+
+ // Name = System.AppUserModel.ID
+ // ShellPKey = PKEY_AppUserModel_ID
+ // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3
+ // PropID = 5
+ // Type = String (VT_LPWSTR)
+ private readonly PropertyKey AppUserModelIDKey =
+ new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5);
+
+ private const int MAX_PATH = 260;
+ private const int INFOTIPSIZE = 1024;
+
+ private const int STGM_READ = 0x00000000; // STGM constants
+ private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags
+
+ #endregion
+
+ #region Private Properties (Interfaces)
+
+ private IPersistFile PersistFile
+ {
+ get
+ {
+ IPersistFile PersistFile = shellLinkW as IPersistFile;
+
+ if (PersistFile == null)
+ throw new COMException("Failed to create IPersistFile.");
+ else
+ return PersistFile;
+ }
+ }
+
+ private IPropertyStore PropertyStore
+ {
+ get
+ {
+ IPropertyStore PropertyStore = shellLinkW as IPropertyStore;
+
+ if (PropertyStore == null)
+ throw new COMException("Failed to create IPropertyStore.");
+ else
+ return PropertyStore;
+ }
+ }
+
+ #endregion
+
+ #region Public Properties (Minimal)
+
+ // Path of loaded shortcut file
+ public string ShortcutFile
+ {
+ get
+ {
+ string shortcutFile;
+
+ PersistFile.GetCurFile(out shortcutFile);
+
+ return shortcutFile;
+ }
+ }
+
+ // Path of target file
+ public string TargetPath
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder targetPath = new StringBuilder(MAX_PATH);
+
+ WIN32_FIND_DATAW data = new WIN32_FIND_DATAW();
+
+ VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data,
+ SLGP_UNCPRIORITY));
+
+ return targetPath.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetPath(value));
+ }
+ }
+
+ public string Arguments
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder arguments = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity));
+
+ return arguments.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetArguments(value));
+ }
+ }
+
+ public string Description
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder description = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity));
+
+ return description.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetDescription(value));
+ }
+ }
+
+ public Tuple IconLocation
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder icon = new StringBuilder(INFOTIPSIZE);
+
+ int index;
+ VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index));
+
+ return new Tuple(icon.ToString(), index);
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2));
+ }
+ }
+
+ // AppUserModelID to be used for Windows 7 or later.
+ public string AppUserModelID
+ {
+ get
+ {
+ using (PropVariant pv = new PropVariant())
+ {
+ VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv));
+
+ if (pv.Value == null)
+ return "Null";
+ else
+ return pv.Value;
+ }
+ }
+ set
+ {
+ using (PropVariant pv = new PropVariant(value))
+ {
+ VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv));
+ VerifySucceeded(PropertyStore.Commit());
+ }
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public ShellLink()
+ : this(null)
+ { }
+
+ // Construct with loading shortcut file.
+ public ShellLink(string file)
+ {
+ try
+ {
+ shellLinkW = (IShellLinkW)new CShellLink();
+ }
+ catch
+ {
+ throw new COMException("Failed to create ShellLink object.");
+ }
+
+ if (file != null)
+ Load(file);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~ShellLink()
+ {
+ Dispose(false);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (shellLinkW != null)
+ {
+ // Release all references.
+ Marshal.FinalReleaseComObject(shellLinkW);
+ shellLinkW = null;
+ }
+ }
+
+ #endregion
+
+ #region Methods
+
+ // Save shortcut file.
+ public void Save()
+ {
+ string file = ShortcutFile;
+
+ if (file == null)
+ throw new InvalidOperationException("File name is not given.");
+ else
+ Save(file);
+ }
+
+ public void Save(string file)
+ {
+ if (file == null)
+ throw new ArgumentNullException("File name is required.");
+ else
+ PersistFile.Save(file, true);
+ }
+
+ // Load shortcut file.
+ public void Load(string file)
+ {
+ if (!File.Exists(file))
+ throw new FileNotFoundException("File is not found.", file);
+ else
+ PersistFile.Load(file, STGM_READ);
+ }
+
+ // Verify if operation succeeded.
+ public static void VerifySucceeded(uint hresult)
+ {
+ if (hresult > 1)
+ throw new InvalidOperationException("Failed with HRESULT: " +
+ hresult.ToString("X"));
+ }
+
+ #endregion
+ }
+}
diff --git a/JumpListUtil/packages.config b/JumpListUtil/packages.config
new file mode 100755
index 0000000..abb0b89
--- /dev/null
+++ b/JumpListUtil/packages.config
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Program.cs b/Program.cs
deleted file mode 100755
index 17420a8..0000000
--- a/Program.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-using System.Windows.Shell;
-
-namespace JumpListTest
-{
- static class Program
- {
- ///
- /// The main entry point for the application.
- ///
- [STAThread]
- static void Main()
- {
- System.Windows.Application wpfApp = new System.Windows.Application();
- JumpTask task = new JumpTask();
- task.ApplicationPath = "wt.exe";
- task.Description = "Work Terminal";
- task.Title = "Terminal";
- JumpList.SetJumpList(wpfApp, new JumpList(new List { task }, false, false));
-
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- Application.Run();
-
-
- }
- }
-}
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
deleted file mode 100755
index 1b650b3..0000000
--- a/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-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("JumpListTest")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("JumpListTest")]
-[assembly: AssemblyCopyright("Copyright © 2020")]
-[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
-
-// 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/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs
deleted file mode 100755
index f29ecc8..0000000
--- a/Properties/Resources.Designer.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// 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 JumpListTest.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("JumpListTest.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/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/Form1.cs b/Form1.cs
deleted file mode 100755
index 74b2085..0000000
--- a/Form1.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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 JumpListTest
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/JumpListTest.csproj b/JumpListTest.csproj
deleted file mode 100755
index 9ad6f29..0000000
--- a/JumpListTest.csproj
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
- WinExe
- JumpListTest
- JumpListTest
- v4.7.2
- 512
- true
- true
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Form
-
-
- 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/JumpListTest.sln b/JumpListTest.sln
deleted file mode 100755
index ad79cd7..0000000
--- a/JumpListTest.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30114.105
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListTest", "JumpListTest.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
- EndGlobalSection
-EndGlobal
diff --git a/JumpListUtil.sln b/JumpListUtil.sln
new file mode 100755
index 0000000..c91e4de
--- /dev/null
+++ b/JumpListUtil.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
+ EndGlobalSection
+EndGlobal
diff --git a/JumpListUtil/App.config b/JumpListUtil/App.config
new file mode 100755
index 0000000..de2fc4c
--- /dev/null
+++ b/JumpListUtil/App.config
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj
new file mode 100755
index 0000000..5f31de9
--- /dev/null
+++ b/JumpListUtil/JumpListUtil.csproj
@@ -0,0 +1,106 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
+ WinExe
+ JumpListUtil
+ JumpListUtil
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
+
+
+
+
+ ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+
+ ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
+
+
+
+ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\packages\System.Text.Encodings.Web.4.7.1\lib\net461\System.Text.Encodings.Web.dll
+
+
+ ..\packages\System.Text.Json.4.7.2\lib\net461\System.Text.Json.dll
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+
+ ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/Program.cs b/JumpListUtil/Program.cs
new file mode 100755
index 0000000..a13d723
--- /dev/null
+++ b/JumpListUtil/Program.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text.Json;
+using System.Threading;
+using System.Windows.Forms;
+using System.Windows.Shell;
+
+namespace JumpListUtil
+{
+ public class Entry
+ {
+ public string Target { get; set; }
+ public string Icon { get; set; }
+ public int IconIndex { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ }
+ static class Program
+ {
+ [DllImport("shell32.dll", SetLastError = true)]
+ static extern void SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr)] string AppID);
+
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ System.Windows.Application wpfApp = new System.Windows.Application();
+ string thisProgram = Process.GetCurrentProcess().MainModule.FileName;
+
+ // parse all arguments
+ string shortcutsFile = "shortcuts.json";
+ string appUserModelId = "Microsoft.WindowsTerminal_8wekyb3d8bbwe!App";
+ int startIndex = 0;
+ bool onlyRefreshJumpList = false;
+
+ int i = 0;
+ string[] args = Environment.GetCommandLineArgs();
+ bool ParseFlag(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length > 2)
+ {
+ args[i] = "-" + args[i].Substring(2);
+ i--;
+ }
+ return true;
+ }
+ else if (args[i] == "--" + longName)
+ {
+ return true;
+ }
+ return false;
+ }
+ string ParseArg(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length == 2)
+ {
+ i++;
+ return args[i];
+ }
+ else
+ {
+ return args[i].Substring(2);
+ }
+ }
+ else if (args[i].IndexOf("--" + longName + "=") == 0)
+ {
+ return args[i].Substring(longName.Length + 3);
+ }
+ return null;
+ }
+
+ string val = null;
+ for (i = 1; i < args.Length; i++)
+ {
+ if ((val = ParseArg('s', "shortcuts")) != null)
+ {
+ shortcutsFile = val;
+ }
+ else if ((val = ParseArg('i', "startIndex")) != null)
+ {
+ startIndex = int.Parse(val);
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if (ParseFlag('r', "refresh"))
+ {
+ onlyRefreshJumpList = true;
+ }
+ }
+
+ SetCurrentProcessExplicitAppUserModelID(appUserModelId);
+
+ List jumpItems = new List();
+
+ Entry[] entries = null;
+
+ try
+ {
+ string shortcutJson = "";
+ using (FileStream input = File.OpenRead(shortcutsFile))
+ {
+ shortcutJson = new StreamReader(input).ReadToEnd();
+ }
+
+
+ entries = (Entry[])JsonSerializer.Deserialize(shortcutJson, typeof(Entry[]), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true, ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true });
+ }
+ catch (Exception e)
+ {
+ MessageBox.Show("Failed to load shortcut entries: " + e);
+ }
+
+ if (entries != null)
+ {
+ foreach (Entry entry in entries)
+ {
+ JumpTask task = new JumpTask();
+ task.ApplicationPath = entry.Target;
+ task.Description = entry.Description;
+ task.Title = entry.Name;
+ task.IconResourcePath = entry.Icon;
+ task.IconResourceIndex = entry.IconIndex;
+
+ jumpItems.Add(task);
+ }
+
+ jumpItems.Insert(0, new JumpTask
+ {
+ Title = "Refresh",
+ Description = "Refreshes the Jump List",
+ ApplicationPath = thisProgram,
+ WorkingDirectory = Environment.CurrentDirectory,
+ IconResourcePath = Environment.ExpandEnvironmentVariables("%systemroot%\\system32\\imageres.dll"),
+ IconResourceIndex = 228,
+ Arguments = "-r"
+ });
+
+ JumpList.SetJumpList(wpfApp, new JumpList(jumpItems, false, false));
+
+ if (!onlyRefreshJumpList)
+ {
+ if (startIndex >= 0 && startIndex < entries.Length)
+ {
+ Entry start = entries[startIndex];
+ Process p = Process.Start(new ProcessStartInfo
+ {
+ FileName = start.Target,
+ UseShellExecute = true
+ });
+ }
+ else
+ {
+ MessageBox.Show("Shortcut index " + startIndex + " is outside the range of valid entries (" + entries.Length + " entries)");
+ }
+ }
+ }
+
+ //Application.EnableVisualStyles();
+ //Application.SetCompatibleTextRenderingDefault(false);
+ //Application.Run();
+ }
+ }
+}
diff --git a/JumpListUtil/Properties/AssemblyInfo.cs b/JumpListUtil/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..e929884
--- /dev/null
+++ b/JumpListUtil/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("JumpListUtil")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("JumpListUtil")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
+
+// 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/JumpListUtil/Properties/Resources.Designer.cs b/JumpListUtil/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..ed070d5
--- /dev/null
+++ b/JumpListUtil/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+ using System;
+
+
+ ///
+ /// 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", "16.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 (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("JumpListUtil.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/JumpListUtil/Properties/Resources.resx b/JumpListUtil/Properties/Resources.resx
new file mode 100755
index 0000000..ffecec8
--- /dev/null
+++ b/JumpListUtil/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/JumpListUtil/Properties/Settings.Designer.cs b/JumpListUtil/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..8593114
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.6.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/JumpListUtil/Properties/Settings.settings b/JumpListUtil/Properties/Settings.settings
new file mode 100755
index 0000000..abf36c5
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs
new file mode 100755
index 0000000..6d13f4e
--- /dev/null
+++ b/JumpListUtil/ShellLink.cs
@@ -0,0 +1,486 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using System.Text;
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+/****************************************************************************
+ * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/
+ ***************************************************************************/
+
+namespace ShellLinkPlus
+{
+ // Modified from http://smdn.jp/programming/tips/createlnk/
+ // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects
+ // /Creating_and_Modifying_Shortcuts/article.asp
+ // Partly based on Sending toast notifications from desktop apps sample
+ public class ShellLink : IDisposable
+ {
+ #region Win32 and COM
+
+ // IShellLink Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("000214F9-0000-0000-C000-000000000046")]
+ private interface IShellLinkW
+ {
+ uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile,
+ int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags);
+ uint GetIDList(out IntPtr ppidl);
+ uint SetIDList(IntPtr pidl);
+ uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName,
+ int cchMaxName);
+ uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
+ uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir,
+ int cchMaxPath);
+ uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
+ uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs,
+ int cchMaxPath);
+ uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
+ uint GetHotKey(out ushort pwHotkey);
+ uint SetHotKey(ushort wHotKey);
+ uint GetShowCmd(out int piShowCmd);
+ uint SetShowCmd(int iShowCmd);
+ uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath,
+ int cchIconPath, out int piIcon);
+ uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
+ uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel,
+ uint dwReserved);
+ uint Resolve(IntPtr hwnd, uint fFlags);
+ uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
+ }
+
+ // ShellLink CoClass (ShellLink object)
+ [ComImport,
+ ClassInterface(ClassInterfaceType.None),
+ Guid("00021401-0000-0000-C000-000000000046")]
+ private class CShellLink { }
+
+ // WIN32_FIND_DATAW Structure
+ [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]
+ private struct WIN32_FIND_DATAW
+ {
+ public uint dwFileAttributes;
+ public ComTypes.FILETIME ftCreationTime;
+ public ComTypes.FILETIME ftLastAccessTime;
+ public ComTypes.FILETIME ftLastWriteTime;
+ public uint nFileSizeHigh;
+ public uint nFileSizeLow;
+ public uint dwReserved0;
+ public uint dwReserved1;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
+ public string cFileName;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
+ public string cAlternateFileName;
+ }
+
+ // IPropertyStore Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")]
+ private interface IPropertyStore
+ {
+ uint GetCount([Out] out uint cProps);
+ uint GetAt([In] uint iProp, out PropertyKey pkey);
+ uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv);
+ uint SetValue([In] ref PropertyKey key, [In] PropVariant pv);
+ uint Commit();
+ }
+
+ // PropertyKey Structure
+ // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ private struct PropertyKey
+ {
+ #region Fields
+
+ private Guid formatId; // Unique GUID for property
+ private Int32 propertyId; // Property identifier (PID)
+
+ #endregion
+
+ #region Public Properties
+
+ public Guid FormatId
+ {
+ get
+ {
+ return formatId;
+ }
+ }
+
+ public Int32 PropertyId
+ {
+ get
+ {
+ return propertyId;
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropertyKey(Guid formatId, Int32 propertyId)
+ {
+ this.formatId = formatId;
+ this.propertyId = propertyId;
+ }
+
+ public PropertyKey(string formatId, Int32 propertyId)
+ {
+ this.formatId = new Guid(formatId);
+ this.propertyId = propertyId;
+ }
+
+ #endregion
+ }
+
+ // PropVariant Class (only for string value)
+ // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1
+ // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11
+ // /interop-with-propvariants-in-net.aspx
+ [StructLayout(LayoutKind.Explicit)]
+ private sealed class PropVariant : IDisposable
+ {
+ #region Fields
+
+ [FieldOffset(0)]
+ ushort valueType; // Value type
+
+ // [FieldOffset(2)]
+ // ushort wReserved1; // Reserved field
+ // [FieldOffset(4)]
+ // ushort wReserved2; // Reserved field
+ // [FieldOffset(6)]
+ // ushort wReserved3; // Reserved field
+
+ [FieldOffset(8)]
+ IntPtr ptr; // Value
+
+ #endregion
+
+ #region Public Properties
+
+ // Value type (System.Runtime.InteropServices.VarEnum)
+ public VarEnum VarType
+ {
+ get { return (VarEnum)valueType; }
+ set { valueType = (ushort)value; }
+ }
+
+ // Whether value is empty or null
+ public bool IsNullOrEmpty
+ {
+ get
+ {
+ return (valueType == (ushort)VarEnum.VT_EMPTY ||
+ valueType == (ushort)VarEnum.VT_NULL);
+ }
+ }
+
+ // Value (only for string value)
+ public string Value
+ {
+ get
+ {
+ return Marshal.PtrToStringUni(ptr);
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropVariant()
+ { }
+
+ // Construct with string value
+ public PropVariant(string value)
+ {
+ if (value == null)
+ throw new ArgumentException("Failed to set value.");
+
+ valueType = (ushort)VarEnum.VT_LPWSTR;
+ ptr = Marshal.StringToCoTaskMemUni(value);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~PropVariant()
+ {
+ Dispose();
+ }
+
+ public void Dispose()
+ {
+ PropVariantClear(this);
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+ }
+
+ [DllImport("Ole32.dll", PreserveSig = false)]
+ private extern static void PropVariantClear([In, Out] PropVariant pvar);
+
+ #endregion
+
+ #region Fields
+
+ private IShellLinkW shellLinkW = null;
+
+ // Name = System.AppUserModel.ID
+ // ShellPKey = PKEY_AppUserModel_ID
+ // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3
+ // PropID = 5
+ // Type = String (VT_LPWSTR)
+ private readonly PropertyKey AppUserModelIDKey =
+ new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5);
+
+ private const int MAX_PATH = 260;
+ private const int INFOTIPSIZE = 1024;
+
+ private const int STGM_READ = 0x00000000; // STGM constants
+ private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags
+
+ #endregion
+
+ #region Private Properties (Interfaces)
+
+ private IPersistFile PersistFile
+ {
+ get
+ {
+ IPersistFile PersistFile = shellLinkW as IPersistFile;
+
+ if (PersistFile == null)
+ throw new COMException("Failed to create IPersistFile.");
+ else
+ return PersistFile;
+ }
+ }
+
+ private IPropertyStore PropertyStore
+ {
+ get
+ {
+ IPropertyStore PropertyStore = shellLinkW as IPropertyStore;
+
+ if (PropertyStore == null)
+ throw new COMException("Failed to create IPropertyStore.");
+ else
+ return PropertyStore;
+ }
+ }
+
+ #endregion
+
+ #region Public Properties (Minimal)
+
+ // Path of loaded shortcut file
+ public string ShortcutFile
+ {
+ get
+ {
+ string shortcutFile;
+
+ PersistFile.GetCurFile(out shortcutFile);
+
+ return shortcutFile;
+ }
+ }
+
+ // Path of target file
+ public string TargetPath
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder targetPath = new StringBuilder(MAX_PATH);
+
+ WIN32_FIND_DATAW data = new WIN32_FIND_DATAW();
+
+ VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data,
+ SLGP_UNCPRIORITY));
+
+ return targetPath.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetPath(value));
+ }
+ }
+
+ public string Arguments
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder arguments = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity));
+
+ return arguments.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetArguments(value));
+ }
+ }
+
+ public string Description
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder description = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity));
+
+ return description.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetDescription(value));
+ }
+ }
+
+ public Tuple IconLocation
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder icon = new StringBuilder(INFOTIPSIZE);
+
+ int index;
+ VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index));
+
+ return new Tuple(icon.ToString(), index);
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2));
+ }
+ }
+
+ // AppUserModelID to be used for Windows 7 or later.
+ public string AppUserModelID
+ {
+ get
+ {
+ using (PropVariant pv = new PropVariant())
+ {
+ VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv));
+
+ if (pv.Value == null)
+ return "Null";
+ else
+ return pv.Value;
+ }
+ }
+ set
+ {
+ using (PropVariant pv = new PropVariant(value))
+ {
+ VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv));
+ VerifySucceeded(PropertyStore.Commit());
+ }
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public ShellLink()
+ : this(null)
+ { }
+
+ // Construct with loading shortcut file.
+ public ShellLink(string file)
+ {
+ try
+ {
+ shellLinkW = (IShellLinkW)new CShellLink();
+ }
+ catch
+ {
+ throw new COMException("Failed to create ShellLink object.");
+ }
+
+ if (file != null)
+ Load(file);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~ShellLink()
+ {
+ Dispose(false);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (shellLinkW != null)
+ {
+ // Release all references.
+ Marshal.FinalReleaseComObject(shellLinkW);
+ shellLinkW = null;
+ }
+ }
+
+ #endregion
+
+ #region Methods
+
+ // Save shortcut file.
+ public void Save()
+ {
+ string file = ShortcutFile;
+
+ if (file == null)
+ throw new InvalidOperationException("File name is not given.");
+ else
+ Save(file);
+ }
+
+ public void Save(string file)
+ {
+ if (file == null)
+ throw new ArgumentNullException("File name is required.");
+ else
+ PersistFile.Save(file, true);
+ }
+
+ // Load shortcut file.
+ public void Load(string file)
+ {
+ if (!File.Exists(file))
+ throw new FileNotFoundException("File is not found.", file);
+ else
+ PersistFile.Load(file, STGM_READ);
+ }
+
+ // Verify if operation succeeded.
+ public static void VerifySucceeded(uint hresult)
+ {
+ if (hresult > 1)
+ throw new InvalidOperationException("Failed with HRESULT: " +
+ hresult.ToString("X"));
+ }
+
+ #endregion
+ }
+}
diff --git a/JumpListUtil/packages.config b/JumpListUtil/packages.config
new file mode 100755
index 0000000..abb0b89
--- /dev/null
+++ b/JumpListUtil/packages.config
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Program.cs b/Program.cs
deleted file mode 100755
index 17420a8..0000000
--- a/Program.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-using System.Windows.Shell;
-
-namespace JumpListTest
-{
- static class Program
- {
- ///
- /// The main entry point for the application.
- ///
- [STAThread]
- static void Main()
- {
- System.Windows.Application wpfApp = new System.Windows.Application();
- JumpTask task = new JumpTask();
- task.ApplicationPath = "wt.exe";
- task.Description = "Work Terminal";
- task.Title = "Terminal";
- JumpList.SetJumpList(wpfApp, new JumpList(new List { task }, false, false));
-
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- Application.Run();
-
-
- }
- }
-}
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
deleted file mode 100755
index 1b650b3..0000000
--- a/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-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("JumpListTest")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("JumpListTest")]
-[assembly: AssemblyCopyright("Copyright © 2020")]
-[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
-
-// 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/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs
deleted file mode 100755
index f29ecc8..0000000
--- a/Properties/Resources.Designer.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// 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 JumpListTest.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("JumpListTest.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/Properties/Resources.resx b/Properties/Resources.resx
deleted file mode 100755
index ffecec8..0000000
--- a/Properties/Resources.resx
+++ /dev/null
@@ -1,117 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 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/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/Form1.cs b/Form1.cs
deleted file mode 100755
index 74b2085..0000000
--- a/Form1.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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 JumpListTest
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/JumpListTest.csproj b/JumpListTest.csproj
deleted file mode 100755
index 9ad6f29..0000000
--- a/JumpListTest.csproj
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
- WinExe
- JumpListTest
- JumpListTest
- v4.7.2
- 512
- true
- true
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Form
-
-
- 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/JumpListTest.sln b/JumpListTest.sln
deleted file mode 100755
index ad79cd7..0000000
--- a/JumpListTest.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30114.105
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListTest", "JumpListTest.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
- EndGlobalSection
-EndGlobal
diff --git a/JumpListUtil.sln b/JumpListUtil.sln
new file mode 100755
index 0000000..c91e4de
--- /dev/null
+++ b/JumpListUtil.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
+ EndGlobalSection
+EndGlobal
diff --git a/JumpListUtil/App.config b/JumpListUtil/App.config
new file mode 100755
index 0000000..de2fc4c
--- /dev/null
+++ b/JumpListUtil/App.config
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj
new file mode 100755
index 0000000..5f31de9
--- /dev/null
+++ b/JumpListUtil/JumpListUtil.csproj
@@ -0,0 +1,106 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
+ WinExe
+ JumpListUtil
+ JumpListUtil
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
+
+
+
+
+ ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+
+ ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
+
+
+
+ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\packages\System.Text.Encodings.Web.4.7.1\lib\net461\System.Text.Encodings.Web.dll
+
+
+ ..\packages\System.Text.Json.4.7.2\lib\net461\System.Text.Json.dll
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+
+ ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/Program.cs b/JumpListUtil/Program.cs
new file mode 100755
index 0000000..a13d723
--- /dev/null
+++ b/JumpListUtil/Program.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text.Json;
+using System.Threading;
+using System.Windows.Forms;
+using System.Windows.Shell;
+
+namespace JumpListUtil
+{
+ public class Entry
+ {
+ public string Target { get; set; }
+ public string Icon { get; set; }
+ public int IconIndex { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ }
+ static class Program
+ {
+ [DllImport("shell32.dll", SetLastError = true)]
+ static extern void SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr)] string AppID);
+
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ System.Windows.Application wpfApp = new System.Windows.Application();
+ string thisProgram = Process.GetCurrentProcess().MainModule.FileName;
+
+ // parse all arguments
+ string shortcutsFile = "shortcuts.json";
+ string appUserModelId = "Microsoft.WindowsTerminal_8wekyb3d8bbwe!App";
+ int startIndex = 0;
+ bool onlyRefreshJumpList = false;
+
+ int i = 0;
+ string[] args = Environment.GetCommandLineArgs();
+ bool ParseFlag(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length > 2)
+ {
+ args[i] = "-" + args[i].Substring(2);
+ i--;
+ }
+ return true;
+ }
+ else if (args[i] == "--" + longName)
+ {
+ return true;
+ }
+ return false;
+ }
+ string ParseArg(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length == 2)
+ {
+ i++;
+ return args[i];
+ }
+ else
+ {
+ return args[i].Substring(2);
+ }
+ }
+ else if (args[i].IndexOf("--" + longName + "=") == 0)
+ {
+ return args[i].Substring(longName.Length + 3);
+ }
+ return null;
+ }
+
+ string val = null;
+ for (i = 1; i < args.Length; i++)
+ {
+ if ((val = ParseArg('s', "shortcuts")) != null)
+ {
+ shortcutsFile = val;
+ }
+ else if ((val = ParseArg('i', "startIndex")) != null)
+ {
+ startIndex = int.Parse(val);
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if (ParseFlag('r', "refresh"))
+ {
+ onlyRefreshJumpList = true;
+ }
+ }
+
+ SetCurrentProcessExplicitAppUserModelID(appUserModelId);
+
+ List jumpItems = new List();
+
+ Entry[] entries = null;
+
+ try
+ {
+ string shortcutJson = "";
+ using (FileStream input = File.OpenRead(shortcutsFile))
+ {
+ shortcutJson = new StreamReader(input).ReadToEnd();
+ }
+
+
+ entries = (Entry[])JsonSerializer.Deserialize(shortcutJson, typeof(Entry[]), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true, ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true });
+ }
+ catch (Exception e)
+ {
+ MessageBox.Show("Failed to load shortcut entries: " + e);
+ }
+
+ if (entries != null)
+ {
+ foreach (Entry entry in entries)
+ {
+ JumpTask task = new JumpTask();
+ task.ApplicationPath = entry.Target;
+ task.Description = entry.Description;
+ task.Title = entry.Name;
+ task.IconResourcePath = entry.Icon;
+ task.IconResourceIndex = entry.IconIndex;
+
+ jumpItems.Add(task);
+ }
+
+ jumpItems.Insert(0, new JumpTask
+ {
+ Title = "Refresh",
+ Description = "Refreshes the Jump List",
+ ApplicationPath = thisProgram,
+ WorkingDirectory = Environment.CurrentDirectory,
+ IconResourcePath = Environment.ExpandEnvironmentVariables("%systemroot%\\system32\\imageres.dll"),
+ IconResourceIndex = 228,
+ Arguments = "-r"
+ });
+
+ JumpList.SetJumpList(wpfApp, new JumpList(jumpItems, false, false));
+
+ if (!onlyRefreshJumpList)
+ {
+ if (startIndex >= 0 && startIndex < entries.Length)
+ {
+ Entry start = entries[startIndex];
+ Process p = Process.Start(new ProcessStartInfo
+ {
+ FileName = start.Target,
+ UseShellExecute = true
+ });
+ }
+ else
+ {
+ MessageBox.Show("Shortcut index " + startIndex + " is outside the range of valid entries (" + entries.Length + " entries)");
+ }
+ }
+ }
+
+ //Application.EnableVisualStyles();
+ //Application.SetCompatibleTextRenderingDefault(false);
+ //Application.Run();
+ }
+ }
+}
diff --git a/JumpListUtil/Properties/AssemblyInfo.cs b/JumpListUtil/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..e929884
--- /dev/null
+++ b/JumpListUtil/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("JumpListUtil")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("JumpListUtil")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
+
+// 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/JumpListUtil/Properties/Resources.Designer.cs b/JumpListUtil/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..ed070d5
--- /dev/null
+++ b/JumpListUtil/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+ using System;
+
+
+ ///
+ /// 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", "16.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 (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("JumpListUtil.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/JumpListUtil/Properties/Resources.resx b/JumpListUtil/Properties/Resources.resx
new file mode 100755
index 0000000..ffecec8
--- /dev/null
+++ b/JumpListUtil/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/JumpListUtil/Properties/Settings.Designer.cs b/JumpListUtil/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..8593114
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.6.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/JumpListUtil/Properties/Settings.settings b/JumpListUtil/Properties/Settings.settings
new file mode 100755
index 0000000..abf36c5
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs
new file mode 100755
index 0000000..6d13f4e
--- /dev/null
+++ b/JumpListUtil/ShellLink.cs
@@ -0,0 +1,486 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using System.Text;
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+/****************************************************************************
+ * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/
+ ***************************************************************************/
+
+namespace ShellLinkPlus
+{
+ // Modified from http://smdn.jp/programming/tips/createlnk/
+ // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects
+ // /Creating_and_Modifying_Shortcuts/article.asp
+ // Partly based on Sending toast notifications from desktop apps sample
+ public class ShellLink : IDisposable
+ {
+ #region Win32 and COM
+
+ // IShellLink Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("000214F9-0000-0000-C000-000000000046")]
+ private interface IShellLinkW
+ {
+ uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile,
+ int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags);
+ uint GetIDList(out IntPtr ppidl);
+ uint SetIDList(IntPtr pidl);
+ uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName,
+ int cchMaxName);
+ uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
+ uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir,
+ int cchMaxPath);
+ uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
+ uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs,
+ int cchMaxPath);
+ uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
+ uint GetHotKey(out ushort pwHotkey);
+ uint SetHotKey(ushort wHotKey);
+ uint GetShowCmd(out int piShowCmd);
+ uint SetShowCmd(int iShowCmd);
+ uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath,
+ int cchIconPath, out int piIcon);
+ uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
+ uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel,
+ uint dwReserved);
+ uint Resolve(IntPtr hwnd, uint fFlags);
+ uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
+ }
+
+ // ShellLink CoClass (ShellLink object)
+ [ComImport,
+ ClassInterface(ClassInterfaceType.None),
+ Guid("00021401-0000-0000-C000-000000000046")]
+ private class CShellLink { }
+
+ // WIN32_FIND_DATAW Structure
+ [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]
+ private struct WIN32_FIND_DATAW
+ {
+ public uint dwFileAttributes;
+ public ComTypes.FILETIME ftCreationTime;
+ public ComTypes.FILETIME ftLastAccessTime;
+ public ComTypes.FILETIME ftLastWriteTime;
+ public uint nFileSizeHigh;
+ public uint nFileSizeLow;
+ public uint dwReserved0;
+ public uint dwReserved1;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
+ public string cFileName;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
+ public string cAlternateFileName;
+ }
+
+ // IPropertyStore Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")]
+ private interface IPropertyStore
+ {
+ uint GetCount([Out] out uint cProps);
+ uint GetAt([In] uint iProp, out PropertyKey pkey);
+ uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv);
+ uint SetValue([In] ref PropertyKey key, [In] PropVariant pv);
+ uint Commit();
+ }
+
+ // PropertyKey Structure
+ // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ private struct PropertyKey
+ {
+ #region Fields
+
+ private Guid formatId; // Unique GUID for property
+ private Int32 propertyId; // Property identifier (PID)
+
+ #endregion
+
+ #region Public Properties
+
+ public Guid FormatId
+ {
+ get
+ {
+ return formatId;
+ }
+ }
+
+ public Int32 PropertyId
+ {
+ get
+ {
+ return propertyId;
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropertyKey(Guid formatId, Int32 propertyId)
+ {
+ this.formatId = formatId;
+ this.propertyId = propertyId;
+ }
+
+ public PropertyKey(string formatId, Int32 propertyId)
+ {
+ this.formatId = new Guid(formatId);
+ this.propertyId = propertyId;
+ }
+
+ #endregion
+ }
+
+ // PropVariant Class (only for string value)
+ // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1
+ // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11
+ // /interop-with-propvariants-in-net.aspx
+ [StructLayout(LayoutKind.Explicit)]
+ private sealed class PropVariant : IDisposable
+ {
+ #region Fields
+
+ [FieldOffset(0)]
+ ushort valueType; // Value type
+
+ // [FieldOffset(2)]
+ // ushort wReserved1; // Reserved field
+ // [FieldOffset(4)]
+ // ushort wReserved2; // Reserved field
+ // [FieldOffset(6)]
+ // ushort wReserved3; // Reserved field
+
+ [FieldOffset(8)]
+ IntPtr ptr; // Value
+
+ #endregion
+
+ #region Public Properties
+
+ // Value type (System.Runtime.InteropServices.VarEnum)
+ public VarEnum VarType
+ {
+ get { return (VarEnum)valueType; }
+ set { valueType = (ushort)value; }
+ }
+
+ // Whether value is empty or null
+ public bool IsNullOrEmpty
+ {
+ get
+ {
+ return (valueType == (ushort)VarEnum.VT_EMPTY ||
+ valueType == (ushort)VarEnum.VT_NULL);
+ }
+ }
+
+ // Value (only for string value)
+ public string Value
+ {
+ get
+ {
+ return Marshal.PtrToStringUni(ptr);
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropVariant()
+ { }
+
+ // Construct with string value
+ public PropVariant(string value)
+ {
+ if (value == null)
+ throw new ArgumentException("Failed to set value.");
+
+ valueType = (ushort)VarEnum.VT_LPWSTR;
+ ptr = Marshal.StringToCoTaskMemUni(value);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~PropVariant()
+ {
+ Dispose();
+ }
+
+ public void Dispose()
+ {
+ PropVariantClear(this);
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+ }
+
+ [DllImport("Ole32.dll", PreserveSig = false)]
+ private extern static void PropVariantClear([In, Out] PropVariant pvar);
+
+ #endregion
+
+ #region Fields
+
+ private IShellLinkW shellLinkW = null;
+
+ // Name = System.AppUserModel.ID
+ // ShellPKey = PKEY_AppUserModel_ID
+ // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3
+ // PropID = 5
+ // Type = String (VT_LPWSTR)
+ private readonly PropertyKey AppUserModelIDKey =
+ new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5);
+
+ private const int MAX_PATH = 260;
+ private const int INFOTIPSIZE = 1024;
+
+ private const int STGM_READ = 0x00000000; // STGM constants
+ private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags
+
+ #endregion
+
+ #region Private Properties (Interfaces)
+
+ private IPersistFile PersistFile
+ {
+ get
+ {
+ IPersistFile PersistFile = shellLinkW as IPersistFile;
+
+ if (PersistFile == null)
+ throw new COMException("Failed to create IPersistFile.");
+ else
+ return PersistFile;
+ }
+ }
+
+ private IPropertyStore PropertyStore
+ {
+ get
+ {
+ IPropertyStore PropertyStore = shellLinkW as IPropertyStore;
+
+ if (PropertyStore == null)
+ throw new COMException("Failed to create IPropertyStore.");
+ else
+ return PropertyStore;
+ }
+ }
+
+ #endregion
+
+ #region Public Properties (Minimal)
+
+ // Path of loaded shortcut file
+ public string ShortcutFile
+ {
+ get
+ {
+ string shortcutFile;
+
+ PersistFile.GetCurFile(out shortcutFile);
+
+ return shortcutFile;
+ }
+ }
+
+ // Path of target file
+ public string TargetPath
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder targetPath = new StringBuilder(MAX_PATH);
+
+ WIN32_FIND_DATAW data = new WIN32_FIND_DATAW();
+
+ VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data,
+ SLGP_UNCPRIORITY));
+
+ return targetPath.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetPath(value));
+ }
+ }
+
+ public string Arguments
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder arguments = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity));
+
+ return arguments.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetArguments(value));
+ }
+ }
+
+ public string Description
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder description = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity));
+
+ return description.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetDescription(value));
+ }
+ }
+
+ public Tuple IconLocation
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder icon = new StringBuilder(INFOTIPSIZE);
+
+ int index;
+ VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index));
+
+ return new Tuple(icon.ToString(), index);
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2));
+ }
+ }
+
+ // AppUserModelID to be used for Windows 7 or later.
+ public string AppUserModelID
+ {
+ get
+ {
+ using (PropVariant pv = new PropVariant())
+ {
+ VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv));
+
+ if (pv.Value == null)
+ return "Null";
+ else
+ return pv.Value;
+ }
+ }
+ set
+ {
+ using (PropVariant pv = new PropVariant(value))
+ {
+ VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv));
+ VerifySucceeded(PropertyStore.Commit());
+ }
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public ShellLink()
+ : this(null)
+ { }
+
+ // Construct with loading shortcut file.
+ public ShellLink(string file)
+ {
+ try
+ {
+ shellLinkW = (IShellLinkW)new CShellLink();
+ }
+ catch
+ {
+ throw new COMException("Failed to create ShellLink object.");
+ }
+
+ if (file != null)
+ Load(file);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~ShellLink()
+ {
+ Dispose(false);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (shellLinkW != null)
+ {
+ // Release all references.
+ Marshal.FinalReleaseComObject(shellLinkW);
+ shellLinkW = null;
+ }
+ }
+
+ #endregion
+
+ #region Methods
+
+ // Save shortcut file.
+ public void Save()
+ {
+ string file = ShortcutFile;
+
+ if (file == null)
+ throw new InvalidOperationException("File name is not given.");
+ else
+ Save(file);
+ }
+
+ public void Save(string file)
+ {
+ if (file == null)
+ throw new ArgumentNullException("File name is required.");
+ else
+ PersistFile.Save(file, true);
+ }
+
+ // Load shortcut file.
+ public void Load(string file)
+ {
+ if (!File.Exists(file))
+ throw new FileNotFoundException("File is not found.", file);
+ else
+ PersistFile.Load(file, STGM_READ);
+ }
+
+ // Verify if operation succeeded.
+ public static void VerifySucceeded(uint hresult)
+ {
+ if (hresult > 1)
+ throw new InvalidOperationException("Failed with HRESULT: " +
+ hresult.ToString("X"));
+ }
+
+ #endregion
+ }
+}
diff --git a/JumpListUtil/packages.config b/JumpListUtil/packages.config
new file mode 100755
index 0000000..abb0b89
--- /dev/null
+++ b/JumpListUtil/packages.config
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Program.cs b/Program.cs
deleted file mode 100755
index 17420a8..0000000
--- a/Program.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-using System.Windows.Shell;
-
-namespace JumpListTest
-{
- static class Program
- {
- ///
- /// The main entry point for the application.
- ///
- [STAThread]
- static void Main()
- {
- System.Windows.Application wpfApp = new System.Windows.Application();
- JumpTask task = new JumpTask();
- task.ApplicationPath = "wt.exe";
- task.Description = "Work Terminal";
- task.Title = "Terminal";
- JumpList.SetJumpList(wpfApp, new JumpList(new List { task }, false, false));
-
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- Application.Run();
-
-
- }
- }
-}
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
deleted file mode 100755
index 1b650b3..0000000
--- a/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-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("JumpListTest")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("JumpListTest")]
-[assembly: AssemblyCopyright("Copyright © 2020")]
-[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
-
-// 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/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs
deleted file mode 100755
index f29ecc8..0000000
--- a/Properties/Resources.Designer.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// 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 JumpListTest.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("JumpListTest.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/Properties/Resources.resx b/Properties/Resources.resx
deleted file mode 100755
index ffecec8..0000000
--- a/Properties/Resources.resx
+++ /dev/null
@@ -1,117 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 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/Properties/Settings.Designer.cs b/Properties/Settings.Designer.cs
deleted file mode 100755
index fa4d9ff..0000000
--- a/Properties/Settings.Designer.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// 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 JumpListTest.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/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/Form1.cs b/Form1.cs
deleted file mode 100755
index 74b2085..0000000
--- a/Form1.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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 JumpListTest
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/JumpListTest.csproj b/JumpListTest.csproj
deleted file mode 100755
index 9ad6f29..0000000
--- a/JumpListTest.csproj
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
- WinExe
- JumpListTest
- JumpListTest
- v4.7.2
- 512
- true
- true
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Form
-
-
- 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/JumpListTest.sln b/JumpListTest.sln
deleted file mode 100755
index ad79cd7..0000000
--- a/JumpListTest.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30114.105
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListTest", "JumpListTest.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
- EndGlobalSection
-EndGlobal
diff --git a/JumpListUtil.sln b/JumpListUtil.sln
new file mode 100755
index 0000000..c91e4de
--- /dev/null
+++ b/JumpListUtil.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
+ EndGlobalSection
+EndGlobal
diff --git a/JumpListUtil/App.config b/JumpListUtil/App.config
new file mode 100755
index 0000000..de2fc4c
--- /dev/null
+++ b/JumpListUtil/App.config
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj
new file mode 100755
index 0000000..5f31de9
--- /dev/null
+++ b/JumpListUtil/JumpListUtil.csproj
@@ -0,0 +1,106 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
+ WinExe
+ JumpListUtil
+ JumpListUtil
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
+
+
+
+
+ ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+
+ ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
+
+
+
+ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\packages\System.Text.Encodings.Web.4.7.1\lib\net461\System.Text.Encodings.Web.dll
+
+
+ ..\packages\System.Text.Json.4.7.2\lib\net461\System.Text.Json.dll
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+
+ ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/Program.cs b/JumpListUtil/Program.cs
new file mode 100755
index 0000000..a13d723
--- /dev/null
+++ b/JumpListUtil/Program.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text.Json;
+using System.Threading;
+using System.Windows.Forms;
+using System.Windows.Shell;
+
+namespace JumpListUtil
+{
+ public class Entry
+ {
+ public string Target { get; set; }
+ public string Icon { get; set; }
+ public int IconIndex { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ }
+ static class Program
+ {
+ [DllImport("shell32.dll", SetLastError = true)]
+ static extern void SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr)] string AppID);
+
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ System.Windows.Application wpfApp = new System.Windows.Application();
+ string thisProgram = Process.GetCurrentProcess().MainModule.FileName;
+
+ // parse all arguments
+ string shortcutsFile = "shortcuts.json";
+ string appUserModelId = "Microsoft.WindowsTerminal_8wekyb3d8bbwe!App";
+ int startIndex = 0;
+ bool onlyRefreshJumpList = false;
+
+ int i = 0;
+ string[] args = Environment.GetCommandLineArgs();
+ bool ParseFlag(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length > 2)
+ {
+ args[i] = "-" + args[i].Substring(2);
+ i--;
+ }
+ return true;
+ }
+ else if (args[i] == "--" + longName)
+ {
+ return true;
+ }
+ return false;
+ }
+ string ParseArg(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length == 2)
+ {
+ i++;
+ return args[i];
+ }
+ else
+ {
+ return args[i].Substring(2);
+ }
+ }
+ else if (args[i].IndexOf("--" + longName + "=") == 0)
+ {
+ return args[i].Substring(longName.Length + 3);
+ }
+ return null;
+ }
+
+ string val = null;
+ for (i = 1; i < args.Length; i++)
+ {
+ if ((val = ParseArg('s', "shortcuts")) != null)
+ {
+ shortcutsFile = val;
+ }
+ else if ((val = ParseArg('i', "startIndex")) != null)
+ {
+ startIndex = int.Parse(val);
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if (ParseFlag('r', "refresh"))
+ {
+ onlyRefreshJumpList = true;
+ }
+ }
+
+ SetCurrentProcessExplicitAppUserModelID(appUserModelId);
+
+ List jumpItems = new List();
+
+ Entry[] entries = null;
+
+ try
+ {
+ string shortcutJson = "";
+ using (FileStream input = File.OpenRead(shortcutsFile))
+ {
+ shortcutJson = new StreamReader(input).ReadToEnd();
+ }
+
+
+ entries = (Entry[])JsonSerializer.Deserialize(shortcutJson, typeof(Entry[]), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true, ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true });
+ }
+ catch (Exception e)
+ {
+ MessageBox.Show("Failed to load shortcut entries: " + e);
+ }
+
+ if (entries != null)
+ {
+ foreach (Entry entry in entries)
+ {
+ JumpTask task = new JumpTask();
+ task.ApplicationPath = entry.Target;
+ task.Description = entry.Description;
+ task.Title = entry.Name;
+ task.IconResourcePath = entry.Icon;
+ task.IconResourceIndex = entry.IconIndex;
+
+ jumpItems.Add(task);
+ }
+
+ jumpItems.Insert(0, new JumpTask
+ {
+ Title = "Refresh",
+ Description = "Refreshes the Jump List",
+ ApplicationPath = thisProgram,
+ WorkingDirectory = Environment.CurrentDirectory,
+ IconResourcePath = Environment.ExpandEnvironmentVariables("%systemroot%\\system32\\imageres.dll"),
+ IconResourceIndex = 228,
+ Arguments = "-r"
+ });
+
+ JumpList.SetJumpList(wpfApp, new JumpList(jumpItems, false, false));
+
+ if (!onlyRefreshJumpList)
+ {
+ if (startIndex >= 0 && startIndex < entries.Length)
+ {
+ Entry start = entries[startIndex];
+ Process p = Process.Start(new ProcessStartInfo
+ {
+ FileName = start.Target,
+ UseShellExecute = true
+ });
+ }
+ else
+ {
+ MessageBox.Show("Shortcut index " + startIndex + " is outside the range of valid entries (" + entries.Length + " entries)");
+ }
+ }
+ }
+
+ //Application.EnableVisualStyles();
+ //Application.SetCompatibleTextRenderingDefault(false);
+ //Application.Run();
+ }
+ }
+}
diff --git a/JumpListUtil/Properties/AssemblyInfo.cs b/JumpListUtil/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..e929884
--- /dev/null
+++ b/JumpListUtil/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("JumpListUtil")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("JumpListUtil")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
+
+// 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/JumpListUtil/Properties/Resources.Designer.cs b/JumpListUtil/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..ed070d5
--- /dev/null
+++ b/JumpListUtil/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+ using System;
+
+
+ ///
+ /// 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", "16.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 (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("JumpListUtil.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/JumpListUtil/Properties/Resources.resx b/JumpListUtil/Properties/Resources.resx
new file mode 100755
index 0000000..ffecec8
--- /dev/null
+++ b/JumpListUtil/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/JumpListUtil/Properties/Settings.Designer.cs b/JumpListUtil/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..8593114
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.6.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/JumpListUtil/Properties/Settings.settings b/JumpListUtil/Properties/Settings.settings
new file mode 100755
index 0000000..abf36c5
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs
new file mode 100755
index 0000000..6d13f4e
--- /dev/null
+++ b/JumpListUtil/ShellLink.cs
@@ -0,0 +1,486 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using System.Text;
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+/****************************************************************************
+ * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/
+ ***************************************************************************/
+
+namespace ShellLinkPlus
+{
+ // Modified from http://smdn.jp/programming/tips/createlnk/
+ // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects
+ // /Creating_and_Modifying_Shortcuts/article.asp
+ // Partly based on Sending toast notifications from desktop apps sample
+ public class ShellLink : IDisposable
+ {
+ #region Win32 and COM
+
+ // IShellLink Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("000214F9-0000-0000-C000-000000000046")]
+ private interface IShellLinkW
+ {
+ uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile,
+ int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags);
+ uint GetIDList(out IntPtr ppidl);
+ uint SetIDList(IntPtr pidl);
+ uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName,
+ int cchMaxName);
+ uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
+ uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir,
+ int cchMaxPath);
+ uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
+ uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs,
+ int cchMaxPath);
+ uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
+ uint GetHotKey(out ushort pwHotkey);
+ uint SetHotKey(ushort wHotKey);
+ uint GetShowCmd(out int piShowCmd);
+ uint SetShowCmd(int iShowCmd);
+ uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath,
+ int cchIconPath, out int piIcon);
+ uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
+ uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel,
+ uint dwReserved);
+ uint Resolve(IntPtr hwnd, uint fFlags);
+ uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
+ }
+
+ // ShellLink CoClass (ShellLink object)
+ [ComImport,
+ ClassInterface(ClassInterfaceType.None),
+ Guid("00021401-0000-0000-C000-000000000046")]
+ private class CShellLink { }
+
+ // WIN32_FIND_DATAW Structure
+ [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]
+ private struct WIN32_FIND_DATAW
+ {
+ public uint dwFileAttributes;
+ public ComTypes.FILETIME ftCreationTime;
+ public ComTypes.FILETIME ftLastAccessTime;
+ public ComTypes.FILETIME ftLastWriteTime;
+ public uint nFileSizeHigh;
+ public uint nFileSizeLow;
+ public uint dwReserved0;
+ public uint dwReserved1;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
+ public string cFileName;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
+ public string cAlternateFileName;
+ }
+
+ // IPropertyStore Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")]
+ private interface IPropertyStore
+ {
+ uint GetCount([Out] out uint cProps);
+ uint GetAt([In] uint iProp, out PropertyKey pkey);
+ uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv);
+ uint SetValue([In] ref PropertyKey key, [In] PropVariant pv);
+ uint Commit();
+ }
+
+ // PropertyKey Structure
+ // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ private struct PropertyKey
+ {
+ #region Fields
+
+ private Guid formatId; // Unique GUID for property
+ private Int32 propertyId; // Property identifier (PID)
+
+ #endregion
+
+ #region Public Properties
+
+ public Guid FormatId
+ {
+ get
+ {
+ return formatId;
+ }
+ }
+
+ public Int32 PropertyId
+ {
+ get
+ {
+ return propertyId;
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropertyKey(Guid formatId, Int32 propertyId)
+ {
+ this.formatId = formatId;
+ this.propertyId = propertyId;
+ }
+
+ public PropertyKey(string formatId, Int32 propertyId)
+ {
+ this.formatId = new Guid(formatId);
+ this.propertyId = propertyId;
+ }
+
+ #endregion
+ }
+
+ // PropVariant Class (only for string value)
+ // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1
+ // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11
+ // /interop-with-propvariants-in-net.aspx
+ [StructLayout(LayoutKind.Explicit)]
+ private sealed class PropVariant : IDisposable
+ {
+ #region Fields
+
+ [FieldOffset(0)]
+ ushort valueType; // Value type
+
+ // [FieldOffset(2)]
+ // ushort wReserved1; // Reserved field
+ // [FieldOffset(4)]
+ // ushort wReserved2; // Reserved field
+ // [FieldOffset(6)]
+ // ushort wReserved3; // Reserved field
+
+ [FieldOffset(8)]
+ IntPtr ptr; // Value
+
+ #endregion
+
+ #region Public Properties
+
+ // Value type (System.Runtime.InteropServices.VarEnum)
+ public VarEnum VarType
+ {
+ get { return (VarEnum)valueType; }
+ set { valueType = (ushort)value; }
+ }
+
+ // Whether value is empty or null
+ public bool IsNullOrEmpty
+ {
+ get
+ {
+ return (valueType == (ushort)VarEnum.VT_EMPTY ||
+ valueType == (ushort)VarEnum.VT_NULL);
+ }
+ }
+
+ // Value (only for string value)
+ public string Value
+ {
+ get
+ {
+ return Marshal.PtrToStringUni(ptr);
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropVariant()
+ { }
+
+ // Construct with string value
+ public PropVariant(string value)
+ {
+ if (value == null)
+ throw new ArgumentException("Failed to set value.");
+
+ valueType = (ushort)VarEnum.VT_LPWSTR;
+ ptr = Marshal.StringToCoTaskMemUni(value);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~PropVariant()
+ {
+ Dispose();
+ }
+
+ public void Dispose()
+ {
+ PropVariantClear(this);
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+ }
+
+ [DllImport("Ole32.dll", PreserveSig = false)]
+ private extern static void PropVariantClear([In, Out] PropVariant pvar);
+
+ #endregion
+
+ #region Fields
+
+ private IShellLinkW shellLinkW = null;
+
+ // Name = System.AppUserModel.ID
+ // ShellPKey = PKEY_AppUserModel_ID
+ // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3
+ // PropID = 5
+ // Type = String (VT_LPWSTR)
+ private readonly PropertyKey AppUserModelIDKey =
+ new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5);
+
+ private const int MAX_PATH = 260;
+ private const int INFOTIPSIZE = 1024;
+
+ private const int STGM_READ = 0x00000000; // STGM constants
+ private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags
+
+ #endregion
+
+ #region Private Properties (Interfaces)
+
+ private IPersistFile PersistFile
+ {
+ get
+ {
+ IPersistFile PersistFile = shellLinkW as IPersistFile;
+
+ if (PersistFile == null)
+ throw new COMException("Failed to create IPersistFile.");
+ else
+ return PersistFile;
+ }
+ }
+
+ private IPropertyStore PropertyStore
+ {
+ get
+ {
+ IPropertyStore PropertyStore = shellLinkW as IPropertyStore;
+
+ if (PropertyStore == null)
+ throw new COMException("Failed to create IPropertyStore.");
+ else
+ return PropertyStore;
+ }
+ }
+
+ #endregion
+
+ #region Public Properties (Minimal)
+
+ // Path of loaded shortcut file
+ public string ShortcutFile
+ {
+ get
+ {
+ string shortcutFile;
+
+ PersistFile.GetCurFile(out shortcutFile);
+
+ return shortcutFile;
+ }
+ }
+
+ // Path of target file
+ public string TargetPath
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder targetPath = new StringBuilder(MAX_PATH);
+
+ WIN32_FIND_DATAW data = new WIN32_FIND_DATAW();
+
+ VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data,
+ SLGP_UNCPRIORITY));
+
+ return targetPath.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetPath(value));
+ }
+ }
+
+ public string Arguments
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder arguments = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity));
+
+ return arguments.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetArguments(value));
+ }
+ }
+
+ public string Description
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder description = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity));
+
+ return description.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetDescription(value));
+ }
+ }
+
+ public Tuple IconLocation
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder icon = new StringBuilder(INFOTIPSIZE);
+
+ int index;
+ VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index));
+
+ return new Tuple(icon.ToString(), index);
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2));
+ }
+ }
+
+ // AppUserModelID to be used for Windows 7 or later.
+ public string AppUserModelID
+ {
+ get
+ {
+ using (PropVariant pv = new PropVariant())
+ {
+ VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv));
+
+ if (pv.Value == null)
+ return "Null";
+ else
+ return pv.Value;
+ }
+ }
+ set
+ {
+ using (PropVariant pv = new PropVariant(value))
+ {
+ VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv));
+ VerifySucceeded(PropertyStore.Commit());
+ }
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public ShellLink()
+ : this(null)
+ { }
+
+ // Construct with loading shortcut file.
+ public ShellLink(string file)
+ {
+ try
+ {
+ shellLinkW = (IShellLinkW)new CShellLink();
+ }
+ catch
+ {
+ throw new COMException("Failed to create ShellLink object.");
+ }
+
+ if (file != null)
+ Load(file);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~ShellLink()
+ {
+ Dispose(false);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (shellLinkW != null)
+ {
+ // Release all references.
+ Marshal.FinalReleaseComObject(shellLinkW);
+ shellLinkW = null;
+ }
+ }
+
+ #endregion
+
+ #region Methods
+
+ // Save shortcut file.
+ public void Save()
+ {
+ string file = ShortcutFile;
+
+ if (file == null)
+ throw new InvalidOperationException("File name is not given.");
+ else
+ Save(file);
+ }
+
+ public void Save(string file)
+ {
+ if (file == null)
+ throw new ArgumentNullException("File name is required.");
+ else
+ PersistFile.Save(file, true);
+ }
+
+ // Load shortcut file.
+ public void Load(string file)
+ {
+ if (!File.Exists(file))
+ throw new FileNotFoundException("File is not found.", file);
+ else
+ PersistFile.Load(file, STGM_READ);
+ }
+
+ // Verify if operation succeeded.
+ public static void VerifySucceeded(uint hresult)
+ {
+ if (hresult > 1)
+ throw new InvalidOperationException("Failed with HRESULT: " +
+ hresult.ToString("X"));
+ }
+
+ #endregion
+ }
+}
diff --git a/JumpListUtil/packages.config b/JumpListUtil/packages.config
new file mode 100755
index 0000000..abb0b89
--- /dev/null
+++ b/JumpListUtil/packages.config
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Program.cs b/Program.cs
deleted file mode 100755
index 17420a8..0000000
--- a/Program.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-using System.Windows.Shell;
-
-namespace JumpListTest
-{
- static class Program
- {
- ///
- /// The main entry point for the application.
- ///
- [STAThread]
- static void Main()
- {
- System.Windows.Application wpfApp = new System.Windows.Application();
- JumpTask task = new JumpTask();
- task.ApplicationPath = "wt.exe";
- task.Description = "Work Terminal";
- task.Title = "Terminal";
- JumpList.SetJumpList(wpfApp, new JumpList(new List { task }, false, false));
-
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- Application.Run();
-
-
- }
- }
-}
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
deleted file mode 100755
index 1b650b3..0000000
--- a/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-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("JumpListTest")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("JumpListTest")]
-[assembly: AssemblyCopyright("Copyright © 2020")]
-[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
-
-// 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/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs
deleted file mode 100755
index f29ecc8..0000000
--- a/Properties/Resources.Designer.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// 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 JumpListTest.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("JumpListTest.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/Properties/Resources.resx b/Properties/Resources.resx
deleted file mode 100755
index ffecec8..0000000
--- a/Properties/Resources.resx
+++ /dev/null
@@ -1,117 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 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/Properties/Settings.Designer.cs b/Properties/Settings.Designer.cs
deleted file mode 100755
index fa4d9ff..0000000
--- a/Properties/Settings.Designer.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// 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 JumpListTest.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/Properties/Settings.settings b/Properties/Settings.settings
deleted file mode 100755
index abf36c5..0000000
--- a/Properties/Settings.settings
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
diff --git a/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/Form1.cs b/Form1.cs
deleted file mode 100755
index 74b2085..0000000
--- a/Form1.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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 JumpListTest
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/JumpListTest.csproj b/JumpListTest.csproj
deleted file mode 100755
index 9ad6f29..0000000
--- a/JumpListTest.csproj
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
- WinExe
- JumpListTest
- JumpListTest
- v4.7.2
- 512
- true
- true
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Form
-
-
- 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/JumpListTest.sln b/JumpListTest.sln
deleted file mode 100755
index ad79cd7..0000000
--- a/JumpListTest.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30114.105
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListTest", "JumpListTest.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
- EndGlobalSection
-EndGlobal
diff --git a/JumpListUtil.sln b/JumpListUtil.sln
new file mode 100755
index 0000000..c91e4de
--- /dev/null
+++ b/JumpListUtil.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
+ EndGlobalSection
+EndGlobal
diff --git a/JumpListUtil/App.config b/JumpListUtil/App.config
new file mode 100755
index 0000000..de2fc4c
--- /dev/null
+++ b/JumpListUtil/App.config
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj
new file mode 100755
index 0000000..5f31de9
--- /dev/null
+++ b/JumpListUtil/JumpListUtil.csproj
@@ -0,0 +1,106 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
+ WinExe
+ JumpListUtil
+ JumpListUtil
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
+
+
+
+
+ ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+
+ ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
+
+
+
+ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\packages\System.Text.Encodings.Web.4.7.1\lib\net461\System.Text.Encodings.Web.dll
+
+
+ ..\packages\System.Text.Json.4.7.2\lib\net461\System.Text.Json.dll
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+
+ ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/Program.cs b/JumpListUtil/Program.cs
new file mode 100755
index 0000000..a13d723
--- /dev/null
+++ b/JumpListUtil/Program.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text.Json;
+using System.Threading;
+using System.Windows.Forms;
+using System.Windows.Shell;
+
+namespace JumpListUtil
+{
+ public class Entry
+ {
+ public string Target { get; set; }
+ public string Icon { get; set; }
+ public int IconIndex { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ }
+ static class Program
+ {
+ [DllImport("shell32.dll", SetLastError = true)]
+ static extern void SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr)] string AppID);
+
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ System.Windows.Application wpfApp = new System.Windows.Application();
+ string thisProgram = Process.GetCurrentProcess().MainModule.FileName;
+
+ // parse all arguments
+ string shortcutsFile = "shortcuts.json";
+ string appUserModelId = "Microsoft.WindowsTerminal_8wekyb3d8bbwe!App";
+ int startIndex = 0;
+ bool onlyRefreshJumpList = false;
+
+ int i = 0;
+ string[] args = Environment.GetCommandLineArgs();
+ bool ParseFlag(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length > 2)
+ {
+ args[i] = "-" + args[i].Substring(2);
+ i--;
+ }
+ return true;
+ }
+ else if (args[i] == "--" + longName)
+ {
+ return true;
+ }
+ return false;
+ }
+ string ParseArg(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length == 2)
+ {
+ i++;
+ return args[i];
+ }
+ else
+ {
+ return args[i].Substring(2);
+ }
+ }
+ else if (args[i].IndexOf("--" + longName + "=") == 0)
+ {
+ return args[i].Substring(longName.Length + 3);
+ }
+ return null;
+ }
+
+ string val = null;
+ for (i = 1; i < args.Length; i++)
+ {
+ if ((val = ParseArg('s', "shortcuts")) != null)
+ {
+ shortcutsFile = val;
+ }
+ else if ((val = ParseArg('i', "startIndex")) != null)
+ {
+ startIndex = int.Parse(val);
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if (ParseFlag('r', "refresh"))
+ {
+ onlyRefreshJumpList = true;
+ }
+ }
+
+ SetCurrentProcessExplicitAppUserModelID(appUserModelId);
+
+ List jumpItems = new List();
+
+ Entry[] entries = null;
+
+ try
+ {
+ string shortcutJson = "";
+ using (FileStream input = File.OpenRead(shortcutsFile))
+ {
+ shortcutJson = new StreamReader(input).ReadToEnd();
+ }
+
+
+ entries = (Entry[])JsonSerializer.Deserialize(shortcutJson, typeof(Entry[]), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true, ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true });
+ }
+ catch (Exception e)
+ {
+ MessageBox.Show("Failed to load shortcut entries: " + e);
+ }
+
+ if (entries != null)
+ {
+ foreach (Entry entry in entries)
+ {
+ JumpTask task = new JumpTask();
+ task.ApplicationPath = entry.Target;
+ task.Description = entry.Description;
+ task.Title = entry.Name;
+ task.IconResourcePath = entry.Icon;
+ task.IconResourceIndex = entry.IconIndex;
+
+ jumpItems.Add(task);
+ }
+
+ jumpItems.Insert(0, new JumpTask
+ {
+ Title = "Refresh",
+ Description = "Refreshes the Jump List",
+ ApplicationPath = thisProgram,
+ WorkingDirectory = Environment.CurrentDirectory,
+ IconResourcePath = Environment.ExpandEnvironmentVariables("%systemroot%\\system32\\imageres.dll"),
+ IconResourceIndex = 228,
+ Arguments = "-r"
+ });
+
+ JumpList.SetJumpList(wpfApp, new JumpList(jumpItems, false, false));
+
+ if (!onlyRefreshJumpList)
+ {
+ if (startIndex >= 0 && startIndex < entries.Length)
+ {
+ Entry start = entries[startIndex];
+ Process p = Process.Start(new ProcessStartInfo
+ {
+ FileName = start.Target,
+ UseShellExecute = true
+ });
+ }
+ else
+ {
+ MessageBox.Show("Shortcut index " + startIndex + " is outside the range of valid entries (" + entries.Length + " entries)");
+ }
+ }
+ }
+
+ //Application.EnableVisualStyles();
+ //Application.SetCompatibleTextRenderingDefault(false);
+ //Application.Run();
+ }
+ }
+}
diff --git a/JumpListUtil/Properties/AssemblyInfo.cs b/JumpListUtil/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..e929884
--- /dev/null
+++ b/JumpListUtil/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("JumpListUtil")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("JumpListUtil")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
+
+// 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/JumpListUtil/Properties/Resources.Designer.cs b/JumpListUtil/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..ed070d5
--- /dev/null
+++ b/JumpListUtil/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+ using System;
+
+
+ ///
+ /// 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", "16.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 (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("JumpListUtil.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/JumpListUtil/Properties/Resources.resx b/JumpListUtil/Properties/Resources.resx
new file mode 100755
index 0000000..ffecec8
--- /dev/null
+++ b/JumpListUtil/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/JumpListUtil/Properties/Settings.Designer.cs b/JumpListUtil/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..8593114
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.6.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/JumpListUtil/Properties/Settings.settings b/JumpListUtil/Properties/Settings.settings
new file mode 100755
index 0000000..abf36c5
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs
new file mode 100755
index 0000000..6d13f4e
--- /dev/null
+++ b/JumpListUtil/ShellLink.cs
@@ -0,0 +1,486 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using System.Text;
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+/****************************************************************************
+ * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/
+ ***************************************************************************/
+
+namespace ShellLinkPlus
+{
+ // Modified from http://smdn.jp/programming/tips/createlnk/
+ // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects
+ // /Creating_and_Modifying_Shortcuts/article.asp
+ // Partly based on Sending toast notifications from desktop apps sample
+ public class ShellLink : IDisposable
+ {
+ #region Win32 and COM
+
+ // IShellLink Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("000214F9-0000-0000-C000-000000000046")]
+ private interface IShellLinkW
+ {
+ uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile,
+ int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags);
+ uint GetIDList(out IntPtr ppidl);
+ uint SetIDList(IntPtr pidl);
+ uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName,
+ int cchMaxName);
+ uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
+ uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir,
+ int cchMaxPath);
+ uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
+ uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs,
+ int cchMaxPath);
+ uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
+ uint GetHotKey(out ushort pwHotkey);
+ uint SetHotKey(ushort wHotKey);
+ uint GetShowCmd(out int piShowCmd);
+ uint SetShowCmd(int iShowCmd);
+ uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath,
+ int cchIconPath, out int piIcon);
+ uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
+ uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel,
+ uint dwReserved);
+ uint Resolve(IntPtr hwnd, uint fFlags);
+ uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
+ }
+
+ // ShellLink CoClass (ShellLink object)
+ [ComImport,
+ ClassInterface(ClassInterfaceType.None),
+ Guid("00021401-0000-0000-C000-000000000046")]
+ private class CShellLink { }
+
+ // WIN32_FIND_DATAW Structure
+ [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]
+ private struct WIN32_FIND_DATAW
+ {
+ public uint dwFileAttributes;
+ public ComTypes.FILETIME ftCreationTime;
+ public ComTypes.FILETIME ftLastAccessTime;
+ public ComTypes.FILETIME ftLastWriteTime;
+ public uint nFileSizeHigh;
+ public uint nFileSizeLow;
+ public uint dwReserved0;
+ public uint dwReserved1;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
+ public string cFileName;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
+ public string cAlternateFileName;
+ }
+
+ // IPropertyStore Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")]
+ private interface IPropertyStore
+ {
+ uint GetCount([Out] out uint cProps);
+ uint GetAt([In] uint iProp, out PropertyKey pkey);
+ uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv);
+ uint SetValue([In] ref PropertyKey key, [In] PropVariant pv);
+ uint Commit();
+ }
+
+ // PropertyKey Structure
+ // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ private struct PropertyKey
+ {
+ #region Fields
+
+ private Guid formatId; // Unique GUID for property
+ private Int32 propertyId; // Property identifier (PID)
+
+ #endregion
+
+ #region Public Properties
+
+ public Guid FormatId
+ {
+ get
+ {
+ return formatId;
+ }
+ }
+
+ public Int32 PropertyId
+ {
+ get
+ {
+ return propertyId;
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropertyKey(Guid formatId, Int32 propertyId)
+ {
+ this.formatId = formatId;
+ this.propertyId = propertyId;
+ }
+
+ public PropertyKey(string formatId, Int32 propertyId)
+ {
+ this.formatId = new Guid(formatId);
+ this.propertyId = propertyId;
+ }
+
+ #endregion
+ }
+
+ // PropVariant Class (only for string value)
+ // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1
+ // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11
+ // /interop-with-propvariants-in-net.aspx
+ [StructLayout(LayoutKind.Explicit)]
+ private sealed class PropVariant : IDisposable
+ {
+ #region Fields
+
+ [FieldOffset(0)]
+ ushort valueType; // Value type
+
+ // [FieldOffset(2)]
+ // ushort wReserved1; // Reserved field
+ // [FieldOffset(4)]
+ // ushort wReserved2; // Reserved field
+ // [FieldOffset(6)]
+ // ushort wReserved3; // Reserved field
+
+ [FieldOffset(8)]
+ IntPtr ptr; // Value
+
+ #endregion
+
+ #region Public Properties
+
+ // Value type (System.Runtime.InteropServices.VarEnum)
+ public VarEnum VarType
+ {
+ get { return (VarEnum)valueType; }
+ set { valueType = (ushort)value; }
+ }
+
+ // Whether value is empty or null
+ public bool IsNullOrEmpty
+ {
+ get
+ {
+ return (valueType == (ushort)VarEnum.VT_EMPTY ||
+ valueType == (ushort)VarEnum.VT_NULL);
+ }
+ }
+
+ // Value (only for string value)
+ public string Value
+ {
+ get
+ {
+ return Marshal.PtrToStringUni(ptr);
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropVariant()
+ { }
+
+ // Construct with string value
+ public PropVariant(string value)
+ {
+ if (value == null)
+ throw new ArgumentException("Failed to set value.");
+
+ valueType = (ushort)VarEnum.VT_LPWSTR;
+ ptr = Marshal.StringToCoTaskMemUni(value);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~PropVariant()
+ {
+ Dispose();
+ }
+
+ public void Dispose()
+ {
+ PropVariantClear(this);
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+ }
+
+ [DllImport("Ole32.dll", PreserveSig = false)]
+ private extern static void PropVariantClear([In, Out] PropVariant pvar);
+
+ #endregion
+
+ #region Fields
+
+ private IShellLinkW shellLinkW = null;
+
+ // Name = System.AppUserModel.ID
+ // ShellPKey = PKEY_AppUserModel_ID
+ // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3
+ // PropID = 5
+ // Type = String (VT_LPWSTR)
+ private readonly PropertyKey AppUserModelIDKey =
+ new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5);
+
+ private const int MAX_PATH = 260;
+ private const int INFOTIPSIZE = 1024;
+
+ private const int STGM_READ = 0x00000000; // STGM constants
+ private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags
+
+ #endregion
+
+ #region Private Properties (Interfaces)
+
+ private IPersistFile PersistFile
+ {
+ get
+ {
+ IPersistFile PersistFile = shellLinkW as IPersistFile;
+
+ if (PersistFile == null)
+ throw new COMException("Failed to create IPersistFile.");
+ else
+ return PersistFile;
+ }
+ }
+
+ private IPropertyStore PropertyStore
+ {
+ get
+ {
+ IPropertyStore PropertyStore = shellLinkW as IPropertyStore;
+
+ if (PropertyStore == null)
+ throw new COMException("Failed to create IPropertyStore.");
+ else
+ return PropertyStore;
+ }
+ }
+
+ #endregion
+
+ #region Public Properties (Minimal)
+
+ // Path of loaded shortcut file
+ public string ShortcutFile
+ {
+ get
+ {
+ string shortcutFile;
+
+ PersistFile.GetCurFile(out shortcutFile);
+
+ return shortcutFile;
+ }
+ }
+
+ // Path of target file
+ public string TargetPath
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder targetPath = new StringBuilder(MAX_PATH);
+
+ WIN32_FIND_DATAW data = new WIN32_FIND_DATAW();
+
+ VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data,
+ SLGP_UNCPRIORITY));
+
+ return targetPath.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetPath(value));
+ }
+ }
+
+ public string Arguments
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder arguments = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity));
+
+ return arguments.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetArguments(value));
+ }
+ }
+
+ public string Description
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder description = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity));
+
+ return description.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetDescription(value));
+ }
+ }
+
+ public Tuple IconLocation
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder icon = new StringBuilder(INFOTIPSIZE);
+
+ int index;
+ VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index));
+
+ return new Tuple(icon.ToString(), index);
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2));
+ }
+ }
+
+ // AppUserModelID to be used for Windows 7 or later.
+ public string AppUserModelID
+ {
+ get
+ {
+ using (PropVariant pv = new PropVariant())
+ {
+ VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv));
+
+ if (pv.Value == null)
+ return "Null";
+ else
+ return pv.Value;
+ }
+ }
+ set
+ {
+ using (PropVariant pv = new PropVariant(value))
+ {
+ VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv));
+ VerifySucceeded(PropertyStore.Commit());
+ }
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public ShellLink()
+ : this(null)
+ { }
+
+ // Construct with loading shortcut file.
+ public ShellLink(string file)
+ {
+ try
+ {
+ shellLinkW = (IShellLinkW)new CShellLink();
+ }
+ catch
+ {
+ throw new COMException("Failed to create ShellLink object.");
+ }
+
+ if (file != null)
+ Load(file);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~ShellLink()
+ {
+ Dispose(false);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (shellLinkW != null)
+ {
+ // Release all references.
+ Marshal.FinalReleaseComObject(shellLinkW);
+ shellLinkW = null;
+ }
+ }
+
+ #endregion
+
+ #region Methods
+
+ // Save shortcut file.
+ public void Save()
+ {
+ string file = ShortcutFile;
+
+ if (file == null)
+ throw new InvalidOperationException("File name is not given.");
+ else
+ Save(file);
+ }
+
+ public void Save(string file)
+ {
+ if (file == null)
+ throw new ArgumentNullException("File name is required.");
+ else
+ PersistFile.Save(file, true);
+ }
+
+ // Load shortcut file.
+ public void Load(string file)
+ {
+ if (!File.Exists(file))
+ throw new FileNotFoundException("File is not found.", file);
+ else
+ PersistFile.Load(file, STGM_READ);
+ }
+
+ // Verify if operation succeeded.
+ public static void VerifySucceeded(uint hresult)
+ {
+ if (hresult > 1)
+ throw new InvalidOperationException("Failed with HRESULT: " +
+ hresult.ToString("X"));
+ }
+
+ #endregion
+ }
+}
diff --git a/JumpListUtil/packages.config b/JumpListUtil/packages.config
new file mode 100755
index 0000000..abb0b89
--- /dev/null
+++ b/JumpListUtil/packages.config
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Program.cs b/Program.cs
deleted file mode 100755
index 17420a8..0000000
--- a/Program.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-using System.Windows.Shell;
-
-namespace JumpListTest
-{
- static class Program
- {
- ///
- /// The main entry point for the application.
- ///
- [STAThread]
- static void Main()
- {
- System.Windows.Application wpfApp = new System.Windows.Application();
- JumpTask task = new JumpTask();
- task.ApplicationPath = "wt.exe";
- task.Description = "Work Terminal";
- task.Title = "Terminal";
- JumpList.SetJumpList(wpfApp, new JumpList(new List { task }, false, false));
-
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- Application.Run();
-
-
- }
- }
-}
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
deleted file mode 100755
index 1b650b3..0000000
--- a/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-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("JumpListTest")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("JumpListTest")]
-[assembly: AssemblyCopyright("Copyright © 2020")]
-[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
-
-// 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/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs
deleted file mode 100755
index f29ecc8..0000000
--- a/Properties/Resources.Designer.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// 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 JumpListTest.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("JumpListTest.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/Properties/Resources.resx b/Properties/Resources.resx
deleted file mode 100755
index ffecec8..0000000
--- a/Properties/Resources.resx
+++ /dev/null
@@ -1,117 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 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/Properties/Settings.Designer.cs b/Properties/Settings.Designer.cs
deleted file mode 100755
index fa4d9ff..0000000
--- a/Properties/Settings.Designer.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// 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 JumpListTest.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/Properties/Settings.settings b/Properties/Settings.settings
deleted file mode 100755
index abf36c5..0000000
--- a/Properties/Settings.settings
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
diff --git a/SetLnkApp/Program.cs b/SetLnkApp/Program.cs
new file mode 100755
index 0000000..08a160a
--- /dev/null
+++ b/SetLnkApp/Program.cs
@@ -0,0 +1,34 @@
+using ShellLinkPlus;
+using System;
+using System.IO;
+using System.Linq;
+
+namespace SetLnkApp
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ bool existing = File.Exists(args[0]);
+ using (ShellLink shortcut = new ShellLink(existing ? args[0] : null))
+ {
+ if (existing)
+ {
+ if (args.Length > 2)
+ {
+ throw new Exception("For an existing shortcut, only pass AppUserModelId");
+ }
+ }
+ else
+ {
+ shortcut.TargetPath = args[2];
+ //shortcut.Arguments = args.Length > 3 ? string.Join(" ", args.Skip(3)) : "";
+ shortcut.Arguments = string.Join(" ", args.Skip(3));
+ }
+ shortcut.AppUserModelID = args[1];
+
+ shortcut.Save(args[0]);
+ }
+ }
+ }
+}
diff --git a/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/Form1.cs b/Form1.cs
deleted file mode 100755
index 74b2085..0000000
--- a/Form1.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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 JumpListTest
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/JumpListTest.csproj b/JumpListTest.csproj
deleted file mode 100755
index 9ad6f29..0000000
--- a/JumpListTest.csproj
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
- WinExe
- JumpListTest
- JumpListTest
- v4.7.2
- 512
- true
- true
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Form
-
-
- 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/JumpListTest.sln b/JumpListTest.sln
deleted file mode 100755
index ad79cd7..0000000
--- a/JumpListTest.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30114.105
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListTest", "JumpListTest.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
- EndGlobalSection
-EndGlobal
diff --git a/JumpListUtil.sln b/JumpListUtil.sln
new file mode 100755
index 0000000..c91e4de
--- /dev/null
+++ b/JumpListUtil.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
+ EndGlobalSection
+EndGlobal
diff --git a/JumpListUtil/App.config b/JumpListUtil/App.config
new file mode 100755
index 0000000..de2fc4c
--- /dev/null
+++ b/JumpListUtil/App.config
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj
new file mode 100755
index 0000000..5f31de9
--- /dev/null
+++ b/JumpListUtil/JumpListUtil.csproj
@@ -0,0 +1,106 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
+ WinExe
+ JumpListUtil
+ JumpListUtil
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
+
+
+
+
+ ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+
+ ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
+
+
+
+ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\packages\System.Text.Encodings.Web.4.7.1\lib\net461\System.Text.Encodings.Web.dll
+
+
+ ..\packages\System.Text.Json.4.7.2\lib\net461\System.Text.Json.dll
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+
+ ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/Program.cs b/JumpListUtil/Program.cs
new file mode 100755
index 0000000..a13d723
--- /dev/null
+++ b/JumpListUtil/Program.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text.Json;
+using System.Threading;
+using System.Windows.Forms;
+using System.Windows.Shell;
+
+namespace JumpListUtil
+{
+ public class Entry
+ {
+ public string Target { get; set; }
+ public string Icon { get; set; }
+ public int IconIndex { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ }
+ static class Program
+ {
+ [DllImport("shell32.dll", SetLastError = true)]
+ static extern void SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr)] string AppID);
+
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ System.Windows.Application wpfApp = new System.Windows.Application();
+ string thisProgram = Process.GetCurrentProcess().MainModule.FileName;
+
+ // parse all arguments
+ string shortcutsFile = "shortcuts.json";
+ string appUserModelId = "Microsoft.WindowsTerminal_8wekyb3d8bbwe!App";
+ int startIndex = 0;
+ bool onlyRefreshJumpList = false;
+
+ int i = 0;
+ string[] args = Environment.GetCommandLineArgs();
+ bool ParseFlag(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length > 2)
+ {
+ args[i] = "-" + args[i].Substring(2);
+ i--;
+ }
+ return true;
+ }
+ else if (args[i] == "--" + longName)
+ {
+ return true;
+ }
+ return false;
+ }
+ string ParseArg(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length == 2)
+ {
+ i++;
+ return args[i];
+ }
+ else
+ {
+ return args[i].Substring(2);
+ }
+ }
+ else if (args[i].IndexOf("--" + longName + "=") == 0)
+ {
+ return args[i].Substring(longName.Length + 3);
+ }
+ return null;
+ }
+
+ string val = null;
+ for (i = 1; i < args.Length; i++)
+ {
+ if ((val = ParseArg('s', "shortcuts")) != null)
+ {
+ shortcutsFile = val;
+ }
+ else if ((val = ParseArg('i', "startIndex")) != null)
+ {
+ startIndex = int.Parse(val);
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if (ParseFlag('r', "refresh"))
+ {
+ onlyRefreshJumpList = true;
+ }
+ }
+
+ SetCurrentProcessExplicitAppUserModelID(appUserModelId);
+
+ List jumpItems = new List();
+
+ Entry[] entries = null;
+
+ try
+ {
+ string shortcutJson = "";
+ using (FileStream input = File.OpenRead(shortcutsFile))
+ {
+ shortcutJson = new StreamReader(input).ReadToEnd();
+ }
+
+
+ entries = (Entry[])JsonSerializer.Deserialize(shortcutJson, typeof(Entry[]), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true, ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true });
+ }
+ catch (Exception e)
+ {
+ MessageBox.Show("Failed to load shortcut entries: " + e);
+ }
+
+ if (entries != null)
+ {
+ foreach (Entry entry in entries)
+ {
+ JumpTask task = new JumpTask();
+ task.ApplicationPath = entry.Target;
+ task.Description = entry.Description;
+ task.Title = entry.Name;
+ task.IconResourcePath = entry.Icon;
+ task.IconResourceIndex = entry.IconIndex;
+
+ jumpItems.Add(task);
+ }
+
+ jumpItems.Insert(0, new JumpTask
+ {
+ Title = "Refresh",
+ Description = "Refreshes the Jump List",
+ ApplicationPath = thisProgram,
+ WorkingDirectory = Environment.CurrentDirectory,
+ IconResourcePath = Environment.ExpandEnvironmentVariables("%systemroot%\\system32\\imageres.dll"),
+ IconResourceIndex = 228,
+ Arguments = "-r"
+ });
+
+ JumpList.SetJumpList(wpfApp, new JumpList(jumpItems, false, false));
+
+ if (!onlyRefreshJumpList)
+ {
+ if (startIndex >= 0 && startIndex < entries.Length)
+ {
+ Entry start = entries[startIndex];
+ Process p = Process.Start(new ProcessStartInfo
+ {
+ FileName = start.Target,
+ UseShellExecute = true
+ });
+ }
+ else
+ {
+ MessageBox.Show("Shortcut index " + startIndex + " is outside the range of valid entries (" + entries.Length + " entries)");
+ }
+ }
+ }
+
+ //Application.EnableVisualStyles();
+ //Application.SetCompatibleTextRenderingDefault(false);
+ //Application.Run();
+ }
+ }
+}
diff --git a/JumpListUtil/Properties/AssemblyInfo.cs b/JumpListUtil/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..e929884
--- /dev/null
+++ b/JumpListUtil/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("JumpListUtil")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("JumpListUtil")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
+
+// 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/JumpListUtil/Properties/Resources.Designer.cs b/JumpListUtil/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..ed070d5
--- /dev/null
+++ b/JumpListUtil/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+ using System;
+
+
+ ///
+ /// 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", "16.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 (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("JumpListUtil.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/JumpListUtil/Properties/Resources.resx b/JumpListUtil/Properties/Resources.resx
new file mode 100755
index 0000000..ffecec8
--- /dev/null
+++ b/JumpListUtil/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/JumpListUtil/Properties/Settings.Designer.cs b/JumpListUtil/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..8593114
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.6.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/JumpListUtil/Properties/Settings.settings b/JumpListUtil/Properties/Settings.settings
new file mode 100755
index 0000000..abf36c5
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs
new file mode 100755
index 0000000..6d13f4e
--- /dev/null
+++ b/JumpListUtil/ShellLink.cs
@@ -0,0 +1,486 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using System.Text;
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+/****************************************************************************
+ * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/
+ ***************************************************************************/
+
+namespace ShellLinkPlus
+{
+ // Modified from http://smdn.jp/programming/tips/createlnk/
+ // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects
+ // /Creating_and_Modifying_Shortcuts/article.asp
+ // Partly based on Sending toast notifications from desktop apps sample
+ public class ShellLink : IDisposable
+ {
+ #region Win32 and COM
+
+ // IShellLink Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("000214F9-0000-0000-C000-000000000046")]
+ private interface IShellLinkW
+ {
+ uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile,
+ int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags);
+ uint GetIDList(out IntPtr ppidl);
+ uint SetIDList(IntPtr pidl);
+ uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName,
+ int cchMaxName);
+ uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
+ uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir,
+ int cchMaxPath);
+ uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
+ uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs,
+ int cchMaxPath);
+ uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
+ uint GetHotKey(out ushort pwHotkey);
+ uint SetHotKey(ushort wHotKey);
+ uint GetShowCmd(out int piShowCmd);
+ uint SetShowCmd(int iShowCmd);
+ uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath,
+ int cchIconPath, out int piIcon);
+ uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
+ uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel,
+ uint dwReserved);
+ uint Resolve(IntPtr hwnd, uint fFlags);
+ uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
+ }
+
+ // ShellLink CoClass (ShellLink object)
+ [ComImport,
+ ClassInterface(ClassInterfaceType.None),
+ Guid("00021401-0000-0000-C000-000000000046")]
+ private class CShellLink { }
+
+ // WIN32_FIND_DATAW Structure
+ [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]
+ private struct WIN32_FIND_DATAW
+ {
+ public uint dwFileAttributes;
+ public ComTypes.FILETIME ftCreationTime;
+ public ComTypes.FILETIME ftLastAccessTime;
+ public ComTypes.FILETIME ftLastWriteTime;
+ public uint nFileSizeHigh;
+ public uint nFileSizeLow;
+ public uint dwReserved0;
+ public uint dwReserved1;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
+ public string cFileName;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
+ public string cAlternateFileName;
+ }
+
+ // IPropertyStore Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")]
+ private interface IPropertyStore
+ {
+ uint GetCount([Out] out uint cProps);
+ uint GetAt([In] uint iProp, out PropertyKey pkey);
+ uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv);
+ uint SetValue([In] ref PropertyKey key, [In] PropVariant pv);
+ uint Commit();
+ }
+
+ // PropertyKey Structure
+ // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ private struct PropertyKey
+ {
+ #region Fields
+
+ private Guid formatId; // Unique GUID for property
+ private Int32 propertyId; // Property identifier (PID)
+
+ #endregion
+
+ #region Public Properties
+
+ public Guid FormatId
+ {
+ get
+ {
+ return formatId;
+ }
+ }
+
+ public Int32 PropertyId
+ {
+ get
+ {
+ return propertyId;
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropertyKey(Guid formatId, Int32 propertyId)
+ {
+ this.formatId = formatId;
+ this.propertyId = propertyId;
+ }
+
+ public PropertyKey(string formatId, Int32 propertyId)
+ {
+ this.formatId = new Guid(formatId);
+ this.propertyId = propertyId;
+ }
+
+ #endregion
+ }
+
+ // PropVariant Class (only for string value)
+ // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1
+ // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11
+ // /interop-with-propvariants-in-net.aspx
+ [StructLayout(LayoutKind.Explicit)]
+ private sealed class PropVariant : IDisposable
+ {
+ #region Fields
+
+ [FieldOffset(0)]
+ ushort valueType; // Value type
+
+ // [FieldOffset(2)]
+ // ushort wReserved1; // Reserved field
+ // [FieldOffset(4)]
+ // ushort wReserved2; // Reserved field
+ // [FieldOffset(6)]
+ // ushort wReserved3; // Reserved field
+
+ [FieldOffset(8)]
+ IntPtr ptr; // Value
+
+ #endregion
+
+ #region Public Properties
+
+ // Value type (System.Runtime.InteropServices.VarEnum)
+ public VarEnum VarType
+ {
+ get { return (VarEnum)valueType; }
+ set { valueType = (ushort)value; }
+ }
+
+ // Whether value is empty or null
+ public bool IsNullOrEmpty
+ {
+ get
+ {
+ return (valueType == (ushort)VarEnum.VT_EMPTY ||
+ valueType == (ushort)VarEnum.VT_NULL);
+ }
+ }
+
+ // Value (only for string value)
+ public string Value
+ {
+ get
+ {
+ return Marshal.PtrToStringUni(ptr);
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropVariant()
+ { }
+
+ // Construct with string value
+ public PropVariant(string value)
+ {
+ if (value == null)
+ throw new ArgumentException("Failed to set value.");
+
+ valueType = (ushort)VarEnum.VT_LPWSTR;
+ ptr = Marshal.StringToCoTaskMemUni(value);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~PropVariant()
+ {
+ Dispose();
+ }
+
+ public void Dispose()
+ {
+ PropVariantClear(this);
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+ }
+
+ [DllImport("Ole32.dll", PreserveSig = false)]
+ private extern static void PropVariantClear([In, Out] PropVariant pvar);
+
+ #endregion
+
+ #region Fields
+
+ private IShellLinkW shellLinkW = null;
+
+ // Name = System.AppUserModel.ID
+ // ShellPKey = PKEY_AppUserModel_ID
+ // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3
+ // PropID = 5
+ // Type = String (VT_LPWSTR)
+ private readonly PropertyKey AppUserModelIDKey =
+ new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5);
+
+ private const int MAX_PATH = 260;
+ private const int INFOTIPSIZE = 1024;
+
+ private const int STGM_READ = 0x00000000; // STGM constants
+ private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags
+
+ #endregion
+
+ #region Private Properties (Interfaces)
+
+ private IPersistFile PersistFile
+ {
+ get
+ {
+ IPersistFile PersistFile = shellLinkW as IPersistFile;
+
+ if (PersistFile == null)
+ throw new COMException("Failed to create IPersistFile.");
+ else
+ return PersistFile;
+ }
+ }
+
+ private IPropertyStore PropertyStore
+ {
+ get
+ {
+ IPropertyStore PropertyStore = shellLinkW as IPropertyStore;
+
+ if (PropertyStore == null)
+ throw new COMException("Failed to create IPropertyStore.");
+ else
+ return PropertyStore;
+ }
+ }
+
+ #endregion
+
+ #region Public Properties (Minimal)
+
+ // Path of loaded shortcut file
+ public string ShortcutFile
+ {
+ get
+ {
+ string shortcutFile;
+
+ PersistFile.GetCurFile(out shortcutFile);
+
+ return shortcutFile;
+ }
+ }
+
+ // Path of target file
+ public string TargetPath
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder targetPath = new StringBuilder(MAX_PATH);
+
+ WIN32_FIND_DATAW data = new WIN32_FIND_DATAW();
+
+ VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data,
+ SLGP_UNCPRIORITY));
+
+ return targetPath.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetPath(value));
+ }
+ }
+
+ public string Arguments
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder arguments = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity));
+
+ return arguments.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetArguments(value));
+ }
+ }
+
+ public string Description
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder description = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity));
+
+ return description.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetDescription(value));
+ }
+ }
+
+ public Tuple IconLocation
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder icon = new StringBuilder(INFOTIPSIZE);
+
+ int index;
+ VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index));
+
+ return new Tuple(icon.ToString(), index);
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2));
+ }
+ }
+
+ // AppUserModelID to be used for Windows 7 or later.
+ public string AppUserModelID
+ {
+ get
+ {
+ using (PropVariant pv = new PropVariant())
+ {
+ VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv));
+
+ if (pv.Value == null)
+ return "Null";
+ else
+ return pv.Value;
+ }
+ }
+ set
+ {
+ using (PropVariant pv = new PropVariant(value))
+ {
+ VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv));
+ VerifySucceeded(PropertyStore.Commit());
+ }
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public ShellLink()
+ : this(null)
+ { }
+
+ // Construct with loading shortcut file.
+ public ShellLink(string file)
+ {
+ try
+ {
+ shellLinkW = (IShellLinkW)new CShellLink();
+ }
+ catch
+ {
+ throw new COMException("Failed to create ShellLink object.");
+ }
+
+ if (file != null)
+ Load(file);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~ShellLink()
+ {
+ Dispose(false);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (shellLinkW != null)
+ {
+ // Release all references.
+ Marshal.FinalReleaseComObject(shellLinkW);
+ shellLinkW = null;
+ }
+ }
+
+ #endregion
+
+ #region Methods
+
+ // Save shortcut file.
+ public void Save()
+ {
+ string file = ShortcutFile;
+
+ if (file == null)
+ throw new InvalidOperationException("File name is not given.");
+ else
+ Save(file);
+ }
+
+ public void Save(string file)
+ {
+ if (file == null)
+ throw new ArgumentNullException("File name is required.");
+ else
+ PersistFile.Save(file, true);
+ }
+
+ // Load shortcut file.
+ public void Load(string file)
+ {
+ if (!File.Exists(file))
+ throw new FileNotFoundException("File is not found.", file);
+ else
+ PersistFile.Load(file, STGM_READ);
+ }
+
+ // Verify if operation succeeded.
+ public static void VerifySucceeded(uint hresult)
+ {
+ if (hresult > 1)
+ throw new InvalidOperationException("Failed with HRESULT: " +
+ hresult.ToString("X"));
+ }
+
+ #endregion
+ }
+}
diff --git a/JumpListUtil/packages.config b/JumpListUtil/packages.config
new file mode 100755
index 0000000..abb0b89
--- /dev/null
+++ b/JumpListUtil/packages.config
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Program.cs b/Program.cs
deleted file mode 100755
index 17420a8..0000000
--- a/Program.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-using System.Windows.Shell;
-
-namespace JumpListTest
-{
- static class Program
- {
- ///
- /// The main entry point for the application.
- ///
- [STAThread]
- static void Main()
- {
- System.Windows.Application wpfApp = new System.Windows.Application();
- JumpTask task = new JumpTask();
- task.ApplicationPath = "wt.exe";
- task.Description = "Work Terminal";
- task.Title = "Terminal";
- JumpList.SetJumpList(wpfApp, new JumpList(new List { task }, false, false));
-
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- Application.Run();
-
-
- }
- }
-}
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
deleted file mode 100755
index 1b650b3..0000000
--- a/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-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("JumpListTest")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("JumpListTest")]
-[assembly: AssemblyCopyright("Copyright © 2020")]
-[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
-
-// 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/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs
deleted file mode 100755
index f29ecc8..0000000
--- a/Properties/Resources.Designer.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// 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 JumpListTest.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("JumpListTest.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/Properties/Resources.resx b/Properties/Resources.resx
deleted file mode 100755
index ffecec8..0000000
--- a/Properties/Resources.resx
+++ /dev/null
@@ -1,117 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 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/Properties/Settings.Designer.cs b/Properties/Settings.Designer.cs
deleted file mode 100755
index fa4d9ff..0000000
--- a/Properties/Settings.Designer.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// 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 JumpListTest.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/Properties/Settings.settings b/Properties/Settings.settings
deleted file mode 100755
index abf36c5..0000000
--- a/Properties/Settings.settings
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
diff --git a/SetLnkApp/Program.cs b/SetLnkApp/Program.cs
new file mode 100755
index 0000000..08a160a
--- /dev/null
+++ b/SetLnkApp/Program.cs
@@ -0,0 +1,34 @@
+using ShellLinkPlus;
+using System;
+using System.IO;
+using System.Linq;
+
+namespace SetLnkApp
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ bool existing = File.Exists(args[0]);
+ using (ShellLink shortcut = new ShellLink(existing ? args[0] : null))
+ {
+ if (existing)
+ {
+ if (args.Length > 2)
+ {
+ throw new Exception("For an existing shortcut, only pass AppUserModelId");
+ }
+ }
+ else
+ {
+ shortcut.TargetPath = args[2];
+ //shortcut.Arguments = args.Length > 3 ? string.Join(" ", args.Skip(3)) : "";
+ shortcut.Arguments = string.Join(" ", args.Skip(3));
+ }
+ shortcut.AppUserModelID = args[1];
+
+ shortcut.Save(args[0]);
+ }
+ }
+ }
+}
diff --git a/SetLnkApp/Properties/launchSettings.json b/SetLnkApp/Properties/launchSettings.json
new file mode 100755
index 0000000..420478a
--- /dev/null
+++ b/SetLnkApp/Properties/launchSettings.json
@@ -0,0 +1,7 @@
+{
+ "profiles": {
+ "SetLnkApp": {
+ "commandName": "Project"
+ }
+ }
+}
\ No newline at end of file
diff --git a/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/Form1.cs b/Form1.cs
deleted file mode 100755
index 74b2085..0000000
--- a/Form1.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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 JumpListTest
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/JumpListTest.csproj b/JumpListTest.csproj
deleted file mode 100755
index 9ad6f29..0000000
--- a/JumpListTest.csproj
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
- WinExe
- JumpListTest
- JumpListTest
- v4.7.2
- 512
- true
- true
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Form
-
-
- 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/JumpListTest.sln b/JumpListTest.sln
deleted file mode 100755
index ad79cd7..0000000
--- a/JumpListTest.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30114.105
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListTest", "JumpListTest.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
- EndGlobalSection
-EndGlobal
diff --git a/JumpListUtil.sln b/JumpListUtil.sln
new file mode 100755
index 0000000..c91e4de
--- /dev/null
+++ b/JumpListUtil.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
+ EndGlobalSection
+EndGlobal
diff --git a/JumpListUtil/App.config b/JumpListUtil/App.config
new file mode 100755
index 0000000..de2fc4c
--- /dev/null
+++ b/JumpListUtil/App.config
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj
new file mode 100755
index 0000000..5f31de9
--- /dev/null
+++ b/JumpListUtil/JumpListUtil.csproj
@@ -0,0 +1,106 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
+ WinExe
+ JumpListUtil
+ JumpListUtil
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
+
+
+
+
+ ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+
+ ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
+
+
+
+ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\packages\System.Text.Encodings.Web.4.7.1\lib\net461\System.Text.Encodings.Web.dll
+
+
+ ..\packages\System.Text.Json.4.7.2\lib\net461\System.Text.Json.dll
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+
+ ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/Program.cs b/JumpListUtil/Program.cs
new file mode 100755
index 0000000..a13d723
--- /dev/null
+++ b/JumpListUtil/Program.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text.Json;
+using System.Threading;
+using System.Windows.Forms;
+using System.Windows.Shell;
+
+namespace JumpListUtil
+{
+ public class Entry
+ {
+ public string Target { get; set; }
+ public string Icon { get; set; }
+ public int IconIndex { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ }
+ static class Program
+ {
+ [DllImport("shell32.dll", SetLastError = true)]
+ static extern void SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr)] string AppID);
+
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ System.Windows.Application wpfApp = new System.Windows.Application();
+ string thisProgram = Process.GetCurrentProcess().MainModule.FileName;
+
+ // parse all arguments
+ string shortcutsFile = "shortcuts.json";
+ string appUserModelId = "Microsoft.WindowsTerminal_8wekyb3d8bbwe!App";
+ int startIndex = 0;
+ bool onlyRefreshJumpList = false;
+
+ int i = 0;
+ string[] args = Environment.GetCommandLineArgs();
+ bool ParseFlag(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length > 2)
+ {
+ args[i] = "-" + args[i].Substring(2);
+ i--;
+ }
+ return true;
+ }
+ else if (args[i] == "--" + longName)
+ {
+ return true;
+ }
+ return false;
+ }
+ string ParseArg(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length == 2)
+ {
+ i++;
+ return args[i];
+ }
+ else
+ {
+ return args[i].Substring(2);
+ }
+ }
+ else if (args[i].IndexOf("--" + longName + "=") == 0)
+ {
+ return args[i].Substring(longName.Length + 3);
+ }
+ return null;
+ }
+
+ string val = null;
+ for (i = 1; i < args.Length; i++)
+ {
+ if ((val = ParseArg('s', "shortcuts")) != null)
+ {
+ shortcutsFile = val;
+ }
+ else if ((val = ParseArg('i', "startIndex")) != null)
+ {
+ startIndex = int.Parse(val);
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if (ParseFlag('r', "refresh"))
+ {
+ onlyRefreshJumpList = true;
+ }
+ }
+
+ SetCurrentProcessExplicitAppUserModelID(appUserModelId);
+
+ List jumpItems = new List();
+
+ Entry[] entries = null;
+
+ try
+ {
+ string shortcutJson = "";
+ using (FileStream input = File.OpenRead(shortcutsFile))
+ {
+ shortcutJson = new StreamReader(input).ReadToEnd();
+ }
+
+
+ entries = (Entry[])JsonSerializer.Deserialize(shortcutJson, typeof(Entry[]), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true, ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true });
+ }
+ catch (Exception e)
+ {
+ MessageBox.Show("Failed to load shortcut entries: " + e);
+ }
+
+ if (entries != null)
+ {
+ foreach (Entry entry in entries)
+ {
+ JumpTask task = new JumpTask();
+ task.ApplicationPath = entry.Target;
+ task.Description = entry.Description;
+ task.Title = entry.Name;
+ task.IconResourcePath = entry.Icon;
+ task.IconResourceIndex = entry.IconIndex;
+
+ jumpItems.Add(task);
+ }
+
+ jumpItems.Insert(0, new JumpTask
+ {
+ Title = "Refresh",
+ Description = "Refreshes the Jump List",
+ ApplicationPath = thisProgram,
+ WorkingDirectory = Environment.CurrentDirectory,
+ IconResourcePath = Environment.ExpandEnvironmentVariables("%systemroot%\\system32\\imageres.dll"),
+ IconResourceIndex = 228,
+ Arguments = "-r"
+ });
+
+ JumpList.SetJumpList(wpfApp, new JumpList(jumpItems, false, false));
+
+ if (!onlyRefreshJumpList)
+ {
+ if (startIndex >= 0 && startIndex < entries.Length)
+ {
+ Entry start = entries[startIndex];
+ Process p = Process.Start(new ProcessStartInfo
+ {
+ FileName = start.Target,
+ UseShellExecute = true
+ });
+ }
+ else
+ {
+ MessageBox.Show("Shortcut index " + startIndex + " is outside the range of valid entries (" + entries.Length + " entries)");
+ }
+ }
+ }
+
+ //Application.EnableVisualStyles();
+ //Application.SetCompatibleTextRenderingDefault(false);
+ //Application.Run();
+ }
+ }
+}
diff --git a/JumpListUtil/Properties/AssemblyInfo.cs b/JumpListUtil/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..e929884
--- /dev/null
+++ b/JumpListUtil/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("JumpListUtil")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("JumpListUtil")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
+
+// 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/JumpListUtil/Properties/Resources.Designer.cs b/JumpListUtil/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..ed070d5
--- /dev/null
+++ b/JumpListUtil/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+ using System;
+
+
+ ///
+ /// 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", "16.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 (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("JumpListUtil.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/JumpListUtil/Properties/Resources.resx b/JumpListUtil/Properties/Resources.resx
new file mode 100755
index 0000000..ffecec8
--- /dev/null
+++ b/JumpListUtil/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/JumpListUtil/Properties/Settings.Designer.cs b/JumpListUtil/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..8593114
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.6.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/JumpListUtil/Properties/Settings.settings b/JumpListUtil/Properties/Settings.settings
new file mode 100755
index 0000000..abf36c5
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs
new file mode 100755
index 0000000..6d13f4e
--- /dev/null
+++ b/JumpListUtil/ShellLink.cs
@@ -0,0 +1,486 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using System.Text;
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+/****************************************************************************
+ * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/
+ ***************************************************************************/
+
+namespace ShellLinkPlus
+{
+ // Modified from http://smdn.jp/programming/tips/createlnk/
+ // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects
+ // /Creating_and_Modifying_Shortcuts/article.asp
+ // Partly based on Sending toast notifications from desktop apps sample
+ public class ShellLink : IDisposable
+ {
+ #region Win32 and COM
+
+ // IShellLink Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("000214F9-0000-0000-C000-000000000046")]
+ private interface IShellLinkW
+ {
+ uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile,
+ int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags);
+ uint GetIDList(out IntPtr ppidl);
+ uint SetIDList(IntPtr pidl);
+ uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName,
+ int cchMaxName);
+ uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
+ uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir,
+ int cchMaxPath);
+ uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
+ uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs,
+ int cchMaxPath);
+ uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
+ uint GetHotKey(out ushort pwHotkey);
+ uint SetHotKey(ushort wHotKey);
+ uint GetShowCmd(out int piShowCmd);
+ uint SetShowCmd(int iShowCmd);
+ uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath,
+ int cchIconPath, out int piIcon);
+ uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
+ uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel,
+ uint dwReserved);
+ uint Resolve(IntPtr hwnd, uint fFlags);
+ uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
+ }
+
+ // ShellLink CoClass (ShellLink object)
+ [ComImport,
+ ClassInterface(ClassInterfaceType.None),
+ Guid("00021401-0000-0000-C000-000000000046")]
+ private class CShellLink { }
+
+ // WIN32_FIND_DATAW Structure
+ [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]
+ private struct WIN32_FIND_DATAW
+ {
+ public uint dwFileAttributes;
+ public ComTypes.FILETIME ftCreationTime;
+ public ComTypes.FILETIME ftLastAccessTime;
+ public ComTypes.FILETIME ftLastWriteTime;
+ public uint nFileSizeHigh;
+ public uint nFileSizeLow;
+ public uint dwReserved0;
+ public uint dwReserved1;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
+ public string cFileName;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
+ public string cAlternateFileName;
+ }
+
+ // IPropertyStore Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")]
+ private interface IPropertyStore
+ {
+ uint GetCount([Out] out uint cProps);
+ uint GetAt([In] uint iProp, out PropertyKey pkey);
+ uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv);
+ uint SetValue([In] ref PropertyKey key, [In] PropVariant pv);
+ uint Commit();
+ }
+
+ // PropertyKey Structure
+ // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ private struct PropertyKey
+ {
+ #region Fields
+
+ private Guid formatId; // Unique GUID for property
+ private Int32 propertyId; // Property identifier (PID)
+
+ #endregion
+
+ #region Public Properties
+
+ public Guid FormatId
+ {
+ get
+ {
+ return formatId;
+ }
+ }
+
+ public Int32 PropertyId
+ {
+ get
+ {
+ return propertyId;
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropertyKey(Guid formatId, Int32 propertyId)
+ {
+ this.formatId = formatId;
+ this.propertyId = propertyId;
+ }
+
+ public PropertyKey(string formatId, Int32 propertyId)
+ {
+ this.formatId = new Guid(formatId);
+ this.propertyId = propertyId;
+ }
+
+ #endregion
+ }
+
+ // PropVariant Class (only for string value)
+ // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1
+ // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11
+ // /interop-with-propvariants-in-net.aspx
+ [StructLayout(LayoutKind.Explicit)]
+ private sealed class PropVariant : IDisposable
+ {
+ #region Fields
+
+ [FieldOffset(0)]
+ ushort valueType; // Value type
+
+ // [FieldOffset(2)]
+ // ushort wReserved1; // Reserved field
+ // [FieldOffset(4)]
+ // ushort wReserved2; // Reserved field
+ // [FieldOffset(6)]
+ // ushort wReserved3; // Reserved field
+
+ [FieldOffset(8)]
+ IntPtr ptr; // Value
+
+ #endregion
+
+ #region Public Properties
+
+ // Value type (System.Runtime.InteropServices.VarEnum)
+ public VarEnum VarType
+ {
+ get { return (VarEnum)valueType; }
+ set { valueType = (ushort)value; }
+ }
+
+ // Whether value is empty or null
+ public bool IsNullOrEmpty
+ {
+ get
+ {
+ return (valueType == (ushort)VarEnum.VT_EMPTY ||
+ valueType == (ushort)VarEnum.VT_NULL);
+ }
+ }
+
+ // Value (only for string value)
+ public string Value
+ {
+ get
+ {
+ return Marshal.PtrToStringUni(ptr);
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropVariant()
+ { }
+
+ // Construct with string value
+ public PropVariant(string value)
+ {
+ if (value == null)
+ throw new ArgumentException("Failed to set value.");
+
+ valueType = (ushort)VarEnum.VT_LPWSTR;
+ ptr = Marshal.StringToCoTaskMemUni(value);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~PropVariant()
+ {
+ Dispose();
+ }
+
+ public void Dispose()
+ {
+ PropVariantClear(this);
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+ }
+
+ [DllImport("Ole32.dll", PreserveSig = false)]
+ private extern static void PropVariantClear([In, Out] PropVariant pvar);
+
+ #endregion
+
+ #region Fields
+
+ private IShellLinkW shellLinkW = null;
+
+ // Name = System.AppUserModel.ID
+ // ShellPKey = PKEY_AppUserModel_ID
+ // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3
+ // PropID = 5
+ // Type = String (VT_LPWSTR)
+ private readonly PropertyKey AppUserModelIDKey =
+ new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5);
+
+ private const int MAX_PATH = 260;
+ private const int INFOTIPSIZE = 1024;
+
+ private const int STGM_READ = 0x00000000; // STGM constants
+ private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags
+
+ #endregion
+
+ #region Private Properties (Interfaces)
+
+ private IPersistFile PersistFile
+ {
+ get
+ {
+ IPersistFile PersistFile = shellLinkW as IPersistFile;
+
+ if (PersistFile == null)
+ throw new COMException("Failed to create IPersistFile.");
+ else
+ return PersistFile;
+ }
+ }
+
+ private IPropertyStore PropertyStore
+ {
+ get
+ {
+ IPropertyStore PropertyStore = shellLinkW as IPropertyStore;
+
+ if (PropertyStore == null)
+ throw new COMException("Failed to create IPropertyStore.");
+ else
+ return PropertyStore;
+ }
+ }
+
+ #endregion
+
+ #region Public Properties (Minimal)
+
+ // Path of loaded shortcut file
+ public string ShortcutFile
+ {
+ get
+ {
+ string shortcutFile;
+
+ PersistFile.GetCurFile(out shortcutFile);
+
+ return shortcutFile;
+ }
+ }
+
+ // Path of target file
+ public string TargetPath
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder targetPath = new StringBuilder(MAX_PATH);
+
+ WIN32_FIND_DATAW data = new WIN32_FIND_DATAW();
+
+ VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data,
+ SLGP_UNCPRIORITY));
+
+ return targetPath.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetPath(value));
+ }
+ }
+
+ public string Arguments
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder arguments = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity));
+
+ return arguments.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetArguments(value));
+ }
+ }
+
+ public string Description
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder description = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity));
+
+ return description.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetDescription(value));
+ }
+ }
+
+ public Tuple IconLocation
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder icon = new StringBuilder(INFOTIPSIZE);
+
+ int index;
+ VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index));
+
+ return new Tuple(icon.ToString(), index);
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2));
+ }
+ }
+
+ // AppUserModelID to be used for Windows 7 or later.
+ public string AppUserModelID
+ {
+ get
+ {
+ using (PropVariant pv = new PropVariant())
+ {
+ VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv));
+
+ if (pv.Value == null)
+ return "Null";
+ else
+ return pv.Value;
+ }
+ }
+ set
+ {
+ using (PropVariant pv = new PropVariant(value))
+ {
+ VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv));
+ VerifySucceeded(PropertyStore.Commit());
+ }
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public ShellLink()
+ : this(null)
+ { }
+
+ // Construct with loading shortcut file.
+ public ShellLink(string file)
+ {
+ try
+ {
+ shellLinkW = (IShellLinkW)new CShellLink();
+ }
+ catch
+ {
+ throw new COMException("Failed to create ShellLink object.");
+ }
+
+ if (file != null)
+ Load(file);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~ShellLink()
+ {
+ Dispose(false);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (shellLinkW != null)
+ {
+ // Release all references.
+ Marshal.FinalReleaseComObject(shellLinkW);
+ shellLinkW = null;
+ }
+ }
+
+ #endregion
+
+ #region Methods
+
+ // Save shortcut file.
+ public void Save()
+ {
+ string file = ShortcutFile;
+
+ if (file == null)
+ throw new InvalidOperationException("File name is not given.");
+ else
+ Save(file);
+ }
+
+ public void Save(string file)
+ {
+ if (file == null)
+ throw new ArgumentNullException("File name is required.");
+ else
+ PersistFile.Save(file, true);
+ }
+
+ // Load shortcut file.
+ public void Load(string file)
+ {
+ if (!File.Exists(file))
+ throw new FileNotFoundException("File is not found.", file);
+ else
+ PersistFile.Load(file, STGM_READ);
+ }
+
+ // Verify if operation succeeded.
+ public static void VerifySucceeded(uint hresult)
+ {
+ if (hresult > 1)
+ throw new InvalidOperationException("Failed with HRESULT: " +
+ hresult.ToString("X"));
+ }
+
+ #endregion
+ }
+}
diff --git a/JumpListUtil/packages.config b/JumpListUtil/packages.config
new file mode 100755
index 0000000..abb0b89
--- /dev/null
+++ b/JumpListUtil/packages.config
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Program.cs b/Program.cs
deleted file mode 100755
index 17420a8..0000000
--- a/Program.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-using System.Windows.Shell;
-
-namespace JumpListTest
-{
- static class Program
- {
- ///
- /// The main entry point for the application.
- ///
- [STAThread]
- static void Main()
- {
- System.Windows.Application wpfApp = new System.Windows.Application();
- JumpTask task = new JumpTask();
- task.ApplicationPath = "wt.exe";
- task.Description = "Work Terminal";
- task.Title = "Terminal";
- JumpList.SetJumpList(wpfApp, new JumpList(new List { task }, false, false));
-
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- Application.Run();
-
-
- }
- }
-}
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
deleted file mode 100755
index 1b650b3..0000000
--- a/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-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("JumpListTest")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("JumpListTest")]
-[assembly: AssemblyCopyright("Copyright © 2020")]
-[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
-
-// 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/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs
deleted file mode 100755
index f29ecc8..0000000
--- a/Properties/Resources.Designer.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// 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 JumpListTest.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("JumpListTest.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/Properties/Resources.resx b/Properties/Resources.resx
deleted file mode 100755
index ffecec8..0000000
--- a/Properties/Resources.resx
+++ /dev/null
@@ -1,117 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 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/Properties/Settings.Designer.cs b/Properties/Settings.Designer.cs
deleted file mode 100755
index fa4d9ff..0000000
--- a/Properties/Settings.Designer.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// 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 JumpListTest.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/Properties/Settings.settings b/Properties/Settings.settings
deleted file mode 100755
index abf36c5..0000000
--- a/Properties/Settings.settings
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
diff --git a/SetLnkApp/Program.cs b/SetLnkApp/Program.cs
new file mode 100755
index 0000000..08a160a
--- /dev/null
+++ b/SetLnkApp/Program.cs
@@ -0,0 +1,34 @@
+using ShellLinkPlus;
+using System;
+using System.IO;
+using System.Linq;
+
+namespace SetLnkApp
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ bool existing = File.Exists(args[0]);
+ using (ShellLink shortcut = new ShellLink(existing ? args[0] : null))
+ {
+ if (existing)
+ {
+ if (args.Length > 2)
+ {
+ throw new Exception("For an existing shortcut, only pass AppUserModelId");
+ }
+ }
+ else
+ {
+ shortcut.TargetPath = args[2];
+ //shortcut.Arguments = args.Length > 3 ? string.Join(" ", args.Skip(3)) : "";
+ shortcut.Arguments = string.Join(" ", args.Skip(3));
+ }
+ shortcut.AppUserModelID = args[1];
+
+ shortcut.Save(args[0]);
+ }
+ }
+ }
+}
diff --git a/SetLnkApp/Properties/launchSettings.json b/SetLnkApp/Properties/launchSettings.json
new file mode 100755
index 0000000..420478a
--- /dev/null
+++ b/SetLnkApp/Properties/launchSettings.json
@@ -0,0 +1,7 @@
+{
+ "profiles": {
+ "SetLnkApp": {
+ "commandName": "Project"
+ }
+ }
+}
\ No newline at end of file
diff --git a/SetLnkApp/SetLnkApp.csproj b/SetLnkApp/SetLnkApp.csproj
new file mode 100755
index 0000000..d453e9a
--- /dev/null
+++ b/SetLnkApp/SetLnkApp.csproj
@@ -0,0 +1,8 @@
+
+
+
+ Exe
+ netcoreapp3.1
+
+
+
diff --git a/App.config b/App.config
deleted file mode 100755
index 5754728..0000000
--- a/App.config
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Form1.Designer.cs b/Form1.Designer.cs
deleted file mode 100755
index 0f447ee..0000000
--- a/Form1.Designer.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace JumpListTest
-{
- 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.components = new System.ComponentModel.Container();
- this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(800, 450);
- this.Text = "Form1";
- }
-
- #endregion
- }
-}
-
diff --git a/Form1.cs b/Form1.cs
deleted file mode 100755
index 74b2085..0000000
--- a/Form1.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-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 JumpListTest
-{
- public partial class Form1 : Form
- {
- public Form1()
- {
- InitializeComponent();
- }
- }
-}
diff --git a/JumpListTest.csproj b/JumpListTest.csproj
deleted file mode 100755
index 9ad6f29..0000000
--- a/JumpListTest.csproj
+++ /dev/null
@@ -1,81 +0,0 @@
-
-
-
-
- Debug
- AnyCPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
- WinExe
- JumpListTest
- JumpListTest
- v4.7.2
- 512
- true
- true
-
-
- AnyCPU
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- AnyCPU
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Form
-
-
- 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/JumpListTest.sln b/JumpListTest.sln
deleted file mode 100755
index ad79cd7..0000000
--- a/JumpListTest.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 16.0.30114.105
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListTest", "JumpListTest.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
- EndGlobalSection
-EndGlobal
diff --git a/JumpListUtil.sln b/JumpListUtil.sln
new file mode 100755
index 0000000..c91e4de
--- /dev/null
+++ b/JumpListUtil.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30114.105
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JumpListUtil", "JumpListUtil\JumpListUtil.csproj", "{66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SetLnkApp", "SetLnkApp\SetLnkApp.csproj", "{D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D64CB67B-A07A-4A10-8CB3-83C5F4D3FF3E}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {60F13606-E5AC-4632-9273-AED10038EAB1}
+ EndGlobalSection
+EndGlobal
diff --git a/JumpListUtil/App.config b/JumpListUtil/App.config
new file mode 100755
index 0000000..de2fc4c
--- /dev/null
+++ b/JumpListUtil/App.config
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/JumpListUtil.csproj b/JumpListUtil/JumpListUtil.csproj
new file mode 100755
index 0000000..5f31de9
--- /dev/null
+++ b/JumpListUtil/JumpListUtil.csproj
@@ -0,0 +1,106 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {66F50737-A71D-4D5B-83F2-4F06B9F9F9B2}
+ WinExe
+ JumpListUtil
+ JumpListUtil
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\Microsoft.Bcl.AsyncInterfaces.1.1.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
+
+
+
+
+ ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+
+ ..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
+
+
+
+ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\packages\System.Runtime.CompilerServices.Unsafe.4.7.1\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\packages\System.Text.Encodings.Web.4.7.1\lib\net461\System.Text.Encodings.Web.dll
+
+
+ ..\packages\System.Text.Json.4.7.2\lib\net461\System.Text.Json.dll
+
+
+ ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
+
+
+ ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/JumpListUtil/Program.cs b/JumpListUtil/Program.cs
new file mode 100755
index 0000000..a13d723
--- /dev/null
+++ b/JumpListUtil/Program.cs
@@ -0,0 +1,178 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text.Json;
+using System.Threading;
+using System.Windows.Forms;
+using System.Windows.Shell;
+
+namespace JumpListUtil
+{
+ public class Entry
+ {
+ public string Target { get; set; }
+ public string Icon { get; set; }
+ public int IconIndex { get; set; }
+ public string Name { get; set; }
+ public string Description { get; set; }
+ }
+ static class Program
+ {
+ [DllImport("shell32.dll", SetLastError = true)]
+ static extern void SetCurrentProcessExplicitAppUserModelID([MarshalAs(UnmanagedType.LPWStr)] string AppID);
+
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ System.Windows.Application wpfApp = new System.Windows.Application();
+ string thisProgram = Process.GetCurrentProcess().MainModule.FileName;
+
+ // parse all arguments
+ string shortcutsFile = "shortcuts.json";
+ string appUserModelId = "Microsoft.WindowsTerminal_8wekyb3d8bbwe!App";
+ int startIndex = 0;
+ bool onlyRefreshJumpList = false;
+
+ int i = 0;
+ string[] args = Environment.GetCommandLineArgs();
+ bool ParseFlag(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length > 2)
+ {
+ args[i] = "-" + args[i].Substring(2);
+ i--;
+ }
+ return true;
+ }
+ else if (args[i] == "--" + longName)
+ {
+ return true;
+ }
+ return false;
+ }
+ string ParseArg(char shortName, string longName)
+ {
+ if (args[i].IndexOf("-" + shortName) == 0)
+ {
+ if (args[i].Length == 2)
+ {
+ i++;
+ return args[i];
+ }
+ else
+ {
+ return args[i].Substring(2);
+ }
+ }
+ else if (args[i].IndexOf("--" + longName + "=") == 0)
+ {
+ return args[i].Substring(longName.Length + 3);
+ }
+ return null;
+ }
+
+ string val = null;
+ for (i = 1; i < args.Length; i++)
+ {
+ if ((val = ParseArg('s', "shortcuts")) != null)
+ {
+ shortcutsFile = val;
+ }
+ else if ((val = ParseArg('i', "startIndex")) != null)
+ {
+ startIndex = int.Parse(val);
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if ((val = ParseArg('a', "appUserModelId")) != null)
+ {
+ appUserModelId = val;
+ }
+ else if (ParseFlag('r', "refresh"))
+ {
+ onlyRefreshJumpList = true;
+ }
+ }
+
+ SetCurrentProcessExplicitAppUserModelID(appUserModelId);
+
+ List jumpItems = new List();
+
+ Entry[] entries = null;
+
+ try
+ {
+ string shortcutJson = "";
+ using (FileStream input = File.OpenRead(shortcutsFile))
+ {
+ shortcutJson = new StreamReader(input).ReadToEnd();
+ }
+
+
+ entries = (Entry[])JsonSerializer.Deserialize(shortcutJson, typeof(Entry[]), new JsonSerializerOptions() { PropertyNameCaseInsensitive = true, ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true });
+ }
+ catch (Exception e)
+ {
+ MessageBox.Show("Failed to load shortcut entries: " + e);
+ }
+
+ if (entries != null)
+ {
+ foreach (Entry entry in entries)
+ {
+ JumpTask task = new JumpTask();
+ task.ApplicationPath = entry.Target;
+ task.Description = entry.Description;
+ task.Title = entry.Name;
+ task.IconResourcePath = entry.Icon;
+ task.IconResourceIndex = entry.IconIndex;
+
+ jumpItems.Add(task);
+ }
+
+ jumpItems.Insert(0, new JumpTask
+ {
+ Title = "Refresh",
+ Description = "Refreshes the Jump List",
+ ApplicationPath = thisProgram,
+ WorkingDirectory = Environment.CurrentDirectory,
+ IconResourcePath = Environment.ExpandEnvironmentVariables("%systemroot%\\system32\\imageres.dll"),
+ IconResourceIndex = 228,
+ Arguments = "-r"
+ });
+
+ JumpList.SetJumpList(wpfApp, new JumpList(jumpItems, false, false));
+
+ if (!onlyRefreshJumpList)
+ {
+ if (startIndex >= 0 && startIndex < entries.Length)
+ {
+ Entry start = entries[startIndex];
+ Process p = Process.Start(new ProcessStartInfo
+ {
+ FileName = start.Target,
+ UseShellExecute = true
+ });
+ }
+ else
+ {
+ MessageBox.Show("Shortcut index " + startIndex + " is outside the range of valid entries (" + entries.Length + " entries)");
+ }
+ }
+ }
+
+ //Application.EnableVisualStyles();
+ //Application.SetCompatibleTextRenderingDefault(false);
+ //Application.Run();
+ }
+ }
+}
diff --git a/JumpListUtil/Properties/AssemblyInfo.cs b/JumpListUtil/Properties/AssemblyInfo.cs
new file mode 100755
index 0000000..e929884
--- /dev/null
+++ b/JumpListUtil/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("JumpListUtil")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("JumpListUtil")]
+[assembly: AssemblyCopyright("Copyright © 2020")]
+[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
+
+// 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/JumpListUtil/Properties/Resources.Designer.cs b/JumpListUtil/Properties/Resources.Designer.cs
new file mode 100755
index 0000000..ed070d5
--- /dev/null
+++ b/JumpListUtil/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+ using System;
+
+
+ ///
+ /// 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", "16.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 (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("JumpListUtil.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/JumpListUtil/Properties/Resources.resx b/JumpListUtil/Properties/Resources.resx
new file mode 100755
index 0000000..ffecec8
--- /dev/null
+++ b/JumpListUtil/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/JumpListUtil/Properties/Settings.Designer.cs b/JumpListUtil/Properties/Settings.Designer.cs
new file mode 100755
index 0000000..8593114
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// 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 JumpListUtil.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.6.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/JumpListUtil/Properties/Settings.settings b/JumpListUtil/Properties/Settings.settings
new file mode 100755
index 0000000..abf36c5
--- /dev/null
+++ b/JumpListUtil/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/JumpListUtil/ShellLink.cs b/JumpListUtil/ShellLink.cs
new file mode 100755
index 0000000..6d13f4e
--- /dev/null
+++ b/JumpListUtil/ShellLink.cs
@@ -0,0 +1,486 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using System.Text;
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+/****************************************************************************
+ * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/
+ ***************************************************************************/
+
+namespace ShellLinkPlus
+{
+ // Modified from http://smdn.jp/programming/tips/createlnk/
+ // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects
+ // /Creating_and_Modifying_Shortcuts/article.asp
+ // Partly based on Sending toast notifications from desktop apps sample
+ public class ShellLink : IDisposable
+ {
+ #region Win32 and COM
+
+ // IShellLink Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("000214F9-0000-0000-C000-000000000046")]
+ private interface IShellLinkW
+ {
+ uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile,
+ int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags);
+ uint GetIDList(out IntPtr ppidl);
+ uint SetIDList(IntPtr pidl);
+ uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName,
+ int cchMaxName);
+ uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
+ uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir,
+ int cchMaxPath);
+ uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
+ uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs,
+ int cchMaxPath);
+ uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
+ uint GetHotKey(out ushort pwHotkey);
+ uint SetHotKey(ushort wHotKey);
+ uint GetShowCmd(out int piShowCmd);
+ uint SetShowCmd(int iShowCmd);
+ uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath,
+ int cchIconPath, out int piIcon);
+ uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
+ uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel,
+ uint dwReserved);
+ uint Resolve(IntPtr hwnd, uint fFlags);
+ uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
+ }
+
+ // ShellLink CoClass (ShellLink object)
+ [ComImport,
+ ClassInterface(ClassInterfaceType.None),
+ Guid("00021401-0000-0000-C000-000000000046")]
+ private class CShellLink { }
+
+ // WIN32_FIND_DATAW Structure
+ [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]
+ private struct WIN32_FIND_DATAW
+ {
+ public uint dwFileAttributes;
+ public ComTypes.FILETIME ftCreationTime;
+ public ComTypes.FILETIME ftLastAccessTime;
+ public ComTypes.FILETIME ftLastWriteTime;
+ public uint nFileSizeHigh;
+ public uint nFileSizeLow;
+ public uint dwReserved0;
+ public uint dwReserved1;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
+ public string cFileName;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
+ public string cAlternateFileName;
+ }
+
+ // IPropertyStore Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")]
+ private interface IPropertyStore
+ {
+ uint GetCount([Out] out uint cProps);
+ uint GetAt([In] uint iProp, out PropertyKey pkey);
+ uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv);
+ uint SetValue([In] ref PropertyKey key, [In] PropVariant pv);
+ uint Commit();
+ }
+
+ // PropertyKey Structure
+ // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ private struct PropertyKey
+ {
+ #region Fields
+
+ private Guid formatId; // Unique GUID for property
+ private Int32 propertyId; // Property identifier (PID)
+
+ #endregion
+
+ #region Public Properties
+
+ public Guid FormatId
+ {
+ get
+ {
+ return formatId;
+ }
+ }
+
+ public Int32 PropertyId
+ {
+ get
+ {
+ return propertyId;
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropertyKey(Guid formatId, Int32 propertyId)
+ {
+ this.formatId = formatId;
+ this.propertyId = propertyId;
+ }
+
+ public PropertyKey(string formatId, Int32 propertyId)
+ {
+ this.formatId = new Guid(formatId);
+ this.propertyId = propertyId;
+ }
+
+ #endregion
+ }
+
+ // PropVariant Class (only for string value)
+ // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1
+ // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11
+ // /interop-with-propvariants-in-net.aspx
+ [StructLayout(LayoutKind.Explicit)]
+ private sealed class PropVariant : IDisposable
+ {
+ #region Fields
+
+ [FieldOffset(0)]
+ ushort valueType; // Value type
+
+ // [FieldOffset(2)]
+ // ushort wReserved1; // Reserved field
+ // [FieldOffset(4)]
+ // ushort wReserved2; // Reserved field
+ // [FieldOffset(6)]
+ // ushort wReserved3; // Reserved field
+
+ [FieldOffset(8)]
+ IntPtr ptr; // Value
+
+ #endregion
+
+ #region Public Properties
+
+ // Value type (System.Runtime.InteropServices.VarEnum)
+ public VarEnum VarType
+ {
+ get { return (VarEnum)valueType; }
+ set { valueType = (ushort)value; }
+ }
+
+ // Whether value is empty or null
+ public bool IsNullOrEmpty
+ {
+ get
+ {
+ return (valueType == (ushort)VarEnum.VT_EMPTY ||
+ valueType == (ushort)VarEnum.VT_NULL);
+ }
+ }
+
+ // Value (only for string value)
+ public string Value
+ {
+ get
+ {
+ return Marshal.PtrToStringUni(ptr);
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropVariant()
+ { }
+
+ // Construct with string value
+ public PropVariant(string value)
+ {
+ if (value == null)
+ throw new ArgumentException("Failed to set value.");
+
+ valueType = (ushort)VarEnum.VT_LPWSTR;
+ ptr = Marshal.StringToCoTaskMemUni(value);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~PropVariant()
+ {
+ Dispose();
+ }
+
+ public void Dispose()
+ {
+ PropVariantClear(this);
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+ }
+
+ [DllImport("Ole32.dll", PreserveSig = false)]
+ private extern static void PropVariantClear([In, Out] PropVariant pvar);
+
+ #endregion
+
+ #region Fields
+
+ private IShellLinkW shellLinkW = null;
+
+ // Name = System.AppUserModel.ID
+ // ShellPKey = PKEY_AppUserModel_ID
+ // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3
+ // PropID = 5
+ // Type = String (VT_LPWSTR)
+ private readonly PropertyKey AppUserModelIDKey =
+ new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5);
+
+ private const int MAX_PATH = 260;
+ private const int INFOTIPSIZE = 1024;
+
+ private const int STGM_READ = 0x00000000; // STGM constants
+ private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags
+
+ #endregion
+
+ #region Private Properties (Interfaces)
+
+ private IPersistFile PersistFile
+ {
+ get
+ {
+ IPersistFile PersistFile = shellLinkW as IPersistFile;
+
+ if (PersistFile == null)
+ throw new COMException("Failed to create IPersistFile.");
+ else
+ return PersistFile;
+ }
+ }
+
+ private IPropertyStore PropertyStore
+ {
+ get
+ {
+ IPropertyStore PropertyStore = shellLinkW as IPropertyStore;
+
+ if (PropertyStore == null)
+ throw new COMException("Failed to create IPropertyStore.");
+ else
+ return PropertyStore;
+ }
+ }
+
+ #endregion
+
+ #region Public Properties (Minimal)
+
+ // Path of loaded shortcut file
+ public string ShortcutFile
+ {
+ get
+ {
+ string shortcutFile;
+
+ PersistFile.GetCurFile(out shortcutFile);
+
+ return shortcutFile;
+ }
+ }
+
+ // Path of target file
+ public string TargetPath
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder targetPath = new StringBuilder(MAX_PATH);
+
+ WIN32_FIND_DATAW data = new WIN32_FIND_DATAW();
+
+ VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data,
+ SLGP_UNCPRIORITY));
+
+ return targetPath.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetPath(value));
+ }
+ }
+
+ public string Arguments
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder arguments = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity));
+
+ return arguments.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetArguments(value));
+ }
+ }
+
+ public string Description
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder description = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity));
+
+ return description.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetDescription(value));
+ }
+ }
+
+ public Tuple IconLocation
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder icon = new StringBuilder(INFOTIPSIZE);
+
+ int index;
+ VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index));
+
+ return new Tuple(icon.ToString(), index);
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2));
+ }
+ }
+
+ // AppUserModelID to be used for Windows 7 or later.
+ public string AppUserModelID
+ {
+ get
+ {
+ using (PropVariant pv = new PropVariant())
+ {
+ VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv));
+
+ if (pv.Value == null)
+ return "Null";
+ else
+ return pv.Value;
+ }
+ }
+ set
+ {
+ using (PropVariant pv = new PropVariant(value))
+ {
+ VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv));
+ VerifySucceeded(PropertyStore.Commit());
+ }
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public ShellLink()
+ : this(null)
+ { }
+
+ // Construct with loading shortcut file.
+ public ShellLink(string file)
+ {
+ try
+ {
+ shellLinkW = (IShellLinkW)new CShellLink();
+ }
+ catch
+ {
+ throw new COMException("Failed to create ShellLink object.");
+ }
+
+ if (file != null)
+ Load(file);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~ShellLink()
+ {
+ Dispose(false);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (shellLinkW != null)
+ {
+ // Release all references.
+ Marshal.FinalReleaseComObject(shellLinkW);
+ shellLinkW = null;
+ }
+ }
+
+ #endregion
+
+ #region Methods
+
+ // Save shortcut file.
+ public void Save()
+ {
+ string file = ShortcutFile;
+
+ if (file == null)
+ throw new InvalidOperationException("File name is not given.");
+ else
+ Save(file);
+ }
+
+ public void Save(string file)
+ {
+ if (file == null)
+ throw new ArgumentNullException("File name is required.");
+ else
+ PersistFile.Save(file, true);
+ }
+
+ // Load shortcut file.
+ public void Load(string file)
+ {
+ if (!File.Exists(file))
+ throw new FileNotFoundException("File is not found.", file);
+ else
+ PersistFile.Load(file, STGM_READ);
+ }
+
+ // Verify if operation succeeded.
+ public static void VerifySucceeded(uint hresult)
+ {
+ if (hresult > 1)
+ throw new InvalidOperationException("Failed with HRESULT: " +
+ hresult.ToString("X"));
+ }
+
+ #endregion
+ }
+}
diff --git a/JumpListUtil/packages.config b/JumpListUtil/packages.config
new file mode 100755
index 0000000..abb0b89
--- /dev/null
+++ b/JumpListUtil/packages.config
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Program.cs b/Program.cs
deleted file mode 100755
index 17420a8..0000000
--- a/Program.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-using System.Windows.Shell;
-
-namespace JumpListTest
-{
- static class Program
- {
- ///
- /// The main entry point for the application.
- ///
- [STAThread]
- static void Main()
- {
- System.Windows.Application wpfApp = new System.Windows.Application();
- JumpTask task = new JumpTask();
- task.ApplicationPath = "wt.exe";
- task.Description = "Work Terminal";
- task.Title = "Terminal";
- JumpList.SetJumpList(wpfApp, new JumpList(new List { task }, false, false));
-
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- Application.Run();
-
-
- }
- }
-}
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
deleted file mode 100755
index 1b650b3..0000000
--- a/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-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("JumpListTest")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("JumpListTest")]
-[assembly: AssemblyCopyright("Copyright © 2020")]
-[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("66f50737-a71d-4d5b-83f2-4f06b9f9f9b2")]
-
-// 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/Properties/Resources.Designer.cs b/Properties/Resources.Designer.cs
deleted file mode 100755
index f29ecc8..0000000
--- a/Properties/Resources.Designer.cs
+++ /dev/null
@@ -1,71 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// 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 JumpListTest.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("JumpListTest.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/Properties/Resources.resx b/Properties/Resources.resx
deleted file mode 100755
index ffecec8..0000000
--- a/Properties/Resources.resx
+++ /dev/null
@@ -1,117 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 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/Properties/Settings.Designer.cs b/Properties/Settings.Designer.cs
deleted file mode 100755
index fa4d9ff..0000000
--- a/Properties/Settings.Designer.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-//------------------------------------------------------------------------------
-//
-// 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 JumpListTest.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/Properties/Settings.settings b/Properties/Settings.settings
deleted file mode 100755
index abf36c5..0000000
--- a/Properties/Settings.settings
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
diff --git a/SetLnkApp/Program.cs b/SetLnkApp/Program.cs
new file mode 100755
index 0000000..08a160a
--- /dev/null
+++ b/SetLnkApp/Program.cs
@@ -0,0 +1,34 @@
+using ShellLinkPlus;
+using System;
+using System.IO;
+using System.Linq;
+
+namespace SetLnkApp
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ bool existing = File.Exists(args[0]);
+ using (ShellLink shortcut = new ShellLink(existing ? args[0] : null))
+ {
+ if (existing)
+ {
+ if (args.Length > 2)
+ {
+ throw new Exception("For an existing shortcut, only pass AppUserModelId");
+ }
+ }
+ else
+ {
+ shortcut.TargetPath = args[2];
+ //shortcut.Arguments = args.Length > 3 ? string.Join(" ", args.Skip(3)) : "";
+ shortcut.Arguments = string.Join(" ", args.Skip(3));
+ }
+ shortcut.AppUserModelID = args[1];
+
+ shortcut.Save(args[0]);
+ }
+ }
+ }
+}
diff --git a/SetLnkApp/Properties/launchSettings.json b/SetLnkApp/Properties/launchSettings.json
new file mode 100755
index 0000000..420478a
--- /dev/null
+++ b/SetLnkApp/Properties/launchSettings.json
@@ -0,0 +1,7 @@
+{
+ "profiles": {
+ "SetLnkApp": {
+ "commandName": "Project"
+ }
+ }
+}
\ No newline at end of file
diff --git a/SetLnkApp/SetLnkApp.csproj b/SetLnkApp/SetLnkApp.csproj
new file mode 100755
index 0000000..d453e9a
--- /dev/null
+++ b/SetLnkApp/SetLnkApp.csproj
@@ -0,0 +1,8 @@
+
+
+
+ Exe
+ netcoreapp3.1
+
+
+
diff --git a/SetLnkApp/ShellLink.cs b/SetLnkApp/ShellLink.cs
new file mode 100755
index 0000000..6d13f4e
--- /dev/null
+++ b/SetLnkApp/ShellLink.cs
@@ -0,0 +1,486 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using System.Text;
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+/****************************************************************************
+ * Code From: https://emoacht.wordpress.com/2012/11/14/csharp-appusermodelid/
+ ***************************************************************************/
+
+namespace ShellLinkPlus
+{
+ // Modified from http://smdn.jp/programming/tips/createlnk/
+ // Originally from http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects
+ // /Creating_and_Modifying_Shortcuts/article.asp
+ // Partly based on Sending toast notifications from desktop apps sample
+ public class ShellLink : IDisposable
+ {
+ #region Win32 and COM
+
+ // IShellLink Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("000214F9-0000-0000-C000-000000000046")]
+ private interface IShellLinkW
+ {
+ uint GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile,
+ int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags);
+ uint GetIDList(out IntPtr ppidl);
+ uint SetIDList(IntPtr pidl);
+ uint GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName,
+ int cchMaxName);
+ uint SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
+ uint GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir,
+ int cchMaxPath);
+ uint SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
+ uint GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs,
+ int cchMaxPath);
+ uint SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
+ uint GetHotKey(out ushort pwHotkey);
+ uint SetHotKey(ushort wHotKey);
+ uint GetShowCmd(out int piShowCmd);
+ uint SetShowCmd(int iShowCmd);
+ uint GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath,
+ int cchIconPath, out int piIcon);
+ uint SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
+ uint SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel,
+ uint dwReserved);
+ uint Resolve(IntPtr hwnd, uint fFlags);
+ uint SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
+ }
+
+ // ShellLink CoClass (ShellLink object)
+ [ComImport,
+ ClassInterface(ClassInterfaceType.None),
+ Guid("00021401-0000-0000-C000-000000000046")]
+ private class CShellLink { }
+
+ // WIN32_FIND_DATAW Structure
+ [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]
+ private struct WIN32_FIND_DATAW
+ {
+ public uint dwFileAttributes;
+ public ComTypes.FILETIME ftCreationTime;
+ public ComTypes.FILETIME ftLastAccessTime;
+ public ComTypes.FILETIME ftLastWriteTime;
+ public uint nFileSizeHigh;
+ public uint nFileSizeLow;
+ public uint dwReserved0;
+ public uint dwReserved1;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
+ public string cFileName;
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
+ public string cAlternateFileName;
+ }
+
+ // IPropertyStore Interface
+ [ComImport,
+ InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
+ Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")]
+ private interface IPropertyStore
+ {
+ uint GetCount([Out] out uint cProps);
+ uint GetAt([In] uint iProp, out PropertyKey pkey);
+ uint GetValue([In] ref PropertyKey key, [Out] PropVariant pv);
+ uint SetValue([In] ref PropertyKey key, [In] PropVariant pv);
+ uint Commit();
+ }
+
+ // PropertyKey Structure
+ // Narrowed down from PropertyKey.cs of Windows API Code Pack 1.1
+ [StructLayout(LayoutKind.Sequential, Pack = 4)]
+ private struct PropertyKey
+ {
+ #region Fields
+
+ private Guid formatId; // Unique GUID for property
+ private Int32 propertyId; // Property identifier (PID)
+
+ #endregion
+
+ #region Public Properties
+
+ public Guid FormatId
+ {
+ get
+ {
+ return formatId;
+ }
+ }
+
+ public Int32 PropertyId
+ {
+ get
+ {
+ return propertyId;
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropertyKey(Guid formatId, Int32 propertyId)
+ {
+ this.formatId = formatId;
+ this.propertyId = propertyId;
+ }
+
+ public PropertyKey(string formatId, Int32 propertyId)
+ {
+ this.formatId = new Guid(formatId);
+ this.propertyId = propertyId;
+ }
+
+ #endregion
+ }
+
+ // PropVariant Class (only for string value)
+ // Narrowed down from PropVariant.cs of Windows API Code Pack 1.1
+ // Originally from http://blogs.msdn.com/b/adamroot/archive/2008/04/11
+ // /interop-with-propvariants-in-net.aspx
+ [StructLayout(LayoutKind.Explicit)]
+ private sealed class PropVariant : IDisposable
+ {
+ #region Fields
+
+ [FieldOffset(0)]
+ ushort valueType; // Value type
+
+ // [FieldOffset(2)]
+ // ushort wReserved1; // Reserved field
+ // [FieldOffset(4)]
+ // ushort wReserved2; // Reserved field
+ // [FieldOffset(6)]
+ // ushort wReserved3; // Reserved field
+
+ [FieldOffset(8)]
+ IntPtr ptr; // Value
+
+ #endregion
+
+ #region Public Properties
+
+ // Value type (System.Runtime.InteropServices.VarEnum)
+ public VarEnum VarType
+ {
+ get { return (VarEnum)valueType; }
+ set { valueType = (ushort)value; }
+ }
+
+ // Whether value is empty or null
+ public bool IsNullOrEmpty
+ {
+ get
+ {
+ return (valueType == (ushort)VarEnum.VT_EMPTY ||
+ valueType == (ushort)VarEnum.VT_NULL);
+ }
+ }
+
+ // Value (only for string value)
+ public string Value
+ {
+ get
+ {
+ return Marshal.PtrToStringUni(ptr);
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public PropVariant()
+ { }
+
+ // Construct with string value
+ public PropVariant(string value)
+ {
+ if (value == null)
+ throw new ArgumentException("Failed to set value.");
+
+ valueType = (ushort)VarEnum.VT_LPWSTR;
+ ptr = Marshal.StringToCoTaskMemUni(value);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~PropVariant()
+ {
+ Dispose();
+ }
+
+ public void Dispose()
+ {
+ PropVariantClear(this);
+ GC.SuppressFinalize(this);
+ }
+
+ #endregion
+ }
+
+ [DllImport("Ole32.dll", PreserveSig = false)]
+ private extern static void PropVariantClear([In, Out] PropVariant pvar);
+
+ #endregion
+
+ #region Fields
+
+ private IShellLinkW shellLinkW = null;
+
+ // Name = System.AppUserModel.ID
+ // ShellPKey = PKEY_AppUserModel_ID
+ // FormatID = 9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3
+ // PropID = 5
+ // Type = String (VT_LPWSTR)
+ private readonly PropertyKey AppUserModelIDKey =
+ new PropertyKey("{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}", 5);
+
+ private const int MAX_PATH = 260;
+ private const int INFOTIPSIZE = 1024;
+
+ private const int STGM_READ = 0x00000000; // STGM constants
+ private const uint SLGP_UNCPRIORITY = 0x0002; // SLGP flags
+
+ #endregion
+
+ #region Private Properties (Interfaces)
+
+ private IPersistFile PersistFile
+ {
+ get
+ {
+ IPersistFile PersistFile = shellLinkW as IPersistFile;
+
+ if (PersistFile == null)
+ throw new COMException("Failed to create IPersistFile.");
+ else
+ return PersistFile;
+ }
+ }
+
+ private IPropertyStore PropertyStore
+ {
+ get
+ {
+ IPropertyStore PropertyStore = shellLinkW as IPropertyStore;
+
+ if (PropertyStore == null)
+ throw new COMException("Failed to create IPropertyStore.");
+ else
+ return PropertyStore;
+ }
+ }
+
+ #endregion
+
+ #region Public Properties (Minimal)
+
+ // Path of loaded shortcut file
+ public string ShortcutFile
+ {
+ get
+ {
+ string shortcutFile;
+
+ PersistFile.GetCurFile(out shortcutFile);
+
+ return shortcutFile;
+ }
+ }
+
+ // Path of target file
+ public string TargetPath
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder targetPath = new StringBuilder(MAX_PATH);
+
+ WIN32_FIND_DATAW data = new WIN32_FIND_DATAW();
+
+ VerifySucceeded(shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data,
+ SLGP_UNCPRIORITY));
+
+ return targetPath.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetPath(value));
+ }
+ }
+
+ public string Arguments
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder arguments = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(arguments, arguments.Capacity));
+
+ return arguments.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetArguments(value));
+ }
+ }
+
+ public string Description
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder description = new StringBuilder(INFOTIPSIZE);
+
+ VerifySucceeded(shellLinkW.GetArguments(description, description.Capacity));
+
+ return description.ToString();
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetDescription(value));
+ }
+ }
+
+ public Tuple IconLocation
+ {
+ get
+ {
+ // No limitation to length of buffer string in the case of Unicode though.
+ StringBuilder icon = new StringBuilder(INFOTIPSIZE);
+
+ int index;
+ VerifySucceeded(shellLinkW.GetIconLocation(icon, icon.Capacity, out index));
+
+ return new Tuple(icon.ToString(), index);
+ }
+ set
+ {
+ VerifySucceeded(shellLinkW.SetIconLocation(value.Item1, value.Item2));
+ }
+ }
+
+ // AppUserModelID to be used for Windows 7 or later.
+ public string AppUserModelID
+ {
+ get
+ {
+ using (PropVariant pv = new PropVariant())
+ {
+ VerifySucceeded(PropertyStore.GetValue(AppUserModelIDKey, pv));
+
+ if (pv.Value == null)
+ return "Null";
+ else
+ return pv.Value;
+ }
+ }
+ set
+ {
+ using (PropVariant pv = new PropVariant(value))
+ {
+ VerifySucceeded(PropertyStore.SetValue(AppUserModelIDKey, pv));
+ VerifySucceeded(PropertyStore.Commit());
+ }
+ }
+ }
+
+ #endregion
+
+ #region Constructor
+
+ public ShellLink()
+ : this(null)
+ { }
+
+ // Construct with loading shortcut file.
+ public ShellLink(string file)
+ {
+ try
+ {
+ shellLinkW = (IShellLinkW)new CShellLink();
+ }
+ catch
+ {
+ throw new COMException("Failed to create ShellLink object.");
+ }
+
+ if (file != null)
+ Load(file);
+ }
+
+ #endregion
+
+ #region Destructor
+
+ ~ShellLink()
+ {
+ Dispose(false);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (shellLinkW != null)
+ {
+ // Release all references.
+ Marshal.FinalReleaseComObject(shellLinkW);
+ shellLinkW = null;
+ }
+ }
+
+ #endregion
+
+ #region Methods
+
+ // Save shortcut file.
+ public void Save()
+ {
+ string file = ShortcutFile;
+
+ if (file == null)
+ throw new InvalidOperationException("File name is not given.");
+ else
+ Save(file);
+ }
+
+ public void Save(string file)
+ {
+ if (file == null)
+ throw new ArgumentNullException("File name is required.");
+ else
+ PersistFile.Save(file, true);
+ }
+
+ // Load shortcut file.
+ public void Load(string file)
+ {
+ if (!File.Exists(file))
+ throw new FileNotFoundException("File is not found.", file);
+ else
+ PersistFile.Load(file, STGM_READ);
+ }
+
+ // Verify if operation succeeded.
+ public static void VerifySucceeded(uint hresult)
+ {
+ if (hresult > 1)
+ throw new InvalidOperationException("Failed with HRESULT: " +
+ hresult.ToString("X"));
+ }
+
+ #endregion
+ }
+}