Problems finding the value of registry keys - command-line

I'm attempting to make a batch script to uninstall various programs with little involvement from the user (Only saying I want to uninstall Group A (Say, Google Chrome and Microsoft Office)), Partially for work and partially for fun and practice. This itself isn't impossible, I can already do this by calling msiexec and pointing it to the uninstall location in the registry (msiexec /x {xxxxx-xxxxx-xxxxxx-xxxx}).
The only problem with this is that this means that whenever the program changes registry keys, as will often happen with updates, I have to find the path again. So, I'm trying to run a piece of code that will search through the HKLM\SOFTWARE\Mincrosoft\Windows\CurrentVersion\Uninstall registry location, and whenever the DisplayName returns a certain value, not necessarily exact (Say "Chrome"), it stores the registry location?(The part that would be put in {xxxxxxx-xxxxxxx-xxxxxxx-xxxxxx}).
This way, the program simply finds the programs and stores their locations so that they can be uninstalled with it as a variable. I have tried, but as far as I know using reg query requires the full location. using reg query HKLM /f returns no results. I've tried a whole range of different workarounds, but nothing seems to work.
Here is a basic version of my code (I am neglecting to post the full version because much of it is repeated. It's mostly just case where's and if then statements)
#echo off
:start
echo Hello
echo.
1: Uninstall Chrome
set /p choice="Enter Choice: "
if "%choice%"=="1" goto uninstall_chrome
:uninstall_chrome
reg query HKLM /f Chrome /t REG_SZ
::msiexec /x{uninstall location for the program}
Thanks.
::UPDATE::
I figured it out. By using some of Rob van der Woude's code, I am now able to do it. The code to do so is:
CALL :Uninstall "Program Name"
:Uninstall
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /F "tokens=* %%A IN ('REG QUERY HKLM\SOFWARE\Microsoft\Windows\CurrentVersion\Uninstall /F "%~1" /D /S 2^>NUL ^| FINDSTR /R /B /C:"HKEY_"') DO (
REG QUERY "%%~A" /F DisplayName /V /E | FINDSTR /R /I /C:" DisplayName .* .*%~1" >NUL 2>&1
FOR /F "tokens=2*" %%B IN ('REG QUERY "%%~A" /F DisplayName /V /E 2^>NUL ^| FIND /I " DisplayName "') DO ECHO Program Name = %%C
FOR /F "tokens=7 delims=\" %%B IN ("%%~A") DO ECHO Unique Identifier = %%B
FOR /F "tokens=2*" %%B IN ('REG QUERY "%%~A" /F UninstallString /V /E ^| FIND /I " UninstallString "') DO %%C /qb
)
ENDLOCAL
This will output the programs name and unique identifier, then uninstall the program, without user input ("Do you want to uninstall x?")

I figured it out. By using some of Rob van der Woude's code, I am now able to do it. The code to do so is:
CALL :Uninstall "Program Name"
:Uninstall
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /F "tokens=* %%A IN ('REG QUERY HKLM\SOFWARE\Microsoft\Windows\CurrentVersion\Uninstall /F "%~1" /D /S 2^>NUL ^| FINDSTR /R /B /C:"HKEY_"') DO (
REG QUERY "%%~A" /F DisplayName /V /E | FINDSTR /R /I /C:" DisplayName .* .*%~1" >NUL 2>&1
FOR /F "tokens=2*" %%B IN ('REG QUERY "%%~A" /F DisplayName /V /E 2^>NUL ^| FIND /I " DisplayName "') DO ECHO Program Name = %%C
FOR /F "tokens=7 delims=\" %%B IN ("%%~A") DO ECHO Unique Identifier = %%B
FOR /F "tokens=2*" %%B IN ('REG QUERY "%%~A" /F UninstallString /V /E ^| FIND /I " UninstallString "') DO %%C /qb
)
ENDLOCAL
This will output the programs name and unique identifier, then uninstall the program, without user input ("Do you want to uninstall x?")

Related

Batch file to rename based on size on disk

I was going to make a batch script to share for ex-Dropbox account holders that will go through and rename a file OR folder if the size on disk is > 1 byte.
Using other forums I've managed to come up with the below.
#ECHO OFF
setlocal
set maxbytesize=1
FOR /F %%i IN ('PowerShell -ExecutionPolicy Bypass -File "FileSizeOnDisk.ps1" "E:\Desktop\Folder"') DO set SizeonDisk=%%i AND if %SizeonDisk% LSS %maxbytesize% (ren *.* *.*-DELETED)
EXIT
I just need help to loop the powershell command for every file, folder and files in a folder. I don't know how to properly place 2 commands after a DO and can't figure out the code to get it to work on multiple files.
#ECHO OFF
setlocal ENABLEDELAYEDEXPANSION
for /f "delims=" %%o in ('dir /b /a-d "nameofdirectorytoscan\filemask"') do
FOR /F %%i IN ('PowerShell -ExecutionPolicy Bypass -File "FileSizeOnDisk.ps1" "nameofdirectorytoscan\%%o"') DO set "Jumba#%%o=%%i"
set size#
pause
The result is a set of variables named Jumba#nameoffile with values of filesize as returned from Powersmell.
You can then scan the list using
for /f "tokens=2,3delims=#=" %%b in ('set Jumba#') do echo name=%%b, size=%%c

Batch File to display file name and then certain lines in the files

I have a folder of .log files where the content of each file has multiple lines of the following format:
yyyy/mm/dd, hh:mm:ss, ComputerName, IPAddress, stuff, stuff
I would like to create a batch file to parse through the .log files and create the following output for any line in a file where ComputerName starts with "XPLT":
filename,yyyy/mm/dd,ComputerName,IPAddress
And preferably, I'd like to only look at files with a modified date within the last 30 days.
So far, I've only gotten the following code which doesn't even work and doesn't even include the file modified date and parsing by ComputerName. Looking for help because I've just not done this very much, and I can't find a good example online.
Echo EID,Date,PCName,IPAdd>CitrixLogs.csv
setlocal enabledelayedexpansion
for /f "tokens=1,3,4" %%i in ('dir /b "C:\LogFiles\*.log"') do (
echo %%i,%%j,%%k,%%l>>CitrixLogs.csv
)
I'd use a bit of FINDSTR magic:
set LOG_DIR=c:\logfiles
for /f "tokens=1-7 delims=:," %%L in ('%SystemRoot%\System32\findstr.exe /r /c:"^[0-9][0-9][0-9][0-9]/[0-9][0-9]/[0-9][0-9],[0-9][0-9]:[0-9][0-9]:[0-9][0-9],xplt.*," %LOG_DIR%\*.log') do #echo %%L,%%M,%%N:%%O:%%P,%%Q,%%R,
`
REM
#ECHO OFF
SETLOCAL
SET "sourcedir=U:\sourcedir"
FOR /f "tokens=2-8delims=:, " %%a IN ('findstr /l /i /c:", XPLT" "%sourcedir%\*.log"') DO (
ECHO %%~nxa,%%b,%%c:%%d:%%e,%%f,%%g
)
GOTO :eof
redirect to your .csv as you will...
#echo off
setlocal enableextensions disabledelayedexpansion
:: configuration
set "logFolder=%cd%"
set "logFiles=*.log"
set "maxFileAge=30"
set "computerName=XPLT"
set "outputFile=CitrixLogs.csv"
:: adjust commands to execute according to configuration
set "ageFilter=robocopy "%logFolder%" "%logFolder%" "%logFiles%" /l /is /njh /njs /nc /ns /ndl /maxage:%maxFileAge%"
set "contentFilter=findstr /f:/ /i /r /c:"^^[^^,]*, [^^,]*, %computerName%" "
:: Generate output file
( echo(EID,Date,PCName,IPAdd
for /f "usebackq tokens=2,* delims=:" %%a in (
`cmd /q /c "for /f tokens^=* %%a in ('%ageFilter%') do echo(%%a" ^| %contentFilter% `
) do for /f "tokens=1,3,4 delims=," %%c in ("%%b") do echo(%%~nxa,%%c,%%d,%%e
) > "%outputFile%"
endlocal
This will use robocopy (or you can change it with forfiles) to search for files with a max age of 30 days in the indicated folder. Files will not be copied (/l) but the list will be echoed (the rest of the switch configure the output). This list of files is piped into findstr (/f:/) indicating where to search for the lines that match the indicated condition. This will generate an output with each line in the input file matching the condition, prefixed with the name (full name) of the file. This line is then splitted to output only the required fields.

How to set variable with the result of findstr

I am trying to write a batch file which searches for pdf files and finds how many pages they have and loop all pages.
I wrote the following. I can find the files, I can even find the pagecounts with a tool named pdftk. The results is as below.
C:\Users\test\Documents\fishes\Fish_1.pdf
NumberOfPages: 5
How can I set a variable which has the value of 5?
#ECHO off
for /R %%i IN (*.pdf) DO (
ECHO %%i
"C:\Program Files (x86)\PDF Labs\PDFtk Server\bin\pdftk.exe" %%i dump_data | findstr NumberOfPages
set pagecount = findstr NumberOfPages ???
FOR /L %%j IN (1,1,%pagecount%) DO (
ECHO "page " + %%j
)
)
You were already 90% there. Use the FOR /F command to process the results of a command. Type HELP FOR from the command prompt for more info.
for /f "tokens=2" %%A in (
'"C:\Program Files (x86)\PDF Labs\PDFtk Server\bin\pdftk.exe" %%i dump_data ^| findstr NumberOfPages'
) do set numberOfPages=%%A

How can i list all hidden files inside all subdirectories using batch scripting for windows XP?

dir /S /aH doesnt work as it wont delve any deeper inside of unhidden folders.
EDIT: turns out it WAS dir /S /aH just there wasnt any hidden or system files or folders within the non hidden files or folders i was testing on.
This is problematic and the only way I know to solve it is ugly and will give you the result in a "function":
#echo off
setlocal ENABLEEXTENSIONS
goto main
:EnumAllFiles
FOR /F "tokens=*" %%A IN ('dir /B /S /A:-D-H "%~1" 2^>nul') DO call :%2 "%%~A"
FOR /F "tokens=*" %%A IN ('dir /B /S /A:-DH "%~1" 2^>nul') DO call :%2 "%%~A"
goto :EOF
:mycallback
echo file=%~1
goto :EOF
:main
call :EnumAllFiles "c:\someDirToSearch" mycallback
(This does not tell the mycallback function about folders since you said you wanted files)
Edit: It seems like dir /B /S /a-D also works

Batch File XCopy Command

I have a batch file which loops through a content of a text file and copies a specific file using xcopy command.
here's the snippet.
for /f %%a in (FilesToCopy.txt) do (
xcopy ..\..\Common\%%a Common\%%a /i /d /c /v /s /y /f
xcopy Common\%%a ..\..\Common\%%a /i /d /C /v /s /y /f
)
%%a contains values like
Images\image1.jpg
Images\image2.jpg
so when xcopy is executed it would look like
xcopy ..\..\Common\Images\image1.jpg Common\Images\image1.jpg /i /d /c /v /s /y
upon execute it would then prompt this message
Does Common\Images\image1.png specify a file name
or directory name on the target
(F = file, D = directory)?
it seems that the /i command doesn' work or i am missing something here to suppress the message above.
Well, you left out the second statement the help gives about /I:
/I If destination does not exist and copying more than one file,
assumes that destination must be a directory.
You are only ever copying one file at a time, so /I doesn't apply.
You can probably hack-solving this by piping F into the command and suppressing output:
echo F|xcopy ..\..\Common\%%a Common\%%a /i /d /c /v /s /y /f >nul
(Won't work on non-English versions of Windows; but probably that's the least of your problems, given that the batch already fails for file names with spaces :-))
You could try building a single long list of file names to copy:
setlocal enabledelayedexpansion enableextensions
set LIST=
for /f %%a in (FilesToCopy.txt) do set LIST=!LIST! "..\..\Common\%%a"
xcopy %LIST% Common /i /d /c /v /s /y /f
This requires two passes over the initial file, though. And it fails when the list of file names gets longer than 8190 characters.
The destination should be a path, then it won't ask:
xcopy ..\..\Common\Images\image1.jpg Common\Images\ /i /d /c /v /s /y
In your case, you can use path extraction with %~p on the destination since you may want to preserve that:
xcopy ..\..\Common\%%a Common\%%~pa /i /d /c /v /s /y