How to detect Steam Library locations(s)?

Grab your favourite IDE and tinker with the innards of game engines

How to detect Steam Library locations(s)?

Postby ChromeAngel on Thu Oct 16, 2014 5:26 pm

I am trying to launch Source SDK utilities from my windows application. Mostly this is working fine, I just look for them in steam/steamapps/common . However they could be installed into a "Steam Library" in another location (probably on another drive).

Does anyone know how I can programiatically detect the locations of Steam Libriaries outside of the main Steam folder?

Once i've found a library I can check for the manifest and see if the SDK i'm looking for is installed there.
User avatar
ChromeAngel
Member
Member
 
Joined: Fri Oct 21, 2011 7:28 am
Location: England

Re: How to detect Steam Library locations(s)?

Postby zombie@computer on Fri Oct 17, 2014 4:41 pm

This is what we used for ducttape, but it may be (extremely) outdated

Code: Select all
        private void GetSteamPaths()
        {
            RegistryKey steamKey = Registry.CurrentUser.OpenSubKey("Software\\Valve\\Steam");
            if (steamKey == null)
            {
                DuctTape.Controls.CustomMessageBox.ShowEx("DuctTape - Fatal Error", "Reinstall Steam", "The registry key HKCU\\Software\\Valve\\Steam does not exist. This location must store the values SteamPath and SteamExe. Is Steam installed? DuctTape will now exit.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Environment.Exit(0);
            }
            else
            {
                steamDir = (steamKey.GetValue("SteamPath") as string).Replace('/', '\\');
                dout("steamDir = " + steamDir, 2);
                steamExePath = (steamKey.GetValue("SteamExe") as string).Replace('/', '\\');
                dout("steamExePath = " + steamExePath, 2);
                steamKey.Close();
            }

            sourceSdkDir = Environment.GetEnvironmentVariable("sourcesdk");
            dout("sourcesdk Environemt Variable = " + sourceSdkDir, 2);
            while (!System.IO.Directory.Exists(sourceSdkDir))
            {
                if (sourceSdkDir == "" || sourceSdkDir == null)
                {
                    System.Windows.Forms.FolderBrowserDialog sdk = new System.Windows.Forms.FolderBrowserDialog();
                    sdk.Description = "The environment variable 'sourcesdk' is not set. Has the SDK ever been run? Please select the path of the SourceSDK. Press cancel to close DuctTape." + Environment.NewLine + "Note: You may need to reboot after the first run of the SDK";
                    if (sdk.ShowDialog() == System.Windows.Forms.DialogResult.Cancel)
                    {
                        Environment.Exit(0);
                    }
                    sourceSdkDir = sdk.SelectedPath;
                    Environment.SetEnvironmentVariable("sourcesdk", sourceSdkDir, EnvironmentVariableTarget.Process);
                    //set for future use = much faster :)
                    try
                    {
                        Environment.SetEnvironmentVariable("sourcesdk", sourceSdkDir, EnvironmentVariableTarget.Machine);
                    }
                    catch (System.Security.SecurityException)
                    {
                        //we can't set it because we don't have admin privi's... but we can at least set it for ourselves
                        //and programs that we start
                    }
                }
                if (!System.IO.Directory.Exists(sourceSdkDir))
                {
                    DuctTape.Controls.CustomMessageBox.ShowEx("DuctTape - SDK not found", "Run or Reinstall Source SDK", "The environment variable 'sourcesdk' is not set to a valid path:" + Environment.NewLine + sourceSdkDir + Environment.NewLine + "Please run or re-install the Source SDK.", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    Environment.Exit(0);
                }
            }

            RegistryKey key = Registry.CurrentUser.OpenSubKey("Software\\Valve\\Hammer\\General");
            if (key != null)
            {
                Object value = key.GetValue("Directory");
                if (value != null)
                {
                    _sourceSDKBinPath = value.ToString();
                    dout("_sourceSDKBinPath = " + _sourceSDKBinPath, 2);
                }
                else
                {
                    dout("Could not get registry value HKCU\\Software\\Valve\\Hammer\\General\\Directory", 1);
                }
                key.Close();
            }

            if (String.IsNullOrEmpty(_sourceSDKBinPath))
            {
                int result = 0; //0 = success, -1 = sdk dir found but not the orangebox or ep1 bin directory, ask user to locate it. -2 = no sourcesdk folder, above code failed?
                RegistryKey userNameKey = Registry.CurrentUser.OpenSubKey("Software\\Valve\\Steam");
                Object value = null;
                if (userNameKey != null) value = userNameKey.GetValue("LastGameNameUsed");
                if (value != null)
                {
                    userName = value.ToString();
                    String tryPath = steamDir + "\\steamapps\\" + userName + "\\sourcesdk\\bin\\orangebox\\bin";
                    if (System.IO.File.Exists(tryPath + "\\filesystem_steam.dll"))
                    {
                        _sourceSDKBinPath = tryPath;
                    }
                    else
                    {
                        tryPath = steamDir + "\\steamapps\\" + userName + "\\sourcesdk\\bin\\ep1\\bin";
                        if (System.IO.File.Exists(tryPath + "\\filesystem_steam.dll"))
                        {
                            _sourceSDKBinPath = tryPath;
                        }
                        else
                        {
                            tryPath = steamDir + "\\steamapps\\" + userName + "\\sourcesdk";
                            if (System.IO.Directory.Exists(tryPath))
                            {
                                result = -1;
                            }
                        }
                    }
                }
                else
                {
                    //There is no LastGameNameUsed key so we gotta try all the folders.
                    foreach (String dir in System.IO.Directory.GetDirectories(steamDir + "\\steamapps\\"))
                    {
                        String tryPath = dir + "\\sourcesdk\\bin\\orangebox\\bin";
                        if (System.IO.File.Exists(tryPath + "\\filesystem_steam.dll"))
                        {
                            _sourceSDKBinPath = tryPath;
                            break;
                        }
                        else
                        {
                            tryPath = dir + "\\sourcesdk\\bin\\ep1\\bin";
                            if (System.IO.File.Exists(tryPath + "\\filesystem_steam.dll"))
                            {
                                _sourceSDKBinPath = tryPath;
                                break;
                            }
                        }
                    }
                    if (_sourceSDKBinPath == null) result = -1;
                }
                if (result == -1)
                {
                    DuctTape.Controls.CustomMessageBox.ShowEx("DuctTape - SDK not found", "The Source SDK was not found.", "The folder:" + Environment.NewLine + sourceSdkDir + Environment.NewLine + "was found but the ep1 or orangebox bin folders were not, please locate them. NOTE: Running the SDK and restarting DuctTape may correct this problem.", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    FolderBrowserDialog dialog = new FolderBrowserDialog();
                    dialog.Description = "Please locate the ep1 or orangebox source SDK bin folder.";
                    dialog.SelectedPath = sourceSdkDir;
                    if (dialog.ShowDialog() == DialogResult.OK)
                    {
                        Environment.SetEnvironmentVariable("sourcesdk", dialog.SelectedPath);
                        GetSteamPaths();
                    }
                    else
                    {
                        Environment.SetEnvironmentVariable("sourcesdk", null);
                        DuctTape.Controls.CustomMessageBox.ShowEx("DuctTape - Closing", "DuctTape will now exit.", "DuctTape cannot proceed without the paths to the sourcesdk directory.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        Environment.Exit(0);
                    }
                }
            }
            if (userName == null)
            {
                //just do a little hack to get userName from _sourceSDKBinPath
                userName = System.IO.Path.GetFileNameWithoutExtension(Utility.StandardizePath(_sourceSDKBinPath + "\\..\\..\\..\\..\\", false, true) + ".ext");
            }

            key = Registry.CurrentUser.OpenSubKey("Software\\Valve\\Steam");
            if (key != null)
            {
                Object value = key.GetValue("SourceModInstallPath");
                if (value != null)
                {
                    _sourceModInstallPath = value.ToString();
                    dout("_sourceModInstallPath = " + _sourceModInstallPath, 2);
                }
                else
                {
                    dout("Could not get registry value HKCU\\Software\\Valve\\Steam\\SourceModInstallPath", 1);
                }
            }
            if (String.IsNullOrEmpty(_sourceModInstallPath))
            {
                //todo: ask the user where the mod install path is since auto detection didn't work
                //of course it seems that we have made no use of this variable, anyway
            }
        }
When you are up to your neck in shit, keep your head up high
zombie@computer
Forum Goer Elite™
Forum Goer Elite™
 
Joined: Fri Dec 31, 2004 5:58 pm
Location: Lent, Netherlands

Re: How to detect Steam Library locations(s)?

Postby ChromeAngel on Fri Oct 17, 2014 7:08 pm

Thanks for sharing Z@C , but I think I have found a more general purpose soloution.

/steam/config/config.vdf is a KeyValues file that contains a key BaseInstallFolder_n for each additional steam library whose value is the full path to the library.

I missed this first time around, when I was searching my Steam folder for references to my test library, because the backslashes in the path were escaped with an extra backslash (eg "D:\\TestLibrary" ).

I've now written myself a function that returns a dictionary of app paths keyed by app id, which I can use to find any version of the Source SDK or any other installed Steam app.

I wonder what other useful things I could do with a complete list of installed apps...
User avatar
ChromeAngel
Member
Member
 
Joined: Fri Oct 21, 2011 7:28 am
Location: England

Re: How to detect Steam Library locations(s)?

Postby SM Sith Lord on Sun Oct 19, 2014 4:27 pm

ChromeAngel wrote:Thanks for sharing Z@C , but I think I have found a more general purpose soloution.

/steam/config/config.vdf is a KeyValues file that contains a key BaseInstallFolder_n for each additional steam library whose value is the full path to the library.

I missed this first time around, when I was searching my Steam folder for references to my test library, because the backslashes in the path were escaped with an extra backslash (eg "D:\\TestLibrary" ).

I've now written myself a function that returns a dictionary of app paths keyed by app id, which I can use to find any version of the Source SDK or any other installed Steam app.

I wonder what other useful things I could do with a complete list of installed apps...


I have been trying to locally get a list of all installed and/or owned apps for a long time. My solution involves grabbing it from your public Steam Community Profile, which works great except things like source mods and other weird apps don't get listed on your profile.

One thing I couldn't figure out from scanning the SteamApps/common folder was the appID's and official game titles that went along with each folder. I didn't want to attempt to manually maintain a dictionary of the folder names associated with each AppID/game title, so I was looking only at what was available from Steam and its folder structure. Were you able to figure out a way to determine these based on scanning the steamapps folder?

On a different issue I'm working on, I have been trying to detect additional Steam Library folder locations for a while and your post is very, very helpful! Thanks. After I'm able to properly detect Steam Library folders, I can fix my game mounting because the method I use now only lets you mount games that are installed into the same Steam Library folder as my mod due to how the |all_source_engine_paths| keyword works.

I opened up my /steam/config/config.vdf and did find my additional Steam Library folder listed in there as BaseInstallFolder_1; however, it concerned me that the primary Steam folder was not listed there.

How can I detect the primary Steam install folder?

Again, thanks for sharing your solution, it's a lot of help.
SM Sith Lord
Been Here A While
Been Here A While
 
Joined: Sat Nov 25, 2006 4:25 pm
Location: Los Angles, CA

Re: How to detect Steam Library locations(s)?

Postby ChromeAngel on Sat Oct 22, 2016 3:07 pm

Wow! has it been 2+ years since we had this conversation?

By now you're probably beyond caring or worked it out for yourself but...

I'm using the registry key to locate the main Steam folder (dunno how this would work with SteamOS) then assuming the default library to be the SteamApps folder inside Steam.

Matching up folders to App IDs was done by parsing the application manifests ( appmenifest_nnnn.acf ) files in the library’s roof folder (eg SteamApps). The nnnn in the file name is the app ID. Again these files are in keyvalues format and contain keys for both the appid, name and installdir .
User avatar
ChromeAngel
Member
Member
 
Joined: Fri Oct 21, 2011 7:28 am
Location: England

Return to Programming

Who is online

Users browsing this forum: No registered users