简体   繁体   English

远程注册表查询问题

[英]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

Edit after big question edit: 大问题后编辑:

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问题:)

Edit after question for another method to find the queried values remotely: 在问题后进行编辑以寻找另一种方法来远程查找查询的值:

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! 随便问!

Edit after chat conversation 聊天对话后编辑

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: 因此,您有两种处理方式:

  1. Simply delete the errortype handling 只需删除错误类型处理
  2. Delete the part && 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。

Edit after finding the mistake in chat: 在聊天中发现错误后进行编辑:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM