diff --git a/ShareX.Steam/CSteamworks.dll b/ShareX.Steam/CSteamworks.dll new file mode 100644 index 000000000..006067d74 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 000000000..5012ff4f1 --- /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 000000000..c0d147050 --- /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 000000000..f253b477c --- /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 000000000..d182c29c2 --- /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 000000000..d020168ba --- /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 000000000..fbdb38ee3 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 000000000..067684798 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 000000000..f4eed1950 --- /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 000000000..8ac7a9735 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 000000000..8ceecdb45 --- /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 f3df12671..e73655e4f 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 000000000..472cbe895 --- /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