Vbscript 为什么不存在的注册表值返回为";1“;而不是空?

Vbscript 为什么不存在的注册表值返回为";1“;而不是空?,vbscript,Vbscript,我不愿意承认我浪费了大量时间试图调整返回已安装程序列表的VB脚本,我正试图理解我哪里出错了 我遇到的问题是,我在网上找到的每一个“列表程序”类型的脚本都会用每个具有“DisplayName”字段的键填充一个文本文件。尽管进行了大量查找,但我找不到只返回填充add/remove或appwiz.cpl的列表的。这是我找到的“抓取一切”类型脚本的一个示例: Const HKLM = &H80000002 'HKEY_LOCAL_MACHINE Set objFSO = CreateObject

我不愿意承认我浪费了大量时间试图调整返回已安装程序列表的VB脚本,我正试图理解我哪里出错了

我遇到的问题是,我在网上找到的每一个“列表程序”类型的脚本都会用每个具有“DisplayName”字段的键填充一个文本文件。尽管进行了大量查找,但我找不到只返回填充add/remove或appwiz.cpl的列表的。这是我找到的“抓取一切”类型脚本的一个示例:

Const HKLM = &H80000002 'HKEY_LOCAL_MACHINE
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set oShell = CreateObject( "WScript.Shell" )
temp=oShell.ExpandEnvironmentStrings("%temp%")
Set objTextFile = objFSO.CreateTextFile(temp & "\software.txt", True)
strComputer = "."
strKey = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"
strKey2 = "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\"
strEntry1a = "DisplayName"
strEntry1b = "QuietDisplayName"
Set objReg = GetObject("winmgmts://" & strComputer & _
 "/root/default:StdRegProv")
objReg.EnumKey HKLM, strKey, arrSubkeys
For Each strSubkey In arrSubkeys
  intRet1 = objReg.GetStringValue(HKLM, strKey & strSubkey, _
   strEntry1a, strValue1)
  If intRet1 <> 0 Then
    objReg.GetStringValue HKLM, strKey & strSubkey, _
     strEntry1b, strValue1
  End If
  If strValue1 <> "" Then
  objTextFile.WriteLine strValue1
  End If
Next
objtextfile.close
Set objTextFile = objFSO.CreateTextFile(temp & "\software.txt", True)
objReg.EnumKey HKLM, strKey2, arrSubkeys
For Each strSubkey In arrSubkeys
  intRet1 = objReg.GetStringValue(HKLM, strKey2 & strSubkey, _
   strEntry1a, strValue1)
  If intRet1 <> 0 Then
    objReg.GetStringValue HKLM, strKey & strSubkey, _
     strEntry1b, strValue1
  End If
  If strValue1 <> "" Then
  objTextFile.WriteLine strValue1
  End If
Next
objtextfile.close

我不太清楚你的问题是什么。您希望哪个值为
Null
(或
非Null
)?从注册表读取的值或用于读取注册表值的函数的返回值?这两种价值观具有完全不同的含义

此外,上一个代码段中的函数调用并不完全正确(尽管它可以工作)

您使用参数
hDefKey
sSubkeyName
sValueName
调用函数,但忽略了实际值(
uValue
)的out参数。但是,函数的返回值不是注册表值
SystemComponent
的数据,但是一个整数状态代码,指示操作是否成功。从注册表值读取的数据通常存储在函数的第4个参数中。由于缺少此参数,因此它默认为
Null
,即运行时环境将函数调用扩展为:

Check = objReg.GetDWORDValue(HKLM, strKey & strSubkey, strEntry1c, Null)
根据
strKey&strSubkey
和/或
strengtry1c
是否存在,检查
的值将为0(成功读取值)、1(值不存在)或2(键不存在)。但是,从注册表读取的任何内容都将被删除,因为没有变量来保存数据(第四个参数是
Null
)。因此,条件
IsNull(Check)
的计算结果总是
False
,并且从不调用
GetStringValue

如果将实际变量作为第四个参数添加到函数调用中:

Check = objReg.GetDWORDValue(HKLM, strKey & strSubkey, strEntry1c, val)
该变量的值要么是从注册表读取的值(
Check=0
),要么是无法读取的值(
Check 0

如果要在DWORD值不存在时调用
GetStringValue
,则还必须将条件从
IsNull(Check)
更改为
Check 0
IsNull(val)

  • @安斯加给出了这么好的解释(+1)
  • user1691832仍在使用空检查进行实验
  • 文档倾向于避免谈论返回值和可能的错误
  • 一些代码显示您应该检查数字返回值以及如何执行该操作:

    Option Explicit
    
    Const HKLM = &H80000002 ' HKEY_LOCAL_MACHINE
    Const BAD  = &H80000010 ' BAD HIVE
    
    Dim oReg   : Set oReg = GetObject("winmgmts://./root/default:StdRegProv")
    Dim aParms : aParms   = Array( _
          Array(HKLM, "SYSTEM\CurrentControlSet\Control\CrashControl", "AutoReboot") _
        , Array(HKLM, "SYSTEM\CurrentControlSet\Control\CrashControl", "YYYYYYYYYY") _
        , Array(HKLM, "SYSTEM\CurrentControlSet\Control\XXXXXXXXXXXX", "AutoReboot") _
        , Array(HKLM, "SYSTEM\CurrentControlSet\Control\XXXXXXXXXXXX", "YYYYYYYYYY") _
        , Array(HKLM, "SYSTEM\CurrentControlSet\Control\CrashControl", "AutoReboot") _
        , Array(BAD , "SYSTEM\CurrentControlSet\Control\CrashControl", "AutoReboot") _
    )
    Dim lValue ' 'dwValue' is type prefix fraud
    Dim aParm
    For Each aParm In aParms
        WScript.Echo "try to get long Value from:", Join(aParm, "\")
        Dim iRet : iRet = oReg.GetDWORDValue(aParm(0), aParm(1), aParm(2), lValue)
        If 0 = iRet Then
           WScript.Echo "       got:", iRet, TypeName(lValue), lValue
        Else
           WScript.Echo "       got:", iRet, "won't try to display", TypeName(lValue)
        End If
    Next
    
    输出:

    cscript 14794473.vbs
    try to get long Value from: -2147483646\SYSTEM\CurrentControlSet\Control\CrashControl\AutoReboot
           got: 0 Long 1
    try to get long Value from: -2147483646\SYSTEM\CurrentControlSet\Control\CrashControl\YYYYYYYYYY
           got: 1 won't try to display Null
    try to get long Value from: -2147483646\SYSTEM\CurrentControlSet\Control\XXXXXXXXXXXX\AutoReboot
           got: 2 won't try to display Null
    try to get long Value from: -2147483646\SYSTEM\CurrentControlSet\Control\XXXXXXXXXXXX\YYYYYYYYYY
           got: 2 won't try to display Null
    try to get long Value from: -2147483646\SYSTEM\CurrentControlSet\Control\CrashControl\AutoReboot
           got: 0 Long 1
    try to get long Value from: -2147483632\SYSTEM\CurrentControlSet\Control\CrashControl\AutoReboot
           got: 6 won't try to display Null
    

    strValue1可能没有在循环中重新初始化它的值?@SpectralGhost否,
    strValue1
    总是在调用
    GetStringValue
    时重新初始化。这很好地解释了这一点,出于某种原因,我认为“Check”应该包含键的实际值。我可能弄错了,但我很确定我尝试的第一件事是:
    strEntry1c=“SystemComponent”Check=objReg.GetDWORDValue(HKLM,strKey&strSubkey,strEntry1c,Chk1)如果为null(Chk1),那么intRet1=objReg.GetStringValue(HKLM,strKey&strSubkey,stry1a,strValue1)
    出于某种原因,这也不起作用,但也许我做错了什么。
    Check = objReg.GetDWORDValue(HKLM, strKey & strSubkey, strEntry1c, val)
    
    Option Explicit
    
    Const HKLM = &H80000002 ' HKEY_LOCAL_MACHINE
    Const BAD  = &H80000010 ' BAD HIVE
    
    Dim oReg   : Set oReg = GetObject("winmgmts://./root/default:StdRegProv")
    Dim aParms : aParms   = Array( _
          Array(HKLM, "SYSTEM\CurrentControlSet\Control\CrashControl", "AutoReboot") _
        , Array(HKLM, "SYSTEM\CurrentControlSet\Control\CrashControl", "YYYYYYYYYY") _
        , Array(HKLM, "SYSTEM\CurrentControlSet\Control\XXXXXXXXXXXX", "AutoReboot") _
        , Array(HKLM, "SYSTEM\CurrentControlSet\Control\XXXXXXXXXXXX", "YYYYYYYYYY") _
        , Array(HKLM, "SYSTEM\CurrentControlSet\Control\CrashControl", "AutoReboot") _
        , Array(BAD , "SYSTEM\CurrentControlSet\Control\CrashControl", "AutoReboot") _
    )
    Dim lValue ' 'dwValue' is type prefix fraud
    Dim aParm
    For Each aParm In aParms
        WScript.Echo "try to get long Value from:", Join(aParm, "\")
        Dim iRet : iRet = oReg.GetDWORDValue(aParm(0), aParm(1), aParm(2), lValue)
        If 0 = iRet Then
           WScript.Echo "       got:", iRet, TypeName(lValue), lValue
        Else
           WScript.Echo "       got:", iRet, "won't try to display", TypeName(lValue)
        End If
    Next
    
    cscript 14794473.vbs
    try to get long Value from: -2147483646\SYSTEM\CurrentControlSet\Control\CrashControl\AutoReboot
           got: 0 Long 1
    try to get long Value from: -2147483646\SYSTEM\CurrentControlSet\Control\CrashControl\YYYYYYYYYY
           got: 1 won't try to display Null
    try to get long Value from: -2147483646\SYSTEM\CurrentControlSet\Control\XXXXXXXXXXXX\AutoReboot
           got: 2 won't try to display Null
    try to get long Value from: -2147483646\SYSTEM\CurrentControlSet\Control\XXXXXXXXXXXX\YYYYYYYYYY
           got: 2 won't try to display Null
    try to get long Value from: -2147483646\SYSTEM\CurrentControlSet\Control\CrashControl\AutoReboot
           got: 0 Long 1
    try to get long Value from: -2147483632\SYSTEM\CurrentControlSet\Control\CrashControl\AutoReboot
           got: 6 won't try to display Null