[英]remote registry query problems
Checking for XP via the registry using this script in batch. 批量使用此脚本通过注册表检查XP。
@echo off
pushd %~dp0
for /f "usebackq tokens=*" %%A in ("%~dp0pxhosts.txt") do (
reg query "\\%%A\HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" | find /i "5.1" > NUL && set OS=XP || set OS=NEWER
echo %os%
pause
)
in pxhost I have the list of pc's to check for xp and then do something, or not. 在pxhost中,我具有要检查XP的PC列表,然后执行某项操作或不执行某项操作。 However I cant get the above to work.
但是我不能使以上工作。 The variable is never set and it just echos back "windows_NT".
该变量从不设置,而只是回显“ windows_NT”。 If, however, I take the for loop out and run the reg query without the variable:-
但是,如果我退出for循环并运行不带变量的reg查询:
reg query "\\xp-4c54fa50d0da\HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" | find /i "5.1" > NUL && set OS=XP || set OS=NEWER
the echo works and reports "XP", or "newer" if I change "5.1" to "5.7" for test purposes. 如果我出于测试目的将“ 5.1”更改为“ 5.7”,则回显有效并报告“ XP”或“较新”。
What's going on? 这是怎么回事? Thanks.
谢谢。
thanks for answers but now I have more problems 感谢您的回答,但现在我有更多问题
From here I can now echo the right responses but the calling doesn't work at all. 现在,我可以从这里回显正确的响应,但是调用根本无法进行。 I have an XP, win 7 32 and win 10 64 in test in the text file pxhosts.
我有一个XP,文本文件pxhosts中的win 7 32和win 10 64在测试中。 XP is first in the list and gets ignored even when it is echo'd back correctly.
XP在列表中排在第一位,即使正确回显,也会被忽略。 something is stopping the calling from happening.
某些事情阻止了呼叫的发生。 Really driving me mental this lol.
真的让我很高兴。
I am trying to write a remote permissions script that applies to either XP filr system or 32 or 64 (newer windows). 我正在尝试编写适用于XP filr系统或32或64(较新的Windows)的远程权限脚本。 The total code is below:-
总代码如下:
@echo off
setlocal enabledelayedexpansion
for /f "usebackq tokens=*" %%A in ("%~dp0pxhosts.txt") do (
reg query "\\%%A\HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" | find /i "5.1" > NUL && set pctype=XP || set pctype=NEWER
cls
echo !pctype!
pause
if !pctype! == !XP! ( call :XP !%%A!)
reg query "\\%%A\HKLM\Hardware\Description\System\CentralProcessor\0" | find /i "x86" > NUL && set arc=32 || set arc=64
cls
echo !arc!
pause
if !arc! == !64! ( call :64 !%%A!)
if !arc! == !32! ( call :32 !%%A!)
)
:32
echo 32 okay
pause
icacls "\\%1\C$\ProgramData\folderFoo" /T /C /grant(:r) "Domain Users":(OI)(CI)(F) /inheritance:e >> "%~dp0%1.txt" 2>&1
pause
rem return from a subroutine
exit /B
:64
echo 64 okay
pause
icacls "\\%1\C$\Program Files (x86)\Folderfoo" /T /C /grant(:r) "Domain Users":(OI)(CI)(F) /inheritance:e >> "%~dp0%1.txt" 2>&1
pause
rem return from a subroutine
exit /B
:XP
echo xp okay
pause
CACLS "\\%1\C$\Documents and Settings\All Users\Application Data\Folderfoo" /E /T /C /G "Domain Users":F >> "%~dp0%1.txt" 2>&1
pause
rem return from a subroutine
exit /B
new edit 201216 新编辑201216
for /f "usebackq tokens=*" %%A in ("%~dp0pxhosts.txt") do (
reg query "\\%%A\HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" | find /i "5.1" > NUL
IF %ERRORLEVEL%==0 set pctype=XP
IF %ERRORLEVEL%==1 set pctype=NO
reg query "\\%%A\HKLM\Hardware\Description\System\CentralProcessor\0" | find /i "x86" > NUL
IF %ERRORLEVEL%==0 set arc=32
IF %ERRORLEVEL%==1 set arc=64
IF !pctype!==XP (call :xp %%A)
IF !pctype!==NO IF !arc!==32 (call :32 %%A)
IF !arc!==64 (call :64 %%A)
)
This is now picking up the 64 or 32 using reg query, however because an XP machine will always be a 32 bit machine it keeps running the code for newer windows PC with 32 bit as well. 现在使用reg查询获取64或32,但是因为XP机器将永远是32位机器,所以它也会继续为32位的更新Windows PC运行代码。 My subroutines for XP are dealing with docuemnts and settings folder, newer 32 machines just the user folder format.
我的XP子程序处理的是文件和设置文件夹,较新的32台计算机只是用户文件夹格式。
I need to run a subroutine on XP machines, 32 bit newer machines and 64 bit machines. 我需要在XP计算机,32位较新的计算机和64位计算机上运行子例程。 At the moment xp code runs on 32 bit machines and vice versa because they share 32 bit architecture.
目前,xp代码在32位计算机上运行,反之亦然,因为它们共享32位体系结构。
I have tried above to eradicate the problem by only running 32 bit routine if the pc is newer with a 32 bit file structure by way of variables (2nd line of IF's). 我上面已经尝试通过仅运行32位例程来消除该问题,如果该PC是通过变量(IF的第二行)使用32位文件结构更新的。 Thanks :)
谢谢 :)
If the thingy works without the for-loop and the variable is not set within a for-loop consider a search for something like Batch variable not set in for-loop
and boom there will be a plenty of questions like yours. 如果啄作品,未经for循环和变量并不在设置一个for循环考虑类似的搜索
Batch variable not set in for-loop
和繁荣将有大量的像你这样的问题。
Answer is the same for all: 答案都一样:
Use Delayed Expansion ! 使用延迟扩展 !
To use that, add the line setlocal EnableDelayedExpansion
to the beginning of the batch-file and whereever you need a variable in a closed set of parenthesis like a for-loop or an if-condition change %myVar%
to !myVar!
要使用它,请将行
setlocal EnableDelayedExpansion
添加到批处理文件的开头,并在需要封闭圆括号的位置(如for循环或if条件更改%myVar%
到!myVar!
任何地方添加变量!myVar!
. 。
Example to verify: 验证示例:
@echo off
setlocal EnableDelayedExpansion
set foo=foo
if 1==1 (
set foo=bar
echo Not delayed: %foo%
echo Delayed: !foo!
) ELSE (
echo If you land here something went heavily wrong...
)
Reasoning: 推理:
In batch closed sets of parenthesis are calculated when the beginning is reached. 在批处理中,当到达起点时,将计算括号的闭集。 In the above example that means that when the program reaches
if 1==1
it knows the value of foo
as "foo" eventhough I changed it seemingly before. 在上面的示例中,这意味着当程序达到
if 1==1
,即使我以前似乎已将其更改,也知道foo
的值为“ foo”。
An alternative is to use 替代方法是使用
call echo %%myVar%%
In your example however you would not even need that variable... In the same positions where you set the value of OS
you could as well simply echo it: 但是,在您的示例中,您甚至不需要该变量...在设置
OS
值的相同位置,您也可以简单地对其进行回显:
... && set OS=XP || set OS=NEWER
... && set OS=XP || set OS=NEWER
-> ... && echo XP || echo NEWER
... && set OS=XP || set OS=NEWER
> ... && echo XP || echo NEWER
... && echo XP || echo NEWER
You only and really only need exclamation marks when accessing a variable that got set within the loop! 访问循环中设置的变量时,您仅而且实际上仅需要惊叹号! You made two major mistakes I spotted so far:
到目前为止,您犯了两个主要错误:
1) For-Loop variables are set in the loops header and with that are an exception from this rule: %%A
is the correct way of accessing it and not !%%A!
1)在循环头中设置了For-Loop变量,这是该规则的例外:
%%A
是访问它的正确方法,而不是!%%A!
2) If you want to make a string comparison like if varValue == thisString
you should NOT surround the string to check with exclamation marks: if !arc!==64
should do the trick here! 2)如果要进行字符串比较(如
if varValue == thisString
,则不应在字符串中使用感叹号进行检查: if !arc!==64
应该在这里if varValue == thisString
!
Else the comparison would look like if 64==!64!
否则,
if 64==!64!
which is not the desired behaviour I guess. 我猜这不是理想的行为。
Read your questions edit closer again: 阅读您的问题,再次仔细编辑:
Something is stopping the calling from happening
某些事情阻止了呼叫的发生
Exactly the problem with the if described above in point 2 :) 正是上述第2点中所述的if问题:)
After a short search and playing around a bit with the results I came up with this (Windows 7+ required on executing machine; tested with Windows 10 Pro) : 经过简短的搜索并仔细研究了结果,我得出了以下结论(执行计算机需要Windows 7+;已通过Windows 10 Pro测试) :
@echo off
setlocal EnableDelayedExpansion
for /f "usebackq tokens=*" %%A in ("%~dp0pxhosts.txt") do (
for /f "tokens=2 delims=:" %%B in ('systeminfo /s "%%~A" ^| findstr /i "Systemtype"') do (
call :removeLeadingSpaces "%%~B" type
echo !type!
)
for /f "tokens=2 delims=:" %%C in ('systeminfo /s "%%~A" ^| findstr /i "Operatingsystemname"') do (
call :removeLeadingSpaces "%%~C" osName
echo !osName!
)
)
pause
Goto:eof
:removeLeadingSpaces
for /f "tokens=* delims= " %%f in ("%~1") do set %2=%%f
Explanation: Reads the computernames from the file as it already does. 说明:已从文件中读取计算机名。 Takes the second part from the output of the command
systeminfo /s <computername>
queried for the specific strings "Systemtype" and "Operatingsystemname". 从命令
systeminfo /s <computername>
的输出中获取第二部分,以查询特定的字符串“ Systemtype”和“ Operatingsystemname”。 The ^
is there to escape the piping symbol |
^
用来逃避管道符号|
. 。 It then sends the string to a subfunction that truncates the leading spaces and sets them to the specified variable.
然后,它将字符串发送到子函数,该子函数会截断前导空格并将其设置为指定的变量。
NOTE: The strings used to query may vary for a different language setting! 注意:用于查询的字符串可能会因语言设置的不同而有所不同! Those above are freely translated from my German OS!
以上内容都是从我的德语操作系统中免费翻译的! To check how they are for your language setting go ahead and open a commandprompt and type
systeminfo
and hit Enter Now look for the ones you need. 要检查它们的语言设置,请打开命令提示符并键入
systeminfo
然后单击Enter Enter查找所需的内容。
Systemtype outputs the processor architecture and OSname the name of the operating system (who would have thought that ey?). Systemtype输出处理器体系结构,而OSname输出操作系统的名称(谁会认为是?)。 If you have found what you need change the strings from my example to your needs.
如果找到了所需的内容,请将字符串从我的示例更改为您的需要。
From where it says echo !type!
从那里说
echo !type!
and echo !osName!
并
echo !osName!
do whatever you want with those variables. 用这些变量做任何您想做的事情。 Any questions left?
还有问题吗? Feel free to ask!
随便问!
Your problem (I think) is here: 您的问题(我认为)在这里:
reg query "\\%%A\HKLM\Hardware\Description\System\CentralProcessor\0" | find /i "x86" > NUL && set arc=32 || set arc=64
IF ERRORLEVEL==0 set arc=32
IF ERRORLEVEL==1 set arc=64
When using the way of processing the outcome of the find directly using && echo positive result || echo negative result
当使用直接使用
&& echo positive result || echo negative result
处理查找&& echo positive result || echo negative result
&& echo positive result || echo negative result
the errorlevel will always reside at 0! && echo positive result || echo negative result
,错误级别将始终为0! So you got two ways of handling this: 因此,您有两种处理方式:
&& set arc=32 || set arc=64
&& set arc=32 || set arc=64
&& set arc=32 || set arc=64
so the errorlevel is set accordingly to the outcome of the command as it is already done at the check for XP && set arc=32 || set arc=64
因此错误级别根据命令的结果进行相应设置,因为它已在XP检查中完成 You can test this on your own in the commandline with the queries from your question: 您可以在命令行中使用问题中的查询自行进行测试:
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" | find /i "5.1" > NUL
echo %ERRORLEVEL%
This should echo 1 if you do not have an XP-computer (what I hope for you ;) ). 如果您没有XP计算机(我希望您有此;),则应该回显1。 This is because
find
could not find the string specified -> falsey value. 这是因为
find
找不到指定的字符串-> falsey值。
Now reset the errorlevel: 现在重置错误级别:
set ERRORLEVEL=0
And try this one: 并尝试以下方法:
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" | find /i "5.1" > NUL && echo should be 0 || echo should be 1
Would be the version without direct errorlevel handling but with acting according to the direct result of the find
command. 将是没有直接错误级别处理但可以根据
find
命令的直接结果进行操作的版本。
Now do echo %ERRORLEVEL%
You will notice that it is 0 eventhough the above command should have returned a falsey value. 现在执行
echo %ERRORLEVEL%
即使上面的命令应该返回一个falsey值,您也会注意到它是0。
In the end it was one lethal space too much... ONE SPACE screwing up parts of the script. 最后,这是一个致命的空间,太多了……一个空格弄乱了脚本的一部分。
Base script: 基本脚本:
@echo off
setlocal EnableDelayedExpansion
pushd %~dp0
for /f "usebackq tokens=*" %%A in ("%~dp0pxhosts.txt") do (
reg query "\\%%A\HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" | find /i "5.1" > NUL
IF !ERRORLEVEL!==0 set pctype=XP
IF !ERRORLEVEL!==1 set pctype=NOXP
CLS
reg query "\\%%A\HKLM\Hardware\Description\System\CentralProcessor\0" | find /i "x86" > NUL
IF !ERRORLEVEL!==0 set arc=fs1
IF !ERRORLEVEL!==1 set arc=fs2
CLS
IF !pctype!==XP (call :XPFS %%A)
IF !pctype!==NOXP IF !arc!==fs1 (call :type1 %%A)
IF !arc!==fs2 (call :type2 %%A)
)
Goto :eof
:XPFS
REM Do things for XP computer
Goto :eof
:type1
REM Do things for 32-bit computer
Goto :eof
:type2
REM Do things for 64-bit computer
Goto :eof
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.