2016-02-09 39 views
4

美好的一天,在GPO中禁用註冊表編輯工具時使用Reg Query? MS Office版本查詢

因此,我寫了一個簡單的.bat文件,我打算在用戶啓動時調用以獲取MS Office版本。對於管理員來說,測試很好,但對於標準用戶來說卻並非如此。我懷疑這是因爲我們有: 阻止訪問註冊表編輯工具 在GPO中的設置,雖然禁用運行silenty的regedit設置爲'no'。

所以我的問題是a)可能的原因,爲什麼我的腳本不工作,b)如果是的話,是否有一個註冊表的替代方案。試着保持它的好和簡單。下面

代碼:

@echo off 

reg query HKEY_CLASSES_ROOT\Access.Application\CurVer 
if errorlevel 1 goto five 

for /f "tokens=3" %%i in ('reg query HKEY_CLASSES_ROOT\Access.Application\CurVer') do (
    if %%i equ Access.Application.15 goto one 
    if %%i equ Access.Application.14 goto two 
    if %%i equ Access.Application.12 goto three 
    if %%i equ Access.Application.11 goto four 
    goto five 
) 

:one REM 2013 Pro 
echo %computername%,Office 2013 Pro" >>\\SERVERNAME\bslogs$\officeVersions.csv 
exit 
:two REM 2010 Pro 
echo %computername%,Office 2010 Pro >>\\SERVERNAME\bslogs$\officeVersions.csv 
exit 
:three REM 2007 Pro 
echo %computername%,Office 2007 Pro" >>\\SERVERNAME\bslogs$\officeVersions.csv 
exit 
:four REM 2003 Pro 
echo %computername%,Office 2003 Pro" >>\\SERVERNAME\bslogs$\officeVersions.csv 
exit 

:five REM Not Pro Verion 
reg query HKEY_CLASSES_ROOT\Word.Application\CurVer 
if errorlevel 1 goto ten 

for /f "tokens=3" %%i in ('reg query HKEY_CLASSES_ROOT\Word.Application\CurVer') do (
    if %%i equ Word.Application.15 goto six 
    if %%i equ Word.Application.14 goto seven 
    if %%i equ Word.Application.12 goto eight 
    if %%i equ Word.Application.11 goto nine 
    goto ten 
) 

:six REM 2013 STD 
echo %computername%,Office 2013 Std" >>\\SERVERNAME\bslogs$\officeVersions.csv 
exit 
:seven REM 2010 STD 
echo %computername%,Office 2010 Std" >>\\SERVERNAME\bslogs$\officeVersions.csv 
exit 
:eight REM 2007 STD 
echo %computername%,Office 2007 Std" >>\\SERVERNAME\bslogs$\officeVersions.csv 
exit 
:nine REM 2003 STD 
echo %computername%,Office 2003 Std" >>\\SERVERNAME\bslogs$\officeVersions.csv 
exit 

:ten REM no idea 
echo %computername%,????" >>\\SERVERNAME\bslogs$\officeVersions.csv exit 

非常感謝, 馬丁

+0

有一個wmi類可以讀取註冊表。雖然這不是很好,但很簡單。只要有機會,我會發佈一個答案,除非其他人感覺像展示。 – rojo

回答

2

A)是爲什麼我的腳本不能正常工作

的可能的原因我不知道。聽起來似乎合理。

B)如果有一個註冊表編輯器替代

您可以查詢註冊表值與WMI和StdRegProv class

試着保持它的美好和簡單。

對不起。這既不好也不簡單。

我不得不使用過去的WMI查詢模擬reg.exe來查詢遠程註冊表。我一起砍了一個:getRegValue函數,可以自動執行這個功能。運行這個,看看它是否會爲你的想法。

@echo off 
setlocal 

call :getRegValue accessVer HKCR\Access.Application\CurVer\ 
echo Result: %accessVer% 

call :getRegValue shell "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell" 
echo Result: %shell% 

goto :EOF 

:getRegValue <return_var> <root\path\valname> 
setlocal enabledelayedexpansion 
rem // constants 
set "hive[HKCR]=&H80000000" 
set "hive[HKCU]=&H80000001" 
set "hive[HKLM]=&H80000002" 
set "hive[HKU]=&H80000003" 
set "hive[HKCC]=&H80000005" 

set "type[1]=GetStringValue" 
set "type[2]=GetExpandedStringValue" 
set "type[3]=GetBinaryValue" 
set "type[4]=GetDWORDValue" 
set "type[7]=GetMultiStringValue" 
set "type[11]=GetQWORDValue" 

SET "wmic=wmic /namespace:\\root\default class stdregprov call" 

rem // split %~2 into hive, path, leaf 
set "regpath=%~2" 
if "%regpath:~-1%"=="\" set "regpath=%regpath%(Default)" 
set hive=%regpath:\=&rem;% 
set "regpath=!regpath:%hive%\=!" 
set "leaf=%regpath%" 
:leaf 
set "leaf=%leaf:*\=%" 
if not "%leaf%"=="%leaf:\=%" goto leaf 
set "regpath=!regpath:\%leaf%=!" 

set "hive=!hive[%hive%]!" 

rem // get data type of leaf (default: string) 
set "method=%type[1]%" 
for %%I in (names types nameidx) do set "%%I=" 

2>NUL (
    for /f "tokens=2 delims={}" %%I in (
     '%wmic% EnumValues hDefKey^="%hive%" sSubkeyName^="%regpath:\=\\%"^ 
     ^| find "= {"' 
    ) do (
     if not defined names (set "names=%%I") else set "types=%%I" 
    ) 
) 

if defined names (
    for %%n in (names types) do (
     set idx=0 
     for %%I in (!%%n!) do (
      if defined nameidx (
       if !idx! equ !nameidx! set "method=!type[%%~I]!" 
      ) else if /i "%%~I"=="%leaf%" (
       set "nameidx=!idx!" 
      ) 
      set /a idx += 1 
     ) 
    ) 
) 

if /i "%leaf%"=="(Default)" set "leaf=" 

rem // get data value of leaf 
2>NUL (
    for /f "delims=" %%I in (
     '%wmic% %method% hDefKey^="%hive%" sSubkeyName^="%regpath:\=\\%"^ 
     sValueName^="%leaf%" ^| findstr "[su]Value"' 
    ) do (
     for %%# in (%%I) do set "ret=%%~#" 
    ) 
) 
endlocal & set "%~1=%ret%" & goto :EOF 

的思想作爲額外的食物,wmic.exe支持以下語法遠程查詢:

wmic /node:remotePC /user:domain\remoteAdmin /password:password verbs... 

而不是讓每個用戶在登錄時運行腳本,你可以使用遙控開關來查詢所有機器都批量生產。


天色作爲一項學術活動,部分來阻止任何人誰可能會想:「你應該使用PowerShell」,我改寫了:getRegValue函數調用PowerShell的混合代碼。不幸的是,使用PowerShell通過WMI查詢註冊表仍然很複雜。雖然字符串操作和對象檢索更容易,但稍微更經濟的代碼並不能證明增加的執行時間。

<# : regval.bat 
@echo off 
setlocal 

call :getRegValue accessVer HKCR\Access.Application\CurVer\ 
echo Result: %accessVer% 

call :getRegValue shell "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell" 
echo Result: %shell% 

goto :EOF 

:getRegValue <return_var> <root\path\valname> 
setlocal 
set "regpath=%~2" 

for /f "delims=" %%I in (
    'powershell -noprofile -noninteractive "iex (gc \"%~f0\" | out-string)"' 
) do (
    endlocal 
    set "%~1=%%~I" 
) 
goto :EOF 
: powershell hybrid code #> 

$hiveConst = @{ 
    "HKCR" = 2147483648 
    "HKCU" = 2147483649 
    "HKLM" = 2147483650 
    "HKU" = 2147483651 
    "HKCC" = 2147483653 
} 

# http://www.vistax64.com/powershell/10160-powershell-remote-registry-access-via-wmi.html 
$reg = gwmi -List -Namespace root\default | ?{ $_.Name -eq "StdRegProv" } 

# split $env:regpath into $hive, $regpath, $leaf 
$regpath = $env:regpath -split "\\" 
$hive = $hiveConst[$regpath[0]] 
$leaf = $regpath[$regpath.length - 1] 
if ($leaf) { 
    $regpath = $regpath[1..($regpath.length - 2)] -join "\" 
} else { 
    $regpath = $regpath[1..($regpath.length - 1)] -join "\" 
} 

if ($leaf -match "^\(Default\)$") { $leaf = "" } 

# get data type of leaf (default: string) 
$method = 1 
$res = $reg.EnumValues($hive, $regpath) 
for ($i = 0; $i -lt $res.sNames.length; $i++) { 
    if ($res.sNames[$i] -eq $leaf) { 
     $method = $res.Types[$i] 
    } 
} 

# get data value of leaf 
switch ($method) { 
    1 { $reg.GetStringValue($hive, $regpath, $leaf).sValue; break } 
    2 { $reg.GetExpandedStringValue($hive, $regpath, $leaf).sValue; break } 
    3 { $reg.GetBinaryValue($hive, $regpath, $leaf).uValue; break } 
    4 { $reg.GetDWORDValue($hive, $regpath, $leaf).uValue; break } 
    7 { $reg.GetMultiStringValue($hive, $regpath, $leaf).sValue; break } 
    11 { $reg.GetQWORDValue($hive, $regpath, $leaf).uValue; break } 
} 

只是因爲我覺得自己是一個挑戰,我決定嘗試第三個版本採用的JScript混合代碼這段時間。相信與否,這是三種方法中最快的。

@if (@CodeSection == @Batch) @then 
@echo off & setlocal 

call :getRegValue accessVer HKCR\Access.Application\CurVer\ 
echo Result: %accessVer% 

call :getRegValue shell "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell" 
echo Result: %shell% 

goto :EOF 

:getRegValue <return_var> <root\path\valname> 
for /f "delims=" %%I in ('cscript /nologo /e:JScript "%~f0" "%~2"') do set "%~1=%%~I" 
goto :EOF 

@end // end batch/begin JScript hybrid code 

function reg(strMethod, objParams) { 
    try { 
     var winmgmts = GetObject('winmgmts:root\\default'), 
      StdRegProv = winmgmts.Get('StdRegProv'); 
      params = StdRegProv.Methods_(strMethod).InParameters.SpawnInstance_(); 

     for (var i in objParams) params[i] = objParams[i]; 
     return winmgmts.ExecMethod('StdRegProv', strMethod, params); 
    } 
    catch(e) { return {'sValue':''} } 
}; 

var hiveConst = { 
     "HKCR" : 2147483648, 
     "HKCU" : 2147483649, 
     "HKLM" : 2147483650, 
     "HKU" : 2147483651, 
     "HKCC" : 2147483653 
    }, 
    methodConst = { 
     "1" : "GetStringValue", 
     "2" : "GetExpandedStringValue", 
     "3" : "GetBinaryValue", 
     "4" : "GetDWORDValue", 
     "7" : "GetMultiStringValue", 
     "11" : "GetQWORDValue" 
    }, 
    regpath = WSH.Arguments(0).split('\\'), 
    hive = hiveConst[regpath.shift()], 
    leaf = regpath.pop(), 
    regpath = regpath.join('\\'); 

if (/^\(Default\)$/.test(leaf)) leaf = ''; 

// get data type of leaf (default: string) 
try { 
    var params = {'hDefKey': hive, 'sSubKeyName': regpath}, 
     res = reg('EnumValues', params), 
     sNames = res.sNames.toArray(), 
     Types = res.Types.toArray(); 

    for (var i in sNames) { 
     if (sNames[i] == leaf) var method = methodConst[Types[i]]; 
    } 
} 
catch(e) { var method = methodConst[1] } 

// get and output data value of leaf 
var params = {'hDefKey': hive, 'sSubKeyName': regpath, 'sValueName': leaf}, 
    res = reg(method, params); 
WSH.Echo(res.sValue || res.uValue); 
+0

這是一個真正令人驚歎的功能,謝謝。不幸的是,一些腳本超出了我的意思,我正在查看錯誤處理,並且我不明白爲什麼當regkey存在時爲什麼會在'2'的函數上得到輸出?這需要根據是否安裝訪問來檢查Pro版本的Office,然後移至Word版本。 – MartinR

+0

關於遠程調用,我嘗試過,但不幸的是得到空白的結果。我認爲這可能是因爲使用HKCR更改爲「HKLM \ Software \ Classes \ Word.Application \ CurVer \」,但確實很愉快。 'SET'wmic = wmic/node:「COMPUTERNAME」/ user:DOMAIN \ USER/password:PASSWORD/namespace:\\ root \ default class stdregprov call「' – MartinR

+0

對此的更新。我真的不知道WMIC爲什麼遠程不使用遠程腳本,因爲之前使用它遠程調用密鑰。作爲一個解決方法,使用PSEXEC和列表功能來做同樣的事情。問題將添加到登錄腳本幾天,以關閉機器並在Excel中整合數據。本來希望將其保留在腳本中,但足以滿足要求。在我原來的腳本中,我只是輸出????當你的':getRegValue'函數沒有找到預期的版本。這將不得不做,直到我瞭解更多。很多人非常感謝你的幫助。 – MartinR