reg.exe is the registry’s command line front end, and Microsoft’s own registry article for advanced users calls it the Console Registry Tool for Windows. It ships with every installation and needs no module and no profile to load, which is most of the reason it is still the tool reached for on Server Core and in recovery scenarios. Eleven operations cover everything from reading a single value to swapping an entire hive out from under a key.
The trouble is that three of the most ordinary things it does are not what they look like. A value you read back can differ from the value that is stored. A key can exist and not exist on the same machine at the same time. And a key you exported before editing cannot be restored by importing it afterwards.
Each of those three is documented, and much of that documentation sits nowhere near the reg reference pages. This article works through all three with Microsoft’s own wording and Microsoft’s own captured output, and shows what each one costs a script that assumes otherwise. It does not repeat the parameter tables, which Learn already has and which are linked at the end.
Applies to: Windows client and Windows Server, all supported versions
Quick answer
Read one value, create one, remove it again. Everything below is under HKCU, which your own account owns, so no elevated prompt is needed and nothing outside your profile is touched.
rem /v names the value, /e demands an exact name match instead of the default
rem behaviour, which returns every value name that merely contains the string
reg query "HKCU\Environment" /v Path /e
rem /t sets the stored type, /d supplies the data, /f skips the overwrite prompt
reg add "HKCU\Software\ZaurTest" /v AppPath /t REG_SZ /d "C:\Program Files\SRV-PROD-01 Agent" /f
rem No /v, so the subkey and everything under it goes. /f means no confirmation
reg delete "HKCU\Software\ZaurTest" /f
0 for success and 1 for failure, which is what makes reg query an existence test. The eleventh documents a third value, and that value is not a failure. See the exit codes section below.
What reg does, and its eleven operations
reg is not one command with switches. It is eleven separate operations, each with its own reference page, its own syntax and its own set of switches. They fall into three groups: the ones that only read, the ones that change the registry in place, and the ones that move registry data through a file. Knowing which group an operation sits in tells you most of what you need about its limits.
| Operation | What it does | Accepts a remote computer |
|---|---|---|
reg add | Adds a subkey or an entry | Yes |
reg compare | Compares two subkeys or entries | Yes |
reg copy | Copies an entry to another location | Yes |
reg delete | Deletes a subkey or entries | Yes |
reg export | Writes subkeys and values to a .reg file | No, local only |
reg import | Merges a .reg file into the registry | No, local only |
reg load | Writes a saved hive into a different subkey | Yes |
reg query | Returns the next tier of subkeys and entries | Yes |
reg restore | Writes a saved hive back to the registry | No, local only |
reg save | Saves subkeys and values to a hive file | Yes |
reg unload | Removes a hive loaded by reg load | Yes |
Eight of the eleven accept a \\computername\ prefix on the key name. The three that do not are export, import and restore. The export and restore pages each state in as many words that the operation only works with the local computer; the import page never offers a computer name at all and describes its target as the registry of the local computer. That asymmetry is worth remembering, because it means a remote machine can be read and edited over the wire but cannot be exported over it.
HKLM and HKU. Every other root is local only. This is documented on each operation’s page rather than in one place, which is why it is so often discovered at runtime.
Before the first example
Four things need to be true before the examples below behave as written. Each one is a single command, and each answers a question that otherwise gets answered halfway through a script.
1. Know whether your prompt is elevated. Nothing in this article needs elevation, because every write goes under HKCU. Anything under HKLM does need it, and the reliable test is the integrity level in your own token rather than group membership.
rem S-1-16-12288 is the High mandatory level SID. It is present only in an
rem elevated token, which is why it beats looking for the word Administrators
whoami /groups | findstr /c:"S-1-16-12288"
2. Confirm the scratch key does not already exist. The examples create HKCU\Software\ZaurTest and delete it again at the end. If it is already there, the export and compare steps will not show what they are meant to show.
rem The answer is the errorlevel, not the text, so 2>nul keeps stderr off
rem the screen. An errorlevel of 1 here is the good outcome: nothing is there yet
reg query "HKCU\Software\ZaurTest" 2>nul
echo %ERRORLEVEL%
3. Create somewhere for the files to land. The export and save operations write files, and the reg save reference states that it uses the current path when none is given. Give them a folder of their own rather than relying on wherever the prompt happens to be sitting.
rem 2>nul keeps stderr off the screen, so the line is safe to re-run even
rem when the folder is already there. dir confirms it exists
md C:\bat\reg 2>nul
dir C:\bat\reg
4. Read the built-in help for the operation you are about to script. The online reference pages and the help compiled into the binary do not list the same switches, and the section on the 32-bit and 64-bit views below shows exactly where they part company. The binary on the machine in front of you is the authority for what it accepts.
rem Help is per operation. Check each one you intend to put in a script
reg query /?
reg export /?
reg.exe actually takes.
The value that changes when you read it
Microsoft’s PowerShell sample page for registry entries reads one particular value two different ways, and prints both results. The value is DevicePath under HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion. Same machine, same key, same entry, one page.
First through reg.exe. The command and the output below are reproduced from that page exactly as Learn prints them.
reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion /v DevicePath
! REG.EXE VERSION 3.0
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion
DevicePath REG_EXPAND_SZ %SystemRoot%\inf
Then the same entry through the PowerShell registry provider, also reproduced from that page.
Get-ItemProperty -Path HKLM:\Software\Microsoft\Windows\CurrentVersion -Name DevicePath
DevicePath : C:\WINDOWS\inf
PSPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\Software\Microsoft\Windows
PSChildName : CurrentVersion
PSDrive : HKLM
PSProvider : Microsoft.PowerShell.Core\Registry
reg.exe returned %SystemRoot%\inf and the provider returned C:\WINDOWS\inf. Only one of those is what is stored. Read a value with Get-ItemProperty, write it to another machine with reg add, and you have quietly replaced a portable value with one machine’s literal path. On a box where Windows is not on C: it is now wrong, and nothing will say so.
The mechanism is documented, just not on the reg pages. The type is REG_EXPAND_SZ, and Learn’s own description of the matching PowerShell property type says the string holds unexpanded references to environment variables which are expanded when the value is retrieved. Expansion on read is the type’s defining behaviour, not a quirk of one cmdlet. reg query is the odd one out here precisely because it shows you the stored bytes.
It is worth being precise about who does the expanding, because the obvious suspect is innocent. PowerShell itself does nothing at all with percent signs in a string, which is easy to confirm without touching a registry.
# ExpandString is what the shell itself would do to a string. If the shell were
# responsible, this would come back different from what went in
$s = '%SystemRoot%\inf'
$ExecutionContext.InvokeCommand.ExpandString($s) -eq $s
True
Get-ItemProperty output comes from the registry provider reading a REG_EXPAND_SZ entry. In CMD the percent sign means a great deal, which is the other half of the same problem.
That other half shows up on the writing side. If you type %SystemRoot% into a reg add command, CMD expands it before reg.exe is even started, and the literal path gets stored. Microsoft’s reg add page covers this in one line of its Remarks, and its own example uses the caret to escape each percent sign.
rem The caret stops CMD expanding the percent signs, so reg.exe receives the
rem variable name rather than this machine's answer to it
reg add "HKCU\Software\ZaurTest" /v LogDir /t REG_EXPAND_SZ /d ^%SystemRoot^%\Logs /f
rem Read it straight back. The stored data should still contain the variable
reg query "HKCU\Software\ZaurTest" /v LogDir /e
C:\WINDOWS\Logs instead of %SystemRoot%\Logs, the percent signs were expanded before reg.exe saw them. The type is still REG_EXPAND_SZ either way, so the only thing that gives it away is the data.
There is a third place the same string can change, and this one is not the shell’s doing at all. The Win32 registry redirector page documents that WOW64 intercepts 32-bit writes of REG_SZ and REG_EXPAND_SZ data and rewrites %ProgramFiles% as %ProgramFiles(x86)%, along with the equivalent substitution for the common files variable. The conditions are stated tightly: the string has to begin with the variable, the comparison is case sensitive, there is a length ceiling, and the substitution does not happen when the key was opened for the 64-bit view.
Practical examples
Five examples, in order, all operating on the same scratch key. The last one removes everything the first four created.
1. Read one value and nothing else
The problem: A deployment check needs to know the value of one named entry, and the script around it treats any output as a match.
The solution: Name the value with /v and add /e, because the documented default is that all matches are returned, not just the exact one.
rem /e demands an exact name match. Without it the documented default is that
rem every matching name is returned, not only the one you asked for
reg query "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion" /v DevicePath /e
rem errorlevel is the answer, not the text. 0 found, 1 not found
echo %ERRORLEVEL%
0. If the entry is absent the errorlevel is 1, which is why testing the errorlevel beats matching on the text: the text changes with the locale and the errorlevel does not.
2. Create a value whose data contains spaces
The problem: An agent needs its install path recorded under the current user, and the path has a space in it, which is to say it is a normal path.
The solution: Quote the data. /f suppresses the overwrite prompt so the line is safe to re-run, which matters more than it sounds: without it a second run stops and waits for a keypress that a scheduled task will never provide.
rem The quotes are for CMD, not for reg. Without them the data stops at the
rem first space and /d takes only "C:\Program"
reg add "HKCU\Software\ZaurTest" /v AppPath /t REG_SZ /d "C:\Program Files\SRV-PROD-01 Agent" /f
rem Read it back to confirm the whole path was stored
reg query "HKCU\Software\ZaurTest" /v AppPath /e
reg add reference states that this version of the command does not ask for confirmation when it adds a subkey. The prompt /f exists to suppress is the one you get when the value already exists.
3. Copy a key and prove the copy matches
The problem: Before changing a block of settings you want a second copy inside the registry itself, and you want to be able to prove later that it is still identical.
The solution: reg copy with /s takes the subkeys too, and reg compare answers in its exit code.
rem /s copies subkeys as well as values, /f skips the confirmation
reg copy "HKCU\Software\ZaurTest" "HKCU\Software\ZaurTestCopy" /s /f
rem /s compares recursively. The default output lists differences only
reg compare "HKCU\Software\ZaurTest" "HKCU\Software\ZaurTestCopy" /s
reg copy does not ask for confirmation when it copies a subkey, which its own Remarks section states. What it does with entries already present at the destination is not documented anywhere on that page, so do not rely on a stale copy from a previous run being cleared out. Delete the destination key first if you need it to be exact.
4. Export the key, change it, then import the export
The problem: The usual habit, and the one this example exists to break: export a key before editing it, in the belief that importing the file afterwards puts things back.
The solution: Run it and look. The import restores what was changed and leaves what was added.
rem The file must have a .reg extension, which the reference states outright.
rem /y overwrites an existing file without prompting
reg export "HKCU\Software\ZaurTest" C:\bat\reg\ZaurTest.reg /y
rem Now make two kinds of change: alter one value, and add one that the
rem exported file knows nothing about
reg add "HKCU\Software\ZaurTest" /v AppPath /t REG_SZ /d "C:\Program Files\SRV-PROD-02 Agent" /f
reg add "HKCU\Software\ZaurTest" /v AddedLater /t REG_DWORD /d 1 /f
rem Put the export back and read the whole key
reg import C:\bat\reg\ZaurTest.reg
reg query "HKCU\Software\ZaurTest"
AppPath comes back to the exported data and AddedLater stays where it is. That follows directly from what Microsoft’s own article on .reg files says: running one merges its contents into the local registry. A merge cannot remove anything, so an export taken before an edit is a record of what the key used to contain, not an undo.
5. Remove everything the examples created
The problem: Two scratch keys and a file are now sitting in a profile that did not have them twenty minutes ago.
The solution: reg delete without /v takes the subkey and everything beneath it, and a final query confirms the removal by failing.
rem No /v, so this is the whole subkey and all its values. /f, so no prompt
reg delete "HKCU\Software\ZaurTest" /f
reg delete "HKCU\Software\ZaurTestCopy" /f
del C:\bat\reg\ZaurTest.reg
rem The confirmation is an errorlevel of 1: the key is gone
reg query "HKCU\Software\ZaurTest" 2>nul
echo %ERRORLEVEL%
echo prints 1. A cleanup step that verifies itself is worth the two extra lines, because the only documented return values are 0 and 1, and a query that finds nothing is the only positive confirmation the tool offers.
Reading a value into a script variable
Every value row that reg query prints has the same three columns: the value name, the type, and the data. That looks like an invitation to split on whitespace. It is not, because two of the three columns are allowed to contain spaces.
The table below runs three rows through CMD’s for /f splitting rules. The first row is Learn’s captured output from earlier in this article. The second and third are laid out in the same three column shape using value names and data that Learn prints for that same key, so they are assembled from documented pieces rather than captured, which is worth saying plainly rather than presenting them as a transcript.
| The row | tokens=1 | tokens=2 | tokens=3 |
|---|---|---|---|
| DevicePath / REG_EXPAND_SZ / %SystemRoot%\inf | DevicePath | REG_EXPAND_SZ | %SystemRoot%\inf |
| ProgramFilesDir (x86) / REG_SZ / C:\Program Files (x86) | ProgramFilesDir | (x86) | REG_SZ |
| AppPath / REG_SZ / C:\Program Files\SRV-PROD-01 Agent | AppPath | REG_SZ | C:\Program |
Only the first row behaves. In the second the value name carries a space, so the type has slid into tokens=3 and tokens=2 returns a fragment of the name. In the third the data carries a space, so tokens=3 returns the first word of a path and throws the rest away. All three results are unchanged if the row is not indented, so leading whitespace is not the problem and stripping it does not help.
tokens= string that reads all three rows correctly. tokens=2,* is right for rows one and three and wrong for row two; tokens=3,* is right for row two and wrong for the other two. Any parser written against the three column layout is guessing about a key it has not seen.
What does work is narrowing the output to one row you chose yourself, for a value name you already know the shape of. Then the star token takes everything after the type column, spaces and all.
rem This line is typed at the prompt, so the loop variable is %A.
rem tokens=2,* puts the type in %A and the whole remaining data in %B.
rem It is safe here only because AppPath is a name with no space in it
for /f "tokens=2,*" %A in ('reg query "HKCU\Software\ZaurTest" /v AppPath /e ^| findstr /c:"REG_"') do @echo %B
%A and %B; inside a .bat or .cmd file they must be %%A and %%B. Paste the script spelling into a prompt and CMD stops with %%A was unexpected at this time. Paste the prompt spelling into a script and Microsoft’s for reference says the variable is ignored and an error message is displayed, so the loop runs and simply produces nothing, which is much harder to notice.
The findstr in that pipeline is doing one job: dropping the blank lines and the key path line so that only the value row reaches the loop. It is filtering on the type column rather than on the value name, and that choice is deliberate.
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion and findstr /c:"Path" selects three of them, while findstr /c:"Dir" selects six. Let reg query do the selecting with /v and /e, and leave findstr to strip the lines that are not value rows at all.
findstr /c:"REG_SZ" does not match a REG_EXPAND_SZ row. The characters REG_SZ do not occur anywhere inside REG_EXPAND_SZ, so a type filter written that way silently drops every expandable string in the key. /c:"REG_" matches both, which is why the loop above uses it.
Exit codes, and the one that is not a failure
Ten of the eleven operations document exactly two return values. reg compare documents three, and the third one means the command worked.
| Operation | 0 | 1 | 2 |
|---|---|---|---|
| add, copy, delete, export, import, load, query, restore, save, unload | Success | Failure | Not documented |
reg compare | Successful, result identical | The comparison failed | Successful, differences found |
That third value collides with the oldest idiom in CMD. Microsoft’s if reference defines errorlevel as true when the exit code is equal to or greater than the number given, so if errorlevel 1 is true for 2 as well. The fix is the numeric comparison, which is the form Microsoft’s own if examples use.
rem Capture the code once: every echo below sets its own errorlevel, so a
rem second reading would be describing the echo rather than the comparison
reg compare "HKCU\Software\ZaurTest" "HKCU\Software\ZaurTestCopy" /s
set RC=%ERRORLEVEL%
rem Each code gets its own test. "if errorlevel 1" would catch 2 as well
rem and report a successful comparison as a failed one
if %RC% EQU 0 echo identical
if %RC% EQU 2 echo differences found
if %RC% EQU 1 echo the comparison itself failed
/on, which the reference describes as displaying nothing. The comparison then produces no output at all and the entire answer lives in the exit code, which is exactly what a script wants and exactly what a human at a prompt does not.
Two registries on one machine
On 64-bit Windows a subset of the registry exists twice. The Win32 registry redirector page describes it as separate logical views for 32-bit and 64-bit applications, mapped onto different physical locations, with the redirection invisible to the application doing the reading. A 32-bit process and a 64-bit process asking for the same path under HKLM\Software are not necessarily asking about the same data. Learn is careful here: only a subset of the registry is redirected, and some keys under redirected paths are shared rather than duplicated, so the two views return one physical copy for those.
This is where two Microsoft pages give an administrator two different mental models, and it is worth having both rather than picking one.
WOW6432Node node, which invites you to navigate there and read them. The Win32 redirector page says redirected keys are mapped to physical locations under that node, that the physical location should be considered reserved by the system, and that applications should not access it directly because it may change. Both are Microsoft. The first describes what you see, the second describes what you should write down in a script.
The supported way to choose a view is a switch, not a path. Query the same key name twice and let reg.exe do the mapping.
rem The same key name through each view. On a 64-bit machine these can return
rem different data, or one of them can report that the value does not exist
reg query "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion" /v ProgramFilesDir /e /reg:64
reg query "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion" /v ProgramFilesDir /e /reg:32
Which operations take those switches is the least satisfying part of the whole reference. Here is what the eleven pages actually say.
| Operation | In the Syntax block | In the parameter table |
|---|---|---|
reg add | Yes | Yes |
reg query | Yes | Yes |
reg import | No | Yes |
reg compare | No | No |
reg copy | No | No |
reg delete | No | No |
reg export | No | No |
reg load | No | No |
reg restore | No | No |
reg save | No | No |
reg unload | No | No |
reg import is the tell: the switches are in its parameter table and missing from its own Syntax block on the same page, which is a documentation defect rather than a behaviour. Run reg export /? on the machine you are scripting for and believe the binary.
reg add documents the view switches and reg delete does not. Whatever the binary turns out to accept, do not write a script that creates a value in a named view and removes it without naming one. Check the help for both halves before you rely on the pair.
Export is not a backup
Example 4 showed the behaviour. This is why it happens, and what the documentation says to use instead.
reg export and reg import deal in .reg files, which are text. Microsoft’s article on those files states that running one merges its contents into the local registry. A merge writes what the file contains and touches nothing else, so anything created after the export survives the import untouched.
reg save and reg restore deal in hive files, which are binary. Both reference pages carry the same sentence in their Remarks, and it is an instruction rather than a description: save the parent subkey before editing any registry entries, and if the edit fails, restore it with reg restore. The Win32 page behind that operation is blunter still, describing the underlying function as replacing the subkeys and values below the specified key with those from the file.
| Operation | File | Scope | Effect on what is already there |
|---|---|---|---|
reg export | .reg, text | Local computer only | Reads only, writes the file |
reg import | .reg, made by reg export | Local computer only | Merges, so additions since the export remain |
reg save | .hiv, binary | Local or remote | Reads only, writes the file |
reg restore | .hiv, made by reg save | Local computer only | Replaces what is below the key |
reg import says its file must be created in advance by reg export, and the reference for reg restore says the same about reg save and a .hiv extension. Mixing the pairs is at least an obvious problem to run into. The quiet one is importing a .reg file and believing the key is back to how it was.
A .reg file can delete, but only if you edit it by hand. Microsoft’s article documents the syntax: a hyphen in front of the bracketed key path removes the key, and a hyphen in place of the data removes a single value. That is an editing step on the file, never something reg export produces on its own, which is the clearest possible confirmation that an untouched export cannot remove anything.
reg load page and the Win32 page behind it do not agree on where a hive may be loaded. The command reference lists five valid root keys; the API page says the data is loaded into a subkey under HKEY_USERS or HKEY_LOCAL_MACHINE. The API page makes the narrower claim and describes the layer that does the work, so plan around it and test the rest.
Hidden gems
A search with no /e is wider than it looks. The /e parameter is documented as returning only exact matches, and the default as returning all of them. On a big key that difference is not a nuisance, it is a wrong answer that a script will act on. If your test is whether a specific entry exists, /e is not optional.
/k narrows a recursive search to key names. reg query KEY /s /f pattern /k searches key names only, and the reference spells out that it has to be used together with /f. Compared with dumping a whole subtree and piping it through findstr it is one process instead of two, and the matching is done by the tool that knows which part of the line is a key name.
reg compare with /on is a silent assertion. The output switches are /oa, /od, /os and /on, and /on displays nothing. Combine it with the three-way exit code and you have a drift check that prints nothing at all unless you choose to print something yourself, which is the shape a scheduled job wants.
Two of the eleven reference pages carry copy and paste damage, and it matters when you are reading fast. The Remarks section on the reg copy page introduces its return values as belonging to reg compare. They are not; the values listed there are reg copy‘s own two. The reg delete page has the matching slip in its parameter table, which names the parameter <keyname1> while its own Syntax block calls it <keyname>. Both pages are correct in substance; only the labels travelled from somewhere else.
Cross-shell equivalent
PowerShell reaches the registry through a provider, so keys behave like folders and entries behave like properties of those folders. That mapping is the source of most of the friction: entries cannot be browsed, only read off the key that holds them.
| Task | reg.exe | PowerShell |
|---|---|---|
| List the value names in a key | reg query KEY | Get-Item -Path KEY | Select-Object -ExpandProperty Property |
| Read one value | reg query KEY /v NAME /e | Get-ItemProperty -Path KEY -Name NAME |
| Create a value | reg add KEY /v NAME /t TYPE /d DATA /f | New-ItemProperty -Path KEY -Name NAME -PropertyType TYPE -Value DATA |
| Change a value | reg add KEY /v NAME /d DATA /f | Set-ItemProperty -Path KEY -Name NAME -Value DATA |
| Delete a value | reg delete KEY /v NAME /f | Remove-ItemProperty -Path KEY -Name NAME |
The first row is the closest thing PowerShell has to a bare reg query. It returns the value names on their own, with none of the PS prefixed properties that the provider adds. Learn’s capture of the output for the CurrentVersion key is five lines.
# Registry keys expose their entries through a property named Property.
# Expanding it gives the same first column reg query prints, and nothing else
Get-Item -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion |
Select-Object -ExpandProperty Property
DevicePath
MediaPathUnexpanded
ProgramFilesDir
CommonFilesDir
ProductId
To get one entry’s data on its own, without the provider’s own properties wrapped around it, expand the named property in the same way. Remember that what comes back from a REG_EXPAND_SZ entry is the expanded form, as the two captures at the top of this article showed.
# Without the Select-Object this prints PSPath, PSParentPath, PSChildName,
# PSDrive and PSProvider alongside the one value you asked for
Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion -Name DevicePath |
Select-Object -ExpandProperty DevicePath
Get-ItemProperty has Filter, Include and Exclude parameters and Learn states plainly that none of them can filter by property name, because they address keys rather than entries. There is no provider equivalent of reg query‘s /f search across value names, so that filtering is yours to write.
Which leaves a fair summary of when to reach for which. Use the provider when you want typed objects and do not want to parse anything. Use reg.exe when you need the stored bytes rather than the interpreted value, when you are working across a view boundary, or when you are somewhere PowerShell is not, which still includes a good number of recovery and imaging scenarios. The PowerShell commands cheat sheet and the Windows command line cheat sheet are the quick lookups for either shell.
Where this matters
- Software inventory across a fleet where half the estate reports an install path that does not exist, because the agent read it through the wrong view.
- Build agents running a 32-bit installer on a 64-bit host, where the key the installer wrote and the key the test looks for have the same name and different contents.
- Change control before a fix, where the rollback plan says “we exported the key” and the plan only works for values that existed at the time.
- Migrating a setting between machines, where a path read through PowerShell arrives on the target with the source machine’s drive letter baked into it.
- Golden image drift, where
reg compareagainst a reference host is the whole check and the wrapper script reads its exit code correctly. - Server Core and recovery consoles, where
reg.exeis what you have and the shell you would rather be using is not there.
Tips and limitations
- Eight of the eleven operations accept a
\\computername\prefix.export,importandrestoreare local only: two of those pages say so outright and the third never offers a computer name. - Against a remote computer the only valid roots are
HKLMandHKU. - The documentation is specific about file extensions:
.regfor export and import,.hivfor the file thatreg restoreandreg loadconsume. reg addcannot add a subtree, which its Remarks state directly. It adds subkeys and entries only.reg deletewith no/vremoves the subkey and everything under it./vais the narrower form: the reference says it deletes all entries within the specified key, and that subkey entries residing within that key are not deleted.- The view switches
/reg:32and/reg:64appear in the Syntax block of two reference pages out of eleven. Treatreg <operation> /?as the authority for switches, and the reference page as the authority for behaviour. - For a
REG_EXPAND_SZvalue, the caret escape in thereg addexample is written for the command prompt. Always read the value back and confirm the variable survived rather than assuming it did. - Microsoft’s own caution sits at the top of the
regreference and is worth repeating: prefer Control Panel or an MMC snap-in where the setting has one, and back the key up before editing it directly.
Official documentation
- reg commands: Windows Commands | Microsoft Learn
- reg query: Windows Commands | Microsoft Learn
- reg add: Windows Commands | Microsoft Learn
- reg compare: Windows Commands | Microsoft Learn
- Windows registry for advanced users | Microsoft Learn
- How to add, modify, or delete registry subkeys and values by using a .reg file | Microsoft Support
- Registry Redirector: Win32 apps | Microsoft Learn
- Registry files: Win32 apps | Microsoft Learn
- Working with registry entries: PowerShell | Microsoft Learn
- for: Windows Commands | Microsoft Learn
Related tools
- Windows 11 registry tweak generator builds the .reg file whose merge behaviour this article explains, so it is worth knowing what the generated file will and will not undo.
Related guides
- runas and UAC token filtering reads two UAC policy values with
reg queryand deliberately never shows how to set them, which is the gap this article fills. - whoami /all and the Windows access token explains the integrity level SID used in the elevation check above.
- findstr and find covers the filtering half of the parsing section, including where substring matching bites.
- vssadmin and shadow copies names a registry value for shadow storage sizing and stops short of setting it.
- dfsutil and dfsdiag for DFS Namespaces uses a parameter family that edits client side registry keys.
- Restoring the old right click menu in Windows 11 is a short, real
reg addandreg deleteworkflow to practise on. - where and Get-Command deals with the other half of application discovery, the search path rather than the registry.
- Windows command line cheat sheet carries the short forms of the registry operations used most often.
Five cheat sheets, one PDF
Subnet masks, PowerShell, Linux commands, HTTP status codes and the ESXi command line - one page each, free to keep. Leave an address and it arrives in a minute.