1

I am trying to put together an excel sheet that lists all the games that I have added shortcuts to Steam. Steam lets you add shortcuts to non-steam games and acts as a launcher for them. The shortcut links that the user adds are in a local database called shortcuts.vdf, which contains all the information relevant to the games Steam has. All I'm basically interested in is the names of the games.

Here is a snippet of what the data in the file looks like in notepad:

shortcuts  0 appid °rõÄappname Cemu Exe "T:\Cemu\App+Update+DLC\Cemu.exe" StartDir "T:\Cemu\App+Update+DLC\" icon  ShortcutPath  LaunchOptions  IsHidden     AllowDesktopConfig    AllowOverlay    openvr     Devkit     DevkitGameID  LastPlayTime ZùÏ_ tags 0 favorite 1 All Games  1 appid }yâappname Citra Nightly Exe "C:\Users\phili\AppData\Local\Citra\nightly-mingw\citra-qt.exe" StartDir "C:\Users\phili\AppData\Local\Citra\nightly-mingw\" icon  ShortcutPath  LaunchOptions  IsHidden     AllowDesktopConfig    AllowOverlay    openvr     Devkit     DevkitGameID  LastPlayTime ¿
ã_ tags 0 favorite 1 All Games  2 appid {Sü¸appname RollerCoaster Tycoon 2: Triple Thrill Pack Open Exe "C:\Program Files\OpenRCT2\openrct2.exe" StartDir "C:\Program Files\OpenRCT2\" icon  ShortcutPath  LaunchOptions  IsHidden     AllowDesktopConfig    AllowOverlay    openvr     Devkit     DevkitGameID  LastPlayTime !Ý_ tags 0 steam 1 All Games  3 appid Iì»Âappname Art Of Fighting 2 Exe "R:\Amazon Games\Library\Art of Fighting 2\ArtOfFighting2.exe" StartDir "R:\Amazon Games\Library\Art of Fighting 2\" icon  ShortcutPath  LaunchOptions  IsHidden     AllowDesktopConfig    AllowOverlay    openvr     Devkit     DevkitGameID  LastPlayTime      tags 0 Shortcuts 1 Amazon 2 All Games  4 appid ñappname Origin Exe "C:\Program Files (x86)\Origin\Origin.exe" StartDir "C:\Program Files (x86)\Origin\" icon  ShortcutPath  LaunchOptions  IsHidden     AllowDesktopConfig    AllowOverlay    openvr     Devkit     DevkitGameID  LastPlayTime ÛÊ*] tags 0 steam 1 All Games  5 appid £á@¤appname A Good Snowman Is Hard To Build Exe "R:\Amazon Games\Library\A Good Snowman Is Hard To Build\Snowman.exe" StartDir "R:\Amazon Games\Library\A Good Snowman Is Hard To Build\" icon  ShortcutPath  LaunchOptions  IsHidden     AllowDesktopConfig    AllowOverlay    openvr     Devkit     DevkitGameID  LastPlayTime      tags 0 Shortcuts 1 Amazon 2 All Games  6 appid ¢‡    æappname Adam Wolfe Exe "R:\Amazon Games\Library\Adam Wolfe\AdamWolfe.exe" StartDir "R:\Amazon

I noticed that the names of games that I added to Steam are always between the words appname and Exe, like this:

£á@¤appname A Good Snowman Is Hard To Build Exe

How can I modify/extract entries from that file so that I have an excel sheet that contains the entry between appname and Exe in one cell per row?

Like so:

List of entries in excel sheet

I was thinking about regular expressions maybe? I don't have Microsoft Office, only Libre Office

Original shortcuts.vdf file upload + txt converted version.

3
  • As you have mentioned - I don't have Microsoft Office, only Libre Office , I assume you are on linux platform and so then you can try using grep, sed and awk to get the info. Try to get your hands dirty on it and you can definitely do it. – C0deDaedalus Jan 10 at 2:04
  • Could you please provide with the absolute path of the shortcuts.vdf file? – C0deDaedalus Jan 11 at 3:57
  • the absolute path of the file is: "C:\Program Files (x86)\Steam\userdata\149576161\config\shortcuts.vdf" – Phil Jan 11 at 18:39
0

This should be simple to achieve, all you need is PowerShell, no Office Suite is needed.

From the syntax of the paths, they start with a drive letter (i.e. T:) and use backslashes (\) to separate the directories, I assume you are on Windows.

You are on Windows, use this to open PowerShell:

Win+R→type PowerShellCtrl+Shift+Enter

Then once you are in PowerShell, you can use this regex to get the game names: (appname)(.*?)(Exe)

Steam .vdf format is a proprietary format, so it can be hard to properly parse the format, though you can probably use this:GitHub:Steam-GetOnTop, I don't use Steam, and I haven't used the package, so I don't guarantee it will work.

But since the file is encoded in plaintext, you can open it with notepad.exe, and all you need is the content between appname and Exe, you can use the brute force way:

$shortcuts=((Get-Content "C:\Program Files (x86)\Steam\userdata\149576161\config\shortcuts.vdf").ToCharArray() | where{![char]::IsControl("$_")}) -join ""
($shortcuts | Select-String -pattern "(appname)(.*?)(Exe)" -AllMatches).matches.value | %{$_.Substring(7,$_.Length-10)} | sort-object | out-file "$([environment]::getfolderpath('desktop'))\gamename.txt"

Explanation:

Step 1: We get the content of the shortcuts.vdf, convert the string to character array, filter out Control Characters, and join into a string

Step 2: We print the content we get in the first step and pass it down the pipeline; We get the content from pipeline and select all strings that matches (appname)(.*?)(Exe), and use ().matches.value to get only the matches, then we get rid of appname and Exe and export it to a file named gamename.txt located on your desktop.

If you insist to export to a Excel sheet with only one column, though, use this:

$shortcuts=((Get-Content "C:\Program Files (x86)\Steam\userdata\149576161\config\shortcuts.vdf").ToCharArray() | where{![char]::IsControl("$_")}) -join ""
($shortcuts | Select-String -pattern "(appname)(.*?)(Exe)" -AllMatches).matches.value | %{$_.Substring(7,$_.Length-10)} | sort-object | %{[PSCustomObject]@{GameName=$_}} | export-csv "$([environment]::getfolderpath('desktop'))\gamename.csv"

The method is almost the same with the first method, but we convert the results to [PSCustomObject] and export the final result to a .csv file located at path "C:\Users\USERNAME\Desktop\gamename.csv" instead of a.txt file.


Further notes:

Microsoft Docs:What is PowerShell?

Microsoft Docs:About Variables

Microsoft Docs:About Foreach

Microsoft Docs:Everything you wanted to know about PSCustomObject

Microsoft Docs:Everything you wanted to know about arrays

Microsoft Docs:About Arrays

Microsoft Docs:Get-Content

Microsoft Docs:Select-String

Microsoft Docs:Out-File

Microsoft Docs:Export-Csv


OutPut

As you said it does not contain any personal information and attached the file to the question, I will post the result I get below:

Google Drive

Output of my first method:

gamename.txt

enter image description here

Output of my second method:

gamename.csv

enter image description here

Output of the vbs method from the other answer:

steam.txt

enter image description here


Code efficiency analysis

The first method is 358 characters long

The second method is 396 characters long

The vbs script is 541 characters long

The first method golfed:

$s=((gc "C:\Program Files (x86)\Steam\userdata\149576161\config\shortcuts.vdf").ToCharArray() | ?{![char]::IsControl("$_")}) -join ""
($s | sls "(appname)(.*?)(Exe)" -all).matches.value | %{$_.Substring(7,$_.Length-10)} | sort >"$([environment]::getfolderpath('desktop'))\gamename.txt"

286 characters long

The second method golfed:

$s=((gc "C:\Program Files (x86)\Steam\userdata\149576161\config\shortcuts.vdf").ToCharArray() | ?{![char]::IsControl("$_")}) -join ""
($s | sls "(appname)(.*?)(Exe)" -all).matches.value | %{$_.Substring(7,$_.Length-10)} | sort | %{[PSCustomObject]@{GameName=$_}} | epcsv "$([environment]::getfolderpath('desktop'))\gamename.csv"

329 characters long

The vbs doesn't sort the results, nor does it automatically output to a file.

Below are the runtime tests:

PS C:\Users\Estranger> measure-command {$s=((gc "C:\Users\Estranger\Downloads\shortcuts.vdf").ToCharArray() | ?{![char]::IsControl("$_")}) -join ""
>> ($s | sls "(appname)(.*?)(Exe)" -all).matches.value | %{$_.Substring(7,$_.Length-10)} | sort >"$([environment]::getfolderpath('desktop'))\gamename.txt"}

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 1
Milliseconds      : 86
Ticks             : 10863660
TotalDays         : 1.25736805555556E-05
TotalHours        : 0.000301768333333333
TotalMinutes      : 0.0181061
TotalSeconds      : 1.086366
TotalMilliseconds : 1086.366

PS C:\Users\Estranger> measure-command {$s=((gc "C:\Users\Estranger\Downloads\shortcuts.vdf").ToCharArray() | ?{![char]::IsControl("$_")}) -join ""
>> ($s | sls "(appname)(.*?)(Exe)" -all).matches.value | %{$_.Substring(7,$_.Length-10)} | sort | %{[PSCustomObject]@{GameName=$_}} | epcsv "$([environment]::getfolderpath('desktop'))\gamename.csv"}

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 1
Milliseconds      : 171
Ticks             : 11716488
TotalDays         : 1.356075E-05
TotalHours        : 0.000325458
TotalMinutes      : 0.01952748
TotalSeconds      : 1.1716488
TotalMilliseconds : 1171.6488

PS C:\Users\Estranger> measure-command {cscript steam.vbs}

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 1
Milliseconds      : 338
Ticks             : 13380483
TotalDays         : 1.54866701388889E-05
TotalHours        : 0.000371680083333333
TotalMinutes      : 0.022300805
TotalSeconds      : 1.3380483
TotalMilliseconds : 1338.0483

My first method obviously won, the downvote is unfair, the OP didn't post the critical information, so my code couldn't have solved the OP's problem at first no matter how good I am.


To whoever downvoted my answer, my answer is now edited and your downvote is no longer locked, please cast votes carefully based on objective facts, and please lift the downvote.

To the OP, the other answer is, objectively, not as efficient as my answer. You didn't post the right information at first, so I only have incorrect information to work with. No matter how good I am, it is impossible for me to solve your problem because "Garbage In, Garbage Out", the other answerer just got lucky and happened to be online when you posted the right information while I was away, and you see the script is not as good as mine, please consider accept my answer instead.


Even shorter code:

Method 1 Golfed

$s=((gc "C:\Program Files (x86)\Steam\userdata\149576161\config\shortcuts.vdf").ToCharArray() | ?{![char]::IsControl("$_")}) -join ""
($s | sls "(?<=appname)(.*?)(?=Exe)" -All).matches.value | sort > "$([environment]::getfolderpath('desktop'))\gamename.txt"

Method 2 Golfed

$s=((gc "C:\Program Files (x86)\Steam\userdata\149576161\config\shortcuts.vdf").ToCharArray() | ?{![char]::IsControl("$_")}) -join ""
($s | sls "(?<=appname)(.*?)(?=Exe)" -All).matches.value | sort | %{[PSCustomObject]@{GameName=$_}} | epcsv "$([environment]::getfolderpath('desktop'))\gamename.csv"

The regex used by these new methods will matches only the game names, but using it increases runtime by 0.3s compared to the first regex.

This is what I see in console using the second method 1 golfed: enter image description here

I want to answer this question and help the OP simply because I find the question interesting, the thing OP wanted is fun, I am just a beginner in Programming, and I want to improve my skills by answering questions others have posted with programs, that's all...

P.S. I really want to be a hacker...

10
  • 1
    I tried both methods. Unfortunately, the first one yields an error: At line:3 char:84 + ... name) {(7..($game.length-4)|%{[char[]]$game[$_]}) -join ""} | out-fil ... + ~ An empty pipe element is not allowed. + CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException + FullyQualifiedErrorId : EmptyPipeElement the second one does nothing, nothing happens – Phil Jan 10 at 11:08
  • 1
    I tested the regex in a google sheet and (?<=\appname )(.*?)(?=\ Exe) did highlight only the names of the games, whereas appname[\s\S]+Exe highlighted everything – Phil Jan 10 at 11:20
  • 1
    there must be something wrong with the file because all I get is an empty output file or none at all. both of your methods plus the visual basic script method don't work. I even saved the vdf file as .txt - same thing: empty output. I have updated the original question and attached the vdf file to it, it does not contain any personal information. I must be doing something wrong – Phil Jan 11 at 18:34
  • @Phil, your collection of games is missing a lot Assassin's Creed games and Anno games... Also, you said the file does not contain personal information, but from the names of games you have played alone, perverts can analyze what type of person you are, and use it for malicious purposes, fortunately I am not such pervert, I see a challenge to overcome, once it's done the job is done. You are not interesting to me, but there are many people who will find you interesting, next time be smarter:) – Xeнεi Ξэnвϵς Jan 12 at 5:13
  • I did not downvote you as I would never downvote anyone who helps me. I tried all three methods and would have preferred the powershell/excel one but it just didn't work I copied the code you posted and even tried after installing the PS version you linked. That's why I uploaded the original file to see if the snippet might miss any information. Also this list is about 80% games that Epic and Amazon have given away for free which is a public list anyway :) – Phil Jan 12 at 9:04
4

Here is a very hacky bit of vbscript which essentially breaks down the shortcuts.vdf file into seperate lines (based on the nul character) and then spits out the next line after the one called AppName. I did try to just split file using Chr(0) as the delimiter but it threw an error .

Save the following file as steam.vbs:

Dim oFile: Set oFile = CreateObject("Scripting.FileSystemObject").GetFile("shortcuts.vdf")
Dim file : file = oFile.OpenAsTextStream().Read(oFile.Size)

Dim content, i, c

For i = 1 To Len(file)
    c = Asc(Mid(file, i, 1))
    If c = 0 Then 
        content = content & VbCrLf
    ElseIf c > 3 Then
        content = content & Chr(c)
    end If
Next

Dim items : items = Split(content, VbCrLf)

For i = 0 To Ubound(items)
    If Instr(LCase(items(i)), "appname") > 0 Then Wscript.Echo items(i+1)
Next

Set oFile = Nothing

Copy the shortcuts.vcf file into the same folder as this code and then from a command line type:

cscript steam.vbs > output.txt

Open the output in any text editor and you'll see a list of all the game shortcuts you have added.

7
  • there must be something wrong with the file because all I get is an empty output file or none at all. both of your methods plus the visual basic script method don't work. I even saved the vdf file as .txt - same thing: empty output. I have updated the original question and attached the vdf file to it, it does not contain any personal information. I must be doing something wrong – Phil Jan 11 at 18:34
  • @Phil Looks like your shortcuts.vdf file has additional characters before the AppName and it is was in lowercase. I've modified the If statement and can now get a list of 353 items. You've got some good games :) – Richard Jan 11 at 18:48
  • Thank you! It worked. Now since I don't understand very much about visual basic I don't really understand the code I just copy pasted it, which one shouldn't do I guess but I will try to comprehend what it does exactly. I also double clicked on the script as I thought that might work too but it only shows me a windows titled Windws Script Host listing every title with an OK option to click. I terminated the process using the Task Manager. – Phil Jan 11 at 19:01
  • Cool, glad to hear it and please don’t forget to tick that it’s been answered. If you’d like, I can modify the code so that when you double-click on the file it creates a shortcuts.txt file containing the list of games. – Richard Jan 11 at 19:07
  • Thanks! I will do that - you know what I'm gonna research how to do that myself as a bit of learning :) – Phil Jan 11 at 19:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.