Windows Batch For-Loop 'input line too long' - windows

My FOR-loops recently created some annoying error messages on both my Windows 10 and 11 computers. I could sware they worked before.
The following three command lines work fine and create the expected results:
powershell.exe -Command Get-ItemPropertyValue -Path 'HKCU:Control Panel\International\' -Name 'LocaleName'
pwsh.exe -Command Get-ItemPropertyValue -Path 'HKCU:Control Panel\International\' -Name 'LocaleName'
reg query "HKCU\Control Panel\International" /v "LocaleName"
But if I enclose them into for-loops for a SetVar-like command as follows, all three create the error message, "the entered line is too long". This happens both with cmd.exe and wt.exe, and both in direct mode and in batch mode (with %%v). Do you have an idea what I am doing wrong here?
for /f "usebackq tokens=* delims=" %v in (`powershell.exe -NoProfile -ExecutionPolicy Bypass -Command Get-ItemPropertyValue -Path 'HKCU:Control Panel\International\' -Name 'LocaleName'`) do set "LOCALE=%v"
for /f "usebackq tokens=* delims=" %v in (`pwsh.exe -NoProfile -ExecutionPolicy Bypass -Command Get-ItemPropertyValue -Path 'HKCU:Control Panel\International\' -Name 'LocaleName'`) do set "LOCALE=%v"
for /f "tokens=3 delims= " %v in ('REG QUERY "HKCU\Control Panel\International" /v "LocaleName"') do set "LOCALE=%v"
Originally, I thought about a PowerShell issue, but then found the same effect with REG QUERY.

No idea what happened - after being back from vacation, everything works as before, though nothing changed in the meantime. I will keep an eye on the issue and add here if something changes again, but for now, I close it.

Related

How To Get The Active User's SID

The scope is running from the user's local computer.
You can use this to get the active user's SID.
Then you could use this with the HKU registry hive.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
ECHO GET THE NAME OF THE ACTIVELY LOGGED ON USER
FOR /F "skip=1" %%G IN ('wmic computersystem get username') DO (
SET aUSER=%%G
GOTO EXITLOOP1
)
:EXITLOOP1
ECHO %aUSER%
ECHO[
REM ECHO TRIM THE USERNAME
SET tUSER=%aUSER:~4%
REM ECHO %tUSER%
ECHO[
ECHO GET SID FOR USER: %tUSER%
FOR /F "usebackq skip=1" %%a IN (`WMIC USERACCOUNT WHERE NAME^='%%tUSER%%' GET SID`) DO (
SET SID=%%a
GOTO EXITLOOP2
)
:EXITLOOP2
ECHO %SID%
BTW, if you wanted to do it without a For loop, you could ask powershell to assist:
%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -Command "(%SystemRoot%\System32\whoami.exe /User /Fo CSV | ConvertFrom-Csv).SID"
Or even without whoami.exe:
%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -Command "Add-Type -AssemblyName System.DirectoryServices.AccountManagement;$([System.DirectoryServices.AccountManagement.UserPrincipal]::Current).SID.Value"
In a cmd.exe console the following command can be used.
powershell -NoLogo -NoProfile -Command ^
"Add-Type -AssemblyName System.DirectoryServices.AccountManagement;" ^
"([System.DirectoryServices.AccountManagement.UserPrincipal]::Current).Sid.AccountDomainSid.Value"
To get the result into a variable, use a FOR loop. (Yeah, I know, it's crazy, right?)
FOR /F "delims=" %%A IN ('powershell -NoLogo -NoProfile -Command ^
"Add-Type -AssemblyName System.DirectoryServices.AccountManagement;" ^
"([System.DirectoryServices.AccountManagement.UserPrincipal]::Current).Sid.AccountDomainSid.Value"') DO (
SET "USER_SID=%%~A"
)
ECHO USER_SID is set to %USER_SID%
There are many other things that can be accessed in this way.
powershell -NoLogo -NoProfile -Command ^
"Add-Type -AssemblyName System.DirectoryServices.AccountManagement;" ^
"[System.DirectoryServices.AccountManagement.UserPrincipal]::Current |" ^
"Format-List * -Force"
As you've raised a question, and in it decided to post some code, I'll offer a quicker and more simple alternative, regardless of whether you decide to post yours as a solution:
From cmd:
For /F Tokens^=3^ Delims^=^" %G In ('%SystemRoot%\System32\whoami.exe /User /Fo CSV /NH') Do #Echo %G
From a batch-file:
#For /F Tokens^=3^ Delims^=^" %%G In ('%SystemRoot%\System32\whoami.exe /User /Fo CSV /NH') Do #Echo %%G

How to get the content of a text file using command FOR on a batch file

I have a text file where the contents have a lot of NUL or spaces between data:
[nul][nul][nul][nul]Name [nul][nul][nul][nul][nul][nul]surname
The data inside of the text file is always different.
I have searched and tested many similar questions using for /F "usebackq delims=" %%a in ("%file%") do echo %%a and similar commands, but i always get empty results.
Please can anyone help?
If you truly have a text file with, for example, the following content:
External image link
And you just want to omit the NUL characters as part of a normal For /F loop file read, then you could ask powershell for help from your batch-file:
#For /F "Delims=" %%G In (
'%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe ^
-Nologo -NoProfile -Command "(Get-Content 'sourcefile.txt')" ^
" -replace '\x00',''"') Do #Echo(%%G
#Pause
I have split that long line up into multiple for easier reading, but you could also have it as a single line batch-file:
#(For /F "Delims=" %%G In ('%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -Nologo -NoProfile -Command "(Get-Content 'sourcefile.txt') -replace '\x00',''"') Do #Echo(%%G) & Pause
And to do it in simple terms directly from the Command Prompt cmd:
For /F "Delims=" %G In ('powershell -NoP "(GC 'sourcefile.txt') -replace '\x00',''"') Do #Echo(%G
[Edit /]
If you wanted to add a single comma, between those two specific words in the exact example you provided, and which I used in my linked image above, then yes, it would be possible.
For example you could do it within the PowerShell part, by changing:
-replace '\x00','' to -replace ' ',', ' -replace '\x00',''
Or, you could do it by changing the For loop option:
"Delims=" to "Tokens=1*"
and then change either:
#Echo(%%G, or #Echo(%G
to:
#Echo(%%G, %%H or #Echo(%G, %H respectively.

how to run cmd like del c:\myapp\*\log\* /s /q

I would like to delete all the files located in folders named \log\ . This folder can be everywhere (at any levels) in sub directories
ideally i want to do something like
del c:\myapp\*\log\* /s /q
how can i do this ?
A single line example from the Command Line, cmd.exe:
For /F "Delims=" %A In ('Dir /B/S/AD "C:\myapp\log" 2^>Nul') Do #Del /A/F/S/Q "%A\*"
If you want it inside a batch file, *.cmd|*.bat:
#For /F "Delims=" %%A In ('Dir /B/S/AD "C:\myapp\log" 2^>Nul') Do #Del /A/F/S/Q "%%A\*"
Here is a command that can be used in a .bat file script. When you are confident that the correct files will be deleted, remove the -WhatIf from the Remove-Item cmdlet.
powershell -NoProfile -Command ^
"Get-ChildItem -Directory -Recurse -Filter 'log' | " ^
"ForEach-Object { Get-ChildItem -File -Path $_.PSPath | Remove-Item -WhatIf }"
Yes, it can be sorter and more cryptic and more expensive to maintain. Almost as much fun as a .bat FOR loop.
powershell -NoProfile -Command "gci -di -rec -filt 't' | %% { gci -file $_.PSPath | ri -WhatIf }"

Windows command line dates

I have an hard coded windows command line with dates (from: yesterday until today)
I want to replace the hard coded dates with an expression like date.add(-1) for yesterday.
I know how to get current date: %date:~10,4%-%date:~4,2%-%date:~7,2%
but how can I do this for yesterday?
thanks!
You can do exactly that in cmd using PowerShell. PowerShell is available for Windows from Windows 7. Are you running Windows 98 or something earlier?
FOR /F %a IN ('powershell -NoProfile -Command "(Get-Date).AddDays(-1).ToString('yyyy-MM-dd')"') do (SET "YD=%a")
ECHO %YD%
Here is a .bat file equivalent.
#ECHO OFF
FOR /F %%a IN ('powershell -NoProfile -Command "(Get-Date).AddDays(-1).ToString('yyyy-MM-dd')"') do (SET "YD=%%a")
ECHO %YD%
EXIT /B 0

PowerShell command in batch script condition

I need a line of script that does something like this:
if (results from PowerShell command not empty) do something
The PowerShell command is basically
powershell -command "GetInstalledFoo"
I tried if (powershell -command "GetInstalledFoo" != "") echo "yes" but get the error -command was unexpected at this time. Is this possible to accomplish? This command will eventually be run as the command to cmd /k.
BartekB's answer works as long as at least one line of output does not start with the FOR /F eol character (defaults to ;) and does not consist entirely of delimiter characters (defaults to space and tab). With appropriate FOR /F options it can be made to always work.
But here is a simpler (and I believe faster) way to handle multiple lines of output that should always work.
for /f %%A in ('powershell -noprofile -command gwmi win32_process ^| find /v /c ""') do if %%A gtr 0 echo yes
Another alternative is to use a temp file.
powershell -noprofile -command gwmi win32_process >temp.txt
for %%F in (temp.txt) if %%~zF gtr 0 echo yes
del temp.txt
Third way: set an environment variable from your PowerShell script and test it in your batch file?
I guess if won't be the best solution for that. I would use for /f instead:
for /f %R in ('powershell -noprofile -command echo foo') do #echo bar
That should give you 'bar', while this:
for /f %R in ('powershell -noprofile -command $null') do #echo bar
... should not. In actual .bat/ .cmd file you have to double % (%%R)
or better yet, if you don't want to many bar's returned...:
(for /f %R in ('powershell -noprofile -command gwmi win32_process') do #echo bar) | find "bar" > nul && echo worked

Resources