├── SteamAccountSwitcher
├── SteamAccountSwitcher.ico
├── FodyWeavers.xml
├── SteamAccount.cs
├── MyTaskbarIcon.cs
├── App.xaml
├── ObjectToTypeConverter.cs
├── Options.xaml.cs
├── Properties
│ ├── Settings.settings
│ ├── Settings.Designer.cs
│ ├── Resources.Designer.cs
│ └── Resources.resx
├── SteamIdToAvatarConverter.cs
├── AppResources.xaml.cs
├── SteamAccountSwitcher.csproj
├── AppResources.xaml
├── App.config
├── SteamAccountCollection.cs
├── App.xaml.cs
├── Options.xaml
├── Resources
│ └── Licenses.txt
└── SteamClient.cs
├── .github
└── workflows
│ ├── build.yml
│ └── deploy.yml
├── SteamAccountSwitcher.sln
├── LICENSE
├── README.md
├── Product.wxs
└── .gitignore
/SteamAccountSwitcher/SteamAccountSwitcher.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/danielchalmers/SteamAccountSwitcher/HEAD/SteamAccountSwitcher/SteamAccountSwitcher.ico
--------------------------------------------------------------------------------
/SteamAccountSwitcher/FodyWeavers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on:
4 | push:
5 | pull_request:
6 |
7 | jobs:
8 | deploy:
9 | runs-on: windows-latest
10 | steps:
11 | - uses: actions/checkout@v3
12 |
13 | - uses: actions/setup-dotnet@v2
14 |
15 | - name: Build
16 | run: dotnet build
17 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher/SteamAccount.cs:
--------------------------------------------------------------------------------
1 | namespace SteamAccountSwitcher
2 | {
3 | public record class SteamAccount
4 | {
5 | public string ID { get; set; }
6 |
7 | public string Name { get; set; }
8 |
9 | public string Alias { get; set; }
10 |
11 | public override string ToString() => Alias ?? Name;
12 | }
13 | }
--------------------------------------------------------------------------------
/SteamAccountSwitcher/MyTaskbarIcon.cs:
--------------------------------------------------------------------------------
1 | using H.NotifyIcon;
2 |
3 | namespace SteamAccountSwitcher
4 | {
5 | public class MyTaskbarIcon : TaskbarIcon
6 | {
7 | public MyTaskbarIcon()
8 | {
9 | ForceCreate();
10 | }
11 |
12 | public void ShowRunningInTrayNotification()
13 | {
14 | ShowNotification("Running in the tray", "Click the icon to see your accounts");
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/SteamAccountSwitcher/App.xaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher/ObjectToTypeConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.Windows.Data;
4 | using System.Windows.Markup;
5 |
6 | namespace SteamAccountSwitcher
7 | {
8 | [ValueConversion(typeof(object), typeof(Type))]
9 | public class ObjectToTypeConverter : MarkupExtension, IValueConverter
10 | {
11 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
12 | {
13 | return value.GetType();
14 | }
15 |
16 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
17 | {
18 | throw new NotImplementedException();
19 | }
20 |
21 | public override object ProvideValue(IServiceProvider serviceProvider) => this;
22 | }
23 | }
--------------------------------------------------------------------------------
/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | name: Deploy
2 |
3 | on:
4 | push:
5 | tags:
6 | - 'v*'
7 |
8 | jobs:
9 | deploy:
10 | runs-on: windows-latest
11 | steps:
12 | - uses: actions/checkout@v3
13 |
14 | - uses: actions/setup-dotnet@v2
15 |
16 | - name: Build
17 | run: dotnet publish -o "publish" -c Release -r win-x64
18 |
19 | - name: Create installer
20 | run: |
21 | dotnet tool install --global wix --version 4.0.0-preview.1
22 | wix build Product.wxs -o "publish/Install Steam Account Switcher.msi"
23 |
24 | - name: Create GitHub release
25 | uses: ncipollo/release-action@v1
26 | with:
27 | artifacts: "publish/*.exe,publish/*.msi"
28 | allowUpdates: true
29 | artifactErrorsFailBuild: true
30 | prerelease: contains(github.ref, 'beta')
31 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.22609.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SteamAccountSwitcher", "SteamAccountSwitcher\SteamAccountSwitcher.csproj", "{AC008FC6-F8BF-44E3-AEBD-A0FCECC5253F}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {AC008FC6-F8BF-44E3-AEBD-A0FCECC5253F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {AC008FC6-F8BF-44E3-AEBD-A0FCECC5253F}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {AC008FC6-F8BF-44E3-AEBD-A0FCECC5253F}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {AC008FC6-F8BF-44E3-AEBD-A0FCECC5253F}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Daniel Chalmers
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher/Options.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Windows;
4 | using SteamAccountSwitcher.Properties;
5 |
6 | namespace SteamAccountSwitcher
7 | {
8 | ///
9 | /// Interaction logic for Options.xaml
10 | ///
11 | public partial class Options : Window
12 | {
13 | public Options()
14 | {
15 | InitializeComponent();
16 | Settings.Default.Save();
17 | }
18 |
19 | private void GitHubHyperlink_Click(object sender, RoutedEventArgs e)
20 | {
21 | Process.Start(Properties.Resources.GitHub);
22 | }
23 |
24 | private void LicensesHyperlink_Click(object sender, RoutedEventArgs e)
25 | {
26 | MessageBox.Show(Properties.Resources.Licenses);
27 | }
28 |
29 | private void OkButton_Click(object sender, RoutedEventArgs e)
30 | {
31 | DialogResult = true;
32 | }
33 |
34 | private void CancelButton_Click(object sender, RoutedEventArgs e)
35 | {
36 | DialogResult = false;
37 | }
38 |
39 | private void Window_Closed(object sender, EventArgs e)
40 | {
41 | if (DialogResult == true)
42 | {
43 | Settings.Default.Save();
44 | }
45 | else
46 | {
47 | Settings.Default.Reload();
48 | }
49 | }
50 | }
51 | }
--------------------------------------------------------------------------------
/SteamAccountSwitcher/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | True
10 |
11 |
12 | False
13 |
14 |
15 | 30000
16 |
17 |
18 | 100
19 |
20 |
21 |
22 |
23 |
24 | True
25 |
26 |
27 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher/SteamIdToAvatarConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 | using System.Windows.Controls;
4 | using System.Windows.Data;
5 | using System.Windows.Markup;
6 | using System.Windows.Media.Imaging;
7 | using System.Xml;
8 | using SteamAccountSwitcher.Properties;
9 |
10 | namespace SteamAccountSwitcher;
11 |
12 | [ValueConversion(typeof(string), typeof(Image))]
13 | public class SteamIdToAvatarConverter : MarkupExtension, IValueConverter
14 | {
15 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
16 | {
17 | try
18 | {
19 | if (Settings.Default.ShowAvatars && value is string id)
20 | {
21 | var profileDocument = new XmlDocument();
22 |
23 | profileDocument.Load($"https://steamcommunity.com/profiles/{id}?xml=1");
24 |
25 | var avatarIconNode = profileDocument.DocumentElement.SelectSingleNode("/profile/avatarIcon");
26 |
27 | return new Image { Source = new BitmapImage(new Uri(avatarIconNode.InnerText)) };
28 | }
29 | }
30 | catch
31 | {
32 | // Couldn't load the image.
33 | }
34 |
35 | return null;
36 | }
37 |
38 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
39 | {
40 | throw new NotImplementedException();
41 | }
42 |
43 | public override object ProvideValue(IServiceProvider serviceProvider) => this;
44 | }
--------------------------------------------------------------------------------
/SteamAccountSwitcher/AppResources.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using System.Windows;
4 | using System.Windows.Controls;
5 |
6 | namespace SteamAccountSwitcher
7 | {
8 | public partial class AppResources : ResourceDictionary
9 | {
10 | public AppResources()
11 | {
12 | InitializeComponent();
13 | }
14 |
15 | private async void MenuItem_Click(object sender, RoutedEventArgs e)
16 | {
17 | var menuItem = (MenuItem)sender;
18 |
19 | if (menuItem.CommandParameter is string stringParameter)
20 | {
21 | if (stringParameter == "add-account")
22 | {
23 | await SteamClient.LogOut();
24 | }
25 | else if (stringParameter == "options")
26 | {
27 | var optionsDialog = Application.Current.Windows.OfType().FirstOrDefault() ?? new Options();
28 |
29 | if (optionsDialog.IsVisible)
30 | {
31 | optionsDialog.Activate();
32 | return;
33 | }
34 |
35 | optionsDialog.ShowDialog();
36 | }
37 | else if (stringParameter == "exit")
38 | {
39 | Application.Current.Shutdown();
40 | }
41 | }
42 | else if (menuItem.CommandParameter is SteamAccount account)
43 | {
44 | menuItem.IsEnabled = false;
45 | await SteamClient.LogIn(account);
46 | menuItem.IsEnabled = true;
47 | }
48 | else
49 | {
50 | throw new NotImplementedException();
51 | }
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Steam Account Switcher
2 |
3 | [](https://github.com/danielchalmers/SteamAccountSwitcher/releases)
4 | [](LICENSE)
5 |
6 | Quickly switch between your Steam accounts with a lightweight and easy to use menu.
7 |
8 | 
9 |
10 | ## Features
11 |
12 | ✅ Fast — switch users through the tray icon
13 | ✅ Easy — accounts are found automatically
14 | ✅ Safe — no VAC risk & doesn't store passwords
15 | ✅ Open — free & open source forever
16 |
17 | ## Download
18 |
19 | ➡️ Get it from the [Releases](https://github.com/danielchalmers/SteamAccountSwitcher/releases) page (see `Assets`).
20 |
21 | Windows 10 [version 1903](https://support.microsoft.com/en-us/windows/which-version-of-windows-operating-system-am-i-running-628bec99-476a-2c13-5296-9dd081cdd808) or newer is recommended.
22 |
23 | ## What's new in v3.0
24 |
25 | - The tray icon is now the default and the main window has been removed in order to streamline the app.
26 | - Accounts are now automatically discovered — no setup needed!
27 | - Passwords are handled entirely by Steam for extra security and ease of use.
28 | - Steam Guard is not required on every login like before.
29 | - Cleaner codebase that's easier to understand and change.
30 |
31 | ## v2.3.1
32 |
33 | Looking for the old version? [Download v2.3.1 here](https://github.com/danielchalmers/SteamAccountSwitcher/releases/tag/v2.3.1).
34 |
35 | 
36 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher/SteamAccountSwitcher.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net48
4 | WinExe
5 | true
6 | true
7 | latest
8 | SteamAccountSwitcher.ico
9 | Steam Account Switcher
10 | Daniel Chalmers
11 | Steam Account Switcher
12 | © Daniel Chalmers 2022
13 | 3.0.0
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | PublicResXFileCodeGenerator
27 | Resources.Designer.cs
28 |
29 |
30 | True
31 | True
32 | Resources.resx
33 |
34 |
35 | SettingsSingleFileGenerator
36 | Settings.Designer.cs
37 |
38 |
39 | True
40 | True
41 | Settings.settings
42 |
43 |
44 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher/AppResources.xaml:
--------------------------------------------------------------------------------
1 |
5 |
9 |
10 |
11 |
12 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | True
21 |
22 |
23 | False
24 |
25 |
26 |
27 |
28 |
29 | True
30 |
31 |
32 |
33 |
34 |
35 |
36 | 30000
37 |
38 |
39 | 100
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher/SteamAccountCollection.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.IO;
5 | using Gameloop.Vdf;
6 |
7 | namespace SteamAccountSwitcher
8 | {
9 | public class SteamAccountCollection : ObservableCollection
10 | {
11 | private FileSystemWatcher _watcher;
12 | private string _installDirectory;
13 | private string _configDirectory;
14 |
15 | ///
16 | /// Sets the Steam installation directory to be used, and reloads the list of accounts.
17 | ///
18 | public void SetDirectory(string installDirectory)
19 | {
20 | if (string.IsNullOrEmpty(installDirectory) || !Directory.Exists(installDirectory))
21 | throw new ArgumentException("The directory doesn't exist.", nameof(installDirectory));
22 |
23 | _installDirectory = installDirectory;
24 | _configDirectory = Path.Combine(installDirectory, "config");
25 |
26 | // Reinitialize filesystem watcher with the new directory.
27 | _watcher?.Dispose();
28 | _watcher = new(_configDirectory, "loginusers.vdf")
29 | {
30 | EnableRaisingEvents = true
31 | };
32 | _watcher.Changed += OnFileChanged;
33 |
34 | Reload();
35 | }
36 |
37 | ///
38 | /// Reloads the list of accounts by reading from the Steam directory.
39 | ///
40 | public void Reload()
41 | {
42 | if (string.IsNullOrEmpty(_installDirectory) || !Directory.Exists(_installDirectory))
43 | throw new InvalidOperationException("Can't reload; Steam directory doesn't exist!");
44 |
45 | Clear();
46 | foreach (var account in GetAccounts(_configDirectory))
47 | Add(account);
48 | }
49 |
50 | private void OnFileChanged(object sender, FileSystemEventArgs e)
51 | {
52 | System.Windows.Application.Current.Dispatcher.Invoke(Reload);
53 | }
54 |
55 | private string GetLoginUsersVdfContent(string configDirectory)
56 | {
57 | var loginUsersVdfPath = Path.Combine(configDirectory, "loginusers.vdf");
58 |
59 | var triesLeft = 10;
60 | while (true)
61 | {
62 | try
63 | {
64 | return File.ReadAllText(loginUsersVdfPath);
65 | }
66 | catch (IOException)
67 | {
68 | // Keep trying to read file if it's locked by another process.
69 | triesLeft--;
70 |
71 | if (triesLeft == 0)
72 | {
73 | // Give up.
74 | throw;
75 | }
76 |
77 | // Blocking the thread is not ideal, but it's a rare situation anyway.
78 | System.Threading.Thread.Sleep(200);
79 | }
80 | }
81 | }
82 |
83 | private IEnumerable GetAccounts(string configDirectory)
84 | {
85 | dynamic loginUsers = VdfConvert.Deserialize(GetLoginUsersVdfContent(configDirectory));
86 |
87 | foreach (var loginUser in loginUsers.Value)
88 | {
89 | yield return new()
90 | {
91 | ID = loginUser.Key,
92 | Name = loginUser.Value.AccountName.Value,
93 | Alias = loginUser.Value.PersonaName?.Value,
94 | };
95 | }
96 | }
97 | }
98 | }
--------------------------------------------------------------------------------
/Product.wxs:
--------------------------------------------------------------------------------
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 |
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 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 | using System.Threading;
3 | using System.Windows;
4 | using System.Windows.Threading;
5 | using Microsoft.Win32;
6 | using SteamAccountSwitcher.Properties;
7 |
8 | namespace SteamAccountSwitcher
9 | {
10 | ///
11 | /// Interaction logic for App.xaml
12 | ///
13 | public partial class App : Application
14 | {
15 | public App()
16 | {
17 | Dispatcher.UnhandledException += OnDispatcherUnhandledException;
18 | }
19 |
20 | public static Mutex AppMutex { get; private set; }
21 | public static MyTaskbarIcon TrayIcon { get; private set; }
22 |
23 | protected override void OnStartup(StartupEventArgs e)
24 | {
25 | base.OnStartup(e);
26 |
27 | AppMutex = new Mutex(true, "22E1FAEA-639E-400B-9DCB-F2D04EC126E1", out var isNewInstance);
28 |
29 | // Exit if another instance is already running.
30 | if (!isNewInstance)
31 | {
32 | Shutdown(1);
33 | return;
34 | }
35 |
36 | // Upgrade settings from an earlier version.
37 | if (Settings.Default.MustUpgrade)
38 | {
39 | Settings.Default.Upgrade();
40 | Settings.Default.MustUpgrade = false;
41 | Settings.Default.Save();
42 | }
43 |
44 | // Load tray icon.
45 | TrayIcon = (MyTaskbarIcon)FindResource("TrayIcon");
46 | TrayIcon.ShowRunningInTrayNotification();
47 |
48 | // Pre-render menu.
49 | TrayIcon.ContextMenu.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
50 | TrayIcon.ContextMenu.Arrange(new Rect(new Point(0, 0), TrayIcon.ContextMenu.DesiredSize));
51 |
52 | LoadAccounts();
53 |
54 | Settings.Default.PropertyChanged += Settings_PropertyChanged;
55 | }
56 |
57 | protected override void OnExit(ExitEventArgs e)
58 | {
59 | base.OnExit(e);
60 |
61 | AppMutex?.Dispose();
62 | TrayIcon?.Dispose();
63 | }
64 |
65 | private void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
66 | {
67 | TrayIcon.ShowNotification("An unhandled error occurred", e.Exception.Message);
68 | }
69 |
70 | private void Settings_PropertyChanged(object sender, PropertyChangedEventArgs e)
71 | {
72 | switch (e.PropertyName)
73 | {
74 | case nameof(Settings.Default.RunOnStartup):
75 | SetRunOnStartup(Settings.Default.RunOnStartup);
76 | break;
77 |
78 | case nameof(Settings.Default.SteamInstallDirectory):
79 | case nameof(Settings.Default.ShowAvatars):
80 | LoadAccounts();
81 | break;
82 | }
83 | }
84 |
85 | private void LoadAccounts()
86 | {
87 | var steamDirectory = SteamClient.FindInstallDirectory();
88 |
89 | if (steamDirectory != null)
90 | SteamClient.Accounts.SetDirectory(steamDirectory);
91 | }
92 |
93 | private void SetRunOnStartup(bool runOnStartup)
94 | {
95 | using var key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run", true);
96 |
97 | if (runOnStartup)
98 | {
99 | key?.SetValue(SteamAccountSwitcher.Properties.Resources.AppPathName, ResourceAssembly.Location);
100 | }
101 | else
102 | {
103 | key?.DeleteValue(SteamAccountSwitcher.Properties.Resources.AppPathName, false);
104 | }
105 | }
106 | }
107 | }
--------------------------------------------------------------------------------
/SteamAccountSwitcher/Options.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 |
34 |
37 |
38 |
42 |
43 |
46 |
47 |
51 |
52 |
55 |
56 |
61 |
62 |
65 |
66 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | Licenses...
91 |
92 |
93 |
94 |
95 |
96 | View on GitHub
97 |
98 |
99 |
100 |
105 |
106 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher/Resources/Licenses.txt:
--------------------------------------------------------------------------------
1 | SteamAccountSwitcher - Copyright (c) 2015 Daniel Chalmers
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
5 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6 |
7 | Costura.Fody - Copyright (c) 2012 Simon Cropp and contributors
8 |
9 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12 |
13 | H.NotifyIcon - Copyright (c) 2020 havendv
14 |
15 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
16 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 |
19 | Vdf.NET - Copyright (c) 2016 Shravan Rajinikanth
20 |
21 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
22 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE..
--------------------------------------------------------------------------------
/SteamAccountSwitcher/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 SteamAccountSwitcher.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.5.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 |
26 | [global::System.Configuration.UserScopedSettingAttribute()]
27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
28 | [global::System.Configuration.DefaultSettingValueAttribute("")]
29 | public string SteamInstallDirectory {
30 | get {
31 | return ((string)(this["SteamInstallDirectory"]));
32 | }
33 | set {
34 | this["SteamInstallDirectory"] = value;
35 | }
36 | }
37 |
38 | [global::System.Configuration.UserScopedSettingAttribute()]
39 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
40 | [global::System.Configuration.DefaultSettingValueAttribute("True")]
41 | public bool MustUpgrade {
42 | get {
43 | return ((bool)(this["MustUpgrade"]));
44 | }
45 | set {
46 | this["MustUpgrade"] = value;
47 | }
48 | }
49 |
50 | [global::System.Configuration.UserScopedSettingAttribute()]
51 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
52 | [global::System.Configuration.DefaultSettingValueAttribute("False")]
53 | public bool RunOnStartup {
54 | get {
55 | return ((bool)(this["RunOnStartup"]));
56 | }
57 | set {
58 | this["RunOnStartup"] = value;
59 | }
60 | }
61 |
62 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
63 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
64 | [global::System.Configuration.DefaultSettingValueAttribute("30000")]
65 | public int SteamLogoutTimeoutMax {
66 | get {
67 | return ((int)(this["SteamLogoutTimeoutMax"]));
68 | }
69 | }
70 |
71 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
72 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
73 | [global::System.Configuration.DefaultSettingValueAttribute("100")]
74 | public int SteamLogoutTimeoutInterval {
75 | get {
76 | return ((int)(this["SteamLogoutTimeoutInterval"]));
77 | }
78 | }
79 |
80 | [global::System.Configuration.UserScopedSettingAttribute()]
81 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
82 | [global::System.Configuration.DefaultSettingValueAttribute("")]
83 | public string SteamArguments {
84 | get {
85 | return ((string)(this["SteamArguments"]));
86 | }
87 | set {
88 | this["SteamArguments"] = value;
89 | }
90 | }
91 |
92 | [global::System.Configuration.UserScopedSettingAttribute()]
93 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
94 | [global::System.Configuration.DefaultSettingValueAttribute("True")]
95 | public bool ShowAvatars {
96 | get {
97 | return ((bool)(this["ShowAvatars"]));
98 | }
99 | set {
100 | this["ShowAvatars"] = value;
101 | }
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher/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 SteamAccountSwitcher.Properties {
12 | using System;
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", "17.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | public class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | public static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SteamAccountSwitcher.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | public static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized string similar to SteamAccountSwitcher.
65 | ///
66 | public static string AppPathName {
67 | get {
68 | return ResourceManager.GetString("AppPathName", resourceCulture);
69 | }
70 | }
71 |
72 | ///
73 | /// Looks up a localized string similar to https://github.com/danielchalmers/SteamAccountSwitcher.
74 | ///
75 | public static string GitHub {
76 | get {
77 | return ResourceManager.GetString("GitHub", resourceCulture);
78 | }
79 | }
80 |
81 | ///
82 | /// Looks up a localized string similar to SteamAccountSwitcher - Copyright (c) 2015 Daniel Chalmers
83 | ///
84 | ///Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
85 | ///The above copyrig [rest of string was truncated]";.
86 | ///
87 | public static string Licenses {
88 | get {
89 | return ResourceManager.GetString("Licenses", resourceCulture);
90 | }
91 | }
92 |
93 | ///
94 | /// Looks up a localized string similar to Steam Login.
95 | ///
96 | public static string SteamNotLoggedInTitle {
97 | get {
98 | return ResourceManager.GetString("SteamNotLoggedInTitle", resourceCulture);
99 | }
100 | }
101 |
102 | ///
103 | /// Looks up a localized string similar to Software\Valve\Steam.
104 | ///
105 | public static string SteamRegistryDirectoryPath {
106 | get {
107 | return ResourceManager.GetString("SteamRegistryDirectoryPath", resourceCulture);
108 | }
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/SteamAccountSwitcher/SteamClient.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 | using H.NotifyIcon.Core;
8 | using Microsoft.Win32;
9 | using SteamAccountSwitcher.Properties;
10 |
11 | namespace SteamAccountSwitcher
12 | {
13 | public static class SteamClient
14 | {
15 | public static SteamAccountCollection Accounts { get; } = new();
16 |
17 | ///
18 | /// Launches Steam with optional arguments and waits for it to start up.
19 | ///
20 | ///
21 | /// Command-line parameters to launch Steam with.
22 | public static async Task Launch(string args = "", CancellationToken cancellationToken = default)
23 | {
24 | var directory = FindInstallDirectory();
25 |
26 | var process = Process.Start(GetSteamExe(directory), args);
27 |
28 | while (!cancellationToken.IsCancellationRequested)
29 | {
30 | process.Refresh();
31 |
32 | if (process.HasExited || !string.IsNullOrEmpty(process.MainWindowTitle))
33 | break;
34 |
35 | await Task.Delay(Settings.Default.SteamLogoutTimeoutInterval, cancellationToken);
36 | }
37 | }
38 |
39 | ///
40 | /// Switches account to the specified user.
41 | ///
42 | /// This will exit Steam then relaunch.
43 | /// The account to switch to.
44 | public static async Task LogIn(SteamAccount account)
45 | {
46 | await Exit();
47 |
48 | if (!TrySetLoginUser(account.Name))
49 | {
50 | App.TrayIcon.ShowNotification(
51 | "Couldn't switch account automatically",
52 | "May not have permission to change the registry",
53 | NotificationIcon.Error);
54 | }
55 |
56 | await Launch(Settings.Default.SteamArguments);
57 | }
58 |
59 | ///
60 | /// Logs out of the current user, if one is logged in.
61 | ///
62 | /// This will exit Steam then relaunch.
63 | public static async Task LogOut()
64 | {
65 | await Exit();
66 |
67 | if (!TryResetLoginUser())
68 | {
69 | App.TrayIcon.ShowNotification(
70 | "Couldn't log out automatically",
71 | "Please log of out Steam and try again",
72 | NotificationIcon.Error);
73 | }
74 |
75 | await Launch(Settings.Default.SteamArguments);
76 | }
77 |
78 | ///
79 | /// Shuts down the Steam client.
80 | ///
81 | /// When cancellation is requested, Steam will be forcefully closed.
82 | public static async Task Exit(CancellationToken cancellationToken)
83 | {
84 | var process = GetProcess();
85 |
86 | if (process == null)
87 | return;
88 |
89 | // The login window doesn't respond to the shutdown argument and needs to be closed through the process.
90 | if (process.MainWindowTitle == Resources.SteamNotLoggedInTitle)
91 | {
92 | // The window title was "Steam Login" before the 2022 UI changed it to "Steam Sign In",
93 | // but the later UI actually does support the shutdown argument so we don't have to check for it.
94 | process.CloseMainWindow();
95 | }
96 | else
97 | {
98 | await Launch("-shutdown", cancellationToken);
99 | }
100 |
101 | // Wait for Steam to gracefully shut down.
102 | while (true)
103 | {
104 | process.Refresh();
105 |
106 | if (process.HasExited)
107 | return;
108 |
109 | if (cancellationToken.IsCancellationRequested)
110 | {
111 | // Grace period has ended so we'll now forcefully exit.
112 | process.Kill();
113 | }
114 |
115 | await Task.Delay(Settings.Default.SteamLogoutTimeoutInterval, cancellationToken);
116 | }
117 | }
118 |
119 | ///
120 | /// Shuts down the Steam client.
121 | ///
122 | /// After a default timeout period, Steam will be forcefully closed.
123 | public static async Task Exit()
124 | {
125 | var cts = new CancellationTokenSource();
126 | cts.CancelAfter(Settings.Default.SteamLogoutTimeoutMax);
127 |
128 | await Exit(cts.Token);
129 | }
130 |
131 | ///
132 | /// Returns the main Steam process.
133 | ///
134 | private static Process GetProcess() =>
135 | Process.GetProcessesByName("steam").FirstOrDefault();
136 |
137 | ///
138 | /// Sets the next user to be automatically logged in.
139 | ///
140 | /// A bool indicating the login user was successfully set.
141 | private static bool TrySetLoginUser(string user)
142 | {
143 | if (user == null)
144 | throw new ArgumentNullException(nameof(user));
145 |
146 | try
147 | {
148 | using var key = Registry.CurrentUser.OpenSubKey(Resources.SteamRegistryDirectoryPath, true);
149 | key?.SetValue("AutoLoginUser", user);
150 | return true;
151 | }
152 | catch
153 | {
154 | return false;
155 | }
156 | }
157 |
158 | ///
159 | /// Clears the value that tells Steam to automatically log in to a specific user.
160 | ///
161 | private static bool TryResetLoginUser() => TrySetLoginUser(string.Empty);
162 |
163 | ///
164 | /// Locates the directory Steam is installed to.
165 | ///
166 | /// The installation directory, or null if it wasn't found.
167 | public static string FindInstallDirectory()
168 | {
169 | // Return the user-specified directory if it's valid.
170 | if (!string.IsNullOrWhiteSpace(Settings.Default.SteamInstallDirectory) && File.Exists(GetSteamExe(Settings.Default.SteamInstallDirectory)))
171 | return Settings.Default.SteamInstallDirectory;
172 |
173 | // Otherwise check the registry.
174 | try
175 | {
176 | using var key = Registry.CurrentUser.OpenSubKey(Resources.SteamRegistryDirectoryPath);
177 | return key?.GetValue("SteamPath").ToString();
178 | }
179 | catch
180 | {
181 | App.TrayIcon.ShowNotification(
182 | "Couldn't find the Steam folder",
183 | "Please manually enter the path in Options",
184 | NotificationIcon.Error);
185 |
186 | return null;
187 | }
188 | }
189 |
190 | ///
191 | /// Returns the main Steam executable from the given installation directory.
192 | ///
193 | private static string GetSteamExe(string installDirectory) => Path.Combine(installDirectory, "steam.exe");
194 | }
195 | }
--------------------------------------------------------------------------------
/SteamAccountSwitcher/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 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | SteamAccountSwitcher
122 |
123 |
124 | https://github.com/danielchalmers/SteamAccountSwitcher
125 |
126 |
127 |
128 | ..\resources\licenses.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8
129 |
130 |
131 | Steam Login
132 |
133 |
134 | Software\Valve\Steam
135 |
136 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Ll]og/
33 | [Ll]ogs/
34 |
35 | # Visual Studio 2015/2017 cache/options directory
36 | .vs/
37 | # Uncomment if you have tasks that create the project's static files in wwwroot
38 | #wwwroot/
39 |
40 | # Visual Studio 2017 auto generated files
41 | Generated\ Files/
42 |
43 | # MSTest test Results
44 | [Tt]est[Rr]esult*/
45 | [Bb]uild[Ll]og.*
46 |
47 | # NUnit
48 | *.VisualState.xml
49 | TestResult.xml
50 | nunit-*.xml
51 |
52 | # Build Results of an ATL Project
53 | [Dd]ebugPS/
54 | [Rr]eleasePS/
55 | dlldata.c
56 |
57 | # Benchmark Results
58 | BenchmarkDotNet.Artifacts/
59 |
60 | # .NET Core
61 | project.lock.json
62 | project.fragment.lock.json
63 | artifacts/
64 |
65 | # ASP.NET Scaffolding
66 | ScaffoldingReadMe.txt
67 |
68 | # StyleCop
69 | StyleCopReport.xml
70 |
71 | # Files built by Visual Studio
72 | *_i.c
73 | *_p.c
74 | *_h.h
75 | *.ilk
76 | *.meta
77 | *.obj
78 | *.iobj
79 | *.pch
80 | *.pdb
81 | *.ipdb
82 | *.pgc
83 | *.pgd
84 | *.rsp
85 | *.sbr
86 | *.tlb
87 | *.tli
88 | *.tlh
89 | *.tmp
90 | *.tmp_proj
91 | *_wpftmp.csproj
92 | *.log
93 | *.vspscc
94 | *.vssscc
95 | .builds
96 | *.pidb
97 | *.svclog
98 | *.scc
99 |
100 | # Chutzpah Test files
101 | _Chutzpah*
102 |
103 | # Visual C++ cache files
104 | ipch/
105 | *.aps
106 | *.ncb
107 | *.opendb
108 | *.opensdf
109 | *.sdf
110 | *.cachefile
111 | *.VC.db
112 | *.VC.VC.opendb
113 |
114 | # Visual Studio profiler
115 | *.psess
116 | *.vsp
117 | *.vspx
118 | *.sap
119 |
120 | # Visual Studio Trace Files
121 | *.e2e
122 |
123 | # TFS 2012 Local Workspace
124 | $tf/
125 |
126 | # Guidance Automation Toolkit
127 | *.gpState
128 |
129 | # ReSharper is a .NET coding add-in
130 | _ReSharper*/
131 | *.[Rr]e[Ss]harper
132 | *.DotSettings.user
133 |
134 | # TeamCity is a build add-in
135 | _TeamCity*
136 |
137 | # DotCover is a Code Coverage Tool
138 | *.dotCover
139 |
140 | # AxoCover is a Code Coverage Tool
141 | .axoCover/*
142 | !.axoCover/settings.json
143 |
144 | # Coverlet is a free, cross platform Code Coverage Tool
145 | coverage*.json
146 | coverage*.xml
147 | coverage*.info
148 |
149 | # Visual Studio code coverage results
150 | *.coverage
151 | *.coveragexml
152 |
153 | # NCrunch
154 | _NCrunch_*
155 | .*crunch*.local.xml
156 | nCrunchTemp_*
157 |
158 | # MightyMoose
159 | *.mm.*
160 | AutoTest.Net/
161 |
162 | # Web workbench (sass)
163 | .sass-cache/
164 |
165 | # Installshield output folder
166 | [Ee]xpress/
167 |
168 | # DocProject is a documentation generator add-in
169 | DocProject/buildhelp/
170 | DocProject/Help/*.HxT
171 | DocProject/Help/*.HxC
172 | DocProject/Help/*.hhc
173 | DocProject/Help/*.hhk
174 | DocProject/Help/*.hhp
175 | DocProject/Help/Html2
176 | DocProject/Help/html
177 |
178 | # Click-Once directory
179 | publish/
180 |
181 | # Publish Web Output
182 | *.[Pp]ublish.xml
183 | *.azurePubxml
184 | # Note: Comment the next line if you want to checkin your web deploy settings,
185 | # but database connection strings (with potential passwords) will be unencrypted
186 | *.pubxml
187 | *.publishproj
188 |
189 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
190 | # checkin your Azure Web App publish settings, but sensitive information contained
191 | # in these scripts will be unencrypted
192 | PublishScripts/
193 |
194 | # NuGet Packages
195 | *.nupkg
196 | # NuGet Symbol Packages
197 | *.snupkg
198 | # The packages folder can be ignored because of Package Restore
199 | **/[Pp]ackages/*
200 | # except build/, which is used as an MSBuild target.
201 | !**/[Pp]ackages/build/
202 | # Uncomment if necessary however generally it will be regenerated when needed
203 | #!**/[Pp]ackages/repositories.config
204 | # NuGet v3's project.json files produces more ignorable files
205 | *.nuget.props
206 | *.nuget.targets
207 |
208 | # Microsoft Azure Build Output
209 | csx/
210 | *.build.csdef
211 |
212 | # Microsoft Azure Emulator
213 | ecf/
214 | rcf/
215 |
216 | # Windows Store app package directories and files
217 | AppPackages/
218 | BundleArtifacts/
219 | Package.StoreAssociation.xml
220 | _pkginfo.txt
221 | *.appx
222 | *.appxbundle
223 | *.appxupload
224 |
225 | # Visual Studio cache files
226 | # files ending in .cache can be ignored
227 | *.[Cc]ache
228 | # but keep track of directories ending in .cache
229 | !?*.[Cc]ache/
230 |
231 | # Others
232 | ClientBin/
233 | ~$*
234 | *~
235 | *.dbmdl
236 | *.dbproj.schemaview
237 | *.jfm
238 | *.pfx
239 | *.publishsettings
240 | orleans.codegen.cs
241 |
242 | # Including strong name files can present a security risk
243 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
244 | #*.snk
245 |
246 | # Since there are multiple workflows, uncomment next line to ignore bower_components
247 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
248 | #bower_components/
249 |
250 | # RIA/Silverlight projects
251 | Generated_Code/
252 |
253 | # Backup & report files from converting an old project file
254 | # to a newer Visual Studio version. Backup files are not needed,
255 | # because we have git ;-)
256 | _UpgradeReport_Files/
257 | Backup*/
258 | UpgradeLog*.XML
259 | UpgradeLog*.htm
260 | ServiceFabricBackup/
261 | *.rptproj.bak
262 |
263 | # SQL Server files
264 | *.mdf
265 | *.ldf
266 | *.ndf
267 |
268 | # Business Intelligence projects
269 | *.rdl.data
270 | *.bim.layout
271 | *.bim_*.settings
272 | *.rptproj.rsuser
273 | *- [Bb]ackup.rdl
274 | *- [Bb]ackup ([0-9]).rdl
275 | *- [Bb]ackup ([0-9][0-9]).rdl
276 |
277 | # Microsoft Fakes
278 | FakesAssemblies/
279 |
280 | # GhostDoc plugin setting file
281 | *.GhostDoc.xml
282 |
283 | # Node.js Tools for Visual Studio
284 | .ntvs_analysis.dat
285 | node_modules/
286 |
287 | # Visual Studio 6 build log
288 | *.plg
289 |
290 | # Visual Studio 6 workspace options file
291 | *.opt
292 |
293 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
294 | *.vbw
295 |
296 | # Visual Studio LightSwitch build output
297 | **/*.HTMLClient/GeneratedArtifacts
298 | **/*.DesktopClient/GeneratedArtifacts
299 | **/*.DesktopClient/ModelManifest.xml
300 | **/*.Server/GeneratedArtifacts
301 | **/*.Server/ModelManifest.xml
302 | _Pvt_Extensions
303 |
304 | # Paket dependency manager
305 | .paket/paket.exe
306 | paket-files/
307 |
308 | # FAKE - F# Make
309 | .fake/
310 |
311 | # CodeRush personal settings
312 | .cr/personal
313 |
314 | # Python Tools for Visual Studio (PTVS)
315 | __pycache__/
316 | *.pyc
317 |
318 | # Cake - Uncomment if you are using it
319 | # tools/**
320 | # !tools/packages.config
321 |
322 | # Tabs Studio
323 | *.tss
324 |
325 | # Telerik's JustMock configuration file
326 | *.jmconfig
327 |
328 | # BizTalk build output
329 | *.btp.cs
330 | *.btm.cs
331 | *.odx.cs
332 | *.xsd.cs
333 |
334 | # OpenCover UI analysis results
335 | OpenCover/
336 |
337 | # Azure Stream Analytics local run output
338 | ASALocalRun/
339 |
340 | # MSBuild Binary and Structured Log
341 | *.binlog
342 |
343 | # NVidia Nsight GPU debugger configuration file
344 | *.nvuser
345 |
346 | # MFractors (Xamarin productivity tool) working folder
347 | .mfractor/
348 |
349 | # Local History for Visual Studio
350 | .localhistory/
351 |
352 | # BeatPulse healthcheck temp database
353 | healthchecksdb
354 |
355 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
356 | MigrationBackup/
357 |
358 | # Ionide (cross platform F# VS Code tools) working folder
359 | .ionide/
360 |
361 | # Fody - auto-generated XML schema
362 | FodyWeavers.xsd
--------------------------------------------------------------------------------