How to use REG_EXPAND_SZ from the commandline? - windows

I was reading the Windows Commandline Documentation (Win+F1) about the commands that modify the Windows registry, particularly the the "reg add" command.
reg add HKCU\testfolder /t REG_EXPAND_SZ /v Stokrotka /d "%systemroot%\system32"
Now, I don't know how this was designed to work.
When I invoke the command above, the variable %systemroot% gets expanded to C:\Windows. I've tried the following not to make the variable to expand, but there is no way I could force it not to:
escaping the `%%`'s with an `%, ^, \` - doesn't work even if I use double quotes around
using the single quotes '' around the whole /d string
use `setlocal setdelayedexpansion`? sth like:
# (setlocal enabledelayedexpansion) && (reg add HKCU\testfolder /t REG_EXPAND_SZ /v Stokrotka /d "!systemroot!\system32") && (setlocal disabledelayedexpansion)
The variable 'data' (/d) field is either like ^%systemroot^% or like !systemroot! or just expands to C:\windows .
I could probably use the .reg file to accomplish my task, but I simply don't want to do it.
I thought that maybe there is something wrong with the program that I use to display the variable contents (regedit / regedt32 / reg query (commandline)), but after checking this is probably not the case.
Any ideas? I'm mainly interested how the variable value should look like in the regedit window, should it be like :"%systemroot%\system32" or "C:\windows\system32" to be properly expanded by other programs.
Regards.

From a command line, this worked for me:
reg add HKCU\testfolder /t REG_EXPAND_SZ /v Stokrotka /d ^%systemroot^%\system32

The syntax suggested by aphoria is correct, without quotes as you discovered. But you run into trouble when you need spaces in the value.
However, it is possible to mix-in quotes in the value. It looks weird, but it works:
REG ADD "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v Path /d ^%SystemRoot^%;c:\Program" Files"\Intel\DMIX;C:\bin /t REG_EXPAND_SZ
You can use quotes where needed, just not around your variables. And not right after a backslash.
Also, beware that the syntax for use in a batch file is not the same as on the command line. If you put that line into a batch file, you need to replace the "^" with another "%":
REG ADD "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v Path /d %%SystemRoot%%;c:\Program" Files"\Intel\DMIX;C:\bin /t REG_EXPAND_SZ
(cmd.exe always reminds me of Henry Spencer's quote "Those who do not understand Unix are condemned to reinvent it, poorly")

I recognize that this is an old thread, but since there doesn't seem to be an answer and I too was driven crazy by this problem, I'll share what I've come up with. It's convoluted, it's ugly, and it looks like this:
SET VAR=% SET
SET VALUE=%VAR%SystemRoot%VAR%\system32...
REG ADD HKLM... /v Test /t
REG_EXPAND_SZ /d %VALUE%
I end up with Test containing the string %SystemRoot%\system32
Edit: Should have finished testing before posting. While this worked from the command line, it failed in my command scripts. What DID work was SET VALUE=%%SystemRoot%%\system32...

We have a use in an autounattend.xml. I was first following aphoria's answer, then I had to use mivk's enhanced answer. I had it working. Then I made a small change and it stopped working. I consider this insight worth reporting, to save others lengthy frustration.
Building on previous answers, here is how to make this work in autounattend.xml:
<CommandLine>cmd.exe /c reg.exe add HKLM\ourkey /v ourvalue /t REG_EXPAND_SZ /d "our data with spaces"^%USERNAME^%"and more spaces" /f</CommandLine>
What matters is the cmd.exe /c. If you don't use cmd.exe then reg.exe still runs, but it puts literally ^% into the registry, not the desired %.
Maybe the answer by ASTX813 would work, but this seems easier to read.

There's no magic here, you must escape every % in command-line with/become: %%.
In batch file, you again must escape them, become %%%%SystemRoot%%%%. Yes, four ampersands. It's ugly, but it's the way it is, and it's pretty consistent though.
note: Using ^ to escape it as literal character might help/cleanup in one step/degree only (as long as it's not interpreted). The advantage using ^ is that you can write in command-line or batch file with identical syntax: eg. "^%SytemRoot^%", since in both environments, % treated equally as literal.

The answer is very simple. Only quote the spaces and escape the %'s.
In command line, escape the %'s with the ^.
reg add HKLM\Software\Microsoft\Command" "Processor /v AutoRun /t REG_SZ /d title" "^%username^% /f
In batch file, escape the %'s with another %.
reg add HKLM\Software\Microsoft\Command" "Processor /v AutoRun /t REG_SZ /d title" "%%username%% /f
This took me a while to figure out. In my mind, I should quote the entire string, but could not get the variable to be passed without expanding it. I broke my way of thinking by quoting spaces instead.

Please try the following:
reg add HKCU\testfolder /t REG_EXPAND_SZ /v Stokrotka /d ^%systemroot%^\system32

From a batch file you end up with problems with quotes, which you can then escape with a backslash, for example:
reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\%name%" /v "UninstallString" /t REG_EXPAND_SZ /d "\"%%comspec%%\" /d /c \"%dest%\uninstall.cmd\""

without quotes
reg add HKCU\testfolder /v Biedronka /t REG_EXPAND_SZ /d "%%%^%systemroot%%%^%\system32"
with quotes
reg add HKCU\testfolder /v Biedronka /t REG_EXPAND_SZ /d "\"^%%systemroot^%%\system32\""

I finally got sick of the banner/logo on CScript and decided to prefix VBS associations with //nologo in my 'new build' batch script. This required modifying a REG_EXPAND_SZ registry entry with an environment variable and this question and its various answers were the best inspiration I could find. Here's the final script.
SET "thecmd=\""%%SystemRoot%%\System32\CScript.exe\"" //nologo \""%%1\"" %%*"
ECHO.%thecmd%
REG.exe ADD "HKEY_CLASSES_ROOT\VBSFile\Shell\Open2\Command" /ve /t REG_EXPAND_SZ /d "%thecmd%" /f
SET thecmd=
Storing the command in a variable and using \"" for " and %% for % are what allows it to work.
If you prefer a one-liner (again, from batch) you can use:
REG.exe ADD "HKEY_CLASSES_ROOT\VBSFile\Shell\Open2\Command" /ve /t REG_EXPAND_SZ /d "\""%%SystemRoot%%\System32\CScript.exe\"" //nologo \""%%1\"" %%*" /f
If you want the same functionality, don't forget to set the verb for VBSFile to Open2 so you can just double-click VBS files to run them with CScript:
REG.exe ADD "HKEY_CLASSES_ROOT\VBSFile\Shell" /ve /t REG_SZ /d "Open2" /f

Related

pwd alias on Windows cmd

I want to create a fixed pwd alias like in this topic, but I want to keep all aliases in one file as in this answer by Argyll. Currently my file cmdAliases.cmd looks like this:
#echo off
doskey ls=dir
doskey pwd=echo ^%cd^%
Running pwd command now prints:
ECHO is on.
I believe the spaces in the command are the problem. Is there a way to fix it using only the cmdAliases.cmd file?
The links you provided show how to do it.
I have my doskey macros in a file aliases.txt in my folder %USERPROFILE%
11:24:16 C:\Users\LotPings________________________________________
> type Aliases.txt
~=CD /D "C:\Users\LotPings"
\=CD \
-=CD ..
Alias=Doskey $*
Aliases=Doskey /MACROS:ALL
And an autorun entry which loads this file
> reg query "HKEY_CURRENT_USER\Software\Microsoft\Command Processor" /v autorun
HKEY_CURRENT_USER\Software\Microsoft\Command Processor
autorun REG_SZ Doskey /MacroFile="C:\Users\LotPings\Aliases.txt"
To generate this Autorun automatically copy the following lines into cmd line or a batch file
Set "Key=HKEY_CURRENT_USER\Software\Microsoft\Command Processor"
Set "Val=Autorun"
Set "Typ=REG_SZ"
Set "Dat=Doskey /Macrofile=\"%USERPROFILE%\Aliases.txt\""
reg add "%Key%" /v %Val% /t %Typ% /d "%Dat%" /f

Puppet: Mixing registry keys and Variables

I am trying to create a module to configure my systems to point at a certain server. I need to change the registry key of the hostname of the server i require.
The way i have done this is, i have a 'params.pp' which is configured with the command i'd like to run. I also have a hiera value specifying the hostname. The idea is if the hostname ever changes, i just change the hiera value and the module does not need to change.
I am getting a syntax error for the reg.exe command (i'm using puppet exec). the issue is the following code;
$server_add = "reg.exe add HKLM\\SOFTWARE\\path\\to\\registry /f /v KeyName /t REG_SZ /d ${server}"
$server_query = "reg.exe query HKLM\\SOFTWARE\\path\\to\\registry /v KeyName | findstr.exe ${server}"
It wants the double quotes around the registry key path. The issue then is my puppet code cannot access find my variable '${server}'.
I've tried many combination with quotes and double quotes and seem to have no luck.
Any help would be great.
Thanks in advance.
For the double qoutes around the registry key, please use \" in your string:
$server_add = "reg.exe add \"HKLM\\SOFTWARE\\path\\to\\registry\" /f /v KeyName /t REG_SZ /d ${server}"
It will give you:
reg.exe add "HKLM\SOFTWARE\path\to\registry" /f /v KeyName /t REG_SZ /d

REG command after SET is "unknown" in DOS/Windows batch file (.BAT)

In my batch file I started to use variables and suddenly the following commands do not work anymore.
Here is the part of my code with the problem
SET "path=MyPath"
REG ADD "HKCU\Software\ETC\ETC" /f /v "MyRegNameA" /t REG_SZ /d "%path%\ETC\"
REG ADD "HKCU\Software\ETC\ETC" /f /v "MyRegNameB" /t REG_SZ /d "%path%"
PAUSE
START "" "%path%\MyProgram.exe"
This code works without the SET... and of course with MyPath instead of %path%. Error Message is:
The command "REG" is either spelled wrong or couldn't be found
I previously found how to use Variables here: stackEx.SetVariables
To my knowledge I am doing it exactly as supposed, and I couldn't find specific help so far.
path is a logical name, but it's not a good name to use as it is assigned by Windows.
path is a semicolon-separated list of the directories that Windows uses to find programs. When you change it, Windows can no longer find reg.exe since reg.exe is not in mypath.
Simply choose another name - don't use path. If you enter set at the prompt, you will see a list of many of the variables that are established by Windows. Simple rule - don't use any of them for user-variables.

Using Batch to change Computer Name and UserName based off of their current Computer Name?

I'm writing a batch that I'll remotely place in the all users startup folder using Desktop Central 9 /PsExec. We are going to start using a naming convention as part of an initiative to overhaul computer management. This batch needs to find what the current PC Name is and then change it based off of what I will have manually defined in the batch itself. It would also be nice to be able to then also change the users name based off of what computer name is initially found. All computers use Windows 7 and above. I wrote a quick batch of what I think it should look like, minus the user name modification, but there are nuances here and there I must be getting wrong. The "If" statement is my weakness with batch, but I know it will be extremely efficient in this case. Can anyone correct what I'm doing wrong here? Much appreciated, this will help us A LOT!
SET WMIC GET COMPUTERNAME %%CURRENT%
If %%CURRENT% = THOMAS-PC then REG ADD
HKLM\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName /v
ComputerName /t REG_SZ /d TGZ-DELL-001 /f
If %%CURRENT% = CHARLES-PC then REG ADD
HKLM\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName /v
ComputerName /t REG_SZ /d TGZ-DELL-002 /f
If %%CURRENT% = MATHEW-PC then REG ADD
HKLM\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName /v
ComputerName /t REG_SZ /d TGZ-DELL-003 /f
%%CURRENT% is incorrect. Use %CURRENT%
IF statements do not have a "then". Use parens if you have multiple lines in IF statement.
Use = to SET and == to compare
Use quotes as shown in my example so that the spaces, etc don't cause problems
No need for WMIC in this case.
How about something like this?
I added /I to make the compare case insensitive. Leave that out if you wish... but then your compare would miss Thomas-PC, etc.
**** CAUTION **** Untested! Of course you will test test on a test machine before messing up the registry on a working machine :)
#echo off
set "RegCmd=REG ADD HKLM\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName /v ComputerName /t REG_SZ /d"
echo(this computer is %ComputerName%
if /I "%ComputerName%"=="THOMAS-PC" %RegCmd% TGZ-DELL-001 /f
if /I "%ComputerName%"=="CHARLES-PC" %RegCmd% TGZ-DELL-002 /f
if /I "%ComputerName%"=="MATHEW-PC" %RegCmd% TGZ-DELL-003 /f

REG ADD a REG_MULTI_SZ Multi-Line Registry Value

To add a REG_MULTI_SZ multi-line registry value, i can do
reg.exe ADD "HKLM\path\to\registry\key" /v RegistryValue /t REG_MULTI_SZ /d "abc\0def\0"
which would add ("abc", "def").
But what if i need to add ("abc", "", "def"), i.e. an empty item in between?
Doing
reg.exe ADD "HKLM\path\to\registry\key" /v RegistryValue /t REG_MULTI_SZ /d "abc\0\0def\0"
gives me an "invalid parameter" error.
This worked for me:
REG ADD "HKLM\LOCATION" /v "Value" /t REG_MULTI_SZ /d item1\0item2 /f
or if your items have whitespace:
REG ADD "HKLM\LOCATION" /v "Value" /t REG_MULTI_SZ /d "item1"\0"item2" /f
Make sure you don't have TWO trailing "\0" separators (one is OK, with or without the trailing \0 you will get your last return character) like the example below (like I saw in a TechNet article), or you will get an "ERROR: Invalid value specified for '/d'.":
REG ADD "HKLM\LOCATION" /v "Value" /t REG_MULTI_SZ /d item1\0item2\0\0 /f
This probably isn't possible using reg add, because the data you're trying to set is improperly formed. REG_MULTI_SZ values are terminated by an empty string, so having an empty string as part of the value is not allowed.
If you really need to, and on the understanding that some software won't be able to read the key correctly, you could use reg import instead. For example, the following file creates a value with an empty string in the middle:
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\software\harrytest]
"test"=hex(7):76,00,61,00,6c,00,75,00,65,00,31,00,00,00,76,00,61,00,6c,00,75,\
00,65,00,32,00,00,00,00,00,76,00,61,00,6c,00,75,00,65,00,34,00,00,00,76,00,\
61,00,6c,00,75,00,65,00,35,00,00,00,00,00
Try this:
#reg.exe add "HKCU\Software\Wirkomatron" /v "MySoftware" /d "Software1"\0"Software2"\0"Software3"\0 /t REG_MULTI_SZ /f
And now you can do it with Batch script propertly.
Just for reference.
If you just want to insert a new line then you will need to simulate it with a space in the desire empty line. If the space would have an undesired impact in what you are trying to achieve then this post is not useful for you.
reg.exe ADD "HKLM\path\to\registry\key" /v RegistryValue /t REG_MULTI_SZ /d "abc\0 \0def\0"

Resources