Strip CMD output to just show directories - powershell

I'm currently trying to replace a powershell script with a cmd script as it's more suitable for what is trying to be done.
In Powershell I'm using this bit of code to return a list of personal folder directories on the computer
$Name = [Environment]::UserName
get-item HKCU:\software\Microsoft\Office\15.0\Outlook\Search\Catalog - ErrorAction SilentlyContinue | select -expandProperty property | Out-File Z:\global\pst\PowershellOutput\$Name.txt -append
This does what I want and outputs a list of directories like so
H:\PST\My Outlook Data File 1.pst
H:\PST\My Outlook Data File 2.pst
C:\PST\My Outlook Data File 3.pst
However when I run this line to extract the registry key
regedit.exe /e Z:\global\battest\%username%.txt "HKEY_CURRENT_USER\Software\Microsoft\Office\15.0\Outlook\Search\Catalog"
I get an output with lots of unnecessary data
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Microsoft\Office\15.0\Outlook\Search\Catalog]
"H:\\PST\\My Outlook Data File 1.pst"=hex:0c,01,00,00,00,00,00,00
"H:\\PST\\My Outlook Data File 2.pst"=hex:f8,00,00,00,00,00,00,00
"C:\\PST\\My Outlook Data File 3.pst"=hex:ac,02,00,00,00,00,00,00
This data is passed onto another program* so a work-around could be to use data within the "" marks however it also has the double backslashes which makes the data awkward to pass on.
Is there a better way to grab these values within CMD or perhaps a parameter which I've missed which just shows the directories?
-Sorry for not including this before however this program is not a CMD program, it's visual basic

While I don't have Office installed to test, this should get the work done
#echo off
setlocal enableextensions disabledelayedexpansion
set "HKCU=&H80000001"
set "subKey=software\Microsoft\Office\15.0\Outlook\Search\Catalog"
>> "Z:\global\pst\PowershellOutput\%username%.txt" (
for /f "tokens=2 delims={" %%a in ('
wmic
/NameSpace:\\root\default
Class StdRegProv
Call EnumValues
hDefKey^="%HKCU%"
sSubKeyName^="%subkey%"
2^>nul
^| find "sNames = {"
') do for %%b in (%%a) do (
for /f delims^=^" %%c in ("%%~b") do echo(%%~fc
)
)
It uses wmic to retrieve the list of values defined under the indicated key and filter the output to only retrieve the line with the names of those values in the form sNames = {"v1", "v2", "v3"}.
The { is used to separate the start of the line from the list of values (%%a) , and this list is iterated (%%b) to get each value. The last element in the list includes an ending } that needs to be removed, this is handled by %%c using the quotes in the value as delimiters.
The equivalent vbs version could be
Option Explicit
Const HKEY_CURRENT_USER = &H80000001
Const ForAppending = 8
Const SUB_KEY = "software\Microsoft\Office\15.0\Outlook\Search\Catalog"
Const OUTPUT_PATH = "Z:\global\pst\PowershellOutput"
Dim fso, shell
Set fso = WScript.CreateObject("Scripting.FileSystemObject")
Set shell = WScript.CreateObject("WScript.Shell")
Dim values
Call GetObject( _
"winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv" _
).EnumValues( _
HKEY_CURRENT_USER, SUB_KEY, values _
)
Dim outputFile
Set outputFile = fso.OpenTextFile( _
fso.BuildPath( _
OUTPUT_PATH, shell.ExpandEnvironmentStrings("%username%") & ".txt" _
) _
, ForAppending _
, True _
)
Dim value
If Not IsNull(values) Then
For Each value In values
Call outputFile.WriteLine(fso.GetAbsolutePathName( value ))
Next
End If
Call outputFile.Close()

You would probably need to use the REG QUERY command. In a single bat file it would like like:
#echo OFF
for /f "usebackq tokens=1-3" %%A in (`REG QUERY "HKCU\Software\Microsoft\Office\15.0\Outlook\Search\Catalog"`) do (
set ValueName=%%A
)
echo %ValueName% > Z:\global\battest\%username%.txt
Got this from How can I get the value of a registry key from within a batch script?

Here is a batch code to get the list of *.pst files (not directories) which work independent on number of *.pst files and their file names as long as the file names end with .pst.
#echo off
setlocal EnableExtensions EnableDelayedExpansion
for /F "skip=1 delims=" %%# in ('%SystemRoot%\System32\reg.exe query HKCU\Software\Microsoft\Office\15.0\Outlook\Search\Catalog 2^>nul') do (
set "RegData=%%#"
set "DelData=!RegData:*.pst=!"
if not "!DelData!" == "!RegData!" call :OutputFileName
)
endlocal
goto :EOF
:OutputFileName
set "RegData=!RegData:%DelData%=!"
echo !RegData:~4!
goto :EOF
*.pst files are Outlook Personal Storage files which are container files for emails, contacts, ...
The command FOR runs console application REG to query all values of registry key:
HKEY_CURRENT_USER\Software\Microsoft\Office\15.0\Outlook\Search\Catalog
The output on Windows Vista and later Windows versions is for the example:
HKEY_CURRENT_USER\Software\Microsoft\Office\15.0\Outlook\Search\Catalog
H:\PST\My Outlook Data File 1.pst REG_SZ whatever the
H:\PST\My Outlook Data File 2.pst REG_SZ data value is
C:\PST\My Outlook Data File 3.pst REG_SZ of each value
There is output the registry key and next the registry values each indented with 4 spaces and with 4 spaces between value name and value type and 4 spaces between value type and data value.
But on Windows XP the output is for the example:
! REG.EXE VERSION 3.0
HKEY_CURRENT_USER\Software\Microsoft\Office\15.0\Outlook\Search\Catalog
H:\PST\My Outlook Data File 1.pst REG_SZ whatever the
H:\PST\My Outlook Data File 2.pst REG_SZ data value is
C:\PST\My Outlook Data File 3.pst REG_SZ of each value
So there are first two header lines before the registry key. The registry values are also indented with 4 spaces. But there are 1 or more tabs instead of spaces between the value name and the value type and there are also 1 or more tabs instead of spaces between value type and data value.
Note: I don't know if REG_SZ is the right registry value type. I don't have this registry key at all in my Windows registry and therefore just added the 3 registry values as string values with the dummy strings.
So the tricky part is how to get the registry value name containing also spaces to get just the name of the *.pst files independent on file name.
This is done by assigning each output line with the exception of first line because of skip=1 to environment variable RegData and get next from this line everything after .pst assigned to environment variable DelData.
If the line contains .pst in any case at all resulting in value of DelData being not equal value of RegData, the subroutine OutputFileName is called for further processing and printing the file name of the *.pst file.
In the subroutine OutputFileName first the string right of *.pst file name is removed from RegData using a string substitution. Next *.pst file name is output without the 4 indent spaces at beginning.
If the number of indent spaces would not be always exactly 4 spaces, the line echo !RegData:~4! could be replaced by following code to work independent on number of indent spaces/tabs.
for /F "tokens=1*" %%I in ("%RegData%") do (
if "%%J" == "" (
echo %%I
) else (
echo %%I %%J
)
)
The usage of REG instead of REGEDIT has the advantage that no elevated privileges of an administrator is necessary for running this batch code.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
call /?
echo /?
for /?
goto /?
reg /?
reg query /?
set /?
setlocal /?
Nothing is output if the registry key does not exist. The error message output to handle STDERR is suppressed here by redirecting it with 2^>nul to device NUL. See the Microsoft article Using command redirection operators for details. The redirection operator > must be escaped here with caret character ^ to be interpreted as literal character on parsing the FOR command line and being interpreted as redirection operator on execution of the REG command line by FOR.

Related

Find the most recently created file in the directories and sub-directories using PowerShell or Windows Batch

I have 30 different folders which I need to iterate thru, within each one there’s a Log folder and inside that, are the text files. I’m after the latest one, which I need to copy to the new location with the preferred name (E.G. 2020-03-28.txt.FolderServerName1, where appended variable FolderServerName1, identifies from which server it came from)
set source="\\ServerName\LogFolders"
set target=" C:\Data\CopiedLogFiles"
FolderServerName1
Log
2020-03-26.txt
2020-03-27.txt
**2020-03-28.txt**
FolderServerName2
Log
2020-03-26.txt
2020-03-27.txt
**2020-03-28.txt**
FolderServerName3
Log
2020-03-26.txt
2020-03-27.txt
**2020-03-28.txt**
https://devblogs.microsoft.com/oldnewthing/20120801-00/?p=6993
The post above is very useful, but I think I need another nested loop within, which I'm struggling with syntactically.
Thank You so much!
This file copying task can be done with:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
for /D %%I in ("\\ServerName\LogFolders\*") do (
set "CopyDone="
for /F "delims=" %%J in ('dir "%%I\Log\20??-??-??.txt" /A-D-H /B /O-N 2^>nul') do if not defined CopyDone (
copy /Y "%%I\Log\%%J" "C:\Data\CopiedLogFiles\%%~nJ_%%~nxI%%~xJ" >nul
set "CopyDone=1"
)
)
endlocal
For each non-hidden subdirectory in \\ServerName\LogFolders the outer FOR loop first deletes the environment variable CopyDone and runs one more FOR loop.
The inner FOR loop starts in background one more command process using %ComSpec% /c and the command line enclosed in ' as additional commands. So executed with Windows installed into C:\Windows is in background for example:
C:\Windows\System32\cmd.exe /c dir "\\ServerName\LogFolders\FolderServerName1\Log\20??-??-??.txt" /A-D /B /O-N 2>nul
The command DIR searches in specified directory
only for non-hidden files because of option /A-D-H (attribute not directory and not hidden)
with a file name matching the wildcard pattern 20??-??-??.txt
and outputs in bare format because of option /B just each file name with extension without path
ordered reverse by name because of option /O-N
to handle STDOUT (standard output) of the background command process.
The reverse output sorted alphabetically by name results for the log file names that 2020-03-28.txt is output on first line, 2020-03-27.txt on second line and 2020-03-26.txt on third line.
It could be that the subdirectory Log does not exist at all or does not contain any file matching the wildcard pattern. In this case command DIR outputs an error message to handle STDERR (standard error) which is suppressed by redirecting it to device NUL with 2>nul.
Read the Microsoft article about Using command redirection operators for an explanation of 2>nul. The redirection operator > must be escaped with caret character ^ on FOR command line to be interpreted as literal character when Windows command interpreter processes this command line before executing command FOR which executes the embedded dir command line with using a separate command process started in background.
The command process processing the batch file captures everything written to handle STDOUT of background command process and FOR processes this captured output line by line after started cmd.exe terminated itself.
FOR ignores empty lines which do not occur here.
FOR would split up by default each line into substrings using normal space and horizontal tab character as string delimiters, would next look if first substring starts with default end of line character ; in which case the line would be also ignored and otherwise would assign just first space/tab delimited string to specified loop variable. It would be possible here to use this default line processing behavior as the file names do not contain a space character. But it is nevertheless better to disable line splitting behavior by using delims= to define an empty list of string delimiters.
So the inner FOR assigns on first loop iteration the file name of newest file according to international formatted date in file name to loop variable J and runs the command IF.
On first loop iteration of the inner FOR loop the environment variable CopyDone is always not defined as made sure on the command line above and so the IF condition is true.
For that reason the file is copied which means for first folder FolderServerName1 that the executed COPY command is:
copy /Y "\\ServerName\LogFolders\FolderServerName1\Log\2020-03-28.txt" "C:\Data\CopiedLogFiles\2020-03-28_FolderServerName1.txt" >nul
The target file name is modified from requested 2020-03-28.txt.FolderServerName1 to 2020-03-28_FolderServerName1.txt. It is in general better to use a dot in the name of a file just once as separator between file name and file extension and keep the file extension at end of the name of the file to be able to open the file with a double click.
The environment variable CopyDone is defined with a value after the file copying is done without verification on success. The string value assigned to environment variable CopyDone does not matter in this case.
The inner FOR continues processing the captured lines by assigning one file name after the other to loop variable J and running the IF condition. But this condition is not true for any other file name than the first file name.
For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.
copy /?
dir /?
echo /?
endlocal /?
for /?
if /?
set /?
setlocal /?

How can I return multiple values from a powershell script to the batch file that is calling it?

How can I return multiple values from a powershell script to the batch file that is calling it?
I have a powershell script that returns multiple values. I want to call it from a batch file and have each individual value go into an individual variable in the batch file.
Only been able to return one value
The powershell code (pstest.ps1):
$p1=11
$p2=22
$p3=33
exit
The batch file:
powershell .\pstest.ps1
:: now I'd like to get those 3 returned values
:: into 3 individual variables so that I can do something like this:
#echo First is %p1%, Second is %p2%, Third is %p3%
So, it should display this:
First is 11, Second is 22, Third is 33
In the exact same way you get several values from any application: one per line...
#echo off
setlocal EnableDelayedExpansion
set "i=0"
for /F "delims=" %%a in ('powershell "$p1=11; $p2=22; $p3=33; $p1; $p2; $p3"') do (
set /A i+=1
set "p!i!=%%a"
)
echo First is %p1%, Second is %p2%, Third is %p3%
I suggest you to read this answer about arrays...
For a more flexible solution using delayed expansion that doesn't require making the PowerShell script output all values on a single line and works with a variable number of outputs, see Aacini's helpful answer.
Assuming that the number of values is fixed and known in advance:
Make the PowerShell script output a single line containing all the values with a known separator.
In the batch file, use for /f "delims=... tokens=..." to capture the values in discrete loop variables, which you can assign to regular variables.
A simplified example that uses a PowerShell command to produce a single-line output with 3 values separated by | (to apply this to your scenario, use -File with your *.ps1 file instead of -c (-Command) with a command string):
#echo off
for /f "delims=| tokens=1,2,3" %%a in ('powershell -c " '11|22|33' "') do set "p1=%%a" & set "p2=%%b" & set "p3=%%c"
:: echo the values of the newly created variables
echo p1: [%p1%]
echo p2: [%p2%]
echo p3: [%p3%]
The above yields:
p1: [11]
p2: [22]
p3: [33]
Apart from using environment variables, you could try something like this base on SachaDee's answer here:
PS:
function get-multiplereturnvalues {
"11"
"22"
"33"
}
get-multiplereturnvalues
BATCH/CMD
#echo First is %p1%, Second is %p2%, Third is %p3%
for /f "delims=" %%a in ('powershell .\multi.ps1') do #echo "$Value=%%a"
Which outputs:
"$Value=11"
"$Value=22"
"$Value=33"
Within the PowerShell script I‘d create a temp file with the results. Within the batch file, after calling the PowerShell script, I‘d parse that temp file with FOR /F in order to get the results and set environment variables as required.

Use Variable insted of Get-Date in powershell

I am using PowerShell "(Get-Date).AddDays(-7).ToString('ddMMyyyy')" in batch script.
I want to use a variable instead of Get-Date function. Is it possible?
ADate is the variable name!
Edited:
As suggested, my script is:
For /F UseBackQ %%A In (
`PowerShell "(Get-Date).AddDays(-7).ToString('ddMMyyyy')"`
) Do Set "Freq=%%A"
Adate is simple string which comes from the file name, and has a value like 16112016.
You need to use a for loop to get the output of an external command in a batch variable:
#echo off
for /f "usebackq tokens=*" %%d in (`powershell "..."`) do set "adate=%%d"
echo %adate%
The usebackq and backticks are just so you don't need to escape the nested single quotes in your command string.
Ok. I got my crystal ball and asked it: "What is the solution here?", and it replied: "Change
PowerShell "(Get-Date).AddDays(-7).ToString('ddMMyyyy')"
by
PowerShell "(Get-Date -Date '!Adate:~4!-!Adate:~2,2!-!Adate:~0,2!').AddDays(-7).ToString('ddMMyyyy')"
", but I have no idea what it is talking about! ;)
You can store the output of the powerShell command into a file and then read that file after that delete that temporary file.
PowerShell "(Get-Date).AddDays(-7).ToString('ddMMyyyy')" >temp.txt
set /p myVarDate= < date_Shell.txt
echo Date from Shell %myVarDate%
del temp.txt
The following takes the last modified time from a known file's properties and creates a variable with a date seven days earlier, (obviously changing C:\Test\TestFile.ext as necessary):
For /F UseBackQ %%A In (
`PowerShell "((gi 'C:\Test\TestFile.ext').LastWriteTime).AddDays(-7).ToString('ddMMyyyy')"`
) Do Set "ADate=%%A"
Edit
The following example takes a date string with a known format, (in this case provided in two variables). It then converts that string to a date object, subtracts seven days and sets it back to a string in the new %ADate% variable:
#Echo Off
Set "DateStr=16112016"
Set "DFormat=ddMMyyyy"
For /F UseBackQ %%A In (`Powershell^
"([datetime]::ParseExact('%DateStr%','%DFormat%', [System.Globalization.CultureInfo]::CurrentCulture)).AddDays(-7).ToString('%DFormat%')"
`) Do Set "ADate=%%A"
Echo(%ADate%
Timeout -1

Remove Carriage Return from String Field in File Windows Command Line

I have a file that is ouput with | as the delimiter. However, one of the fields is a description field from the source system which contains carriage returns. This is an issue when trying to read the file as it breaks it on to a new line. What I would like to do is remove all CF/LF that aren't preceeded by a |.
I feel like this should be possible on command line but haven't been able to come up with it.
Sample data
|A|Testing CF/LF
This|CF/LF
Expected Output
|A|Testing This|CF/LF
#ECHO Off
SETLOCAL
SET "line="
(
FOR /f "delims=" %%a IN (q26895698.txt) DO (
CALL :generate "%%a"
)
)>newfile.txt
TYPE newfile.txt
GOTO :EOF
:generate
SET "line=%line%%~1"
IF "%line:~-1%"=="|" SET "line="&FOR %%x IN ("%line%") DO ECHO(%%~x
GOTO :eof
I used a file named q26895698.txt containing your data (such as it was) for my testing.
Produces newfile.txt
Can't help but get the impression that you'd be better off with SED thouh - google "GNU SED" for details...

How to launch Windows' RegEdit with certain path?

How do I launch Windows' RegEdit with certain path located, like "HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\8.0", so I don't have to do the clicking?
What's the command line argument to do this? Or is there a place to find the explanation of RegEdit's switches?
Use the following batch file (add to filename.bat):
REG ADD HKCU\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit /v LastKey /t REG_SZ /d Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Veritas\NetBackup\CurrentVersion\Config /f
START regedit
to replace:
Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Veritas\NetBackup\CurrentVersion\Config
with your registry path.
There's a program called RegJump, by Mark Russinovich, that does just what you want. It'll launch regedit and move it to the key you want from the command line.
RegJump uses (or at least used to) use the same regedit window on each invoke, so if you want multiple regedit sessions open, you'll still have to do things the old fashioned way for all but the one RegJump has adopted. A minor caveat, but one to keep note of, anyway.
From http://windowsxp.mvps.org/jumpreg.htm (I have not tried any of these):
When you start Regedit, it automatically opens the last key that was viewed. (Registry Editor in Windows XP saves the last viewed registry key in a separate location). If you wish to jump to a particular registry key directly without navigating the paths manually, you may use any of these methods / tools.
Option 1
Using a VBScript: Copy these lines to a Notepad document as save as registry.vbs
'Launches Registry Editor with the chosen branch open automatically
'Author : Ramesh Srinivasan
'Website: http://windowsxp.mvps.org
Set WshShell = CreateObject("WScript.Shell")
Dim MyKey
MyKey = Inputbox("Type the Registry path")
MyKey = "My Computer\" & MyKey
WshShell.RegWrite "HKCU\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit\Lastkey",MyKey,"REG_SZ"
WshShell.Run "regedit", 1,True
Set WshShell = Nothing
Double-click Registry.vbs and then type the full registry path which you want to open.
Example: HKEY_CLASSES_ROOT\.MP3
Limitation: The above method does not help if Regedit is already open.
Note: For Windows 7, you need to replace the line MyKey = "My Computer\" & MyKey with MyKey = "Computer\" & MyKey (remove the string My). For a German Windows XP the string "My Computer\" must be replaced by "Arbeitsplatz\".
Option 2
Regjump from Sysinternals.com
This little command-line applet takes a registry path and makes Regedit open to that path. It accepts root keys in standard (e.g. HKEY_LOCAL_MACHINE) and abbreviated form (e.g. HKLM).
Usage: regjump [path]
Example: C:\Regjump HKEY_CLASSES_ROOT\.mp3
Option 3
12Ghosts JumpReg from 12ghosts.com
Jump to registry keys from a tray icon! This is a surprisingly useful tool. You can manage and directly jump to frequently accessed registry keys. Unlimited list size, jump to keys and values, get current key with one click, jump to key in clipboard, jump to same in key in HKCU or HKLM. Manage and sort keys with comments in an easy-to-use tray icon menu. Create shortcuts for registry keys.
I'd also like to note that you can view and edit the registry from within PowerShell. Launch it, and use set-location to open the registry location of your choice. The short name of an HKEY is used like a drive letter in the file system (so to go to HKEY_LOCAL_MACHINE\Software, you'd say: set-location hklm:\Software).
More details about managing the registry in PowerShell can be found by typing get-help Registry at the PowerShell command prompt.
Here is one more batch file solution with several enhancements in comparison to the other batch solutions posted here.
It sets also string value LastKey updated by Regedit itself on every exit to show after start the same key as on last exit.
#echo off
setlocal EnableExtensions DisableDelayedExpansion
set "RootName=Computer"
set "RegKey=%~1"
if defined RegKey goto PrepareKey
echo/
echo Please enter the path of the registry key to open.
echo/
set "RegKey="
set /P "RegKey=Key path: "
rem Exit batch file without starting Regedit if nothing entered by user.
if not defined RegKey goto EndBatch
:PrepareKey
rem Remove double quotes and square brackets from entered key path.
set "RegKey=%RegKey:"=%"
if not defined RegKey goto EndBatch
set "RegKey=%RegKey:[=%"
if not defined RegKey goto EndBatch
set "RegKey=%RegKey:]=%"
if not defined RegKey goto EndBatch
rem Replace hive name abbreviation by appropriate long name.
set "Abbreviation=%RegKey:~0,4%"
if /I "%Abbreviation%" == "HKCC" set "RegKey=HKEY_CURRENT_CONFIG%RegKey:~4%" & goto GetRootName
if /I "%Abbreviation%" == "HKCR" set "RegKey=HKEY_CLASSES_ROOT%RegKey:~4%" & goto GetRootName
if /I "%Abbreviation%" == "HKCU" set "RegKey=HKEY_CURRENT_USER%RegKey:~4%" & goto GetRootName
if /I "%Abbreviation%" == "HKLM" set "RegKey=HKEY_LOCAL_MACHINE%RegKey:~4%" & goto GetRootName
if /I "%RegKey:~0,3%" == "HKU" set "RegKey=HKEY_USERS%RegKey:~3%"
:GetRootName
rem Try to determine automatically name of registry root.
if not exist %SystemRoot%\Sysnative\reg.exe (set "RegEXE=%SystemRoot%\System32\reg.exe") else set "RegEXE=%SystemRoot%\Sysnative\reg.exe"
for /F "skip=2 tokens=1,2*" %%K in ('%RegEXE% QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit" /v "LastKey"') do if /I "%%K" == "LastKey" for /F "delims=\" %%N in ("%%M") do set "RootName=%%N"
rem Is Regedit already running?
%SystemRoot%\System32\tasklist.exe /NH /FI "IMAGENAME eq regedit.exe" | %SystemRoot%\System32\findstr.exe /B /I /L regedit.exe >nul || goto SetRegPath
echo/
echo Regedit is already running. Path can be set only when Regedit is not running.
echo/
set "UserChoice=N"
set /P "UserChoice=Terminate Regedit (y/N): "
if /I "%UserChoice:"=%" == "y" %SystemRoot%\System32\taskkill.exe /IM regedit.exe >nul 2>nul & goto SetRegPath
echo Switch to running instance of Regedit without setting entered path.
goto StartRegedit
:SetRegPath
rem Add this key as last key to registry for Regedit.
%RegEXE% ADD "HKCU\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit" /v "LastKey" /d "%RootName%\%RegKey%" /f >nul 2>nul
:StartRegedit
if not exist %SystemRoot%\Sysnative\cmd.exe (start %SystemRoot%\regedit.exe) else %SystemRoot%\Sysnative\cmd.exe /D /C start %SystemRoot%\regedit.exe
:EndBatch
endlocal
The enhancements are:
Registry path can be passed also as command line parameter to the batch script.
Registry path can be entered or pasted with or without surrounding double quotes.
Registry path can be entered or pasted or passed as parameter with or without surrounding square brackets.
Registry path can be entered or pasted or passed as parameter also with an abbreviated hive name (HKCC, HKCU, HKCR, HKLM, HKU).
Batch script checks for already running Regedit as registry key is not shown when starting Regedit while Regedit is already running. The batch user is asked if running instance should be terminated to restart it for showing entered registry path. If the batch user chooses not to terminate all instances of Regedit, Regedit is started without setting entered path resulting (usually) in just getting Regedit window to foreground.
The batch file tries to automatically get name of registry root which is on English Windows XP My Computer, on German Windows XP, Arbeitsplatz, and on Windows 7 and newer Windows just Computer. This could fail if the value LastKey of Regedit is missing or empty in registry. Please set the right root name in third line of the batch code for this case.
The batch file runs on 64-bit Windows always Regedit in 64-bit execution environment even on batch file being processed by 32-bit %SystemRoot%\SysWOW64\cmd.exe on 64-bit Windows which is important for registry keys affected by WOW64.
Copy the below text and save it as a batch file and run
#ECHO OFF
SET /P "showkey=Please enter the path of the registry key: "
REG ADD "HKCU\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit" /v "LastKey" /d "%showkey%" /f
start "" regedit
Input the path of the registry key you wish to open when the batch file prompts for it, and press Enter. Regedit opens to the key defined in that value.
I thought this C# solution might help:
By making use of an earlier suggestion, we can trick RegEdit into opening the key we want even though we can't pass the key as a parameter.
In this example, a menu option of "Registry Settings" opens RegEdit to the node for the program that called it.
Program's form:
private void registrySettingsToolStripMenuItem_Click(object sender, EventArgs e)
{
string path = string.Format(#"Computer\HKEY_CURRENT_USER\Software\{0}\{1}\",
Application.CompanyName, Application.ProductName);
MyCommonFunctions.Registry.OpenToKey(path);
}
MyCommonFunctions.Registry
/// <summary>Opens RegEdit to the provided key
/// <para><example>#"Computer\HKEY_CURRENT_USER\Software\MyCompanyName\MyProgramName\"</example></para>
/// </summary>
/// <param name="FullKeyPath"></param>
public static void OpenToKey(string FullKeyPath)
{
RegistryKey rKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(#"SOFTWARE\Microsoft\Windows\CurrentVersion\Applets\Regedit", true);
rKey.SetValue("LastKey",FullKeyPath);
Process.Start("regedit.exe");
}
Of course, you could put it all in one method of the form, but I like reusablity.
Here is a simple PowerShell function based off of this answer above https://stackoverflow.com/a/12516008/1179573
function jumpReg ($registryPath)
{
New-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit" `
-Name "LastKey" `
-Value $registryPath `
-PropertyType String `
-Force
regedit
}
jumpReg ("Computer\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run") | Out-Null
The answer above doesn't actually explain very well what it does. When you close RegEdit, it saves your last known position in HKCU:\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit, so this merely replaces the last known position with where you want to jump, then opens it.
Create a BAT file using clipboard.exe and regjump.exe
to jump to the key in the clipboard:
clipboard.exe > "%~dp0clipdata.txt"
set /p clipdata=input < "%~dp0clipdata.txt"
regjump.exe %clipdata%
( %~dp0 means "the path to the BAT file" )
Building on lionkingrafiki's answer, here's a more robust solution that will accept a reg key path as an argument and will automatically translate HKLM to HKEY_LOCAL_MACHINE or similar as needed. If no argument, the script checks the clipboard using the htmlfile COM object invoked by a JScript hybrid chimera. The copied data will be split and tokenized, so it doesn't matter if it's not trimmed or even among an entire paragraph of copied dirt. And finally, the key's existence is verified before LastKey is modified. Key paths containing spaces must be within double quotes.
#if (#CodeSection == #Batch) #then
:: regjump.bat
#echo off & setlocal & goto main
:usage
echo Usage:
echo * %~nx0 regkey
echo * %~nx0 with no args will search the clipboard for a reg key
goto :EOF
:main
rem // ensure variables are unset
for %%I in (hive query regpath) do set "%%I="
rem // if argument, try navigating to argument. Else find key in clipboard.
if not "%~1"=="" (set "query=%~1") else (
for /f "delims=" %%I in ('cscript /nologo /e:JScript "%~f0"') do (
set "query=%%~I"
)
)
if not defined query (
echo No registry key was found in the clipboard.
goto usage
)
rem // convert HKLM to HKEY_LOCAL_MACHINE, etc. while checking key exists
for /f "delims=\" %%I in ('reg query "%query%" 2^>NUL') do (
set "hive=%%~I" & goto next
)
:next
if not defined hive (
echo %query% not found in the registry
goto usage
)
rem // normalize query, expanding HKLM, HKCU, etc.
for /f "tokens=1* delims=\" %%I in ("%query%") do set "regpath=%hive%\%%~J"
if "%regpath:~-1%"=="\" set "regpath=%regpath:~0,-1%"
rem // https://stackoverflow.com/a/22697203/1683264
>NUL 2>NUL (
REG ADD "HKCU\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit"^
/v "LastKey" /d "%regpath%" /f
)
echo %regpath%
start "" regedit
goto :EOF
#end // begin JScript hybrid chimera
// https://stackoverflow.com/a/15747067/1683264
var clip = WSH.CreateObject('htmlfile').parentWindow.clipboardData.getData('text');
clip.replace(/"[^"]+"|\S+/g, function($0) {
if (/^\"?(HK[CLU]|HKEY_)/i.test($0)) {
WSH.Echo($0);
WSH.Quit(0);
}
});
This seems horribly out of date, but Registration Info Editor (REGEDIT) Command-Line Switches claims that it doesn't support this.
You can make it appear like regedit does this behaviour by creating a batch file (from the submissions already given) but call it regedit.bat and put it in the C:\WINDOWS\system32 folder. (you may want it to skip editting the lastkey in the registry if no command line args are given, so "regedit" on its own works as regedit always did) Then "regedit HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\8.0" will do what you want.
This uses the fact that the order in PATH is usually C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem; etc
If the main goal is just to avoid "the clicking", then in Windows 10 you can just type or paste the destination path into RegEdit's address bar and hit enter.
The Computer\ prefix here is added automatically. It will also work if you simply type or paste a path starting with e.g. HKEY_CURRENT_USER\....
PowerShell code:
# key you want to open
$regKey = "Computer\HKEY_LOCAL_MACHINE\Software\Microsoft\IntuneManagementExtension\Policies\"
# set starting location for regedit
Set-ItemProperty "HKCU:\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit" "LastKey" $regKey
# open regedit (-m allows multiple regedit windows)
regedit.exe -m
This is the best answer overall, as it's quick, simple and there's no need to install any program.
By Byron Persino, improved by Matt Miller. (Many thanks to both of them!)
I'm rewording more correctly and clearly to help other readers like me, as I had a lot of trouble getting it clear and make it working.
Make a .bat file, eg. 'GoToRegEditPath.bat' , write the following code inside and save it:
CODE:
#echo off
set /p regPath="Open regedit at path: "
REG ADD HKCU\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit /v LastKey /t REG_SZ /d "%regPath%" /f
START regedit
exit
:: source:
https://stackoverflow.com/questions/137182/how-to-launch-windows-regedit-with-certain-path?answertab=modifieddesc#tab-top
Maybe this .bat use must "Run as Administrator"
To use it, Just run it and paste (R-Click) in it the copied RegEdit Path.
Tip: if R-click does not work inside command prompt:
R-click on title bar > Properties > check both under "Edit Options"