Executing GOTO/CALL in a cmd.exe < NotBatch.txt file!

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Executing GOTO/CALL in a cmd.exe < NotBatch.txt file!

#16 Post by penpen » 27 Oct 2015 15:04

Without warranty (i haven'tchecked it, so it still may contain errors) this may be the fixed Versions:
- upper

Code: Select all

cmd /D /E:ON /V:ON /C "@echo on&pushd "C:\Windows\Temp"&SET "KEY_NAME=HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"&SET VALUE_NAME="Userinit"&(FOR /F \"USEBACKQ SKIP=2 TOKENS=1-4\" %A IN (`REG QUERY "!KEY_NAME!" /v "!VALUE_NAME" 2^>NUL`) DO (SET "VALUE_NAME=%A"&SET "VALUE_TYPE=%B"&SET "CURREGVALUE=%C %D"))&(IF DEFINED VALUE_NAME (>Userinitreg.txt ECHO !CURREGVALUE!&PAUSE >NUL&(IF "!errorlevel!" NEQ "0" (ECHO Copy reg record failed.&PAUSE >NUL))) ELSE (ECHO "!KEY_NAME!\!VALUE_NAME%! not found.&PAUSE >NUL))&POPD&PAUSE >NUL"
- lower

Code: Select all

cmd /D /E:ON /V:ON /C "@echo on&pushd "C:\Windows\Temp"&SET "KEY_NAME=HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"&SET "VALUE_NAME=Userinit"&(FOR /F "USEBACKQ SKIP=2 TOKENS=1-4" %A IN (`CALL REG QUERY "!KEY_NAME!" /v "!VALUE_NAME!" 2^>NUL`) DO (SET "VALUE_NAME=%A"&SET "VALUE_TYPE=%B"&SET "CURREGVALUE=%C %D"))&ECHO HELLO&PAUSE >NUL"

With this, you should reread Aacinis posts.

Maybe it helps you to create oneliners this way:
1) Create a batch file (for example: "test.bat") that solves your task (to ensure that the logic is OK)
2) Copy this batch file to "test.txt".
3) Remove all that doesn't work in command line context (see first post); check the functionality of this command line script within a dos command shell:

Code: Select all

Microsoft Windows [Version 6.3.9600]
(c) 2013 Microsoft Corporation. Alle Rechte vorbehalten.

Z:\><test.txt cmd
4) Enclose the "if" and "for" in parenthesis:

Code: Select all

(IF "a" == "a" (echo ok)else(echo not ok))

5) Add ampersands between Statements and create a single line; note that if you want to use extensions or delayed Expansion you have to execute this oneliner within one cmd Statement (as a Parameter; see above, see cmd /?):

Code: Select all

cmd /E:ON /V:ON /C "oneliner"
6)escape characters to create the system command.


penpen

lmstearn
Posts: 50
Joined: 07 Dec 2014 15:15
Location: Australia
Contact:

Re: Executing GOTO/CALL in a cmd.exe < NotBatch.txt file!

#17 Post by lmstearn » 29 Oct 2015 06:03

Edit: Ah thanks PenPen, I missed your post. Yes, done very much along the lines of what you suggested. The REG QUERY didn't like the quotes or the bangs. Plus a spits the dummy at a lot of other options. including the /z verbose. But the observation on the nested IFs still stands: Nested IFs require the outer IF to have an ELSE block otherwise nada_workies.
But a another issue has arisen. :P

Have the very unusual behaviour of the component path strings ending with backslashes along with the the trailing comma omitted in the capture of the reg string:

Code: Select all

system ("cd\\ & PUSHD %SystemRoot%\\Temp & CALL SET KEY_NAME=\"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" & CALL SET VALUE_NAME=\"Userinit\" & (FOR /F \"USEBACKQ SKIP=1 TOKENS=1-4\" %A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME% 2^>NUL`) DO (CALL SET VALUE_NAME=\"%A\" & CALL SET VALUE_TYPE=\"%B\" & CALL SET CURREGVALUE=\"%C\")) & (IF DEFINED VALUE_NAME (>Userinitreg.txt CALL ECHO %CURREGVALUE% & PAUSE >NUL & (IF '%errorlevel%' NEQ '0' (CALL ECHO Copy reg record failed. & PAUSE >NUL))) ELSE (ECHO Registry Error!? & PAUSE >NUL)) & POPD & PAUSE >NUL");

The string in question is:

Code: Select all

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon

The value is Userinit and the sz is C:\Windows\system32\userinit.exe,. The captured string in Userinitreg.txt is "userinit.exe". The double quotes also included. Presumably the registry structure handled by req query is typical for all systems post Vista?
What's required in the reg query to ensure the contents of Userinitreg.txt replicates the actual reg value string?
:shock: Edit: Oh my, the 64 bit subsys redirects all REG QUERY (Gideons comment looks scary- we do not touch Wow6432Node?) to
"HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\
The value is just Userinit.exe as is expected. However running the code as plain batch we do not get the redirection:

Code: Select all

@echo off & cd\ & pushd C:\Windows\Temp & set KEY_NAME="HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" & SET VALUE_NAME="Userinit"
(FOR /F "usebackq skip=2 tokens=1-4" %%A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME% 2^>nul`) DO set curregValue=%%C %%D)
(IF DEFINED VALUE_NAME (
>Userinitreg.txt echo %curregValue% & pause >nul
(IF '%errorlevel%' NEQ '0' (
@echo Copy reg record failed.
pause >nul
))) ELSE (
@echo "%KEY_NAME:"=%\%VALUE_NAME%" not found.
pause >nul
)) & popd & pause >nul

The string is "C:\Windows\system32\userinit.exe, " as is seen in HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon.
Something in the C compiler settings perhaps? Turns out the host program is run in 64 bit mode.
Interesting that even with REG QUERY %KEY_NAME% /reg:32 in the 64 bit app, the Wow6432Node value is still queried.

lmstearn
Posts: 50
Joined: 07 Dec 2014 15:15
Location: Australia
Contact:

Re: Executing GOTO/CALL in a cmd.exe < NotBatch.txt file!

#18 Post by lmstearn » 01 Nov 2015 22:28

Guess it's reasonable to let you guys know what I want to do. The aim is to create a directory of more than 260 chars. The hunch is that explorer interferes with this, so the attempt is to run the program at logon. Cancelling explore isn't an option. The aim is to backup whatever was in the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon key to a text file in Windows\Temp. Modify this key to insert CreateLargeDir.exe before userinit.exe and run the copy from Windows\Temp, then cleanup. Can load up a copy at Github, but there's not too much at this stage.
The problem now is the percentages used in this code. The compiler jumps to the else block, and I'm trying to figure out why:

Code: Select all

system ("@ECHO On & SET \"OSB=64BIT\" & SET \"CURREGVALUE=userinit.exe\" & (IF %OSB%==\"64BIT\" (CALL SET \"OSB=64BIT\" & PAUSE>NUL & (CALL SET \"TMPSTR=%SystemRoot%\\Temp\\CreateLargeDir.exe, userinit.exe\") & (CALL SET \"NEWREGVALUE=%CURREGVALUE:userinit.exe=%%TMPSTR%%%\")) ELSE (CALL SET TMPSTR=%SystemRoot%\\Temp\\CreateLargeDir.exe, %SystemRoot%\\system32\\userinit.exe & CALL SET \"NEWREGVALUE=%CURREGVALUE:%SystemRoot%\\system32\\userinit.exe=%%TMPSTR%%%\")) & CALL ECHO %OSB% %CURREGVALUE% %TMPSTR% & POPD & PAUSE >NUL");

There's more to go in there, but the parsing isn't working as expected: the percentages look like they are the problem. Thoughts?
Edit: Is there any way (or point) to toggling delayed expansion with V:ON?
Last edited by lmstearn on 13 Nov 2015 06:35, edited 1 time in total.

Aacini
Expert
Posts: 1913
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Executing GOTO/CALL in a cmd.exe < NotBatch.txt file!

#19 Post by Aacini » 02 Nov 2015 00:58

I suggest you to solve this problem via the steps recommended by penpen above:

  1. Write a Batch file that solve your problem that does not use delayed expansion. It should be clear that have no sense to try to pass to next steps if you don't complete this one first!
  2. Convert the Batch file to a "NotBatch.txt" one so it run correctly accordingly to the modifications described in this thread.
  3. Eliminate separate lines and insert "&" signs at the proper places until produce a single long line that works in the same way than previous text file.
  4. Finally, just insert this line in your C code.

You should realize that any recommendation we could do if you not follow this procedure is just a wasted time, because nor you nor we could anticipate what would be the effect of any change in the code if we don't know how the original code behaves! :? We must start from a base we know if you want to solve this problem, and such base is a Batch file.

Antonio

lmstearn
Posts: 50
Joined: 07 Dec 2014 15:15
Location: Australia
Contact:

Re: Executing GOTO/CALL in a cmd.exe < NotBatch.txt file!

#20 Post by lmstearn » 02 Nov 2015 05:39

Heh, I think it has stalled at step /1, but thanks. :)
The block of code I posted above has a few errors, but any any rate not capable of writing such one line code without delayed expansion. The following is the closest "native" batch, but will update on any developments:

Code: Select all

@ECHO On & SETLOCAL ENABLEDELAYEDEXPANSION & SET "OSB=64BIT" & SET "CURREGVALUE=userinit.exe" & (IF !OSB!==64BIT (CALL SET "TMPSTR=%SystemRoot%\Temp\CreateLargeDir.exe, userinit.exe" & CALL SET "NEWREGVALUE=!CURREGVALUE:userinit.exe=!!TMPSTR!!!" & ECHO !OSB!) ELSE (CALL SET "TMPSTR=%SystemRoot%\Temp\CreateLargeDir.exe, %SystemRoot%\system32\userinit.exe" & CALL SET "NEWREGVALUE=!CURREGVALUE:%SystemRoot%\system32\userinit.exe=!!TMPSTR!!!")) & ECHO !OSB! !CURREGVALUE! !NEWREGVALUE! & POPD & PAUSE >NUL EXIT /b

The following is a carbon copy of above except the ! are swapped for % and delayed expansion is removed. It doesn't execute:

Code: Select all

@ECHO On & SET "OSB=64BIT" & SET "CURREGVALUE=userinit.exe" & (IF %OSB%==64BIT (CALL SET "TMPSTR=%SystemRoot%\Temp\CreateLargeDir.exe, userinit.exe" & CALL SET "NEWREGVALUE=%CURREGVALUE:userinit.exe=%%TMPSTR%%%" & ECHO %OSB%) ELSE (CALL SET "TMPSTR=%SystemRoot%\Temp\CreateLargeDir.exe, %SystemRoot%\system32\userinit.exe" & CALL SET "NEWREGVALUE=%CURREGVALUE:%SystemRoot%\system32\userinit.exe=%%TMPSTR%%%")) & ECHO %OSB% %CURREGVALUE% %NEWREGVALUE% & POPD & PAUSE >NUL EXIT /b

Here's a more readable version:

Code: Select all

@ECHO OFF & SET "OSB=64BIT" & SET "CURREGVALUE=userinit.exe" 
IF %OSB%==64BIT (
CALL SET "TMPSTR=%SystemRoot%\Temp\CreateLargeDir.exe, userinit.exe" & CALL SET "NEWREGVALUE=%CURREGVALUE:userinit.exe=%%TMPSTR%%%"
) ELSE (
CALL SET "TMPSTR=%SystemRoot%\Temp\CreateLargeDir.exe, userinit.exe" & CALL SET "NEWREGVALUE=%CURREGVALUE:userinit.exe=%%TMPSTR%%%"
)
ECHO %OSB% %CURREGVALUE% %NEWREGVALUE% & POPD & PAUSE >NUL EXIT /b

Without delayed expansion, NEWREGVALUE is inaccessible. Maybe a C program that can do a memcopy of the address pointee, but then are we chasing our tails?
Edit: After a cup of tea came the epiphany. Just declare all variables globally!

Aacini
Expert
Posts: 1913
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Executing GOTO/CALL in a cmd.exe < NotBatch.txt file!

#21 Post by Aacini » 02 Nov 2015 08:24

This is your original Delayed Expansion working code with a couple small changes you easily identify; I also removed the POPD command:

Code: Select all

@ECHO OFF & SETLOCAL ENABLEDELAYEDEXPANSION & SET "OSB=64BIT" & SET "CURREGVALUE=userinit.exe"

(IF !OSB!==64BIT (
   SET "TMPSTR=%SystemRoot%\Temp\CreateLargeDir.exe, userinit.exe" & CALL SET "NEWREGVALUE=!CURREGVALUE:userinit.exe=!!TMPSTR!!!" & ECHO !OSB!
) ELSE (
   SET "TMPSTR=%SystemRoot%\Temp\CreateLargeDir.exe, %SystemRoot%\system32\userinit.exe" & CALL SET "NEWREGVALUE=!CURREGVALUE:%SystemRoot%\system32\userinit.exe=!!TMPSTR!!!"
))

ECHO !OSB! !CURREGVALUE! !NEWREGVALUE! & PAUSE >NUL & EXIT /b

It works!

Code: Select all

C:\Users\Antonio\Documents\ASMB
> test.bat
64BIT
64BIT userinit.exe C:\WINDOWS\Temp\CreateLargeDir.exe, userinit.exe

Note that if "SET OSB=32BIT" the output is incorrect because the value of CURREGVALUE does not include "%SystemRoot%\system32\userinit.exe" string (but this is a bug unrelated to this problem).

This is the same code without Delayed Expansion; it produce the same output when "SET OSB=64BIT":

Code: Select all

@ECHO OFF & SET "OSB=64BIT" & SET "CURREGVALUE=userinit.exe"

(IF %OSB%==64BIT (
   SET "TMPSTR=%SystemRoot%\Temp\CreateLargeDir.exe, userinit.exe" & CALL CALL SET "NEWREGVALUE=%%%%CURREGVALUE:userinit.exe=%%TMPSTR%%%%%%" & CALL ECHO %%OSB%%
) ELSE (
   SET "TMPSTR=%SystemRoot%\Temp\CreateLargeDir.exe, %SystemRoot%\system32\userinit.exe" & CALL CALL SET "NEWREGVALUE=%%%%CURREGVALUE:%SystemRoot%\system32\userinit.exe=%%TMPSTR%%%%%%"
))

ECHO %OSB% %CURREGVALUE% %NEWREGVALUE% & PAUSE >NUL & EXIT /b

This is the one-liner version of previous code:

Code: Select all

@ECHO OFF & SET "OSB=64BIT" & SET "CURREGVALUE=userinit.exe" & (IF %OSB%==64BIT (SET "TMPSTR=%SystemRoot%\Temp\CreateLargeDir.exe, userinit.exe" & CALL CALL SET "NEWREGVALUE=%%%%CURREGVALUE:userinit.exe=%%TMPSTR%%%%%%" & CALL ECHO %%OSB%%) ELSE (SET "TMPSTR=%SystemRoot%\Temp\CreateLargeDir.exe, %SystemRoot%\system32\userinit.exe" & CALL CALL SET "NEWREGVALUE=%%%%CURREGVALUE:%SystemRoot%\system32\userinit.exe=%%TMPSTR%%%%%%")) & ECHO %OSB% %CURREGVALUE% %NEWREGVALUE% & PAUSE >NUL & EXIT /b

This version is the same NotBatch.txt code that will run when redirected into cmd.exe, with just one minor adjustment. And it works!

Code: Select all

C:\Users\Antonio\Documents\ASMB
> cmd.exe < NotBatch.txt
Microsoft Windows [Versión 6.3.9600]
(c) 2013 Microsoft Corporation. Todos los derechos reservados.

C:\Users\Antonio\Documents\ASMB
>@ECHO OFF & SET "OSB=64BIT" & SET "CURREGVALUE=userinit.exe" & (IF %OSB%==64BIT
 (SET "TMPSTR=%SystemRoot%\Temp\CreateLargeDir.exe, userinit.exe" & CALL CALL SE
T "NEWREGVALUE=%%%%CURREGVALUE:userinit.exe=%%TMPSTR%%%%%%" & ECHO %OSB%) ELSE (
SET "TMPSTR=%SystemRoot%\Temp\CreateLargeDir.exe, %SystemRoot%\system32\userinit
.exe" & CALL CALL SET "NEWREGVALUE=%%%%CURREGVALUE:%SystemRoot%\system32\userini
t.exe=%%TMPSTR%%%%%%")) & ECHO %OSB% %CURREGVALUE% %NEWREGVALUE% & PAUSE >NUL &
EXIT /b
64BIT
64BIT userinit.exe C:\WINDOWS\Temp\CreateLargeDir.exe, userinit.exe

Antonio

lmstearn
Posts: 50
Joined: 07 Dec 2014 15:15
Location: Australia
Contact:

Re: Executing GOTO/CALL in a cmd.exe < NotBatch.txt file!

#22 Post by lmstearn » 02 Nov 2015 22:16

Thanks Antonio, that's great! Never picked up on the use of nested CALL or the use of the %. Interesting to note that neither the inclusion of brackets enclosing the entire if/else block nor the inclusion of %SystemRoot% in TMPSTRING has any apparent effect on their application here.
Having fun with this in VS10 :roll: :

Code: Select all

system ("@ECHO OFF & SET \"OSB=64BIT\" & SET \"CURREGVALUE=userinit.exe\" & (IF %OSB%==64BIT (SET \"TMPSTR=%SystemRoot%\\Temp\\CreateLargeDir.exe, userinit.exe\" & CALL SET \"NEWREGVALUE=%%%%CURREGVALUE:userinit.exe=%%TMPSTR%%%%%%\" & CALL ECHO %OSB%) ELSE (ECHO NADA)) & CALL ECHO %OSB% %CURREGVALUE% %NEWREGVALUE% & PAUSE >NUL");

The pasted (and escaped) code above doesn't echo any values, only variable names. However the last echo with a CALL inserted does produce the first two variable contents. The bigger problem is that "IF %OSB%==64BIT" never evaluates to true so it always jumps to NADA.
Edit: Would you believe the following executes correctly:

Code: Select all

system ("@ECHO OFF & REG QUERY \"HKLM\\Hardware\\Description\\System\\CentralProcessor\\0\" | FIND /i \"x86\" >NUL && CALL SET \"OSB=\" || CALL SET \"OSB=64BIT\") & SET \"CURREGVALUE=userinit.exe\" & (IF DEFINED OSB (SET \"TMPSTR=%SystemRoot%\\Temp\\CreateLargeDir.exe, userinit.exe\" & CALL SET \"NEWREGVALUE=%CURREGVALUE:userinit.exe=%%TMPSTR%\") ELSE (ECHO NADA)) & CALL ECHO %OSB% %CURREGVALUE% %NEWREGVALUE% & PAUSE >NUL");

lmstearn
Posts: 50
Joined: 07 Dec 2014 15:15
Location: Australia
Contact:

Re: Executing GOTO/CALL in a cmd.exe < NotBatch.txt file!

#23 Post by lmstearn » 05 Nov 2015 09:07

There's a problem with with REG ADD that's cropped up:

Code: Select all

SET KEY_NAME="HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
SET "VALUE_NAME=Userinit"
SET "NEWREGVALUE=C:\Windows\System32\userinit.exe,"
ECHO %KEY_NAME% %VALUE_NAME% %CURREGVALUE% %NEWREGVALUE%
REG ADD %KEY_NAME% /v %VALUE_NAME% /d %NEWREGVALUE% /f
POPD & PAUSE >NUL & Exit /b

works well. In VS the following gives an invalid key name error:

Code: Select all

REG ADD %KEY_NAME% /v %VALUE_NAME% /d %NEWREGVALUE% /f

However if "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon" is used instead of the variable KEY_NAME, it will create a new value as %VALUE_NAME% with sz %NEWREGVALUE%. Tried any combo of percentages, and even "CALL" REG which plainly doesn't work.
Not reproduced with REG QUERY when the following worked:

Code: Select all

FOR /F \"USEBACKQ SKIP=2 TOKENS=1-4 DELIMS= \" %A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME% /reg:32 2^>Userinitregerror.txt`) DO CALL SET \"CURREGVALUE=%C%D\"

Out of ideas, unless VS2015 offers any better. :(
Last edited by lmstearn on 13 Nov 2015 06:36, edited 1 time in total.

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Executing GOTO/CALL in a cmd.exe < NotBatch.txt file!

#24 Post by penpen » 05 Nov 2015 13:17

lmstearn wrote:In VS the following gives an invalid key name error:

Code: Select all

REG ADD %KEY_NAME% /v %VALUE_NAME% /d %NEWREGVALUE% /f
It would be interesting to know the variableassignment of "KEY_NAME", "VALUE_NAME" and "NEWREGVALUE".
Your echo command above the reg line prints all to screen, so this information is needed.
In addition you could post the c source code.
(If i had to guess, i would think, you haven't escaped the backslash characters, or you might want to use delayedExpansion or "call".)


penpen

lmstearn
Posts: 50
Joined: 07 Dec 2014 15:15
Location: Australia
Contact:

Re: Executing GOTO/CALL in a cmd.exe < NotBatch.txt file!

#25 Post by lmstearn » 05 Nov 2015 22:14

Here's the entire block to date:

Code: Select all

system ("CD\\ & PUSHD %SystemRoot%\\Temp & 
SET KEY_NAME=\"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" & SET \"VALUE_NAME=Userinit\" & (FOR /F \"USEBACKQ SKIP=2 TOKENS=1-4 DELIMS= \" %A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME% /reg:32 2^>Userinitregerror.txt`) DO SET \"CURREGVALUE=%C %D\") &
(>NUL FINDSTR \"^\" \"Userinitregerror.txt\" && SET \"OSB=\" || SET \"OSB=1\" &
 (IF DEFINED OSB (>Userinitreg.txt CALL ECHO %CURREGVALUE% & (IF '%errorlevel%' NEQ '0' (CALL ECHO Copy reg record failed! & PAUSE >NUL))) ELSE (ECHO No reg key! & PAUSE NUL)) &
REG QUERY \"HKLM\\Hardware\\Description\\System\\CentralProcessor\\0\" | FIND /i \"x86\" >NUL && CALL SET \"OSB=\" || CALL SET \"OSB=64BIT\") & (IF DEFINED OSB (SET \"TMPSTR=%SystemRoot%\\Temp\\CreateLargeDir.exe, userinit.exe\" &
 CALL SET \"NEWREGVALUE=%CURREGVALUE:userinit.exe=%%TMPSTR%\")
 ELSE (SET \"TMPSTR=%SystemRoot%\\Temp\\CreateLargeDir.exe, %SystemRoot%\\system32\\userinit.exe\" & CALL SET \"NEWREGVALUE=%CURREGVALUE:%SystemRoot%\\system32\\userinit.exe=%%TMPSTR%\")) &
 (REG ADD %KEY_NAME% /v %VALUE_NAME% /d %NEWREGVALUE% /f) & CALL ECHO %KEY_NAME% %VALUE_NAME% %CURREGVALUE% %NEWREGVALUE%
 & POPD & PAUSE >NUL");

It creates two small files in Windows\Temp.

Not all seems healthy as the processor echoes back the last SET assignment {CURREGVALUE} of the first truncated block:

Code: Select all

system ("CD\\ & PUSHD %SystemRoot%\\Temp & SET KEY_NAME=\"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" & SET \"VALUE_NAME=Userinit\" & (FOR /F \"USEBACKQ SKIP=2 TOKENS=1-4 DELIMS= \" %A IN (`REG QUERY %KEY_NAME% /v %VALUE_NAME% /reg:32 2^>Userinitregerror.txt`) DO SET \"CURREGVALUE=%C %D\")           & POPD & PAUSE >NUL");

All the variables have their correct assignations. The REG ADD wants something a little extra. It's interesting to note that if KEY_NAME is not set to a quoted string, the script will fail. All other variables do not require the double quotes.
Also tried \\\\ as the KEY_NAME separators. On the same theme, looking at this post, he uses REG REG ADD. Comes up with syntax error in VS though. Is it worth taking a ticket with MSFT at this point or just eat crow and expand the variables manually (messy)?

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Executing GOTO/CALL in a cmd.exe < NotBatch.txt file!

#26 Post by penpen » 06 Nov 2015 04:09

lmstearn wrote:Not all seems healthy as the processor echoes back the last SET assignment {CURREGVALUE} of the first truncated block:
Do you mean the processor prints the following line, and then executes it?

Code: Select all

SET \"CURREGVALUE=%C %D\
That is default command line context behavior when executing a "for" loop. Just use an at character ('@') in front of the set command ("@SET ...") to suppress this echo.
This issue should have been created by step 3 (so actually you shouldn't have used any ampersands ('&') in the file "test.txt").

lmstearn wrote:The REG ADD wants something a little extra. It's interesting to note that if KEY_NAME is not set to a quoted string, the script will fail. All other variables do not require the double quotes.
I'm not sure how you mean it:
Any parameter needs to be enclosed in doublequotes if it contains a space character (' '), else it is recognized as two parameters (which in your case breaks the syntax of the reg command).

lmstearn wrote:Also tried \\\\ as the KEY_NAME separators. On the same theme, looking at this post, he uses REG REG ADD.
???
(There are no \\ in this post! Or doesn't does my browser hide it?)

lmstearn wrote:Comes up with syntax error in VS though. Is it worth taking a ticket with MSFT at this point or just eat crow and expand the variables manually (messy)?
At the moment i doubt that the error is caused by anything else than your script, so a ticket wouldn't help.


Im unsure: Is your script ("test.bat" from step 1) is doing what you need?

If not please post the batch file you have so far (under a new topic), to solve all issues (explain the issues and copy-paste all output to codeblocks):
Would be offtopic here.

(I assume step 2, 4, 5 and 6 would produce no issues.)

If the "step 1" script is working, and step 3 causes problems, then post the "test.txt" file and all output (of "<test.txt cmd") to codeblocks (under this topic) and describe what's working wrong.


penpen

lmstearn
Posts: 50
Joined: 07 Dec 2014 15:15
Location: Australia
Contact:

Re: Executing GOTO/CALL in a cmd.exe < NotBatch.txt file!

#27 Post by lmstearn » 06 Nov 2015 05:13

Thanks PenPen -I meant his use of "REG REG ADD" Have you seen this command work?
How do we get all commands echoed in console from "cmd.exe < C:\Users\New\Desktop\NotBatch.txt" to output file?
This is the NotBatch file:

Code: Select all

@ECHO OFF
CD\
PUSHD C:\Users\New\Desktop
SET KEY_NAME="HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
SET "VALUE_NAME=Userinit"
SET "NEWREGVALUE=C:\Windows\System32\userinit.exe,"
REG ADD %KEY_NAME% /v %VALUE_NAME% /d %NEWREGVALUE% /f
ECHO %KEY_NAME% %VALUE_NAME% %NEWREGVALUE% >CON
POPD
PAUSE
Exit /b

This works, but it's worth noting that interchanging the order of POPD and PAUSE gets an error " 'OPD' is not recognized...."
The code for VS system command is as follows:

Code: Select all

system ("@ECHO OFF & CD\\ & PUSHD C:\\Users\\New\\Desktop & SET KEY_NAME=\"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" & SET \"VALUE_NAME=Userinit\" & SET \"NEWREGVALUE=C:\\Windows\\System32\\userinit.exe,\" & REG ADD %KEY_NAME% /v %VALUE_NAME% /d %NEWREGVALUE% /f & CALL ECHO %KEY_NAME% %VALUE_NAME% %NEWREGVALUE% >CON & POPD & PAUSE & Exit /b");

A CALL is inserted before the last ECHO to make it work. Comes up with Invalid_Key_Error with REG ADD as explained above.

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Executing GOTO/CALL in a cmd.exe < NotBatch.txt file!

#28 Post by penpen » 06 Nov 2015 07:08

lmstearn wrote:Thanks PenPen -I meant his use of "REG REG ADD" Have you seen this command work?
I've overseen his typo:
"reg reg add" should never work.

lmstearn wrote:How do we get all commands echoed in console from "cmd.exe < C:\Users\New\Desktop\NotBatch.txt" to output file?
Just redirect the output to a file, for example "output.txt":

Code: Select all

<"C:\Users\New\Desktop\NotBatch.txt" >"output.txt" cmd.exe 


lmstearn wrote:This works, but it's worth noting that interchanging the order of POPD and PAUSE gets an error " 'OPD' is ot recognized...."
You haver redirected the input via "< C:\Users\New\Desktop\NotBatch.txt", so the file contains the input; it is the next character in the file after the pause line ("pause\r\n") so the 'P' character is cunsumed by the pause copmmand. Then the program continues, and the next input read from file is "OPD" which is no command.
=> Error (message).

If you want a pause, that is working, you have to redirect both STDIN and STDOUT of the pause command to the console:
- STDIN ("<con") to wait for input typed to the console, and
- STDOUT (">con") to be able to see the text message.
(The redirection is not needed in the final oneliner.)

lmstearn wrote:

Code: Select all

(...) & REG ADD %KEY_NAME% /v %VALUE_NAME% /d %NEWREGVALUE% /f & (...)

(...) Comes up with Invalid_Key_Error with REG ADD as explained before.
You should know why, because you were able to solve this issue for the following echo command:
lmstearn wrote:

Code: Select all

(...) & CALL ECHO %KEY_NAME% %VALUE_NAME% %NEWREGVALUE% >CON & (...)

A CALL is inserted before the last ECHO to make it work.

Or in other words:
The key "%KEY_NAME%" is invalid.
To replace this string with the content of the environment variable, you have to use "call" ("call reg add ..."; or you could use "for/F", delayedExpansion, ... but "call" is the simplest solution here).


penpen

lmstearn
Posts: 50
Joined: 07 Dec 2014 15:15
Location: Australia
Contact:

Re: Executing GOTO/CALL in a cmd.exe < NotBatch.txt file!

#29 Post by lmstearn » 06 Nov 2015 10:22

Great! The mysteries of cmd are still unravelling:
Let's now add two lines of code, similar to Antonio's last post:

Code: Select all

@ECHO OFF
CD\
PUSHD C:\Users\New\Desktop
SET KEY_NAME="HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
SET "VALUE_NAME=Userinit"
CALL SET "CURREGVALUE=%SystemRoot%\System32\userinit.exe,"
(IF %VALUE_NAME%==Userinit (SET "TMPSTR=%SystemRoot%\Temp\CreateLargeDir.exe, %SystemRoot%\system32\userinit.exe" & CALL CALL SET "NEWREGVALUE=%%%%CURREGVALUE:%SystemRoot%\system32\userinit.exe=%%TMPSTR%%%%%%"))
CALL REG ADD %KEY_NAME% /v %VALUE_NAME% /d %NEWREGVALUE% /f
ECHO %KEY_NAME% %VALUE_NAME% %CURREGVALUE% %NEWREGVALUE% >CON
POPD
PAUSE
Exit /b

If this is run as a .bat it works, but for the syntax error in REG ADD. But if it runs as a NotBatch the percentages don't escape.
The proposed replacement code for NotBatch is

Code: Select all

CALL SET "NEWREGVALUE=%CURREGVALUE:%SystemRoot%\system32\userinit.exe=%%TMPSTR%"

This doesn't look right, and the syntax error in REG ADD is a problem as well. Do you think it has anything to do with escaping the percentages in %SystemRoot%?

penpen
Expert
Posts: 2009
Joined: 23 Jun 2013 06:15
Location: Germany

Re: Executing GOTO/CALL in a cmd.exe < NotBatch.txt file!

#30 Post by penpen » 06 Nov 2015 13:27

lmstearn wrote:

Code: Select all

CALL SET "NEWREGVALUE=%CURREGVALUE:%SystemRoot%\system32\userinit.exe=%%TMPSTR%"
I assume you just made a flaw; in detail:
The batch context command line interpreter processes the call commands from left to right.
Because "call" builds a string (escape characters, ...) and then executes it, the call commands are executed from inner to outer.
Two percentages ("%%") computes to one in batch context; so we do this manually:
Aacini wrote:

Code: Select all

CALL CALL SET "NEWREGVALUE=%%%%CURREGVALUE:%SystemRoot%\system32\userinit.exe=%%TMPSTR%%%%%%"
Assumed (%SystemRoot% == "[SystemRoot]", and %TMPSTR% == "[tmpStr]"): =>

Code: Select all

CALL SET "NEWREGVALUE=%%CURREGVALUE:[SystemRoot]\system32\userinit.exe=%TMPSTR%%%"
=>

Code: Select all

SET "NEWREGVALUE=%CURREGVALUE:[SystemRoot]\system32\userinit.exe=[tmpStr]%"
(This command is executed then.)

Now reversed in command line context. If a variable is undefined, the variable expansion is aborted; in that case the left percentage is taken as the start of the next variable:

Code: Select all

Y:\>set "a=" & set "b=Y"

Y:\> echo %a%b%
%aY


So now one could reverse the process in command line context (assumed "CURREGVALUE:" and "" are both undefined):

Code: Select all

SET "NEWREGVALUE=%CURREGVALUE:[SystemRoot]\system32\userinit.exe=[tmpStr]%"
=>

Code: Select all

call SET "NEWREGVALUE=%CURREGVALUE:%SystemRoot%\system32\userinit.exe=%tmpStr%%"
So only one percentage is at the wrong position in your above solution.


For more details about how the command line Interpreter parses lines, see:
http://stackoverflow.com/questions/4094699/how-does-the-windows-command-interpreter-cmd-exe-parse-scripts.
Thanks to jeb and dbenham.


penpen

Post Reply