├── MetroForSteamAutoUpdater
├── FodyWeavers.xml
├── steamIcon.ico
├── Models
│ ├── Steam.cs
│ ├── Package.cs
│ └── AppSetting.cs
├── App.config
├── Properties
│ ├── Settings.settings
│ ├── Settings.Designer.cs
│ └── AssemblyInfo.cs
├── packages.config
├── Helpers
│ ├── ConsoleHelper.cs
│ └── RegistryHelper.cs
├── MetroForSteamAutoUpdater.csproj
└── Program.cs
├── MetroForSteamAutoUpdater.sln
├── LICENSE
├── README.md
└── .gitignore
/MetroForSteamAutoUpdater/FodyWeavers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/MetroForSteamAutoUpdater/steamIcon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Hertizch/MetroForSteamAutoUpdater/HEAD/MetroForSteamAutoUpdater/steamIcon.ico
--------------------------------------------------------------------------------
/MetroForSteamAutoUpdater/Models/Steam.cs:
--------------------------------------------------------------------------------
1 | namespace MetroForSteamAutoUpdater.Models
2 | {
3 | public static class Steam
4 | {
5 | public static string SkinsPath { get; set; }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/MetroForSteamAutoUpdater/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/MetroForSteamAutoUpdater/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/MetroForSteamAutoUpdater/Models/Package.cs:
--------------------------------------------------------------------------------
1 | namespace MetroForSteamAutoUpdater.Models
2 | {
3 | public static class Package
4 | {
5 | public static string DownloadUrl { get; set; }
6 |
7 | public static string DownloadPath { get; set; }
8 |
9 | public static string ThemeName { get; set; }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/MetroForSteamAutoUpdater/Models/AppSetting.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 |
3 | namespace MetroForSteamAutoUpdater.Models
4 | {
5 | public static class AppSetting
6 | {
7 | public static string Name { get; set; } = Assembly.GetExecutingAssembly().GetName().Name;
8 |
9 | public static string LogFilename { get; set; } = $"{Assembly.GetExecutingAssembly().GetName().Name}.log";
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/MetroForSteamAutoUpdater/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/MetroForSteamAutoUpdater/Helpers/ConsoleHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace MetroForSteamAutoUpdater.Helpers
4 | {
5 | public static class ConsoleHelper
6 | {
7 | ///
8 | /// Write errors to console
9 | ///
10 | /// Value to write
11 | public static void WriteError(string value)
12 | {
13 | Console.ForegroundColor = ConsoleColor.Red;
14 | Console.WriteLine($"{value}");
15 | Console.ResetColor();
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/MetroForSteamAutoUpdater/Helpers/RegistryHelper.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using Microsoft.Win32;
3 |
4 | namespace MetroForSteamAutoUpdater.Helpers
5 | {
6 | public static class RegistryHelper
7 | {
8 | ///
9 | /// Gets the Steam skins path from the registry
10 | ///
11 | ///
12 | public static string GetSteamSkinsPath()
13 | {
14 | string path = null;
15 |
16 | using (var registryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Valve\\Steam"))
17 | {
18 | var value = registryKey?.GetValue("SteamPath");
19 | if (value != null)
20 | path = Path.Combine(value.ToString().Replace(@"/", @"\"), "skins");
21 | }
22 |
23 | return path;
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/MetroForSteamAutoUpdater.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25123.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MetroForSteamAutoUpdater", "MetroForSteamAutoUpdater\MetroForSteamAutoUpdater.csproj", "{CE368B88-80F0-4DB3-814B-95753C5A9981}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {CE368B88-80F0-4DB3-814B-95753C5A9981}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {CE368B88-80F0-4DB3-814B-95753C5A9981}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {CE368B88-80F0-4DB3-814B-95753C5A9981}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {CE368B88-80F0-4DB3-814B-95753C5A9981}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/MetroForSteamAutoUpdater/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace MetroForSteamAutoUpdater.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ##This project is dead and buried. Would not advice attempting to use it.
2 |
3 | # Metro For Steam Auto-Updater
4 | Automatically updates the Steam Metro skin by BoneyardBrew: http://metroforsteam.com/. Should work on all versions of Windows, as long as you have .NET 4.5.2 or higher installed. Please report any issues or bugs ;)
5 |
6 | ## Features
7 | - Downloads the latest version of the skin, and extracts it to your steam skins folder.
8 | - Automatically detects your steam install location.
9 | - Does not overwrite your custom.styles -- unless the updated package contains a newer version.
10 |
11 | ## Changelog
12 |
13 | ### 1.0.9:
14 | - Removed self-updater until I can redo it
15 |
16 | ### 1.0.8:
17 | - Yet again fixed to work with new website changes
18 |
19 | ### 1.0.7:
20 | - Changed GitHub authentication
21 |
22 | ### 1.0.6:
23 | (Retracted)
24 |
25 | ### 1.0.5:
26 | - Added self-updater.
27 |
28 | ### 1.0.4:
29 | - Updated to work with the new metroforsteam website.
30 | - Updated dependencies.
31 |
32 | ### 1.0.3:
33 | - Fixed to work with the new metroforsteam.com website layout.
34 |
35 | ### 1.0.2:
36 | - Minor changes.
37 |
38 | ### 1.0.1:
39 | - Handling for unexpected errors.
40 | - Does not overwrite your custom.styles, unless the updated package contains a newer version.
41 | - Cleans up temporary file at exit.
42 | - Changed name ;)
43 |
44 | ### 1.0.0:
45 | - Initial relase.
46 |
--------------------------------------------------------------------------------
/MetroForSteamAutoUpdater/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Resources;
2 | using System.Reflection;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("Metro For Steam Auto-Updater")]
9 | [assembly: AssemblyDescription("Metro For Steam Auto-Updater")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("Hertizch.com")]
12 | [assembly: AssemblyProduct("Metro For Steam Auto-Updater")]
13 | [assembly: AssemblyCopyright("MIT")]
14 | [assembly: AssemblyTrademark("Hertizch.com")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("ce368b88-80f0-4db3-814b-95753c5a9981")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.9.0")]
36 | [assembly: AssemblyFileVersion("1.0.9.0")]
37 | [assembly: NeutralResourcesLanguage("en")]
38 |
39 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 | xApp.config
10 |
11 | # User-specific files (MonoDevelop/Xamarin Studio)
12 | *.userprefs
13 |
14 | # Build results
15 | [Dd]ebug/
16 | [Dd]ebugPublic/
17 | [Rr]elease/
18 | [Rr]eleases/
19 | x64/
20 | x86/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | artifacts/
46 |
47 | *_i.c
48 | *_p.c
49 | *_i.h
50 | *.ilk
51 | *.meta
52 | *.obj
53 | *.pch
54 | *.pdb
55 | *.pgc
56 | *.pgd
57 | *.rsp
58 | *.sbr
59 | *.tlb
60 | *.tli
61 | *.tlh
62 | *.tmp
63 | *.tmp_proj
64 | *.log
65 | *.vspscc
66 | *.vssscc
67 | .builds
68 | *.pidb
69 | *.svclog
70 | *.scc
71 |
72 | # Chutzpah Test files
73 | _Chutzpah*
74 |
75 | # Visual C++ cache files
76 | ipch/
77 | *.aps
78 | *.ncb
79 | *.opendb
80 | *.opensdf
81 | *.sdf
82 | *.cachefile
83 |
84 | # Visual Studio profiler
85 | *.psess
86 | *.vsp
87 | *.vspx
88 | *.sap
89 |
90 | # TFS 2012 Local Workspace
91 | $tf/
92 |
93 | # Guidance Automation Toolkit
94 | *.gpState
95 |
96 | # ReSharper is a .NET coding add-in
97 | _ReSharper*/
98 | *.[Rr]e[Ss]harper
99 | *.DotSettings.user
100 |
101 | # JustCode is a .NET coding add-in
102 | .JustCode
103 |
104 | # TeamCity is a build add-in
105 | _TeamCity*
106 |
107 | # DotCover is a Code Coverage Tool
108 | *.dotCover
109 |
110 | # NCrunch
111 | _NCrunch_*
112 | .*crunch*.local.xml
113 | nCrunchTemp_*
114 |
115 | # MightyMoose
116 | *.mm.*
117 | AutoTest.Net/
118 |
119 | # Web workbench (sass)
120 | .sass-cache/
121 |
122 | # Installshield output folder
123 | [Ee]xpress/
124 |
125 | # DocProject is a documentation generator add-in
126 | DocProject/buildhelp/
127 | DocProject/Help/*.HxT
128 | DocProject/Help/*.HxC
129 | DocProject/Help/*.hhc
130 | DocProject/Help/*.hhk
131 | DocProject/Help/*.hhp
132 | DocProject/Help/Html2
133 | DocProject/Help/html
134 |
135 | # Click-Once directory
136 | publish/
137 |
138 | # Publish Web Output
139 | *.[Pp]ublish.xml
140 | *.azurePubxml
141 | # TODO: Comment the next line if you want to checkin your web deploy settings
142 | # but database connection strings (with potential passwords) will be unencrypted
143 | *.pubxml
144 | *.publishproj
145 |
146 | # NuGet Packages
147 | *.nupkg
148 | # The packages folder can be ignored because of Package Restore
149 | **/packages/*
150 | # except build/, which is used as an MSBuild target.
151 | !**/packages/build/
152 | # Uncomment if necessary however generally it will be regenerated when needed
153 | #!**/packages/repositories.config
154 | # NuGet v3's project.json files produces more ignoreable files
155 | *.nuget.props
156 | *.nuget.targets
157 |
158 | # Microsoft Azure Build Output
159 | csx/
160 | *.build.csdef
161 |
162 | # Microsoft Azure Emulator
163 | ecf/
164 | rcf/
165 |
166 | # Microsoft Azure ApplicationInsights config file
167 | ApplicationInsights.config
168 |
169 | # Windows Store app package directory
170 | AppPackages/
171 | BundleArtifacts/
172 |
173 | # Visual Studio cache files
174 | # files ending in .cache can be ignored
175 | *.[Cc]ache
176 | # but keep track of directories ending in .cache
177 | !*.[Cc]ache/
178 |
179 | # Others
180 | ClientBin/
181 | ~$*
182 | *~
183 | *.dbmdl
184 | *.dbproj.schemaview
185 | *.pfx
186 | *.publishsettings
187 | node_modules/
188 | orleans.codegen.cs
189 |
190 | # RIA/Silverlight projects
191 | Generated_Code/
192 |
193 | # Backup & report files from converting an old project file
194 | # to a newer Visual Studio version. Backup files are not needed,
195 | # because we have git ;-)
196 | _UpgradeReport_Files/
197 | Backup*/
198 | UpgradeLog*.XML
199 | UpgradeLog*.htm
200 |
201 | # SQL Server files
202 | *.mdf
203 | *.ldf
204 |
205 | # Business Intelligence projects
206 | *.rdl.data
207 | *.bim.layout
208 | *.bim_*.settings
209 |
210 | # Microsoft Fakes
211 | FakesAssemblies/
212 |
213 | # GhostDoc plugin setting file
214 | *.GhostDoc.xml
215 |
216 | # Node.js Tools for Visual Studio
217 | .ntvs_analysis.dat
218 |
219 | # Visual Studio 6 build log
220 | *.plg
221 |
222 | # Visual Studio 6 workspace options file
223 | *.opt
224 |
225 | # Visual Studio LightSwitch build output
226 | **/*.HTMLClient/GeneratedArtifacts
227 | **/*.DesktopClient/GeneratedArtifacts
228 | **/*.DesktopClient/ModelManifest.xml
229 | **/*.Server/GeneratedArtifacts
230 | **/*.Server/ModelManifest.xml
231 | _Pvt_Extensions
232 |
233 | # Paket dependency manager
234 | .paket/paket.exe
235 |
236 | # FAKE - F# Make
237 | .fake/
238 |
--------------------------------------------------------------------------------
/MetroForSteamAutoUpdater/MetroForSteamAutoUpdater.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Debug
7 | AnyCPU
8 | {CE368B88-80F0-4DB3-814B-95753C5A9981}
9 | Exe
10 | Properties
11 | MetroForSteamAutoUpdater
12 | Metro For Steam Auto-Updater
13 | v4.5.2
14 | 512
15 | true
16 |
17 |
18 |
19 |
20 | AnyCPU
21 | true
22 | full
23 | false
24 | bin\Debug\
25 | DEBUG;TRACE
26 | prompt
27 | 4
28 |
29 |
30 | AnyCPU
31 | pdbonly
32 | true
33 | bin\Release\
34 | TRACE
35 | prompt
36 | 4
37 |
38 |
39 | steamIcon.ico
40 |
41 |
42 |
43 | ..\packages\DotNetZip.1.11.0\lib\net20\DotNetZip.dll
44 |
45 |
46 |
47 | ..\packages\Octokit.0.32.0\lib\net45\Octokit.dll
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | True
68 | True
69 | Settings.settings
70 |
71 |
72 |
73 |
74 |
75 |
76 | SettingsSingleFileGenerator
77 | Settings.Designer.cs
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
88 |
89 |
90 |
91 |
92 |
93 |
100 |
--------------------------------------------------------------------------------
/MetroForSteamAutoUpdater/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Globalization;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Net;
7 | using System.Reflection;
8 | using System.Text;
9 | using System.Text.RegularExpressions;
10 | using System.Threading.Tasks;
11 | using Ionic.Zip;
12 | using MetroForSteamAutoUpdater.Helpers;
13 | using MetroForSteamAutoUpdater.Models;
14 | using Octokit;
15 |
16 | namespace MetroForSteamAutoUpdater
17 | {
18 | class Program
19 | {
20 | static void Main()
21 | {
22 | // Events
23 | AppDomain.CurrentDomain.ProcessExit += (sender, eventArgs) => Cleanup();
24 | AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper;
25 |
26 | // Settings
27 | Console.Title = AppSetting.Name;
28 |
29 | Package.ThemeName = "Metro for Steam";
30 |
31 | // Main
32 | Execute();
33 |
34 | Console.ReadKey();
35 | }
36 |
37 | ///
38 | ///
39 | ///
40 | ///
41 | ///
42 | static void UnhandledExceptionTrapper(object sender, UnhandledExceptionEventArgs e)
43 | {
44 | Exception exception = null;
45 |
46 | if (e.ExceptionObject != null)
47 | {
48 | try
49 | {
50 | File.AppendAllText(AppSetting.LogFilename, e.ExceptionObject.ToString());
51 | }
52 | catch (Exception ex)
53 | {
54 | exception = ex;
55 | ConsoleHelper.WriteError($"ERROR: Could not write error details to file: {AppSetting.LogFilename} - Error message: {ex.Message}");
56 | }
57 | finally
58 | {
59 | if (exception == null)
60 | Console.WriteLine($"Error details written to file: {AppSetting.LogFilename}");
61 | }
62 | }
63 |
64 | ConsoleHelper.WriteError($"FATAL: Something went wrong! - Error details written to file: {AppSetting.LogFilename}");
65 | Console.WriteLine("Press any key to exit...");
66 | Console.ReadKey();
67 | Environment.Exit(1);
68 | }
69 |
70 | ///
71 | /// Executes all methods
72 | ///
73 | private static async void Execute()
74 | {
75 | Console.Write("Attempting to find Steam skins path...");
76 | Steam.SkinsPath = RegistryHelper.GetSteamSkinsPath();
77 |
78 | if (Directory.Exists(Steam.SkinsPath))
79 | Console.Write($"\rFound Steam skins path at: {Steam.SkinsPath}\n");
80 | else
81 | {
82 | ConsoleHelper.WriteError($"ERROR: Steam skins path does not exist at {Steam.SkinsPath}\nPlease double-check your steam path!");
83 | Console.WriteLine("Press any key to exit...");
84 | Console.ReadKey();
85 | Environment.Exit(1);
86 | }
87 |
88 | await CheckForAppUpdate();
89 |
90 | Package.DownloadUrl = await GetLatestVersion();
91 | if (Package.DownloadUrl != null)
92 | Package.DownloadPath = Path.Combine(Path.GetTempPath(), Path.GetFileName(Package.DownloadUrl));
93 |
94 | await GetPackage();
95 |
96 | ExtractPackage();
97 | }
98 |
99 | private static async Task GetLatestVersion()
100 | {
101 | string output = null;
102 | string source;
103 |
104 | using (var webClient = new WebClient())
105 | {
106 | webClient.Proxy = null;
107 |
108 | source = await webClient.DownloadStringTaskAsync("http://metroforsteam.com/");
109 | }
110 |
111 | if (source == null) return null;
112 |
113 | var regex = Regex.Match(source, "Download<\\/a>");
114 |
115 | if (regex.Success)
116 | {
117 | output = "http://metroforsteam.com/downloads/" + regex.Groups[1].Value;
118 |
119 | Debug.WriteLine($"Found latest version: {regex.Groups[1].Value}");
120 | }
121 |
122 | return output;
123 | }
124 |
125 | ///
126 | /// Downloads the update package from metroforsteam.com
127 | ///
128 | ///
129 | private static async Task GetPackage()
130 | {
131 | if (Package.DownloadUrl == null)
132 | return;
133 |
134 | // Package download client
135 | using (var webClient = new WebClient())
136 | {
137 | webClient.Proxy = null;
138 | webClient.DownloadProgressChanged += (sender, args) => Console.Write($"\rDownloading package... ({args.ProgressPercentage}%)");
139 |
140 | try
141 | {
142 | await webClient.DownloadFileTaskAsync(Package.DownloadUrl, Package.DownloadPath);
143 | }
144 | catch (Exception ex)
145 | {
146 | ConsoleHelper.WriteError($"\nERROR: Failed to download package - Error message: {ex.Message}");
147 | }
148 | finally
149 | {
150 | Console.WriteLine("");
151 | }
152 | }
153 | }
154 |
155 | ///
156 | /// Extracts the downloaded package to Steam skins folder
157 | ///
158 | private static void ExtractPackage()
159 | {
160 | var filesExtracted = 0;
161 | var foldersExtracted = 0;
162 | var skippedEntries = 0;
163 | Exception exception = null;
164 |
165 | try
166 | {
167 | using (var zip = ZipFile.Read(Package.DownloadPath))
168 | {
169 | // Get only the files we need
170 | var selection = (from entry in zip.Entries where (entry.FileName).StartsWith(Package.ThemeName) select entry);
171 |
172 | // Create base directory if it does not exist
173 | if (!Directory.Exists(Path.Combine(Steam.SkinsPath, Package.ThemeName)))
174 | {
175 | Directory.CreateDirectory(Path.Combine(Steam.SkinsPath, Package.ThemeName));
176 | Console.WriteLine($"Created directory: {Path.Combine(Steam.SkinsPath, Package.ThemeName)}");
177 | }
178 |
179 | Console.WriteLine($"Extracting package to: {Path.Combine(Steam.SkinsPath, Package.ThemeName)}");
180 |
181 | var rootFolder = Path.GetDirectoryName(zip.Entries.First(x => x.FileName.Contains(Package.ThemeName)).FileName);
182 |
183 | foreach (var entry in selection.ToList())
184 | {
185 | if (rootFolder != null)
186 | {
187 | var newName = entry.FileName.Replace(rootFolder, Package.ThemeName);
188 | entry.FileName = newName;
189 | }
190 |
191 | // Do not overwrite custom.styles (if it exists) unless package contains newer version
192 | if (entry.FileName.Contains("custom.styles") &&
193 | File.Exists(Path.Combine(Steam.SkinsPath, entry.FileName)) &&
194 | entry.LastModified <= File.GetLastWriteTime(Path.Combine(Steam.SkinsPath, entry.FileName)))
195 | {
196 | Console.WriteLine($"Skipped file: {entry.FileName} - Newer version already exists.");
197 | skippedEntries++;
198 | continue;
199 | }
200 |
201 | // Extract contents
202 | entry.Extract(Steam.SkinsPath, ExtractExistingFileAction.OverwriteSilently);
203 | Console.WriteLine($"Extracted: {entry.FileName}");
204 |
205 | // Count stuff...
206 | if (entry.IsDirectory)
207 | foldersExtracted++;
208 | else
209 | filesExtracted++;
210 | }
211 | }
212 | }
213 | catch (Exception ex)
214 | {
215 | exception = ex;
216 | ConsoleHelper.WriteError($"ERROR: Failed to extract package - Error message: {ex.Message}");
217 | }
218 | finally
219 | {
220 | if (exception == null)
221 | {
222 | Console.WriteLine($"Package extraced - ({filesExtracted} file(s) - {foldersExtracted} folder(s) - {skippedEntries} skipped file(s)).");
223 |
224 | Console.ForegroundColor = ConsoleColor.Green;
225 | Console.WriteLine("\nCOMPLETE! - You need to restart Steam for the skin to update!");
226 | Console.ResetColor();
227 |
228 | Console.WriteLine("Press any key to exit...");
229 | Console.ReadKey();
230 | }
231 | }
232 | }
233 |
234 | private static GitHubClient _gitHubClient;
235 |
236 | private static async Task CheckForAppUpdate()
237 | {
238 | Console.WriteLine($"Communicating with GitHub to check if the application needs to be updated...");
239 |
240 | _gitHubClient = new GitHubClient(new ProductHeaderValue("MetroForSteamAutoUpdater"))
241 | {
242 | Credentials = Credentials.Anonymous
243 | };
244 |
245 | // Check rate limits
246 | var rateLimits = await _gitHubClient.Miscellaneous.GetRateLimits();
247 |
248 | // Gets the TimeSpan when the rate limit resets
249 | var resetTime = DateTime.Parse(rateLimits.Resources.Core.Reset.ToString()) - DateTime.Now;
250 |
251 | // If the rate limit has exceeded, return
252 | if (rateLimits.Resources.Core.Remaining < 1)
253 | {
254 | Console.WriteLine($"Unable to check for application updates -- GitHub API request rate limit exceeded, will reset in {resetTime.Minutes} minutes");
255 | return;
256 | }
257 |
258 | // Get releases
259 | var releases = await _gitHubClient.Repository.Release.GetAll("Hertizch", "MetroForSteamAutoUpdater");
260 |
261 | // Get latest release
262 | if (releases != null)
263 | {
264 | var latestRelease = releases.First();
265 |
266 | // Get current version
267 | var assembly = Assembly.GetExecutingAssembly();
268 | var fileVersionInfo = FileVersionInfo.GetVersionInfo(assembly.Location);
269 | var currentVersion = Version.Parse(fileVersionInfo.ProductVersion);
270 |
271 | // Get latest version
272 | Version latestVersion;
273 | Version.TryParse(latestRelease.TagName.Replace("v", ""), out latestVersion);
274 |
275 | // Compare version to determine if update is needed
276 | if (latestVersion > currentVersion)
277 | {
278 | Console.WriteLine($"A newer version ({latestVersion}) of the application has been found -- download it on GitHub!");
279 |
280 | /*var browserDownloadUrl = latestRelease.Assets.First().BrowserDownloadUrl;
281 |
282 | if (browserDownloadUrl != null)
283 | await DownloadAppPackage(browserDownloadUrl, latestVersion.ToString());
284 |
285 | if (browserDownloadUrl != null)
286 | RunUpdateScript(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Path.GetFileName(browserDownloadUrl)));*/
287 | }
288 | else
289 | {
290 | Console.WriteLine($"No application updates found -- continuing...");
291 | }
292 | }
293 | else
294 | {
295 | Console.WriteLine($"No releases found");
296 | }
297 | }
298 |
299 | private static async Task DownloadAppPackage(string browserDownloadUrl, string latestVersion)
300 | {
301 | // Create the webclient
302 | var webClient = new WebClient
303 | {
304 | Proxy = null
305 | };
306 |
307 | // Add fake user agent (reqired by github api)
308 | webClient.Headers.Add("user-agent", AppSetting.Name);
309 |
310 | double progressPercentage;
311 |
312 | // Progress changed event
313 | webClient.DownloadProgressChanged += (sender, args) =>
314 | {
315 | progressPercentage = args.ProgressPercentage;
316 |
317 | if (progressPercentage.ToString(CultureInfo.InvariantCulture).Contains("-") || Math.Abs(progressPercentage) < 0.001)
318 | progressPercentage = ((double)args.BytesReceived / args.TotalBytesToReceive) * 100;
319 |
320 | Console.Write($"\rDownloading: {progressPercentage}% ({args.BytesReceived} bytes of {args.TotalBytesToReceive} bytes)");
321 | };
322 |
323 | // Download complete event
324 | webClient.DownloadFileCompleted += (sender, args) =>
325 | {
326 | Console.WriteLine(args.Error == null
327 | ? $"\nDownload complete without error!"
328 | : $"\nDownload failed: {args.Error.Message}");
329 | };
330 |
331 | // Execute download
332 | if (browserDownloadUrl != null)
333 | await webClient.DownloadFileTaskAsync(browserDownloadUrl, $"{Path.Combine(AppDomain.CurrentDomain.BaseDirectory, latestVersion + Path.GetFileName(browserDownloadUrl))}");
334 | }
335 |
336 | private static void RunUpdateScript(string newFilename)
337 | {
338 | var scriptFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Path.GetFileName(Path.GetTempFileName() + ".bat"));
339 |
340 | var sb = new StringBuilder();
341 |
342 | sb.AppendLine("timeout /t 2 /nobreak");
343 |
344 | if (AppSetting.Name != null)
345 | sb.AppendLine($"del \"{Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AppSetting.Name + ".exe")}\"");
346 |
347 | sb.AppendLine("timeout /t 2 /nobreak");
348 | sb.AppendLine($"ren \"{newFilename}\" \"{AppSetting.Name + ".exe"}\"");
349 | sb.AppendLine("timeout /t 2 /nobreak");
350 | sb.AppendLine($"start \"\" \"{Path.Combine(AppDomain.CurrentDomain.BaseDirectory, AppSetting.Name + ".exe")}\"");
351 | sb.AppendLine("exit");
352 |
353 | File.WriteAllText(scriptFilename, sb.ToString());
354 |
355 | Process.Start(scriptFilename);
356 |
357 | Environment.Exit(2);
358 | }
359 |
360 | ///
361 | /// Cleans up the temporary downloaded package zip file
362 | ///
363 | private static void Cleanup()
364 | {
365 | if (!File.Exists(Package.DownloadPath)) return;
366 |
367 | Exception exception = null;
368 |
369 | try
370 | {
371 | File.Delete(Package.DownloadPath);
372 | }
373 | catch (Exception ex)
374 | {
375 | exception = ex;
376 | ConsoleHelper.WriteError($"ERROR: Failed to delete file: {Package.DownloadPath} - Error message: {ex.Message}");
377 | }
378 | finally
379 | {
380 | if (exception == null)
381 | Console.WriteLine($"Deleted temporary file: {Package.DownloadPath}");
382 | }
383 | }
384 | }
385 | }
386 |
--------------------------------------------------------------------------------