diff --git a/ShareX.Steam/CSteamworks.dll b/ShareX.Steam/CSteamworks.dll
new file mode 100644
index 00000000000..006067d749f
Binary files /dev/null and b/ShareX.Steam/CSteamworks.dll differ
diff --git a/ShareX.Steam/Helpers.cs b/ShareX.Steam/Helpers.cs
new file mode 100644
index 00000000000..5012ff4f1ba
--- /dev/null
+++ b/ShareX.Steam/Helpers.cs
@@ -0,0 +1,129 @@
+#region License Information (GPL v3)
+
+/*
+ ShareX - A program that allows you to take screenshots and share any file type
+ Copyright (c) 2007-2016 ShareX Team
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Optionally you can also view the license at .
+*/
+
+#endregion License Information (GPL v3)
+
+using System;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Windows.Forms;
+
+namespace ShareX.Steam
+{
+ public static class Helpers
+ {
+ [DllImport("kernel32.dll")]
+ public static extern uint WinExec(string lpCmdLine, uint uCmdShow);
+
+ public static string GetAbsolutePath(string path)
+ {
+ if (!Path.IsPathRooted(path)) // Is relative path?
+ {
+ path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, path);
+ }
+
+ return Path.GetFullPath(path);
+ }
+
+ public static bool IsRunning(string name)
+ {
+ bool createdNew = true;
+
+ try
+ {
+ using (Mutex mutex = new Mutex(false, name, out createdNew))
+ {
+ }
+ }
+ catch
+ {
+ }
+
+ return !createdNew;
+ }
+
+ ///
+ /// If version1 newer than version2 = 1
+ /// If version1 equal to version2 = 0
+ /// If version1 older than version2 = -1
+ ///
+ public static int CompareVersion(string version1, string version2)
+ {
+ return ParseVersion(version1).CompareTo(ParseVersion(version2));
+ }
+
+ private static Version ParseVersion(string version)
+ {
+ return NormalizeVersion(Version.Parse(version));
+ }
+
+ private static Version NormalizeVersion(Version version)
+ {
+ return new Version(Math.Max(version.Major, 0), Math.Max(version.Minor, 0), Math.Max(version.Build, 0), Math.Max(version.Revision, 0));
+ }
+
+ public static void ShowError(Exception e)
+ {
+ MessageBox.Show(e.ToString(), "ShareX - Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+
+ public static void CopyAll(string sourceDirectory, string targetDirectory)
+ {
+ DirectoryInfo diSource = new DirectoryInfo(sourceDirectory);
+ DirectoryInfo diTarget = new DirectoryInfo(targetDirectory);
+
+ CopyAll(diSource, diTarget);
+ }
+
+ public static void CopyAll(DirectoryInfo source, DirectoryInfo target)
+ {
+ if (!Directory.Exists(target.FullName))
+ {
+ Directory.CreateDirectory(target.FullName);
+ }
+
+ foreach (FileInfo fi in source.GetFiles())
+ {
+ fi.CopyTo(Path.Combine(target.FullName, fi.Name), true);
+ }
+
+ foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
+ {
+ DirectoryInfo nextTargetSubDir = target.CreateSubdirectory(diSourceSubDir.Name);
+ CopyAll(diSourceSubDir, nextTargetSubDir);
+ }
+ }
+
+ public static bool IsCommandExist(string[] args, string command)
+ {
+ if (args != null && !string.IsNullOrEmpty(command))
+ {
+ return args.Any(arg => !string.IsNullOrEmpty(arg) && arg.Equals(command, StringComparison.InvariantCultureIgnoreCase));
+ }
+
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ShareX.Steam/Launcher.cs b/ShareX.Steam/Launcher.cs
new file mode 100644
index 00000000000..c0d1470506d
--- /dev/null
+++ b/ShareX.Steam/Launcher.cs
@@ -0,0 +1,267 @@
+#region License Information (GPL v3)
+
+/*
+ ShareX - A program that allows you to take screenshots and share any file type
+ Copyright (c) 2007-2016 ShareX Team
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Optionally you can also view the license at .
+*/
+
+#endregion License Information (GPL v3)
+
+using Steamworks;
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Threading;
+using System.Windows.Forms;
+
+namespace ShareX.Steam
+{
+ public static class Launcher
+ {
+ private static string ContentFolderPath => Helpers.GetAbsolutePath("ShareX");
+ private static string ContentExecutablePath => Path.Combine(ContentFolderPath, "ShareX.exe");
+ private static string ContentSteamFilePath => Path.Combine(ContentFolderPath, "Steam");
+ private static string UpdateFolderPath => Helpers.GetAbsolutePath("Updates");
+ private static string UpdateExecutablePath => Path.Combine(UpdateFolderPath, "ShareX.exe");
+ private static string UpdatingTempFilePath => Path.Combine(ContentFolderPath, "Updating");
+
+ private static bool IsFirstTimeRunning { get; set; }
+ private static bool IsStartupRun { get; set; }
+ private static bool ShowInApp => File.Exists(ContentSteamFilePath);
+
+ public static void Run(string[] args)
+ {
+ Stopwatch startTimer = Stopwatch.StartNew();
+
+ if (Helpers.IsCommandExist(args, "-uninstall"))
+ {
+ UninstallShareX();
+ return;
+ }
+
+ bool isSteamInit = false;
+
+ IsStartupRun = Helpers.IsCommandExist(args, "-silent");
+
+ if (!IsShareXRunning())
+ {
+ // If running on startup and need to show "In-app" then wait until Steam is open
+ if (IsStartupRun && ShowInApp)
+ {
+ for (int i = 0; i < 10 && !SteamAPI.IsSteamRunning(); i++)
+ {
+ Thread.Sleep(1000);
+ }
+ }
+
+ if (SteamAPI.IsSteamRunning())
+ {
+ isSteamInit = SteamAPI.Init();
+ }
+
+ if (IsUpdateRequired())
+ {
+ DoUpdate();
+ }
+
+ if (isSteamInit)
+ {
+ SteamAPI.Shutdown();
+ }
+ }
+
+ if (File.Exists(ContentExecutablePath))
+ {
+ string arguments = "";
+
+ if (IsFirstTimeRunning)
+ {
+ // Show first time config window
+ arguments = "-SteamConfig";
+ }
+ else if (IsStartupRun)
+ {
+ // Don't show ShareX main window
+ arguments = "-silent";
+ }
+
+ RunShareX(arguments);
+
+ if (isSteamInit)
+ {
+ // Reason for this workaround because Steam only allows writing review if you played game at least 5 minutes
+ // So launcher will stay on for 10 seconds and eventually users can reach 5 minutes that way (It will require 30 times opening)
+ // Otherwise nobody can write review
+ int waitTime = 10000 - (int)startTimer.ElapsedMilliseconds;
+
+ if (waitTime > 0)
+ {
+ Thread.Sleep(waitTime);
+ }
+ }
+ }
+ }
+
+ private static bool IsShareXRunning()
+ {
+ // Check ShareX mutex
+ return Helpers.IsRunning("82E6AC09-0FEF-4390-AD9F-0DD3F5561EFC");
+ }
+
+ private static bool IsUpdateRequired()
+ {
+ try
+ {
+ // First time running?
+ if (!Directory.Exists(ContentFolderPath) || !File.Exists(ContentExecutablePath))
+ {
+ IsFirstTimeRunning = true;
+ return true;
+ }
+
+ // Need repair?
+ if (File.Exists(UpdatingTempFilePath))
+ {
+ return true;
+ }
+
+ // Need update?
+ FileVersionInfo contentVersionInfo = FileVersionInfo.GetVersionInfo(ContentExecutablePath);
+ FileVersionInfo updateVersionInfo = FileVersionInfo.GetVersionInfo(UpdateExecutablePath);
+
+ return Helpers.CompareVersion(contentVersionInfo.FileVersion, updateVersionInfo.FileVersion) < 0;
+ }
+ catch (Exception e)
+ {
+ Helpers.ShowError(e);
+ }
+
+ return false;
+ }
+
+ private static void DoUpdate()
+ {
+ try
+ {
+ if (!Directory.Exists(ContentFolderPath))
+ {
+ Directory.CreateDirectory(ContentFolderPath);
+ }
+
+ // In case updating terminate middle of it, in next Launcher start it can repair
+ File.Create(UpdatingTempFilePath).Dispose();
+ Helpers.CopyAll(UpdateFolderPath, ContentFolderPath);
+ File.Delete(UpdatingTempFilePath);
+ }
+ catch (Exception e)
+ {
+ Helpers.ShowError(e);
+ }
+ }
+
+ private static void RunShareX(string arguments = "")
+ {
+ try
+ {
+ if (ShowInApp)
+ {
+ ProcessStartInfo startInfo = new ProcessStartInfo()
+ {
+ Arguments = arguments,
+ FileName = ContentExecutablePath,
+ UseShellExecute = true
+ };
+
+ Process.Start(startInfo);
+ }
+ else
+ {
+ try
+ {
+ // Workaround for don't show "In-app"
+ uint result = Helpers.WinExec($"\"{ContentExecutablePath}\" {arguments}", 5);
+
+ // If the function succeeds, the return value is greater than 31
+ if (result > 31)
+ {
+ return;
+ }
+ }
+ catch { }
+
+ // Workaround 2
+ string path = Path.Combine(Environment.SystemDirectory, "cmd.exe");
+
+ if (!File.Exists(path))
+ {
+ path = "cmd.exe";
+ }
+
+ ProcessStartInfo startInfo = new ProcessStartInfo()
+ {
+ Arguments = $"/C start \"\" \"{ContentExecutablePath}\" {arguments}",
+ CreateNoWindow = true,
+ FileName = path,
+ UseShellExecute = false
+ };
+
+ Process.Start(startInfo);
+ }
+ }
+ catch (Exception e)
+ {
+ Helpers.ShowError(e);
+ }
+ }
+
+ private static void UninstallShareX()
+ {
+ try
+ {
+ while (IsShareXRunning())
+ {
+ if (MessageBox.Show("ShareX is currently running.\r\n\r\nPlease close ShareX and press \"Retry\" button after it is closed.", "ShareX - Uninstaller",
+ MessageBoxButtons.RetryCancel, MessageBoxIcon.Warning) == DialogResult.Cancel)
+ {
+ return;
+ }
+ }
+
+ if (Directory.Exists(ContentFolderPath))
+ {
+ if (File.Exists(ContentExecutablePath))
+ {
+ Process process = Process.Start(ContentExecutablePath, "-uninstall");
+
+ if (process != null)
+ {
+ process.WaitForExit();
+ }
+ }
+
+ Directory.Delete(ContentFolderPath, true);
+ }
+ }
+ catch (Exception e)
+ {
+ Helpers.ShowError(e);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ShareX.Steam/Program.cs b/ShareX.Steam/Program.cs
new file mode 100644
index 00000000000..f253b477cda
--- /dev/null
+++ b/ShareX.Steam/Program.cs
@@ -0,0 +1,40 @@
+#region License Information (GPL v3)
+
+/*
+ ShareX - A program that allows you to take screenshots and share any file type
+ Copyright (c) 2007-2016 ShareX Team
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Optionally you can also view the license at .
+*/
+
+#endregion License Information (GPL v3)
+
+using System.Windows.Forms;
+
+namespace ShareX.Steam
+{
+ internal static class Program
+ {
+ private static void Main(string[] args)
+ {
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+
+ Launcher.Run(args);
+ }
+ }
+}
\ No newline at end of file
diff --git a/ShareX.Steam/Properties/AssemblyInfo.cs b/ShareX.Steam/Properties/AssemblyInfo.cs
new file mode 100644
index 00000000000..d182c29c204
--- /dev/null
+++ b/ShareX.Steam/Properties/AssemblyInfo.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+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("ShareX Launcher")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("ShareX Team")]
+[assembly: AssemblyProduct("ShareX")]
+[assembly: AssemblyCopyright("Copyright (c) 2007-2016 ShareX Team")]
+[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("7f6adfc5-2563-4a5f-b202-93b553578719")]
+
+// 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")]
\ No newline at end of file
diff --git a/ShareX.Steam/ShareX.Steam.csproj b/ShareX.Steam/ShareX.Steam.csproj
new file mode 100644
index 00000000000..d020168ba69
--- /dev/null
+++ b/ShareX.Steam/ShareX.Steam.csproj
@@ -0,0 +1,78 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {7F6ADFC5-2563-4A5F-B202-93B553578719}
+ WinExe
+ Properties
+ ShareX.Steam
+ ShareX_Launcher
+ v4.0
+ 512
+
+
+ x86
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ Off
+
+
+ x86
+ none
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ Off
+
+
+ ShareX_Icon.ico
+
+
+
+ False
+ .\Steamworks.NET.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+
+
+
\ No newline at end of file
diff --git a/ShareX.Steam/ShareX_Icon.ico b/ShareX.Steam/ShareX_Icon.ico
new file mode 100644
index 00000000000..fbdb38ee346
Binary files /dev/null and b/ShareX.Steam/ShareX_Icon.ico differ
diff --git a/ShareX.Steam/Steamworks.NET.dll b/ShareX.Steam/Steamworks.NET.dll
new file mode 100644
index 00000000000..06768479800
Binary files /dev/null and b/ShareX.Steam/Steamworks.NET.dll differ
diff --git a/ShareX.Steam/installscript.vdf b/ShareX.Steam/installscript.vdf
new file mode 100644
index 00000000000..f4eed1950b2
--- /dev/null
+++ b/ShareX.Steam/installscript.vdf
@@ -0,0 +1,11 @@
+"InstallScript"
+{
+ "Run Process On Uninstall"
+ {
+ "Uninstaller"
+ {
+ "Process 1" "%INSTALLDIR%\\ShareX_Launcher.exe"
+ "Command 1" "-uninstall"
+ }
+ }
+}
\ No newline at end of file
diff --git a/ShareX.Steam/steam_api.dll b/ShareX.Steam/steam_api.dll
new file mode 100644
index 00000000000..8ac7a973546
Binary files /dev/null and b/ShareX.Steam/steam_api.dll differ
diff --git a/ShareX.Steam/steam_appid.txt b/ShareX.Steam/steam_appid.txt
new file mode 100644
index 00000000000..8ceecdb4506
--- /dev/null
+++ b/ShareX.Steam/steam_appid.txt
@@ -0,0 +1 @@
+400040
\ No newline at end of file
diff --git a/ShareX.sln b/ShareX.sln
index f3df12671b0..e73655e4fbe 100644
--- a/ShareX.sln
+++ b/ShareX.sln
@@ -30,6 +30,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShareX.Setup", "ShareX.Setu
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShareX.MediaLib", "ShareX.MediaLib\ShareX.MediaLib.csproj", "{1A190E53-1419-4CC2-B0E5-3BC7EA861C8B}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShareX.Steam", "ShareX.Steam\ShareX.Steam.csproj", "{7F6ADFC5-2563-4A5F-B202-93B553578719}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -97,6 +99,12 @@ Global
{1A190E53-1419-4CC2-B0E5-3BC7EA861C8B}.Release|Any CPU.Build.0 = Release|Any CPU
{1A190E53-1419-4CC2-B0E5-3BC7EA861C8B}.Steam|Any CPU.ActiveCfg = Steam|Any CPU
{1A190E53-1419-4CC2-B0E5-3BC7EA861C8B}.Steam|Any CPU.Build.0 = Steam|Any CPU
+ {7F6ADFC5-2563-4A5F-B202-93B553578719}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7F6ADFC5-2563-4A5F-B202-93B553578719}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7F6ADFC5-2563-4A5F-B202-93B553578719}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7F6ADFC5-2563-4A5F-B202-93B553578719}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7F6ADFC5-2563-4A5F-B202-93B553578719}.Steam|Any CPU.ActiveCfg = Release|Any CPU
+ {7F6ADFC5-2563-4A5F-B202-93B553578719}.Steam|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/ShareX_Steam.sln b/ShareX_Steam.sln
new file mode 100644
index 00000000000..472cbe89517
--- /dev/null
+++ b/ShareX_Steam.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.23107.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShareX.Steam", "ShareX.Steam\ShareX.Steam.csproj", "{7F6ADFC5-2563-4A5F-B202-93B553578719}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {7F6ADFC5-2563-4A5F-B202-93B553578719}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7F6ADFC5-2563-4A5F-B202-93B553578719}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7F6ADFC5-2563-4A5F-B202-93B553578719}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7F6ADFC5-2563-4A5F-B202-93B553578719}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal