How do I set a registry variable in batch code with SETX?

1

I am trying to make a custom tool that works with Steam. Because the user may have a different install directory than myself, I want to use the SteamPath registry string value as a variable in my batch code to get the correct path. I am attempting to use the code below to make my custom STEAMDIR variable:

@ECHO OFF

SETX STEAMDIR /K "HKEY_CURRENT_USER\Software\Valve\Steam\SteamPath" /m

IF NOT EXIST "STEAMDIR" GOTO :NOSTEAM
IF EXIST "STEAMDIR" GOTO :FOUND

:FOUND
CLS
SET msgboxTitle=Success!
SET msgboxBody=Steam found!
SET tmpmsgbox=%TEMP%\Message.vbs
IF EXIST "%tmpmsgbox%" DEL /F /Q "%tmpmsgbox%"
ECHO msgbox "%msgboxBody%",0,"%msgboxTitle%">"%tmpmsgbox%"
WScript "%tmpmsgbox%"
GOTO :END

:NOSTEAM
CLS
SET msgboxTitle=Error!
SET msgboxBody=You don't kave any Kenshi workshop mods installed!
SET tmpmsgbox=%TEMP%\Message.vbs
IF EXIST "%tmpmsgbox%" DEL /F /Q "%tmpmsgbox%"
ECHO msgbox "%msgboxBody%",0,"%msgboxTitle%">"%tmpmsgbox%"
WScript "%tmpmsgbox%"
GOTO :END

:END

I am to use SETX as demonstrated IN this SS64 page, but my attempts have been unsuccessful. Any help is appreciated, but I'd like to ask that solutions using PowerShell or VisualBasic not be suggested. I get these a lot and I do not have enough experience in either language to re-write my code as I still have things to add.

Mr. Mendelli

Posted 2019-03-06T07:50:46.847

Reputation: 1 061

But you're already running VBScript from within your batch script. – user1686 – 2019-03-06T07:59:00.190

I am aware @grawity, it was made from a template using an answer I received on a different question. I will be adding XCOPY programming that is in batch and I do not know how to translate it. – Mr. Mendelli – 2019-03-06T08:00:52.583

You can still run the same xcopy.exe from within any other programming language, and I would honestly suggest that the overall framework better be written in something not requiring such arcane hacks as for /f to do even trivial operations. Port it while it's still small. – user1686 – 2019-03-06T08:15:31.600

I will have to decline your suggestion, I do not have the time right now to learn another language. – Mr. Mendelli – 2019-03-06T08:17:12.043

1I'd suggest you to read a help for set command. You do the assignment completely wrong. – montonero – 2019-03-06T08:28:08.630

1If you don't mind it requiring a second run you can set it with setx which can parse a value directly from the registry. – shawn – 2019-03-06T08:36:11.320

Answers

1

Your previous formulation was better. Besides the problem signaled by grawity, your main problem when using the for /f command was that it produces separate variables for each token.

For your value of c:/program files (x86)/steam, you would have:

%%a=c:/program files
%%b=(x86)/steam

You would need to accumulate the values %%a, %%b etc. using code such as:

setlocal EnableDelayedExpansion
for /f "usebackq tokens=3*" %%a in (`reg query "HKCU\Software\Valve\Steam" /V "SteamPath" ^| find "REG_SZ"`) do (
  set STEAMDIR=%%a
  set b=%%b
  set c=%%c
)  
if "%b%" neq "%%b" set STEAMDIR=%STEAMDIR% %b%
if "%c%" neq "%%c" set STEAMDIR=%STEAMDIR% %c%
echo STEAMDIR=%STEAMDIR%

For completeness, I have added a check for the third component, although there isn't one for your value.

harrymc

Posted 2019-03-06T07:50:46.847

Reputation: 306 093

This worked exactly as I needed, thank you for putting this answer together! – Mr. Mendelli – 2019-03-06T11:03:26.213

1

You have:

SET %STEAMDIR%=for /f "tokens=3" %%a in [...] do echo %%a

The first problem is the usage of % on the left-hand side. In batch scripts, the percent signs aren't part of the variable's name; they're operators which trigger the expansion of that variable. You don't want them on the left-hand side of an assignment (except in special cases), because currently your command expands to this – which tries to set a variable with no name:

SET =for /f "tokens=3" %%a in [...] do echo %%a

The correct usage (of SET, not of the whole thing) would be:

SET STEAMDIR=for /f "tokens=3" %%a in [...] do echo %%a

The second problem is that the right-hand side of variable assignments is the value. It's not a command that produces this value. You're literally setting the variable's contents to the characters for /f ...

Other languages have functions or "command substitution" operators which allow running a command and using its output as the value of an outer command (e.g. var=`cmd` or var=$(cmd) in bash), but Windows Cmd.exe doesn't really have that.

Instead, the for /f ... invocation gets the output and runs inner command (the part after do), which can then access the output as the single-letter parameter %%a, %%b, etc. If the output needs to be stored in a "normal" variable, that needs to be done in the for ... do command, like this:

for /f "tokens=3" %%a in [...] do SET STEAMDIR=%%a

user1686

Posted 2019-03-06T07:50:46.847

Reputation: 283 655