I need to receive a string with processes whose name is equal to "MSSQLSERVER" or starts with "MSSQL$". The names should be separated by forward slashes (/).
I am trying to do it with such script:
#echo off
set mssqlDependenties=
set defaultSqlServerServiceName="MSSQLSERVER"
set namedSqlServerServiceNameBeginning="MSSQL$"
setlocal enabledelayedexpansion
for /f "tokens=2" %%s in ('sc query state^= all ^| find "SERVICE_NAME: MSSQL"') do (
set serviceName=%%s
if "%%s" equ %defaultSqlServerServiceName% (
set mssqlDependenties=!mssqlDependenties!/%%s
)
if "%serviceName:~0,7%" equ %namedSqlServerServiceNameBeginning% (
set mssqlDependenties=!mssqlDependenties!/%%s
)
)
echo %mssqlDependenties%
But I receive an error:
The syntax of the command is incorrect.
mssqlDependenties should contain MSSQLSERVER/MSSQL$1/MSSQL$2/MSSQL$3, etc.
The solution from avery_larry works perfectly:
I changed
if "%serviceName:~0,7%" equ %namedSqlServerServiceNameBeginning% (
to
if "!serviceName:~0,7!" equ %namedSqlServerServiceNameBeginning% (
Related
Let's say we have a variable that contains multiple lines of text containing full file names, such as
C:\Program Files\gs\gs9.26\Resource\CMap\Adobe-Japan2-0
C:\Program Files\Inkscape\share\poppler\cMap\Adobe-Japan2\Adobe-Japan2-0
...and this multi-line text is assigned to the variable var.
In Windows/DOS command prompt (not PowerShell), without a use of any external tools, how can I remove everything after the last occurrence of the character \ in the first line, i.e. for the above example to get only
C:\Program Files\gs\gs9.26\Resource\CMap\
Here is a part of the code I use:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
for /f %%x in ('copy /z "%~dpf0" nul') do set "CR=%%x"
(set LF=^
%==%
)
set TAB= "
set "TAB=%TAB:"=%
net session >nul 2>&1
if !errorLevel! NEQ 0 (
echo ERROR: Use "Run as administrator" to execute this file.!LF!
pause
exit /b 1
)
<nul set/p"=Analyzing... "
set "nil= "
for /l %%i in (2,1,80) do call set "nil=%%nil%%%nil%"
set "STDOUT="
set "STDERR="
for /f "delims=" %%E in ('
2^>^&1 ^(^
for /f "delims=" %%O in ^('^
where /R "%programfiles%" "*adobe*.*"
^^^^^^^| findstr /i /n /r "japan2"^
'^) do #^(^
echo ^^^^^^^|%%O^
^)^
^) ^| findstr /n /r "^"
') do (
set "LINE=%%E"
set "LINE=!LINE:*:=!"
if "!LINE:~,1!" == "|" (
set "STDOUT=!STDOUT!!LINE:*:=!!LF!"
) else (
set "STDERR=!STDERR!!LINE!!LF!"
)
)
The original code created trailing whitespace to each path it found. I modified the code to get rid of this.
The paths had to be double quote as they contain whitespace in the path as well. The variable !STDOUT! with therefore have the following format:
"C:\Program Files\gs\gs9.26\Resource\CMap\Adobe-Japan2-0"
"C:\Program Files\Inkscape\share\poppler\cMap\Adobe-Japan2\Adobe-Japan2-0"
You mentioned that this is only part of the code, so you need to make sure that everything else works as expected.
Note however that you need to copy this part of the code "exactly" as is as I have amended a few parts of it, if you don't, it will not work as expected.
Lastly, I have to add. I am not sure of the reason this code was designed like this, I cannot see any specific reason, based on the current scenario.
This code is a bit of an overkill for now, unless you can provide a specific reason. I do not see any reason why the variable cannot be set without the line feeds.
Anyway, here it is:
#echo off
setlocal EnableExtensions EnableDelayedExpansion
for /f %%x in ('copy /z "%~dpf0" nul') do set "CR=%%x"
(set LF=^
%==%
)
set TAB= "
set "TAB=%TAB:"=%
net session >nul 2>&1
if !errorLevel! NEQ 0 (
echo ERROR: Use "Run as administrator" to execute this file.!LF!
pause
exit /b 1
)
<nul set/p"=Analyzing... "
echo(
set "nil= "
for /l %%i in (2,1,80) do call set "nil=%%nil%%%nil%"
set "STDOUT="
set "STDERR="
for /f "delims=" %%E in ('
2^>^&1 ^(^
for /f "delims=" %%O in ^('^
where /R "%programfiles%" "*adobe*.*"
^^^^^^^| findstr /i /n /r "japan2"^
'^) do #^(^
echo ^^^^^^^|%%O^
^)^
^) ^| findstr /n /r "^"
') do (
set "LINE=%%E"
set "LINE=!LINE:*:=!"
set "LINE=!LINE: =!"
if "!LINE:~,1!" == "|" (
set STDOUT=!STDOUT!"!LINE:*:=!"!LF!
) else (
set "STDERR=!STDERR!!LINE!!LF!"
)
)
for %%i in (!STDOUT!) do set "dir=%%~dpi" & goto cont:
:cont
echo !dir!
The main changes in the code you provided are here:
set "LINE=!LINE: =!" :: Removed the two trailing whitespaces
if "!LINE:~,1!" == "|" (
set STDOUT=!STDOUT!"!LINE:*:=!"!LF! :: Double quote the line so we can format them correctly.
This will allow proper usage of the strings in a list form.
Then, my code added. This sets a pth variable using drive and path to file. We then strip the trailing \ to allow the next %%~dpa to assign the drive and path to the point where you wanted it.
for %%i in (!STDOUT!) do set "dir=%%~dpi" & goto cont:
:cont
echo !dir!
The result will then be:
C:\Program Files\gs\gs9.26\Resource\CMap\
Finally, if you want to see that my part of the code does in fact remove the parts from path as you wanted, you can do this in my code section:
for %%i in (!STDOUT!) do (
echo %%~dpi
)
Or if you want to set each of them to a dir[n] to resemble an array, then place this in my code section:
set _n=1
for %%i in (!STDOUT!) do (
set "dir[!_n!]=%%~dpi"
set /a _n+=1
)
for /l %%n in (0,1,!_n!) do echo(!dir[%%n]!
set dir
I need to search multiple files within a folder in batch script and echo the not exist file and assign a variable for further logging, but unable to achieve that whenever my pattern contain (*) mark. Anyway i can achieve this?
SET pattern="abc*.txt" "ijk_*.txt" "xyz_*.txt"
SET count=0
FOR %%A IN (%pattern%) DO (IF EXIST "%%A" (SET /a count+=1) ELSE (
ECHO %date% %time%: %%A file missing.
SET fileList=!fileList! %%A
))
You can use a trick and split pattern into a multi-line variable and than iterate over each line. I'm using the question mark ? as a delimeter because it is a reserved character and can't be used within file names.
#echo off
SETLOCAL EnableDelayedExpansion
set patternlist="abc*.txt"?"ijk _*.txt"?"xyz_*.txt"
set pattern=!patternlist:?=^
!
SET count=0
FOR /F "delims=" %%A IN (!pattern!) DO (
if exist %%A (
SET /a count+=1
) ELSE (
ECHO %date% %time%: %%A file missing.
SET fileList=!fileList! %%A
)
)
i am trying to make an inventory of installed software in domain PCs by following reg command
Reg Query HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall /S ^| Find /I "DisplayName"
I am using Find /I "DisplayName" to get software-name. I also need the version number (and may be few more fields later), but its in another line as DisplayVersion.
Since I am running this on multiple computers, my script looks like this:
for /f %%i in (computers_ALL.txt) do (
for /f "tokens=1,2,*" %%j in ('psexec \\%%i Reg Query HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall /S ^| Find /I "DisplayName"') do (
echo x64 %%i %%l >>%OUTPUT_FILE%
)
for /f "tokens=1,2,*" %%j in ('psexec \\%%i Reg Query HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall /S ^| Find /I "DisplayName"') do (
echo x86 %%i %%l >>%OUTPUT_FILE%
)
)
Now I can only find DisplayName. How can I find DisplayVersion which is on another line and add it to second column? My output will be like,
ComputerName, Platform (32-64 bit), Software Name, Software Version
I can take care upto software-name, but having difficulty to get version and put it on second column. Appreciate your help. Thanks.
Following script works against a local Windows machine. Adapting it for a list computers_ALL.txt instead of "%computername%" and adding psexec \\%_comp% should be a simple task.
#ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion
set "OUTPUT_FILE=%temp%\41887529.txt"
for /F %%i in ("%computername%") do (
set "_comp=%%i"
call :proHive "x64" "\Software\Microsoft\Windows\CurrentVersion\Uninstall"
call :proHive "x86" "\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
)
rem debugging output
type "%OUTPUT_FILE%"
ENDLOCAL
goto :eof
:proHive
rem %1 platform
rem %2 registry key
>>"%OUTPUT_FILE%" (
for /f "tokens=*" %%G in ('
Reg Query "HKLM%~2" /S /V DisplayName ^| Find /I "HKEY_LOCAL_MACHINE%~2"
') do (
set "_DisplayName="
set "_DisplayVersion="
for /f "tokens=1,2,*" %%j in ('
Reg Query "%%G" ^| Findstr /I "DisplayName\> DisplayVersion\>"') do set "_%%j=%%l"
SETLOCAL EnableDelayedExpansion
echo %_comp%,%~1,!_DisplayVersion!,!_DisplayName!
ENDLOCAL
)
)
goto :eof
#ECHO OFF
SETLOCAL
SET "output_file=u:\report.txt"
DEL "%output_file%" /F /Q
for /f %%i in (q41887529.txt) do (
SET "compname=%%i"
CALL :clrsoft
FOR %%z IN (\ \Wow6432Node\) DO (
for /f "tokens=1,2,*" %%j in (
'Reg Query HKLM\Software%%zMicrosoft\Windows\CurrentVersion\Uninstall /S ^| Findstr /I "DisplayName DisplayVersion HKEY_LOCAL_MACHINE\\"'
) do (
IF /i "%%j"=="Displayname" (
SET "softname=%%l"
) ELSE (
IF /i "%%j"=="Displayversion" (
SET "softver=%%l"
) ELSE (
CALL :report %%z
)
)
)
REM processed all data - final report
CALL :report %%z
)
)
GOTO :EOF
:: Report routine parameters :
:: %1 indicates x64 ("\") or x86 (\Wow6432Node\)
:report
IF NOT DEFINED softname GOTO clrsoft
IF "%1"=="\" (
ECHO "%compname%",x64,"%softname%","%softver%">>"%output_file%"
) ELSE (
ECHO "%compname%",x86,"%softname%","%softver%">>"%output_file%"
)
:clrsoft
SET "softname="
SET "softver="
GOTO :EOF
Naturally, you'd need to set up your own output filename. I've also removed the psexec \\%%i and set up my machine name in q41887529.txt for testing on my machine.
Since the only difference between the queries is the node, I combined the steps and controlled them using %%z.
Clear the tempvars, then process each return line for one of the three target strings.
If it's a name, then call :report to report any accumulated data, then record the name
If it's a version, record the version and since this should now give us a pair, report it.
If it's neither, then it must be a new key, so report what we have so far.
The wart is that the version need not exist - and the final entry may be versionless, so we try reporting again to ensure any accumulated data is output.
I've revised this now and replaced the original.
It will report the machine name extracted from the file and I believe that the often-missing version number has been fixed - the order of name and version are unpredictable, so the report is triggered with the data accumulated between instances of HKEY_ and at the very end.
So I am using a batch to go through a text file line by line. The reason why I can't do a regular search is because I need to see what is written on each line and then determine how I want to process the next line. Anyway, my basic code is:
for /f "usebackq delims=" %%a in (%SourceLicenseFile%) do (
Set LineofFile=%%a
echo !LineofFile! | find /i "TIMESTAMP" >nul
if !errorlevel! EQU 0 (
FOR %%b IN (!LineofFile!) DO SET LogDate=%%b
)
echo %%a | find /i "(LOGTIME) IN" >nul
if !errorlevel! EQU 0 (
FOR %%d IN (!LineofFile!) DO SET Username=%%d
FOR /f "tokens=1" %%c IN ("!LineofFile!") DO (
SET Logtime=%%c
)
echo !LogDate! !LogTime! !Username!
>> !ExportLicenseLog! echo !LogDate! !LogTime! !Username!
)
)
I believe the echo is slowing down this processing. I have a file with thousands of lines and it would take me over a minute to process. Is there another method I can use to go through each line quicker?
Yes, the echo ... | find ... slowdown the process, not because the echo, but for the pipe...
You have not clearly explained the purpose of your program. However, to check if !LineofFile! variable have the "TIMESTAMP" string, you may use this code:
if "!LineofFile:TIMESTAMP=!" neq "!LineofFile!" (
echo TIMESTAMP string found in LineofFile variable
)
This code means: "Try to remove TIMESTAMP string from LineofFile variable. If the string was found, it was removed, so the replaced value is different than the original".
You don't need the echo:
find /i "SOMETHING"<%SourceLicenseFile%
Escape thus ^< inside a for parentheses.
OK. I got it. Using substitution is MUCH faster
for /f "usebackq delims=" %%a in (%SourceLicenseFile%) do (
Set LineofFile=%%a
if not "x!LineofFile:TIMESTAMP=!" EQU "x!LineofFile!" (
FOR %%b IN (!LineofFile!) DO SET LogDate=%%b
)
if not "x!LineofFile:IN:=!" EQU "x!LineofFile!" (
FOR /f "tokens=1,5" %%c IN ("!LineofFile!") DO (
SET Logtime=%%c
SET Username=%%d
)
if "!LogDate!" NEQ "DATE NOT FOUND" (
echo !LogDate! !LogTime! !Username!
>> !ExportLicenseLog! echo !LogDate! !LogTime! !Username!
)
)
Set /A LineNumber=!LineNumber!+1
Set /A PercentDone=!LineNumber!/%TotalLines%
)
after running this script shows somesoftware was unexpected this time i am using windows 7 64 bit. trying to get installed location of software using registry. if i echo THE_NAME then i get proper installed location but script exits in if else says somesoftware was unexpected this time
setlocal ENABLEEXTENSIONS
set KEY_NAME=HKEY_CURRENT_USER\Software\somesoftware
set VALUE_NAME=InstallDirectory
SET THEME_NAME=
FOR /f "usebackq tokens=2,*" %%a in (`REG QUERY "HKEY_CURRENT_USER\Software\somesoftware" /v InstallDirectory`) DO (
SET THEME_NAME=%%b
)
echo %THEME_NAME%
if defined THEME_NAME (
set PathValue= %THEME_NAME%
) else (
echo %KEY_NAME%\%VALUE_NAME% not found.
)
Your script does not make use of KEY_NAME or VALUE_NAME, and this might be just how you trimmed your example down.
I modified your script as shown below for testing, and it appeared to work as I expected.
setlocal ENABLEEXTENSIONS
set KEY_NAME=HKEY_CURRENT_USER\Software\%1
set VALUE_NAME=InstallDirectory
SET THEME_NAME=
FOR /f "usebackq tokens=2,*" %%a in (`REG QUERY "%KEY_NAME%" /v %VALUE_NAME%`) DO (
SET THEME_NAME=%%b)
echo THEME_NAME=%THEME_NAME%
if NOT ""=="%THEME_NAME%" (
set PathValue=%THEME_NAME%
echo PathValue=%PathValue%
) else (
echo %KEY_NAME%\%VALUE_NAME% not found.
)
NOTE: I changed the IF test to just test for empty string, an echo for my own debugging, I used %1 so I could test...
You will want to use this as a guide to inform your final script.