├── .gitattributes
├── .gitignore
├── README.md
├── SteamAccountSwitcher2.sln
├── SteamAccountSwitcher2
├── AccountLoader.cs
├── AccountType.cs
├── AccountWindow.xaml
├── AccountWindow.xaml.cs
├── App.config
├── App.xaml
├── App.xaml.cs
├── CachedAccountManager.cs
├── Encryption
│ └── EncryptionHelper.cs
├── EncryptionType.cs
├── ImageHelper.cs
├── LogWindow.xaml
├── LogWindow.xaml.cs
├── MainWindow.xaml
├── MainWindow.xaml.cs
├── PasswordWindow.xaml
├── PasswordWindow.xaml.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ ├── Settings.settings
│ └── app.manifest
├── SasManager.cs
├── Settings
│ ├── SettingsWindow.xaml
│ ├── SettingsWindow.xaml.cs
│ └── UserSettings.cs
├── Steam.cs
├── SteamAccount.cs
├── SteamAccountSwitcher.csproj
├── SteamStatus.cs
├── UserInteraction.cs
├── edit.png
├── images
│ ├── acc-bg-banned.jpg
│ ├── acc-bg-friend.jpg
│ ├── acc-bg-main.jpg
│ ├── acc-bg-smurf.jpg
│ ├── cross-button.png
│ ├── gear.png
│ ├── icons
│ │ ├── download.png
│ │ ├── edit.png
│ │ ├── export.png
│ │ ├── external.png
│ │ ├── full_trash.png
│ │ ├── import.png
│ │ ├── internal.png
│ │ ├── key.png
│ │ ├── lock.png
│ │ ├── minus.png
│ │ ├── multiple_inputs.png
│ │ ├── plus.png
│ │ ├── search.png
│ │ ├── settings.png
│ │ ├── small
│ │ │ ├── download.png
│ │ │ ├── edit.png
│ │ │ ├── export.png
│ │ │ ├── external.png
│ │ │ ├── full_trash.png
│ │ │ ├── import.png
│ │ │ ├── internal.png
│ │ │ ├── key.png
│ │ │ ├── lock.png
│ │ │ ├── minus.png
│ │ │ ├── multiple_inputs.png
│ │ │ ├── plus.png
│ │ │ ├── search.png
│ │ │ ├── settings.png
│ │ │ ├── synchronize.png
│ │ │ ├── unlock.png
│ │ │ └── upload.png
│ │ ├── synchronize.png
│ │ ├── unlock.png
│ │ └── upload.png
│ ├── lock.png
│ ├── minus-button.png
│ ├── pencil-button.png
│ ├── pencil.png
│ ├── plus-button.png
│ ├── plus.png
│ └── plus_old.png
└── packages.config
└── SteamAccountSwitcherSetup
├── SteamAccountSwitcherSetup-SetupFiles
└── SteamAccountSwitcherSetup.msi
├── SteamAccountSwitcherSetup-cache
├── cacheIndex.txt
└── part2
│ ├── disk1.cab
│ └── output-info.ini
├── SteamAccountSwitcherSetup.aip
└── SteamAccountSwitcherSetup.aiproj
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.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 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | build/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 |
28 | # MSTest test Results
29 | [Tt]est[Rr]esult*/
30 | [Bb]uild[Ll]og.*
31 |
32 | # NUNIT
33 | *.VisualState.xml
34 | TestResult.xml
35 |
36 | # Build Results of an ATL Project
37 | [Dd]ebugPS/
38 | [Rr]eleasePS/
39 | dlldata.c
40 |
41 | # DNX
42 | project.lock.json
43 | artifacts/
44 |
45 | *_i.c
46 | *_p.c
47 | *_i.h
48 | *.ilk
49 | *.meta
50 | *.obj
51 | *.pch
52 | *.pdb
53 | *.pgc
54 | *.pgd
55 | *.rsp
56 | *.sbr
57 | *.tlb
58 | *.tli
59 | *.tlh
60 | *.tmp
61 | *.tmp_proj
62 | *.log
63 | *.vspscc
64 | *.vssscc
65 | .builds
66 | *.pidb
67 | *.svclog
68 | *.scc
69 |
70 | # Chutzpah Test files
71 | _Chutzpah*
72 |
73 | # Visual C++ cache files
74 | ipch/
75 | *.aps
76 | *.ncb
77 | *.opensdf
78 | *.sdf
79 | *.cachefile
80 |
81 | # Visual Studio profiler
82 | *.psess
83 | *.vsp
84 | *.vspx
85 |
86 | # TFS 2012 Local Workspace
87 | $tf/
88 |
89 | # Guidance Automation Toolkit
90 | *.gpState
91 |
92 | # ReSharper is a .NET coding add-in
93 | _ReSharper*/
94 | *.[Rr]e[Ss]harper
95 | *.DotSettings.user
96 |
97 | # JustCode is a .NET coding add-in
98 | .JustCode
99 |
100 | # TeamCity is a build add-in
101 | _TeamCity*
102 |
103 | # DotCover is a Code Coverage Tool
104 | *.dotCover
105 |
106 | # NCrunch
107 | _NCrunch_*
108 | .*crunch*.local.xml
109 |
110 | # MightyMoose
111 | *.mm.*
112 | AutoTest.Net/
113 |
114 | # Web workbench (sass)
115 | .sass-cache/
116 |
117 | # Installshield output folder
118 | [Ee]xpress/
119 |
120 | # DocProject is a documentation generator add-in
121 | DocProject/buildhelp/
122 | DocProject/Help/*.HxT
123 | DocProject/Help/*.HxC
124 | DocProject/Help/*.hhc
125 | DocProject/Help/*.hhk
126 | DocProject/Help/*.hhp
127 | DocProject/Help/Html2
128 | DocProject/Help/html
129 |
130 | # Click-Once directory
131 | publish/
132 |
133 | # Publish Web Output
134 | *.[Pp]ublish.xml
135 | *.azurePubxml
136 | ## TODO: Comment the next line if you want to checkin your
137 | ## web deploy settings but do note that will include unencrypted
138 | ## passwords
139 | #*.pubxml
140 |
141 | *.publishproj
142 |
143 | # NuGet Packages
144 | *.nupkg
145 | # The packages folder can be ignored because of Package Restore
146 | **/packages/*
147 | # except build/, which is used as an MSBuild target.
148 | !**/packages/build/
149 | # Uncomment if necessary however generally it will be regenerated when needed
150 | #!**/packages/repositories.config
151 |
152 | # Windows Azure Build Output
153 | csx/
154 | *.build.csdef
155 |
156 | # Windows Store app package directory
157 | AppPackages/
158 |
159 | # Visual Studio cache files
160 | # files ending in .cache can be ignored
161 | *.[Cc]ache
162 | # but keep track of directories ending in .cache
163 | !*.[Cc]ache/
164 |
165 | # Others
166 | ClientBin/
167 | [Ss]tyle[Cc]op.*
168 | ~$*
169 | *~
170 | *.dbmdl
171 | *.dbproj.schemaview
172 | *.pfx
173 | *.publishsettings
174 | node_modules/
175 | orleans.codegen.cs
176 |
177 | # RIA/Silverlight projects
178 | Generated_Code/
179 |
180 | # Backup & report files from converting an old project file
181 | # to a newer Visual Studio version. Backup files are not needed,
182 | # because we have git ;-)
183 | _UpgradeReport_Files/
184 | Backup*/
185 | UpgradeLog*.XML
186 | UpgradeLog*.htm
187 |
188 | # SQL Server files
189 | *.mdf
190 | *.ldf
191 |
192 | # Business Intelligence projects
193 | *.rdl.data
194 | *.bim.layout
195 | *.bim_*.settings
196 |
197 | # Microsoft Fakes
198 | FakesAssemblies/
199 |
200 | # Node.js Tools for Visual Studio
201 | .ntvs_analysis.dat
202 |
203 | # Visual Studio 6 build log
204 | *.plg
205 |
206 | # Visual Studio 6 workspace options file
207 | *.opt
208 |
209 | # LightSwitch generated files
210 | GeneratedArtifacts/
211 | _Pvt_Extensions/
212 | ModelManifest.xml
213 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SteamAccountSwitcher2
2 | Completely rewritten account switcher for Steam.
3 |
4 | This is work in progress!
5 | There are major bugs and missing features in this current version!
6 |
7 | ### Download
8 | *There is no download yet, there are a lot of things to do before you should install this as your new Account Switcher!*
9 | If you clone this and use it, expect things to break.
10 |
11 | ### Current Features
12 | - new UI
13 | - launching Steam Account
14 | - SafeMode to protect password (could be seen in task manager)
15 | - Saves and encrypts accounts locally (now AES-256 bit encryption)
16 | - Reorder accounts by drag and drop
17 |
18 | ### More info
19 | If you are interested, you can check out my blog, will share some stuff there, because i don't want to spam the old github repo with info about a unfinished second version ;)
20 | [Blog](https://wedenig.org/blog/steamaccountswitcher-v2)
21 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher2.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29613.14
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SteamAccountSwitcher", "SteamAccountSwitcher2\SteamAccountSwitcher.csproj", "{CD84E7B0-56E4-43F0-8532-55972070F563}"
7 | EndProject
8 | Project("{840C416C-B8F3-42BC-B0DD-F6BB14C9F8CB}") = "SteamAccountSwitcherSetup", "SteamAccountSwitcherSetup\SteamAccountSwitcherSetup.aiproj", "{DF67B771-6F39-474C-9833-5FC8AE064EEA}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | All|Any CPU = All|Any CPU
13 | CD_ROM|Any CPU = CD_ROM|Any CPU
14 | Debug|Any CPU = Debug|Any CPU
15 | Deploy|Any CPU = Deploy|Any CPU
16 | DVD-5|Any CPU = DVD-5|Any CPU
17 | Release|Any CPU = Release|Any CPU
18 | SingleImage|Any CPU = SingleImage|Any CPU
19 | EndGlobalSection
20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
21 | {CD84E7B0-56E4-43F0-8532-55972070F563}.All|Any CPU.ActiveCfg = Release|Any CPU
22 | {CD84E7B0-56E4-43F0-8532-55972070F563}.All|Any CPU.Build.0 = Release|Any CPU
23 | {CD84E7B0-56E4-43F0-8532-55972070F563}.CD_ROM|Any CPU.ActiveCfg = Deploy|Any CPU
24 | {CD84E7B0-56E4-43F0-8532-55972070F563}.CD_ROM|Any CPU.Build.0 = Deploy|Any CPU
25 | {CD84E7B0-56E4-43F0-8532-55972070F563}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
26 | {CD84E7B0-56E4-43F0-8532-55972070F563}.Debug|Any CPU.Build.0 = Debug|Any CPU
27 | {CD84E7B0-56E4-43F0-8532-55972070F563}.Deploy|Any CPU.ActiveCfg = Deploy|Any CPU
28 | {CD84E7B0-56E4-43F0-8532-55972070F563}.Deploy|Any CPU.Build.0 = Deploy|Any CPU
29 | {CD84E7B0-56E4-43F0-8532-55972070F563}.Deploy|Any CPU.Deploy.0 = Deploy|Any CPU
30 | {CD84E7B0-56E4-43F0-8532-55972070F563}.DVD-5|Any CPU.ActiveCfg = Deploy|Any CPU
31 | {CD84E7B0-56E4-43F0-8532-55972070F563}.DVD-5|Any CPU.Build.0 = Deploy|Any CPU
32 | {CD84E7B0-56E4-43F0-8532-55972070F563}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 | {CD84E7B0-56E4-43F0-8532-55972070F563}.Release|Any CPU.Build.0 = Release|Any CPU
34 | {CD84E7B0-56E4-43F0-8532-55972070F563}.SingleImage|Any CPU.ActiveCfg = Deploy|Any CPU
35 | {CD84E7B0-56E4-43F0-8532-55972070F563}.SingleImage|Any CPU.Build.0 = Deploy|Any CPU
36 | {DF67B771-6F39-474C-9833-5FC8AE064EEA}.All|Any CPU.ActiveCfg = DefaultBuild
37 | {DF67B771-6F39-474C-9833-5FC8AE064EEA}.All|Any CPU.Build.0 = DefaultBuild
38 | {DF67B771-6F39-474C-9833-5FC8AE064EEA}.CD_ROM|Any CPU.ActiveCfg = DefaultBuild
39 | {DF67B771-6F39-474C-9833-5FC8AE064EEA}.CD_ROM|Any CPU.Build.0 = DefaultBuild
40 | {DF67B771-6F39-474C-9833-5FC8AE064EEA}.Debug|Any CPU.ActiveCfg = DefaultBuild
41 | {DF67B771-6F39-474C-9833-5FC8AE064EEA}.Debug|Any CPU.Build.0 = DefaultBuild
42 | {DF67B771-6F39-474C-9833-5FC8AE064EEA}.Deploy|Any CPU.ActiveCfg = DefaultBuild
43 | {DF67B771-6F39-474C-9833-5FC8AE064EEA}.Deploy|Any CPU.Build.0 = DefaultBuild
44 | {DF67B771-6F39-474C-9833-5FC8AE064EEA}.DVD-5|Any CPU.ActiveCfg = DefaultBuild
45 | {DF67B771-6F39-474C-9833-5FC8AE064EEA}.DVD-5|Any CPU.Build.0 = DefaultBuild
46 | {DF67B771-6F39-474C-9833-5FC8AE064EEA}.Release|Any CPU.ActiveCfg = DefaultBuild
47 | {DF67B771-6F39-474C-9833-5FC8AE064EEA}.Release|Any CPU.Build.0 = DefaultBuild
48 | {DF67B771-6F39-474C-9833-5FC8AE064EEA}.SingleImage|Any CPU.ActiveCfg = DefaultBuild
49 | {DF67B771-6F39-474C-9833-5FC8AE064EEA}.SingleImage|Any CPU.Build.0 = DefaultBuild
50 | EndGlobalSection
51 | GlobalSection(SolutionProperties) = preSolution
52 | HideSolutionNode = FALSE
53 | EndGlobalSection
54 | GlobalSection(ExtensibilityGlobals) = postSolution
55 | SolutionGuid = {3CC09722-36B7-4CBB-B9F9-73DBF8664D57}
56 | EndGlobalSection
57 | EndGlobal
58 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/AccountLoader.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.IO;
5 | using System.Security.Cryptography;
6 | using System.Windows;
7 | using SteamAccountSwitcher2.Encryption;
8 |
9 | namespace SteamAccountSwitcher2
10 | {
11 | class AccountLoader
12 | {
13 | EncryptionType _encryptionType;
14 | string _directory;
15 | private string _password;
16 |
17 | const string BasicKey = "OQPTu9Rf4u4vkywWy+GCBptmXeqC0e456SR3N31vutU=";
18 |
19 | public AccountLoader(EncryptionType e)
20 | {
21 | _encryptionType = e;
22 | this._directory = AppDomain.CurrentDomain.BaseDirectory;
23 | }
24 |
25 | public AccountLoader(EncryptionType e, string directory)
26 | {
27 | _encryptionType = e;
28 | this._directory = directory;
29 | }
30 |
31 | public EncryptionType EncryptionType
32 | {
33 | get => _encryptionType;
34 | set => _encryptionType = value;
35 | }
36 |
37 | ///
38 | /// Password that is used only when Encryption Type is set to Password!
39 | ///
40 | public string Password
41 | {
42 | get => _password;
43 | set => _password = value;
44 | }
45 |
46 | public string AccountsFilePath => Path.Combine(_directory, "accounts.ini");
47 |
48 | public List LoadAccounts()
49 | {
50 | bool retry = true;
51 | while (retry)
52 | {
53 | string encryptionKey;
54 | switch (_encryptionType)
55 | {
56 | case EncryptionType.Basic:
57 | encryptionKey = BasicKey;
58 | break;
59 | case EncryptionType.Password:
60 | if (!string.IsNullOrEmpty(_password))
61 | {
62 | encryptionKey = _password;
63 | }
64 | else
65 | {
66 | _password = AskForPassword();
67 | encryptionKey = _password;
68 | }
69 |
70 | break;
71 | default:
72 | throw new ArgumentException("Unsupported EncryptionType type!");
73 | }
74 |
75 | try
76 | {
77 | string encrypted = File.ReadAllText(this._directory + "accounts.ini");
78 | string decrypted = EncryptionHelper.Decrypt(encrypted, encryptionKey);
79 | List accountList = JsonConvert.DeserializeObject>(decrypted);
80 | return accountList;
81 | }
82 | catch (CryptographicException e)
83 | {
84 | MessageBox.Show("Try entering the password again.", "Could not decrypt");
85 | _password = null;
86 | }
87 | catch (JsonException e)
88 | {
89 | MessageBox.Show(e.Message, "Fatal Error when reading accounts file!");
90 | retry = false;
91 | }
92 | catch (Exception e)
93 | {
94 | retry = false;
95 | }
96 | }
97 |
98 | return null;
99 | }
100 |
101 | private string AskForPassword()
102 | {
103 | PasswordWindow passwordWindow = new PasswordWindow(false);
104 | passwordWindow.ShowDialog();
105 | if (passwordWindow.Password == null)
106 | {
107 | System.Environment.Exit(1);
108 | }
109 |
110 | return passwordWindow.Password;
111 | }
112 |
113 | public void SaveAccounts(List list)
114 | {
115 | string encryptionKey;
116 | switch (_encryptionType)
117 | {
118 | case EncryptionType.Basic:
119 | encryptionKey = BasicKey;
120 | break;
121 | case EncryptionType.Password:
122 | encryptionKey = _password;
123 | break;
124 | default:
125 | throw new ArgumentException("Unsupported EncryptionType type!");
126 | }
127 |
128 |
129 | string output = JsonConvert.SerializeObject(list, Formatting.None);
130 | string encrypted = EncryptionHelper.Encrypt(output, encryptionKey);
131 |
132 | File.WriteAllText(AccountsFilePath, encrypted);
133 | }
134 |
135 | public bool AccountFileExists()
136 | {
137 | return File.Exists(AccountsFilePath);
138 | }
139 |
140 | private static byte[] GetBytes(string str)
141 | {
142 | byte[] bytes = new byte[str.Length * sizeof(char)];
143 | System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
144 | return bytes;
145 | }
146 |
147 | private static string GetString(byte[] bytes)
148 | {
149 | char[] chars = new char[bytes.Length / sizeof(char)];
150 | System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
151 | return new string(chars);
152 | }
153 | }
154 | }
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/AccountType.cs:
--------------------------------------------------------------------------------
1 | namespace SteamAccountSwitcher2
2 | {
3 | public enum AccountType
4 | {
5 | Main, Smurf, Friend, Banned
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/AccountWindow.xaml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/AccountWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows;
3 |
4 | namespace SteamAccountSwitcher2
5 | {
6 | ///
7 | /// Interaction logic for AccountWindow.xaml
8 | ///
9 | public partial class AccountWindow : Window
10 | {
11 | private SteamAccount newAcc;
12 |
13 | ///
14 | /// Creates a new instance of the AccountWindow class. Allows the user to create new accounts.
15 | ///
16 | public AccountWindow()
17 | {
18 | InitializeComponent();
19 | comboBoxType.ItemsSource = Enum.GetValues(typeof(AccountType));
20 | comboBoxType.SelectedIndex = 0;
21 | labelIsCached.Visibility = Visibility.Collapsed;
22 | }
23 |
24 | ///
25 | /// Creates a new instance of the AccountWindow class. Allows the user to edit new accounts
26 | ///
27 | /// The account to edit.
28 | public AccountWindow(SteamAccount accToEdit)
29 | {
30 | if (accToEdit == null)
31 | throw new ArgumentNullException();
32 |
33 | InitializeComponent();
34 | this.Title = "Edit Account";
35 | newAcc = accToEdit;
36 |
37 | comboBoxType.ItemsSource = Enum.GetValues(typeof(AccountType));
38 | comboBoxType.SelectedItem = accToEdit.Type;
39 |
40 | textBoxName.Text = accToEdit.Name;
41 | textBoxUsername.Text = accToEdit.AccountName;
42 | textBoxPassword.Password = accToEdit.Password;
43 |
44 | textBoxUsername.IsEnabled = accToEdit.CachedAccount;
45 | labelIsCached.Visibility = accToEdit.CachedAccount ? Visibility.Visible : Visibility.Collapsed;
46 | }
47 |
48 | ///
49 | /// Accessor to the Account associated with the window.
50 | ///
51 | public SteamAccount Account => newAcc;
52 |
53 | private void buttonSave_Click(object sender, RoutedEventArgs e)
54 | {
55 | if (ValidateInput())
56 | {
57 | if (newAcc == null)
58 | {
59 | newAcc = new SteamAccount(textBoxUsername.Text, textBoxPassword.Password);
60 | newAcc.Type = (AccountType)comboBoxType.SelectedValue;
61 | newAcc.Name = textBoxName.Text;
62 | }
63 | else
64 | {
65 | newAcc.AccountName = textBoxUsername.Text;
66 | newAcc.Password = textBoxPassword.Password;
67 | newAcc.Name = textBoxName.Text;
68 | newAcc.Type = (AccountType)comboBoxType.SelectedValue;
69 | }
70 |
71 |
72 | Close();
73 | }
74 | }
75 |
76 | private bool ValidateInput()
77 | {
78 | bool success = true;
79 | string errorstring = "";
80 | if (String.IsNullOrEmpty(textBoxName.Text))
81 | {
82 | success = false;
83 | errorstring += "Profile name cannot be empty!\n";
84 | }
85 |
86 | if (String.IsNullOrEmpty(textBoxUsername.Text))
87 | {
88 | success = false;
89 | errorstring += "Username cannot be empty!\n";
90 | }
91 |
92 | if (String.IsNullOrEmpty(textBoxPassword.Password) && labelIsCached.Visibility != Visibility.Visible)
93 | {
94 | success = false;
95 | errorstring += "Password cannot be empty!\n";
96 | }
97 |
98 | if (success)
99 | {
100 | return true;
101 | }
102 | else
103 | {
104 | MessageBox.Show(errorstring, "Validation problem", MessageBoxButton.OK, MessageBoxImage.Information);
105 | return false;
106 | }
107 | }
108 |
109 | private void buttonCancel_Click(object sender, RoutedEventArgs e)
110 | {
111 | newAcc = null;
112 | Close();
113 | }
114 | }
115 | }
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | 0
22 |
23 |
24 | 0
25 |
26 |
27 | 400
28 |
29 |
30 | 300
31 |
32 |
33 | False
34 |
35 |
36 | Basic
37 |
38 |
39 | False
40 |
41 |
42 | False
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 |
3 | namespace SteamAccountSwitcher2
4 | {
5 | ///
6 | /// Interaction logic for App.xaml
7 | ///
8 | public partial class App : Application
9 | {
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/CachedAccountManager.cs:
--------------------------------------------------------------------------------
1 | using Gameloop.Vdf;
2 | using Microsoft.Win32;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using System.Windows;
7 |
8 | namespace SteamAccountSwitcher2
9 | {
10 | ///
11 | /// Manages everything related to cached steam accounts
12 | ///
13 | class CachedAccountManager
14 | {
15 | private Steam _steamInstallation;
16 | List _cachedAccounts = new List();
17 | private string loginUsersVDFPath;
18 |
19 | public CachedAccountManager(Steam installation)
20 | {
21 | _steamInstallation = installation;
22 | loginUsersVDFPath = Path.Combine(installation.InstallDir, "config/loginusers.vdf");
23 | }
24 |
25 | public IEnumerable CachedAccounts => _cachedAccounts;
26 |
27 | public void scanForAccounts()
28 | {
29 | dynamic loginUsersVdf = VdfConvert.Deserialize(File.ReadAllText(loginUsersVDFPath));
30 | // 'volvo' is a VProperty, analogous to Json.NET's JProperty
31 | _cachedAccounts.Clear();
32 | foreach (var account in loginUsersVdf.Value)
33 | {
34 | _cachedAccounts.Add(new SteamAccount(
35 | (string)account.Key.ToString(),
36 | (string)account.Value.AccountName.Value.ToString(),
37 | (string)account.Value.PersonaName.Value.ToString(),
38 | account.Value.RememberPassword.Value.ToString() == "1",
39 | account.Value.MostRecent?.Value.ToString() == "1",
40 | long.Parse(account.Value.Timestamp.Value.ToString())
41 | ));
42 | }
43 | }
44 |
45 | ///
46 | /// Uses the technique from TcNo Account Switcher to change the loginUsers.vdf and
47 | /// some registry values so on next start steam is starting with the defined user
48 | /// only works if the user already logged in once with this account and chose "remember password"!
49 | ///
50 | /// the account to start with
51 | public void startCachedAccount(SteamAccount selectedAccount)
52 | {
53 | _steamInstallation.KillSteam();
54 | dynamic loginUsersVdf = VdfConvert.Deserialize(File.ReadAllText(loginUsersVDFPath));
55 | try
56 | {
57 | foreach (var account in loginUsersVdf.Value)
58 | {
59 | if (account.Key.ToString() == selectedAccount.SteamId)
60 | {
61 | account.Value.MostRecent.Value = "1";
62 | if (account.Value.RememberPassword.Value == "0")
63 | {
64 | // Steam does not remember this accounts password!
65 | if (!string.IsNullOrEmpty(selectedAccount.Password))
66 | {
67 | // If the user has a password, we use that to log in the old way
68 | resetActiveAccount();
69 | _steamInstallation.StartSteamAccount(selectedAccount);
70 | }
71 | else
72 | {
73 | // Else we notify the user and let him log in
74 | MessageBox.Show(
75 | "This account does not have a password associated with it and can only be started if it has already logged in once and 'Remember Password' has been checked. Log in and select 'Remember Password' now or add a password in SteamAccountSwitcher.",
76 | "Cannot start with selected account", MessageBoxButton.OK, MessageBoxImage.Exclamation);
77 | break;
78 | }
79 |
80 | }
81 | }
82 | else
83 | {
84 | account.Value.MostRecent.Value = "0";
85 | }
86 | }
87 |
88 | File.WriteAllText(loginUsersVDFPath, loginUsersVdf.ToString());
89 |
90 | using (RegistryKey key = Registry.CurrentUser.CreateSubKey(@"Software\Valve\Steam"))
91 | {
92 | key.SetValue("AutoLoginUser", selectedAccount.AccountName);
93 | key.SetValue("RememberPassword", 1);
94 | }
95 | _steamInstallation.Start();
96 | }
97 | catch (Exception e)
98 | {
99 | MessageBox.Show(e.Message);
100 | }
101 | }
102 |
103 | public void resetActiveAccount()
104 | {
105 | using (RegistryKey key = Registry.CurrentUser.CreateSubKey(@"Software\Valve\Steam"))
106 | {
107 | key.DeleteValue("AutoLoginUser");
108 | key.SetValue("RememberPassword", 1);
109 | }
110 | }
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/Encryption/EncryptionHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Security.Cryptography;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace SteamAccountSwitcher2.Encryption
10 | {
11 | class EncryptionHelper
12 | {
13 | // This constant is used to determine the keysize of the encryption algorithm in bits.
14 | // We divide this by 8 within the code below to get the equivalent number of bytes.
15 | private const int Keysize = 256;
16 |
17 | // This constant determines the number of iterations for the password bytes generation function.
18 | private const int DerivationIterations = 1000;
19 |
20 | public static string Encrypt(string plainText, string passPhrase)
21 | {
22 | // Salt and IV is randomly generated each time, but is preprended to encrypted cipher text
23 | // so that the same Salt and IV values can be used when decrypting.
24 | var saltStringBytes = Generate256BitsOfRandomEntropy();
25 | var ivStringBytes = Generate256BitsOfRandomEntropy();
26 | var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
27 | using (var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations))
28 | {
29 | var keyBytes = password.GetBytes(Keysize / 8);
30 | using (var symmetricKey = new RijndaelManaged())
31 | {
32 | symmetricKey.BlockSize = 256;
33 | symmetricKey.Mode = CipherMode.CBC;
34 | symmetricKey.Padding = PaddingMode.PKCS7;
35 | using (var encryptor = symmetricKey.CreateEncryptor(keyBytes, ivStringBytes))
36 | {
37 | using (var memoryStream = new MemoryStream())
38 | {
39 | using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
40 | {
41 | cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
42 | cryptoStream.FlushFinalBlock();
43 | // Create the final bytes as a concatenation of the random salt bytes, the random iv bytes and the cipher bytes.
44 | var cipherTextBytes = saltStringBytes;
45 | cipherTextBytes = cipherTextBytes.Concat(ivStringBytes).ToArray();
46 | cipherTextBytes = cipherTextBytes.Concat(memoryStream.ToArray()).ToArray();
47 | memoryStream.Close();
48 | cryptoStream.Close();
49 | return Convert.ToBase64String(cipherTextBytes);
50 | }
51 | }
52 | }
53 | }
54 | }
55 | }
56 |
57 | public static string Decrypt(string cipherText, string passPhrase)
58 | {
59 | // Get the complete stream of bytes that represent:
60 | // [32 bytes of Salt] + [32 bytes of IV] + [n bytes of CipherText]
61 | var cipherTextBytesWithSaltAndIv = Convert.FromBase64String(cipherText);
62 | // Get the saltbytes by extracting the first 32 bytes from the supplied cipherText bytes.
63 | var saltStringBytes = cipherTextBytesWithSaltAndIv.Take(Keysize / 8).ToArray();
64 | // Get the IV bytes by extracting the next 32 bytes from the supplied cipherText bytes.
65 | var ivStringBytes = cipherTextBytesWithSaltAndIv.Skip(Keysize / 8).Take(Keysize / 8).ToArray();
66 | // Get the actual cipher text bytes by removing the first 64 bytes from the cipherText string.
67 | var cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip((Keysize / 8) * 2).Take(cipherTextBytesWithSaltAndIv.Length - ((Keysize / 8) * 2)).ToArray();
68 |
69 | using (var password = new Rfc2898DeriveBytes(passPhrase, saltStringBytes, DerivationIterations))
70 | {
71 | var keyBytes = password.GetBytes(Keysize / 8);
72 | using (var symmetricKey = new RijndaelManaged())
73 | {
74 | symmetricKey.BlockSize = 256;
75 | symmetricKey.Mode = CipherMode.CBC;
76 | symmetricKey.Padding = PaddingMode.PKCS7;
77 | using (var decryptor = symmetricKey.CreateDecryptor(keyBytes, ivStringBytes))
78 | {
79 | using (var memoryStream = new MemoryStream(cipherTextBytes))
80 | {
81 | using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
82 | {
83 | var plainTextBytes = new byte[cipherTextBytes.Length];
84 | var decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
85 | memoryStream.Close();
86 | cryptoStream.Close();
87 | return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
88 | }
89 | }
90 | }
91 | }
92 | }
93 | }
94 |
95 | private static byte[] Generate256BitsOfRandomEntropy()
96 | {
97 | var randomBytes = new byte[32]; // 32 Bytes will give us 256 bits.
98 | using (var rngCsp = new RNGCryptoServiceProvider())
99 | {
100 | // Fill the array with cryptographically secure random bytes.
101 | rngCsp.GetBytes(randomBytes);
102 | }
103 | return randomBytes;
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/EncryptionType.cs:
--------------------------------------------------------------------------------
1 | namespace SteamAccountSwitcher2
2 | {
3 | public enum EncryptionType
4 | {
5 | Basic, Password
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/ImageHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows.Media;
7 | using System.Windows.Media.Imaging;
8 |
9 | namespace SteamAccountSwitcher2
10 | {
11 | public class ImageHelper
12 | {
13 | public static ImageSource GetIconImageSource(string name)
14 | {
15 | return new BitmapImage(new Uri(@"images/icons/" + name + ".png", UriKind.Relative));
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/LogWindow.xaml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/LogWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 |
3 | namespace SteamAccountSwitcher2
4 | {
5 | ///
6 | /// Interaction logic for LogWindow.xaml
7 | ///
8 | public partial class LogWindow : Window
9 | {
10 | public LogWindow()
11 | {
12 | InitializeComponent();
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/MainWindow.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
20 |
26 |
32 |
38 |
39 |
47 |
48 |
54 |
55 |
56 |
57 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
108 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
125 |
126 |
131 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using AutoUpdaterDotNET;
2 | using System;
3 | using System.Diagnostics;
4 | using System.Windows;
5 | using System.Windows.Controls;
6 | using System.Windows.Input;
7 |
8 | namespace SteamAccountSwitcher2
9 | {
10 | ///
11 | /// Interaction logic for MainWindow.xaml
12 | ///
13 | ///
14 | public partial class MainWindow : Window
15 | {
16 | //ObservableCollection accountList = new ObservableCollection();
17 |
18 | public MainWindow()
19 | {
20 | AutoUpdater.Start("https://wedenig.org/SteamAccountSwitcher/version.xml");
21 |
22 | InitializeComponent();
23 |
24 | //Restore size
25 | this.Top = Properties.Settings.Default.Top;
26 | this.Left = Properties.Settings.Default.Left;
27 | this.Height = Properties.Settings.Default.Height;
28 | this.Width = Properties.Settings.Default.Width;
29 |
30 | if (Properties.Settings.Default.Maximized)
31 | {
32 | WindowState = WindowState.Maximized;
33 | }
34 |
35 | fixOutOfBoundsWindow();
36 |
37 | askUserForSteamLocation();
38 |
39 | showSteamStatus();
40 |
41 |
42 | try
43 | {
44 | SasManager.Instance.InitializeAccountsFromFile();
45 | }
46 | catch
47 | {
48 | MessageBox.Show(
49 | "Account file is currupted or wrong encryption method is set. Check Settings and try again. Save on close has been disabled so that nothing can be overwritten! Make sure to restart the applications after switching EncryptionType method!",
50 | "Error parsing file", MessageBoxButton.OK, MessageBoxImage.Exclamation);
51 | }
52 |
53 |
54 | SteamAccount sa = new SteamAccount("username", "testpw");
55 | sa.Name = "profile name";
56 | //accountList.Add(sa);
57 |
58 | listBoxAccounts.ItemsSource = SasManager.Instance.AccountList;
59 | listBoxAccounts.Items.Refresh();
60 |
61 | Style itemContainerStyle = new Style(typeof(ListBoxItem));
62 | //take full width
63 | itemContainerStyle.Setters.Add(new Setter(HorizontalContentAlignmentProperty, HorizontalAlignment.Stretch));
64 | listBoxAccounts.ItemContainerStyle = itemContainerStyle;
65 | }
66 |
67 | private void askUserForSteamLocation()
68 | {
69 | //No steam directory in Settings, let's find 'em!
70 | if (Properties.Settings.Default.steamInstallDir == String.Empty)
71 | {
72 | //Run this on first start
73 | string installDir = UserInteraction.selectSteamDirectory(@"C:\Program Files (x86)\Steam");
74 | if (installDir == null)
75 | {
76 | MessageBox.Show(
77 | "You cannot use SteamAccountSwitcher without selecting your Steam.exe. Program will close now.",
78 | "Steam missing", MessageBoxButton.OK, MessageBoxImage.Error);
79 | Close();
80 | }
81 | else
82 | {
83 | SasManager.Instance.SetSteamInstallDir(installDir);
84 | }
85 | }
86 | }
87 |
88 | private void showSteamStatus()
89 | {
90 | statusBarLabel.Content = SasManager.Instance.SteamStatus.steamStatusMessage();
91 | statusbar.Background = SasManager.Instance.SteamStatus.getStatusColor();
92 | }
93 |
94 | private void settingsButton_Click(object sender, RoutedEventArgs e)
95 | {
96 | SettingsWindow settingsWindow = new SettingsWindow();
97 | settingsWindow.Owner = this;
98 | settingsWindow.ShowDialog();
99 | }
100 |
101 | private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
102 | {
103 | SasManager.Instance.SaveAccounts();
104 |
105 | if (WindowState == WindowState.Maximized)
106 | {
107 | // Use the RestoreBounds as the current values will be 0, 0 and the size of the screen
108 | Properties.Settings.Default.Top = RestoreBounds.Top;
109 | Properties.Settings.Default.Left = RestoreBounds.Left;
110 | Properties.Settings.Default.Height = RestoreBounds.Height;
111 | Properties.Settings.Default.Width = RestoreBounds.Width;
112 | Properties.Settings.Default.Maximized = true;
113 | }
114 | else
115 | {
116 | Properties.Settings.Default.Top = this.Top;
117 | Properties.Settings.Default.Left = this.Left;
118 | Properties.Settings.Default.Height = this.Height;
119 | Properties.Settings.Default.Width = this.Width;
120 | Properties.Settings.Default.Maximized = false;
121 | }
122 |
123 | Properties.Settings.Default.Save();
124 | }
125 |
126 | private void buttonAdd_Click(object sender, RoutedEventArgs e)
127 | {
128 | AccountWindow newAccWindow = new AccountWindow();
129 | newAccWindow.Owner = this;
130 | newAccWindow.ShowDialog();
131 | if (newAccWindow.Account != null)
132 | {
133 | SasManager.Instance.AccountList.Add(newAccWindow.Account);
134 | }
135 | }
136 |
137 | private void listBoxAccounts_SelectionChanged(object sender, SelectionChangedEventArgs e)
138 | {
139 | if (sender != null)
140 | {
141 | buttonEdit.IsEnabled = true;
142 | }
143 | else
144 | {
145 | buttonEdit.IsEnabled = false;
146 | }
147 |
148 | listBoxAccounts.Items.Refresh();
149 | }
150 |
151 | private void listContextMenuRemove_Click(object sender, RoutedEventArgs e)
152 | {
153 | AskForDeletionOfAccount((SteamAccount) listBoxAccounts.SelectedItem);
154 | }
155 |
156 | private void listContextMenuEdit_Click(object sender, RoutedEventArgs e)
157 | {
158 | if (listBoxAccounts.SelectedItem != null)
159 | {
160 | AccountWindow newAccWindow = new AccountWindow((SteamAccount) listBoxAccounts.SelectedItem);
161 | newAccWindow.Owner = this;
162 | newAccWindow.ShowDialog();
163 | listBoxAccounts.Items.Refresh();
164 | }
165 | }
166 |
167 | private void fixOutOfBoundsWindow()
168 | {
169 | bool outOfBounds =
170 | (this.Left <= SystemParameters.VirtualScreenLeft - this.Width) ||
171 | (this.Top <= SystemParameters.VirtualScreenTop - this.Height) ||
172 | (SystemParameters.VirtualScreenLeft +
173 | SystemParameters.VirtualScreenWidth <= this.Left) ||
174 | (SystemParameters.VirtualScreenTop +
175 | SystemParameters.VirtualScreenHeight <= this.Top);
176 |
177 | if (outOfBounds)
178 | {
179 | Debug.WriteLine("Out of bounds window was reset to default offsets");
180 | this.Left = 0;
181 | this.Top = 0;
182 | this.Width = 450;
183 | this.Height = 400;
184 | }
185 | }
186 |
187 | private void buttonEdit_Click(object sender, RoutedEventArgs e)
188 | {
189 | listContextMenuEdit_Click(sender, e);
190 | }
191 |
192 | private void buttonScanAccounts_Click(object sender, RoutedEventArgs e)
193 | {
194 | SasManager.Instance.ScanAndAddAccounts();
195 | listBoxAccounts.Items.Refresh();
196 | }
197 |
198 | private void steamAccount_MouseDown(object sender, MouseButtonEventArgs e)
199 | {
200 | if (e.ClickCount >= 2)
201 | {
202 | SteamAccount selectedAcc = (SteamAccount) listBoxAccounts.SelectedItem;
203 | SasManager.Instance.StartSteamWithAccount(selectedAcc);
204 | }
205 | }
206 |
207 | ///
208 | /// Handles key downs on listBox with steam accounts
209 | ///
210 | private void OnKeyDownHandler(object sender, KeyEventArgs e)
211 | {
212 | if (e.Key == Key.Delete)
213 | {
214 | AskForDeletionOfAccount((SteamAccount) listBoxAccounts.SelectedItem);
215 | }
216 | }
217 |
218 | private void AskForDeletionOfAccount(SteamAccount selectedAccount)
219 | {
220 | var result = MessageBox.Show(
221 | "Are you sure you want to delete the account profile of " + selectedAccount.ToString() + "?",
222 | "Deletion prompt",
223 | MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No);
224 | if (result == MessageBoxResult.Yes)
225 | {
226 | SasManager.Instance.AccountList.Remove(selectedAccount);
227 | buttonEdit.IsEnabled = false; // Cannot edit deleted account
228 | listBoxAccounts.Items.Refresh();
229 | }
230 | }
231 | }
232 | }
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/PasswordWindow.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/PasswordWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 | using System.Windows;
7 | using System.Windows.Controls;
8 | using System.Windows.Data;
9 | using System.Windows.Documents;
10 | using System.Windows.Input;
11 | using System.Windows.Media;
12 | using System.Windows.Media.Imaging;
13 | using System.Windows.Shapes;
14 |
15 | namespace SteamAccountSwitcher2
16 | {
17 | ///
18 | /// Interaction logic for PasswordWindow.xaml
19 | ///
20 | public partial class PasswordWindow : Window
21 | {
22 | private string _password;
23 | private readonly bool _setNewPw;
24 |
25 | ///
26 | /// A password window where the user enters a password (duh?)
27 | ///
28 | /// Set to true to make the user enter a password twice for verification
29 | public PasswordWindow(bool setNewPw)
30 | {
31 | _setNewPw = setNewPw;
32 | InitializeComponent();
33 | passwordBox.Focus();
34 | if (_setNewPw)
35 | {
36 | PwWindow.Title = "Set new password";
37 | PwWindow.Height = 140;
38 | repeatPasswordPanel.Visibility = Visibility.Visible;
39 | Image.Source = ImageHelper.GetIconImageSource("key");
40 | }
41 | else
42 | {
43 | PwWindow.Title = "Decrypt accounts with password";
44 | PwWindow.Height = 120;
45 | repeatPasswordPanel.Visibility = Visibility.Collapsed;
46 | Image.Source = ImageHelper.GetIconImageSource("unlock");
47 | }
48 | }
49 |
50 | public string Password => _password;
51 |
52 | private void ButtonOK_Click(object sender, RoutedEventArgs e)
53 | {
54 | if (passwordBox.Password == passwordBoxRepeat.Password || !_setNewPw)
55 | {
56 | _password = passwordBox.Password;
57 | Close();
58 | }
59 | else
60 | {
61 | MessageBox.Show("Passwords do not match. Try again.", "Passwords not matching", MessageBoxButton.OK,
62 | MessageBoxImage.Exclamation);
63 | }
64 | }
65 |
66 | private void ButtonCancel_Click(object sender, RoutedEventArgs e)
67 | {
68 | Close();
69 | }
70 | }
71 | }
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.InteropServices;
4 | using System.Windows;
5 |
6 | // General Information about an assembly is controlled through the following
7 | // set of attributes. Change these attribute values to modify the information
8 | // associated with an assembly.
9 | [assembly: AssemblyTitle("SteamAccountSwitcher2")]
10 | [assembly: AssemblyDescription("")]
11 | [assembly: AssemblyConfiguration("")]
12 | [assembly: AssemblyCompany("")]
13 | [assembly: AssemblyProduct("SteamAccountSwitcher2")]
14 | [assembly: AssemblyCopyright("Copyright © 2016 Christoph Wedenig")]
15 | [assembly: AssemblyTrademark("")]
16 | [assembly: AssemblyCulture("")]
17 |
18 | // Setting ComVisible to false makes the types in this assembly not visible
19 | // to COM components. If you need to access a type in this assembly from
20 | // COM, set the ComVisible attribute to true on that type.
21 | [assembly: ComVisible(false)]
22 |
23 | //In order to begin building localizable applications, set
24 | //CultureYouAreCodingWith in your .csproj file
25 | //inside a . For example, if you are using US english
26 | //in your source files, set the to en-US. Then uncomment
27 | //the NeutralResourceLanguage attribute below. Update the "en-US" in
28 | //the line below to match the UICulture setting in the project file.
29 |
30 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
31 |
32 |
33 | [assembly: ThemeInfo(
34 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
35 | //(used if a resource is not found in the page,
36 | // or application resource dictionaries)
37 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
38 | //(used if a resource is not found in the page,
39 | // app, or any theme specific resource dictionaries)
40 | )]
41 |
42 |
43 | // Version information for an assembly consists of the following four values:
44 | //
45 | // Major Version
46 | // Minor Version
47 | // Build Number
48 | // Revision
49 | //
50 | // You can specify all the values or you can default the Build and Revision Numbers
51 | // by using the '*' as shown below:
52 | // [assembly: AssemblyVersion("1.0.*")]
53 | [assembly: AssemblyVersion("2.0.0.0")]
54 | [assembly: AssemblyFileVersion("1.0.0.0")]
55 | [assembly: NeutralResourcesLanguage("")]
56 |
57 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/Properties/Resources.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 SteamAccountSwitcher2.Properties
12 | {
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// Returns the cached ResourceManager instance used by this class.
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SteamAccountSwitcher2.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// Overrides the current thread's CurrentUICulture property for all
56 | /// resource lookups using this strongly typed resource class.
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/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 SteamAccountSwitcher2.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.4.0.0")]
16 | public 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 | [global::System.Configuration.UserScopedSettingAttribute()]
27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
28 | [global::System.Configuration.DefaultSettingValueAttribute("")]
29 | public string steamInstallDir {
30 | get {
31 | return ((string)(this["steamInstallDir"]));
32 | }
33 | set {
34 | this["steamInstallDir"] = value;
35 | }
36 | }
37 |
38 | [global::System.Configuration.UserScopedSettingAttribute()]
39 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
40 | [global::System.Configuration.DefaultSettingValueAttribute("0")]
41 | public double Top {
42 | get {
43 | return ((double)(this["Top"]));
44 | }
45 | set {
46 | this["Top"] = value;
47 | }
48 | }
49 |
50 | [global::System.Configuration.UserScopedSettingAttribute()]
51 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
52 | [global::System.Configuration.DefaultSettingValueAttribute("0")]
53 | public double Left {
54 | get {
55 | return ((double)(this["Left"]));
56 | }
57 | set {
58 | this["Left"] = value;
59 | }
60 | }
61 |
62 | [global::System.Configuration.UserScopedSettingAttribute()]
63 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
64 | [global::System.Configuration.DefaultSettingValueAttribute("400")]
65 | public double Height {
66 | get {
67 | return ((double)(this["Height"]));
68 | }
69 | set {
70 | this["Height"] = value;
71 | }
72 | }
73 |
74 | [global::System.Configuration.UserScopedSettingAttribute()]
75 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
76 | [global::System.Configuration.DefaultSettingValueAttribute("300")]
77 | public double Width {
78 | get {
79 | return ((double)(this["Width"]));
80 | }
81 | set {
82 | this["Width"] = value;
83 | }
84 | }
85 |
86 | [global::System.Configuration.UserScopedSettingAttribute()]
87 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
88 | [global::System.Configuration.DefaultSettingValueAttribute("False")]
89 | public bool Maximized {
90 | get {
91 | return ((bool)(this["Maximized"]));
92 | }
93 | set {
94 | this["Maximized"] = value;
95 | }
96 | }
97 |
98 | [global::System.Configuration.UserScopedSettingAttribute()]
99 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
100 | [global::System.Configuration.DefaultSettingValueAttribute("Basic")]
101 | public string encryption {
102 | get {
103 | return ((string)(this["encryption"]));
104 | }
105 | set {
106 | this["encryption"] = value;
107 | }
108 | }
109 |
110 | [global::System.Configuration.UserScopedSettingAttribute()]
111 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
112 | [global::System.Configuration.DefaultSettingValueAttribute("False")]
113 | public bool safemode {
114 | get {
115 | return ((bool)(this["safemode"]));
116 | }
117 | set {
118 | this["safemode"] = value;
119 | }
120 | }
121 |
122 | [global::System.Configuration.UserScopedSettingAttribute()]
123 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
124 | [global::System.Configuration.DefaultSettingValueAttribute("False")]
125 | public bool autostart {
126 | get {
127 | return ((bool)(this["autostart"]));
128 | }
129 | set {
130 | this["autostart"] = value;
131 | }
132 | }
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 0
10 |
11 |
12 | 0
13 |
14 |
15 | 400
16 |
17 |
18 | 300
19 |
20 |
21 | False
22 |
23 |
24 | Basic
25 |
26 |
27 | False
28 |
29 |
30 | False
31 |
32 |
33 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/Properties/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
48 |
55 |
56 |
70 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/SasManager.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.ObjectModel;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Reflection;
6 | using System.Windows;
7 | using SteamAccountSwitcher2.Settings;
8 |
9 | namespace SteamAccountSwitcher2
10 | {
11 | public sealed class SasManager
12 | {
13 | private ObservableCollection _accountList = new ObservableCollection();
14 |
15 | private Steam _steamInstallation;
16 | private CachedAccountManager _cachedAccountManager;
17 | private UserSettings _globalSettings;
18 | private AccountLoader loader;
19 | private SteamStatus _steamStatus;
20 |
21 | bool autosaveAccounts = true;
22 |
23 | private SasManager()
24 | {
25 | _globalSettings = new UserSettings(true);
26 | _steamInstallation = new Steam(GlobalSettings.SteamInstallDir);
27 |
28 | _cachedAccountManager = new CachedAccountManager(_steamInstallation);
29 | _steamStatus = new SteamStatus();
30 | }
31 |
32 | private static SasManager _instance = null;
33 |
34 | public static SasManager Instance
35 | {
36 | get
37 | {
38 | if (_instance == null)
39 | {
40 | _instance = new SasManager();
41 | }
42 |
43 | return _instance;
44 | }
45 | }
46 |
47 | public Steam SteamInstallation => _steamInstallation;
48 |
49 | public SteamStatus SteamStatus => _steamStatus;
50 |
51 | public ObservableCollection AccountList => _accountList;
52 |
53 | public UserSettings GlobalSettings
54 | {
55 | get => _globalSettings
56 | .Copy(); // Only give copies so no accidental global changes can be made, copy is non global
57 | }
58 |
59 | public void SetSteamInstallDir(string installDir)
60 | {
61 | if (installDir != null)
62 | {
63 | _steamInstallation = new Steam(installDir);
64 | _globalSettings.SteamInstallDir = installDir;
65 | }
66 | }
67 |
68 | public void InitializeAccountsFromFile()
69 | {
70 | loader = new AccountLoader(GlobalSettings.EcryptionType);
71 |
72 | if (loader.AccountFileExists())
73 | {
74 | _accountList = new ObservableCollection(loader.LoadAccounts());
75 | }
76 | else
77 | {
78 | _accountList = new ObservableCollection();
79 | }
80 | }
81 |
82 | public void SaveAccounts()
83 | {
84 | //User has exited the application, save all accounts
85 | if (autosaveAccounts)
86 | {
87 | loader.SaveAccounts(_accountList.ToList());
88 | }
89 | }
90 |
91 | public void StartSteamWithAccount(SteamAccount selectedAcc)
92 | {
93 | try
94 | {
95 | if (selectedAcc.CachedAccount)
96 | {
97 | // If no password login is possible / needed
98 | _cachedAccountManager.startCachedAccount(selectedAcc);
99 | }
100 | else
101 | {
102 | _cachedAccountManager.resetActiveAccount();
103 | _steamInstallation.StartSteamAccount(selectedAcc);
104 | }
105 | }
106 | catch (Exception e)
107 | {
108 | MessageBox.Show(e.Message, "Error when starting account", MessageBoxButton.OK, MessageBoxImage.Error);
109 | }
110 | }
111 |
112 | public void SetAutoStart(bool autostart)
113 | {
114 | try
115 | {
116 | Microsoft.Win32.RegistryKey key =
117 | Microsoft.Win32.Registry.CurrentUser.OpenSubKey(
118 | "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run",
119 | true);
120 | Assembly curAssembly = Assembly.GetExecutingAssembly();
121 | if (autostart)
122 | {
123 | key.SetValue(curAssembly.GetName().Name, curAssembly.Location);
124 | }
125 | else
126 | {
127 | key.DeleteValue(curAssembly.GetName().Name);
128 | }
129 |
130 | // Success
131 | _globalSettings.Autostart = autostart;
132 | }
133 | catch
134 | {
135 | Debug.WriteLine("Failed to set autostart to " + autostart);
136 | }
137 | }
138 |
139 | public void ScanAndAddAccounts()
140 | {
141 | _cachedAccountManager.scanForAccounts();
142 |
143 | foreach (var scannerAccount in _cachedAccountManager.CachedAccounts)
144 | {
145 | if (!_accountList.Contains(scannerAccount))
146 | _accountList.Add(scannerAccount);
147 | }
148 | }
149 |
150 | public void ApplyUserSettings(UserSettings newSettings)
151 | {
152 | if (newSettings.Autostart != _globalSettings.Autostart)
153 | {
154 | SetAutoStart(newSettings.Autostart);
155 | }
156 |
157 | if (newSettings.SteamInstallDir != _globalSettings.SteamInstallDir)
158 | {
159 | SetSteamInstallDir(newSettings.SteamInstallDir);
160 | }
161 |
162 | if (newSettings.EcryptionType != _globalSettings.EcryptionType)
163 | {
164 | SetEncryption(newSettings.EcryptionType);
165 | }
166 | }
167 |
168 | public void SetEncryption(EncryptionType newEcryptionType)
169 | {
170 | switch (newEcryptionType)
171 | {
172 | case EncryptionType.Password:
173 | PasswordWindow passwordWindow = new PasswordWindow(true);
174 | passwordWindow.ShowDialog();
175 | var password = passwordWindow.Password;
176 | if (string.IsNullOrEmpty(password))
177 | {
178 | Debug.WriteLine("Will not change encryption to empty password");
179 | return;
180 | }
181 |
182 | loader.Password = password;
183 | break;
184 | case EncryptionType.Basic:
185 | loader.Password = null;
186 | break;
187 | }
188 |
189 | loader.EncryptionType = newEcryptionType;
190 | loader.SaveAccounts(AccountList.ToList());
191 | _globalSettings.EcryptionType = newEcryptionType;
192 | }
193 | }
194 | }
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/Settings/SettingsWindow.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
13 |
14 |
15 |
17 | Steam Installation Directory
18 |
19 |
20 |
21 |
22 |
24 |
27 |
28 |
29 |
31 | AutoStart
32 |
33 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
48 | Encryption Method
49 |
50 |
51 |
52 |
53 |
55 |
56 |
57 |
59 |
60 |
61 |
62 |
63 |
64 |
66 | Password Options
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/Settings/SettingsWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows;
3 | using SteamAccountSwitcher2.Settings;
4 |
5 | namespace SteamAccountSwitcher2
6 | {
7 | ///
8 | /// Interaction logic for SettingsWindow.xaml
9 | ///
10 | public partial class SettingsWindow : Window
11 | {
12 | private UserSettings _windowSettings;
13 |
14 | public SettingsWindow()
15 | {
16 | InitializeComponent();
17 |
18 | RefreshGUIWithSettings();
19 | }
20 |
21 | private void RefreshGUIWithSettings()
22 | {
23 | //Initialize Settings to GUI
24 | _windowSettings = SasManager.Instance.GlobalSettings;
25 |
26 | textSteamInstallDir.Text = _windowSettings.SteamInstallDir;
27 | checkBoxAutostart.IsChecked = _windowSettings.Autostart;
28 |
29 | EncryptionType enc = _windowSettings.EcryptionType;
30 | switch (enc)
31 | {
32 | case EncryptionType.Basic:
33 | radioButtonBasicEnc.IsChecked = true;
34 | PasswordOptionsGroupBox.Visibility = Visibility.Collapsed;
35 | break;
36 | case EncryptionType.Password:
37 | radioButtonPasswordEnc.IsChecked = true;
38 | PasswordOptionsGroupBox.Visibility = Visibility.Visible;
39 | break;
40 | default:
41 | MessageBox.Show(
42 | "Encryption type not supported! Make sure you are using the latest SteamAccountSwitcher!",
43 | "Unspported Encryption Type", MessageBoxButton.OK, MessageBoxImage.Error);
44 | radioButtonBasicEnc.IsChecked = false;
45 | radioButtonBasicEnc.IsEnabled = false;
46 | radioButtonPasswordEnc.IsChecked = false;
47 | radioButtonPasswordEnc.IsEnabled = false;
48 | break;
49 | }
50 | }
51 |
52 | public bool HasUnwrittenChanges()
53 | {
54 | return !SasManager.Instance.GlobalSettings.Equals(_windowSettings);
55 | }
56 |
57 | private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
58 | {
59 | var doClose = TryClosing();
60 | e.Cancel = !doClose;
61 | }
62 |
63 | private void buttonBrowseSteamInstallDir_Click(object sender, RoutedEventArgs e)
64 | {
65 | string installDir = UserInteraction.selectSteamDirectory(@"C:\Program Files (x86)\Steam");
66 | if (installDir != null)
67 | {
68 | _windowSettings.SteamInstallDir = installDir;
69 | textSteamInstallDir.Text = _windowSettings.SteamInstallDir;
70 | MadeChange();
71 | }
72 | }
73 |
74 | private void MadeChange()
75 | {
76 | // TODO refactor this using events or something
77 | buttonApply.IsEnabled = HasUnwrittenChanges();
78 | }
79 |
80 | private void checkBox_Checked(object sender, RoutedEventArgs e)
81 | {
82 | _windowSettings.Autostart = true;
83 | MadeChange();
84 | }
85 |
86 | private void checkBox_Unchecked(object sender, RoutedEventArgs e)
87 | {
88 | _windowSettings.Autostart = false;
89 | MadeChange();
90 | }
91 |
92 | private void buttonApply_Click(object sender, RoutedEventArgs e)
93 | {
94 | SasManager.Instance.ApplyUserSettings(_windowSettings);
95 | buttonApply.IsEnabled = HasUnwrittenChanges();
96 | RefreshGUIWithSettings();
97 | }
98 |
99 | private void buttonOk_Click(object sender, RoutedEventArgs e)
100 | {
101 | SasManager.Instance.ApplyUserSettings(_windowSettings);
102 | Close();
103 | }
104 |
105 | private void buttonCancel_Click(object sender, RoutedEventArgs e)
106 | {
107 | Close();
108 | }
109 |
110 |
111 | private bool TryClosing()
112 | {
113 | if (!SasManager.Instance.GlobalSettings.Equals(_windowSettings))
114 | {
115 | var result = MessageBox.Show("Are you sure you want to discard changed settings?", "Unsaved changes",
116 | MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No);
117 | return result == MessageBoxResult.Yes;
118 | }
119 |
120 | return true;
121 | }
122 |
123 | private void radioButtonBasicEnc_Checked(object sender, RoutedEventArgs e)
124 | {
125 | _windowSettings.EcryptionType = EncryptionType.Basic;
126 | MadeChange();
127 | }
128 |
129 | private void radioButtonPasswordEnc_Checked(object sender, RoutedEventArgs e)
130 | {
131 | _windowSettings.EcryptionType = EncryptionType.Password;
132 | MadeChange();
133 | }
134 |
135 | private void ButtonSetPassword_Click(object sender, RoutedEventArgs e)
136 | {
137 | SasManager.Instance.SetEncryption(EncryptionType.Password);
138 | }
139 | }
140 | }
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/Settings/UserSettings.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SteamAccountSwitcher2.Settings
4 | {
5 | public class UserSettings
6 | {
7 | private bool _globalSettings;
8 |
9 | private string _steamInstallDir;
10 | private EncryptionType _ecryptionType;
11 | private bool _autostart;
12 |
13 |
14 | public UserSettings() : this(false)
15 | {
16 |
17 | }
18 |
19 | public UserSettings(bool global)
20 | {
21 | _globalSettings = global;
22 | if (_globalSettings)
23 | {
24 | _autostart = Properties.Settings.Default.autostart;
25 | _steamInstallDir = Properties.Settings.Default.steamInstallDir;
26 | _ecryptionType =
27 | (EncryptionType) Enum.Parse(typeof(EncryptionType), Properties.Settings.Default.encryption);
28 | }
29 | }
30 |
31 | public string SteamInstallDir
32 | {
33 | get => _steamInstallDir;
34 | set
35 | {
36 | _steamInstallDir = value;
37 | if(_globalSettings) Properties.Settings.Default.steamInstallDir = value;
38 | }
39 | }
40 |
41 | public EncryptionType EcryptionType
42 | {
43 | get => _ecryptionType;
44 | set
45 | {
46 | _ecryptionType = value;
47 | if (_globalSettings)
48 | Properties.Settings.Default.encryption = value.ToString();
49 | }
50 | }
51 |
52 | public bool Autostart
53 | {
54 | get => _autostart;
55 | set
56 | {
57 | _autostart = value;
58 | if (_globalSettings) Properties.Settings.Default.autostart = value;
59 | }
60 | }
61 |
62 | protected bool Equals(UserSettings otherUserSettings)
63 | {
64 | return _steamInstallDir == otherUserSettings._steamInstallDir &&
65 | _ecryptionType == otherUserSettings._ecryptionType &&
66 | _autostart == otherUserSettings._autostart;
67 | }
68 |
69 | public UserSettings Copy()
70 | {
71 | var copySettings = new UserSettings
72 | {
73 | Autostart = Autostart,
74 | SteamInstallDir = SteamInstallDir,
75 | EcryptionType = EcryptionType
76 | };
77 | return copySettings;
78 | }
79 |
80 | public override bool Equals(object obj)
81 | {
82 | if (ReferenceEquals(null, obj)) return false;
83 | if (ReferenceEquals(this, obj)) return true;
84 | if (obj.GetType() != this.GetType()) return false;
85 | return Equals((UserSettings) obj);
86 | }
87 |
88 | public override int GetHashCode()
89 | {
90 | unchecked
91 | {
92 | var hashCode = (_steamInstallDir != null ? _steamInstallDir.GetHashCode() : 0);
93 | hashCode = (hashCode * 397) ^ (_ecryptionType != null ? _ecryptionType.GetHashCode() : 0);
94 | hashCode = (hashCode * 397) ^ _autostart.GetHashCode();
95 | return hashCode;
96 | }
97 | }
98 | }
99 | }
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/Steam.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.IO;
4 | using System.Text;
5 | using System.Threading;
6 |
7 | namespace SteamAccountSwitcher2
8 | {
9 | public class Steam
10 | {
11 | [System.Runtime.InteropServices.DllImport("User32.dll")]
12 | private static extern bool SetForegroundWindow(IntPtr handle);
13 |
14 | [System.Runtime.InteropServices.DllImport("User32.dll")]
15 | private static extern bool ShowWindow(IntPtr handle, int nCmdShow);
16 |
17 | [System.Runtime.InteropServices.DllImport("User32.dll")]
18 | private static extern bool IsIconic(IntPtr handle);
19 |
20 | private const int SW_RESTORE = 9;
21 |
22 | private string _installLocation;
23 |
24 | public Steam(string installLocation)
25 | {
26 | _installLocation = installLocation;
27 | }
28 |
29 | public string InstallLocation
30 | {
31 | get => _installLocation;
32 | set => _installLocation = value;
33 | }
34 |
35 | // TODO improve this
36 | public string InstallDir => _installLocation.Replace("Steam.exe", "").Replace("steam.exe", "");
37 |
38 | public bool IsSteamRunning()
39 | {
40 | var steamProcesses = Process.GetProcessesByName("steam");
41 | return steamProcesses.Length > 0;
42 | }
43 |
44 | public void KillSteam()
45 | {
46 | var steamProcesses = Process.GetProcessesByName("steam");
47 | if (steamProcesses.Length > 0)
48 | steamProcesses[0].Kill();
49 | }
50 |
51 | public void CleanKillSteam()
52 | {
53 | var proc = Process.GetProcessesByName("steam");
54 | if (proc.Length > 0)
55 | {
56 | proc[0].CloseMainWindow();
57 | proc[0].Close();
58 | }
59 | }
60 |
61 | public void Start()
62 | {
63 | var p = new Process();
64 | if (File.Exists(_installLocation))
65 | {
66 | p.StartInfo = new ProcessStartInfo(_installLocation);
67 | p.Start();
68 | }
69 | }
70 |
71 | public bool StartSteamAccount(SteamAccount acc)
72 | {
73 | var finished = false;
74 |
75 | if (IsSteamRunning()) CleanKillSteam();
76 |
77 | var waitTimer = 30;
78 | while (finished == false)
79 | {
80 | if (waitTimer == 0)
81 | {
82 | KillSteam();
83 | Debug.WriteLine("Hard killed steam.");
84 | }
85 |
86 | if (IsSteamRunning() == false)
87 | {
88 | var p = new Process();
89 | if (File.Exists(_installLocation))
90 | {
91 | p.StartInfo = new ProcessStartInfo(_installLocation, acc.StartParameters());
92 | p.Start();
93 | finished = true;
94 |
95 | return true;
96 | }
97 | }
98 |
99 | Thread.Sleep(100);
100 | waitTimer--;
101 | }
102 |
103 | return false;
104 | }
105 |
106 | [Obsolete("IsSteamReady is deprecated.")]
107 | private bool IsSteamReady()
108 | {
109 | var logDir = _installLocation.Replace("Steam.exe", "logs\\");
110 | var filename = logDir + "bootstrap_log.txt";
111 |
112 | using (var fs = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
113 | {
114 | // Seek 1024 bytes from the end of the file
115 | fs.Seek(-512, SeekOrigin.End);
116 | // read 1024 bytes
117 | var bytes = new byte[512];
118 | fs.Read(bytes, 0, 512);
119 | // Convert bytes to string
120 | var s = Encoding.Default.GetString(bytes);
121 | // or string s = Encoding.UTF8.GetString(bytes);
122 | // and output to console
123 | //Debug.WriteLine(s);
124 | var splitter = new string[1];
125 | splitter[0] = "Startup - updater";
126 | var parts = s.Split(splitter, StringSplitOptions.RemoveEmptyEntries);
127 |
128 | var steamDone = parts[parts.Length - 1].Contains("Background update loop checking for update.");
129 | Debug.WriteLineIf(steamDone, "steam is Done.");
130 | return steamDone;
131 | }
132 | }
133 |
134 | public bool LogoutSteam()
135 | {
136 | var p = new Process();
137 | if (File.Exists(_installLocation))
138 | {
139 | p.StartInfo = new ProcessStartInfo(_installLocation, "-shutdown");
140 | p.Start();
141 | return true;
142 | }
143 |
144 | return false;
145 | }
146 | }
147 | }
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/SteamAccount.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.IO;
3 |
4 | namespace SteamAccountSwitcher2
5 | {
6 | public class SteamAccount
7 | {
8 | private string _name;
9 | private string _accountName;
10 | private string _password;
11 | private AccountType _type;
12 | private string _steamId;
13 | private string _personaName;
14 | private bool _rememberPassword;
15 | private bool _mostrecent;
16 | private long _timestamp;
17 | private bool _cachedAccount;
18 |
19 | private const string ImageFolder = "images";
20 |
21 | public SteamAccount()
22 | {
23 | // Empty constructor must exist for the JSON Converter!
24 | }
25 |
26 | public SteamAccount(string accountName, string password)
27 | {
28 | Name = accountName;
29 | AccountName = accountName;
30 | Password = password;
31 | Type = AccountType.Main;
32 | }
33 |
34 | public SteamAccount(string steamId, string accountName, string personaName, bool rememberPassword,
35 | bool mostrecent, long timestamp)
36 | {
37 | Name = PersonaName = personaName;
38 | SteamId = steamId;
39 | AccountName = accountName;
40 | PersonaName = personaName;
41 | RememberPassword = rememberPassword;
42 | Mostrecent = mostrecent;
43 | Timestamp = timestamp;
44 | Type = AccountType.Main;
45 | }
46 |
47 | public string SteamId
48 | {
49 | get => _steamId;
50 | set => _steamId = value;
51 | }
52 |
53 | public string AccountName
54 | {
55 | get => _accountName;
56 | set => _accountName = value;
57 | }
58 |
59 | public string PersonaName
60 | {
61 | get => _personaName;
62 | set => _personaName = value;
63 | }
64 |
65 | public bool RememberPassword
66 | {
67 | get => _rememberPassword;
68 | set => _rememberPassword = value;
69 | }
70 |
71 | public bool Mostrecent
72 | {
73 | get => _mostrecent;
74 | set => _mostrecent = value;
75 | }
76 |
77 | public long Timestamp
78 | {
79 | get => _timestamp;
80 | set => _timestamp = value;
81 | }
82 |
83 | public string Name
84 | {
85 | get => _name;
86 | set => this._name = value;
87 | }
88 |
89 | public string Password
90 | {
91 | get => _password;
92 | set => this._password = value;
93 | }
94 |
95 | public AccountType Type
96 | {
97 | get => _type;
98 | set => this._type = value;
99 | }
100 |
101 | public string AccountImage => Path.Combine(SasManager.Instance.SteamInstallation.InstallDir, "config\\avatarcache", SteamId + ".png");
102 |
103 | public string BGImage => ImageFolder + "/acc-bg-" + _type.ToString().ToLower() + ".jpg";
104 |
105 | //public bool IsCached => string.IsNullOrEmpty(_password);
106 | public bool CachedAccount
107 | {
108 | get => string.IsNullOrEmpty(_password);
109 | //set => _cachedAccount = value;
110 | }
111 |
112 | public string StartParameters()
113 | {
114 | return "-login " + AccountName + " " + Password;
115 | }
116 |
117 | public override string ToString()
118 | {
119 | return Name + " (Username: " + AccountName + ")";
120 | }
121 |
122 | protected bool Equals(SteamAccount other)
123 | {
124 | return Name == other._name && _accountName == other._accountName && _password == other._password && _type == other._type && _steamId == other._steamId && _personaName == other._personaName && _cachedAccount == other._cachedAccount;
125 | }
126 |
127 | public override bool Equals(object obj)
128 | {
129 | if (ReferenceEquals(null, obj)) return false;
130 | if (ReferenceEquals(this, obj)) return true;
131 | if (obj.GetType() != this.GetType()) return false;
132 | return Equals((SteamAccount) obj);
133 | }
134 |
135 | public override int GetHashCode()
136 | {
137 | unchecked
138 | {
139 | var hashCode = (_name != null ? _name.GetHashCode() : 0);
140 | hashCode = (hashCode * 397) ^ (_accountName != null ? _accountName.GetHashCode() : 0);
141 | hashCode = (hashCode * 397) ^ (_password != null ? _password.GetHashCode() : 0);
142 | hashCode = (hashCode * 397) ^ (int) _type;
143 | hashCode = (hashCode * 397) ^ (_steamId != null ? _steamId.GetHashCode() : 0);
144 | hashCode = (hashCode * 397) ^ (_personaName != null ? _personaName.GetHashCode() : 0);
145 | hashCode = (hashCode * 397) ^ _cachedAccount.GetHashCode();
146 | return hashCode;
147 | }
148 | }
149 | }
150 | }
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/SteamAccountSwitcher.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {CD84E7B0-56E4-43F0-8532-55972070F563}
8 | WinExe
9 | Properties
10 | SteamAccountSwitcher2
11 | SteamAccountSwitcher2
12 | v4.5.2
13 | 512
14 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
15 | 4
16 | true
17 | true
18 | sftp://wedenig.org:22/
19 | true
20 | Web
21 | true
22 | Foreground
23 | 7
24 | Days
25 | false
26 | false
27 | true
28 | https://wedenig.org/SteamAccountSwitcher/
29 | https://wedenig.org/SteamAccountSwitcher
30 | en
31 | Steam Account Switcher
32 | W3D3
33 | true
34 | publish.htm
35 | 2
36 | 1.0.0.%2a
37 | true
38 | true
39 | true
40 | true
41 |
42 |
43 | AnyCPU
44 | true
45 | full
46 | false
47 | bin\Debug\
48 | DEBUG;TRACE
49 | prompt
50 | 4
51 |
52 |
53 | AnyCPU
54 | pdbonly
55 | true
56 | bin\Release\
57 | TRACE
58 | prompt
59 | 4
60 |
61 |
62 | 69F542697F0151D28C1C4134BDF7ABCB0873C713
63 |
64 |
65 | SteamAccountSwitcher2_1_TemporaryKey.pfx
66 |
67 |
68 | true
69 |
70 |
71 | false
72 |
73 |
74 | Properties\app.manifest
75 |
76 |
77 | Custom
78 |
79 |
80 | false
81 |
82 |
83 |
84 |
85 |
86 |
87 | bin\Deploy\
88 | TRACE
89 | true
90 | pdbonly
91 | AnyCPU
92 | prompt
93 | MinimumRecommendedRules.ruleset
94 | true
95 |
96 |
97 |
98 | ..\packages\Autoupdater.NET.Official.1.5.8\lib\net40\AutoUpdater.NET.dll
99 |
100 |
101 | ..\packages\Gameloop.Vdf.0.5.0\lib\net45\Gameloop.Vdf.dll
102 |
103 |
104 | ..\packages\gong-wpf-dragdrop.2.2.0\lib\net45\GongSolutions.WPF.DragDrop.dll
105 |
106 |
107 | ..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 | 4.0
119 |
120 |
121 |
122 |
123 |
124 | ..\packages\InputSimulator.1.0.4.0\lib\net20\WindowsInput.dll
125 | True
126 |
127 |
128 |
129 |
130 | MSBuild:Compile
131 | Designer
132 |
133 |
134 |
135 |
136 |
137 | AccountWindow.xaml
138 |
139 |
140 |
141 |
142 |
143 | PasswordWindow.xaml
144 |
145 |
146 |
147 |
148 |
149 |
150 | Designer
151 | MSBuild:Compile
152 |
153 |
154 | Designer
155 | MSBuild:Compile
156 |
157 |
158 | MSBuild:Compile
159 | Designer
160 |
161 |
162 | App.xaml
163 | Code
164 |
165 |
166 | LogWindow.xaml
167 |
168 |
169 | SettingsWindow.xaml
170 |
171 |
172 |
173 |
174 | MainWindow.xaml
175 | Code
176 |
177 |
178 | Designer
179 | MSBuild:Compile
180 |
181 |
182 | Designer
183 | MSBuild:Compile
184 |
185 |
186 |
187 |
188 | Code
189 |
190 |
191 | True
192 | True
193 | Resources.resx
194 |
195 |
196 | True
197 | Settings.settings
198 | True
199 |
200 |
201 | ResXFileCodeGenerator
202 | Resources.Designer.cs
203 |
204 |
205 |
206 |
207 | SettingsSingleFileGenerator
208 | Settings.Designer.cs
209 |
210 |
211 |
212 |
213 |
214 | Designer
215 |
216 |
217 |
218 |
219 | False
220 | Microsoft .NET Framework 4.5.2 %28x86 and x64%29
221 | true
222 |
223 |
224 | False
225 | .NET Framework 3.5 SP1
226 | false
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |
309 |
310 |
317 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/SteamStatus.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json.Linq;
2 | using System.Net;
3 | using System.Text;
4 | using System.Windows.Media;
5 |
6 | namespace SteamAccountSwitcher2
7 | {
8 | ///
9 | /// The Class is offering steam status information.
10 | ///
11 | public class SteamStatus
12 | {
13 | const string STATUS_API = "https://crowbar.steamstat.us/gravity.json";
14 | private bool onlineStatusGood = false;
15 |
16 | public SteamStatus()
17 | {
18 | ServicePointManager.Expect100Continue = true;
19 | ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
20 | refreshStatus();
21 | }
22 |
23 | public void refreshStatus()
24 | {
25 | onlineStatusGood = checkSteamStatus();
26 | }
27 |
28 | ///
29 | /// Checks Steam status by calling an external service.
30 | ///
31 | /// true if steam is up, false if not.
32 | private static bool checkSteamStatus()
33 | {
34 | try
35 | {
36 | WebClient client = new WebClient() { Encoding = Encoding.UTF8 };
37 | client.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");
38 | string statusJson = client.DownloadString(STATUS_API);
39 | JObject status = JObject.Parse(statusJson);
40 |
41 | // TODO get a proper steam status check, this is unreliable
42 | string state = status["services"][2][1].ToString();
43 | if (state == "0")
44 | return true;
45 | else
46 | return false;
47 | }
48 | catch
49 | {
50 | return false;
51 | }
52 |
53 | }
54 |
55 | ///
56 | /// Generates a GUI friendly string describing Steam's status at the time of last refresh.
57 | ///
58 | /// GUI friendly .
59 | public string steamStatusMessage()
60 | {
61 | return onlineStatusGood ? "Steam is operating normally." : "Steam is currently having issues!";
62 | }
63 |
64 | ///
65 | /// Generates a indicating Steam's status at the time of last refresh.
66 | ///
67 | /// status indicator
68 | public SolidColorBrush getStatusColor()
69 | {
70 | if (onlineStatusGood)
71 | {
72 | Color green = Color.FromRgb(146, 247, 181);
73 | SolidColorBrush greenbrush = new SolidColorBrush(green);
74 | return greenbrush;
75 | }
76 | else
77 | {
78 | Color red = Color.FromRgb(250, 165, 165);
79 | SolidColorBrush redbrush = new SolidColorBrush(red);
80 | return redbrush;
81 | }
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/UserInteraction.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Win32;
2 |
3 | namespace SteamAccountSwitcher2
4 | {
5 | class UserInteraction
6 | {
7 | public static string selectSteamDirectory(string initialDirectory)
8 | {
9 | OpenFileDialog dialog = new OpenFileDialog();
10 | dialog.Filter =
11 | "Steam |steam.exe";
12 | dialog.InitialDirectory = initialDirectory;
13 | dialog.Title = "Select your Steam Installation";
14 | return (dialog.ShowDialog() == true)
15 | ? dialog.FileName : null;
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/edit.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/acc-bg-banned.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/acc-bg-banned.jpg
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/acc-bg-friend.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/acc-bg-friend.jpg
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/acc-bg-main.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/acc-bg-main.jpg
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/acc-bg-smurf.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/acc-bg-smurf.jpg
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/cross-button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/cross-button.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/gear.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/gear.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/download.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/download.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/edit.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/export.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/export.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/external.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/external.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/full_trash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/full_trash.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/import.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/import.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/internal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/internal.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/key.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/key.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/lock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/lock.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/minus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/minus.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/multiple_inputs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/multiple_inputs.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/plus.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/search.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/settings.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/small/download.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/small/download.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/small/edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/small/edit.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/small/export.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/small/export.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/small/external.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/small/external.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/small/full_trash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/small/full_trash.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/small/import.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/small/import.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/small/internal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/small/internal.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/small/key.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/small/key.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/small/lock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/small/lock.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/small/minus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/small/minus.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/small/multiple_inputs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/small/multiple_inputs.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/small/plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/small/plus.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/small/search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/small/search.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/small/settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/small/settings.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/small/synchronize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/small/synchronize.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/small/unlock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/small/unlock.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/small/upload.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/small/upload.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/synchronize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/synchronize.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/unlock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/unlock.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/icons/upload.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/icons/upload.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/lock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/lock.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/minus-button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/minus-button.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/pencil-button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/pencil-button.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/pencil.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/pencil.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/plus-button.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/plus-button.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/plus.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/images/plus_old.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcher2/images/plus_old.png
--------------------------------------------------------------------------------
/SteamAccountSwitcher2/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/SteamAccountSwitcherSetup/SteamAccountSwitcherSetup-SetupFiles/SteamAccountSwitcherSetup.msi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcherSetup/SteamAccountSwitcherSetup-SetupFiles/SteamAccountSwitcherSetup.msi
--------------------------------------------------------------------------------
/SteamAccountSwitcherSetup/SteamAccountSwitcherSetup-cache/cacheIndex.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcherSetup/SteamAccountSwitcherSetup-cache/cacheIndex.txt
--------------------------------------------------------------------------------
/SteamAccountSwitcherSetup/SteamAccountSwitcherSetup-cache/part2/disk1.cab:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcherSetup/SteamAccountSwitcherSetup-cache/part2/disk1.cab
--------------------------------------------------------------------------------
/SteamAccountSwitcherSetup/SteamAccountSwitcherSetup-cache/part2/output-info.ini:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/W3D3/SteamAccountSwitcher2/acd53ee73a7eb98be6e0190180cde13889eda2d0/SteamAccountSwitcherSetup/SteamAccountSwitcherSetup-cache/part2/output-info.ini
--------------------------------------------------------------------------------
/SteamAccountSwitcherSetup/SteamAccountSwitcherSetup.aip:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
--------------------------------------------------------------------------------
/SteamAccountSwitcherSetup/SteamAccountSwitcherSetup.aiproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | All
4 | 2.0
5 | df67b771-6f39-474c-9833-5fc8ae064eea
6 | msi
7 | .
8 | SteamAccountSwitcherSetup.aip
9 |
10 |
11 | .
12 | True
13 | SteamAccountSwitcherSetup
14 | SteamAccountSwitcherSetup
15 | SteamAccountSwitcherSetup
16 |
17 |
18 |
19 |
20 |
21 |
22 | Code
23 |
24 |
25 |
26 |
27 | SteamAccountSwitcher
28 | {cd84e7b0-56e4-43f0-8532-55972070f563}
29 | True
30 | PrimaryOutput;References
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------