Game explorer
Author: codev (talk, contrib) |
Description
Microsoft Windows Vista ships with a feature called Game Explorer that allows a developer to list games in a central explorer location. This page contains code that allows a NSIS installer to add and remove a game from the Game Explorer.
Before using this code, a game with an implemented GDF must already be prepared. GDF stands for Game Definition File and is actually a XML embedded as a resource in the game executable. The resource type should be named DATA and the resource itself should be named __GDF_XML. For more information, see MSDN.
Code
# user interface !define GameExplorer_GenerateGUID '!insertmacro GameExplorer_GenerateGUID' !define GameExplorer_AddGame '!insertmacro GameExplorer_AddGame' !define GameExplorer_UpdateGame '!insertmacro GameExplorer_UpdateGame' !define GameExplorer_RemoveGame '!insertmacro GameExplorer_RemoveGame' # internal stuff !define CLSCTX_INPROC_SERVER 1 !define IID_IGameExplorer {E7B2FB72-D728-49B3-A5F2-18EBF5F1349E} !define CLSID_GameExplorer {9A5EA990-3034-4D6F-9128-01F3C61022BC} !define GIS_CURRENT_USER 2 !define GIS_ALL_USERS 3 !define IGameExplorer_QueryInterface 0 !define IGameExplorer_AddRef 1 !define IGameExplorer_Release 2 !define IGameExplorer_AddGame 3 !define IGameExplorer_RemoveGame 4 !define IGameExplorer_UpdateGame 5 !define IGameExplorer_VerifyAccess 6 # includes !include LogicLib.nsh # the actual code !macro GameExplorer_GenerateGUID System::Call 'ole32::CoCreateGuid(g .s)' !macroend !macro GameExplorer_AddGame CONTEXT GDF INSTDIR EXE GUID !define __GAME_EXPLORER_UNIQUE "${__LINE__}${__FILE__}" Push $0 Push $1 Push $R0 Push $R1 Push $R2 Push $R3 Push "${EXE}" Push "${GUID}" Push "${INSTDIR}" Push "${GDF}" Pop $R0 # == ${GDF} Pop $R1 # == ${INSTDIR} Pop $R2 # == ${GUID} Pop $R3 # == ${EXE} ClearErrors System::Call "ole32::CoCreateInstance( \ g '${CLSID_GameExplorer}', i 0, \ i ${CLSCTX_INPROC_SERVER}, \ g '${IID_IGameExplorer}', *i .r1) i .r0" ${If} $0 != 0 # S_OK SetErrors Goto "done_${__GAME_EXPLORER_UNIQUE}" ${EndIf} !if ${CONTEXT} == all System::Call "$1->${IGameExplorer_AddGame}(w R0, w R1, i ${GIS_ALL_USERS}, g R2) i .r0" !else if ${CONTEXT} == user System::Call "$1->${IGameExplorer_AddGame}(w R0, w R1, i ${GIS_CURRENT_USER}, g R2) i .r0" !else !error "Invalid CONTEXT passed to GameExplorer_AddGame! Must be `user` or `all`." !endif ${If} $0 != 0 # S_OK SetErrors ${Else} # Create play task !if ${CONTEXT} == all SetShellVarContext all CreateDirectory $APPDATA\Microsoft\Windows\GameExplorer\$R2\PlayTasks\0 CreateShortcut $APPDATA\Microsoft\Windows\GameExplorer\$R2\PlayTasks\0\Play.lnk $R3 !else if ${CONTEXT} == user SetShellVarContext current CreateDirectory $LocalAPPDATA\Microsoft\Windows\GameExplorer\$R2\PlayTasks\0 CreateShortcut $LocalAPPDATA\Microsoft\Windows\GameExplorer\$R2\PlayTasks\0\Play.lnk $R3 !endif ${EndIf} System::Call "$1->${IGameExplorer_Release}()" "done_${__GAME_EXPLORER_UNIQUE}:" Pop $R3 Pop $R2 Pop $R1 Pop $R0 Pop $1 Pop $0 !undef __GAME_EXPLORER_UNIQUE !macroend !macro _GameExplorer_GUID_Function Function GUID !define __GAME_EXPLORER_UNIQUE "${__LINE__}${__FILE__}" Push $0 Push $1 Push $2 Push $3 Push $4 Push $5 Push $R0 Push "${GUID}" Pop $R0 # == ${GUID} System::Alloc 16 Exch $R0 System::Call "ole32::CLSIDFromString(w s, i R0)" System::Call "*$R0(i .r2, i .r3, i .r4, i .r5)" System::Free $R0 ClearErrors System::Call "ole32::CoCreateInstance( \ g '${CLSID_GameExplorer}', i 0, \ i ${CLSCTX_INPROC_SERVER}, \ g '${IID_IGameExplorer}', *i .r1) i .r0" ${If} $0 != 0 # S_OK SetErrors Goto "done_${__GAME_EXPLORER_UNIQUE}" ${EndIf} System::Call "$1->${Function}(i r2, i r3, i r4, i r5) i .r0" ${If} $0 != 0 # S_OK SetErrors ${EndIf} System::Call "$1->${IGameExplorer_Release}()" "done_${__GAME_EXPLORER_UNIQUE}:" Pop $R0 Pop $5 Pop $4 Pop $3 Pop $2 Pop $1 Pop $0 !undef __GAME_EXPLORER_UNIQUE !macroend !macro GameExplorer_UpdateGame GUID !insertmacro _GameExplorer_GUID_Function ${IGameExplorer_UpdateGame} "${GUID}" !macroend !macro GameExplorer_RemoveGame GUID !insertmacro _GameExplorer_GUID_Function ${IGameExplorer_RemoveGame} "${GUID}" !macroend
Usage
Save the code above in a file named GameExplorer.nsh and include it from your script before using the macros.
!include GameExplorer.nsh
Adding Games
First, an instance GUID for the game installation must be created with GameExplorer_GenerateGUID or any other GUID generation method. The generated instance GUID must be saved for later usage as it's required for the removal and updating of the game.
${GameExplorer_GenerateGUID} Pop $0 # instance GUID saved to $0
Next, simply call GameExplorer_AddGame with all the details.
${GameExplorer_AddGame} all $INSTDIR\GDF.dll $INSTDIR $INSTDIR\Game.exe $0 # `all` means installation for all users # `$INSTDIR\GDF.dll` is the path to the executable containing the GDF # `$INSTDIR` is the installation directory # `$INSTDIR\Game.exe` is the path to the main game executable # `$0` is the instance GUID
The error flag is set in case of an error.
Additional Tasks
GameExplorer_AddGame creates only one task by default - the Play task. To create more, a shortcut must be created in a numbered directory under $APPDATA\Microsoft\Windows\GameExplorer\<instance GUID>\PlayTasks\<task number> or $APPDATA\Microsoft\Windows\GameExplorer\<instance GUID>\SupportTasks\<task number>. The Play task is numbered 0 under PlayTasks, so the next play task should be numbered 1, while the next support task should be numbered 0.
SetShellVarContext all # restore instance GUID to $0 somehow CreateDirectory $APPDATA\Microsoft\Windows\GameExplorer\$0\PlayTasks\1 CreateShortcut "$APPDATA\Microsoft\Windows\GameExplorer\$0\PlayTasks\1\Network Play.lnk" \ "$INSTDIR\Game.exe" "-network" CreateDirectory $APPDATA\Microsoft\Windows\GameExplorer\$0\SupportTasks\0 CreateShortcut "$APPDATA\Microsoft\Windows\GameExplorer\$0\SupportTasks\0\Help.lnk" \ "$INSTDIR\Support.exe"
Updating Games
Restore the instance GUID and pass it to GameExplorer_UpdateGame.
# restore instance GUID to $0 somehow ${GameExplorer_UpdateGame} $0
The error flag is set in case of an error.
Removing Games
Restore the instance GUID and pass it to GameExplorer_RemoveGame.
# restore instance GUID to $0 somehow ${GameExplorer_RemoveGame} $0
The error flag is set in case of an error.
Related MSDN Pages
See Also
Games plug-in A plug-in for NSIS that will help you register your game with Games Explorer as well as Media Center.
Games Explorer Manager (Screenshot) For someone who doesn't need to build an installer. Allows user to add any program or game currently installed into the Games Explorer.
Games_Explorer_Manager_Install for the Games Explorer Manager
ratings.xml (GDF file must be signed)