0

我不想承认我浪费了大量时间来尝试调整返回已安装程序列表的 VB 脚本,并且我试图了解我哪里出错了。

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

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

因为找不到,所以决定自己做。查找 Windows 用来排除条目的字段非常容易。如果注册表中的 Uninstall 项中列出的所有项包含字段“ParentDisplayName”或“SystemComponent”,则它们将被排除。我所要做的就是引入一种方法来筛选包含上述字段的键,这样它们就不会添加到 ObjTextFile.WriteLine 中。

我的问题是应该为 null 的值会返回为“1”吗?我真的很想知道出了什么问题,所以我避免在未来浪费太多时间。

我终于开始工作的脚本在这里:

(请注意,提交给文本文件的“SystemComponent”和“ParentDisplayName”必须同时具有“1”才能被排除。但我不知道为什么它是“1”而不是 Null。

Const HKLM = &H80000002 'HKEY_LOCAL_MACHINE
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set oShell = CreateObject( "WScript.Shell" )       
System=oShell.ExpandEnvironmentStrings("%systemroot%")    
Set objTextFile = objFSO.CreateTextFile("installed.txt", True)
strComputer = "."
strKey = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"
strKey2 = "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\"
strEntry1a = "DisplayName"
strEntry1b = "QuietDisplayName"
strEntry1c = "SystemComponent"
strEntry1d = "ParentDisplayName"
Set objReg = GetObject("winmgmts://" & strComputer & _
 "/root/default:StdRegProv")
objReg.EnumKey HKLM, strKey, arrSubkeys
For Each strSubkey In arrSubkeys
  Check1 = objReg.GetDWORDValue(HKLM, strKey & strSubkey, _
   strEntry1c)
  Check2 = objReg.GetStringValue(HKLM, strKey & strSubkey, _
   strEntry1d)
  intRet1 = objReg.GetStringValue(HKLM, strKey & strSubkey, _
   strEntry1a, strValue1)
  If intRet1 <> 0 Then
    objReg.GetStringValue HKLM, strKey & strSubkey, _
     strEntry1b, strValue1
  End If
  If strValue1 <> "" and check1 = 1 and check2 = 1 Then
  objTextFile.WriteLine strValue1
  End If
Next

If objfso.folderexists (system & "\syswow64\") then
objReg.EnumKey HKLM, strKey2, arrSubkeys
For Each strSubkey In arrSubkeys
  Check1 = objReg.GetDWORDValue(HKLM, strKey2 & strSubkey, _
   strEntry1c)
  Check2 = objReg.GetStringValue(HKLM, strKey2 & strSubkey, _
   strEntry1d)
  intRet1 = objReg.GetStringValue(HKLM, strKey2 & strSubkey, _
   strEntry1a, strValue1)
  If intRet1 <> 0 Then
    objReg.GetStringValue HKLM, strKey & strSubkey, _
     strEntry1b, strValue1
  End If
  If strValue1 <> "" and check1 = 1 and check2 = 1 then
  objTextFile.WriteLine strValue1
  End If
Next
objtextfile.close
else
end if

这就是我被抓住的地方;尝试无穷无尽的变化:

  strEntry1c = "SystemComponent"
    Check = objReg.GetDWORDValue(HKLM, strKey & strSubkey, _
       strEntry1c)
    IF isNull(Check) Then
      intRet1 = objReg.GetStringValue(HKLM, strKey & strSubkey, _
       strEntry1a, strValue1)
4

2 回答 2

2

It's not quite clear to me what your question is here. Which value do you expect to be Null (or Not Null)? The value read from the registry or the return value of the function you use to read the registry value? Those two values have entirely different meanings.

Besides, the function call in your last code snippet isn't quite right (although it will work).

strEntry1c = "SystemComponent"
Check = objReg.GetDWORDValue(HKLM, strKey & strSubkey, strEntry1c)

You're calling the function GetDWORDValue with the parameters hDefKey, sSubkeyName and sValueName, but omit the out parameter for the actual value (uValue).The return value of the function, however, is not the data of the registry value SystemComponent, but an integer status code indicating if the operation was successful or not. The data read from the registry value would normally be stored in the function's 4th parameter. Since this parameter is missing, it defaults to Null, i.e. the runtime environment expands the function call to this:

Check = objReg.GetDWORDValue(HKLM, strKey & strSubkey, strEntry1c, Null)

Depending on whether strKey & strSubkey and/or strEntry1c do or don't exist, the value of Check will be either 0 (value successfully read), 1 (value doesn't exist), or 2 (key doesn't exist). Whatever is read from the registry will be dropped, though, because there's no variable to hold the data (4th parameter is Null). Because of this the condition IsNull(Check) always evaluates to False and GetStringValue is never called.

If you add an actual variable as the 4th parameter to the function call:

Check = objReg.GetDWORDValue(HKLM, strKey & strSubkey, strEntry1c, val)

the value of that variable will be either the value read from the registry (Check = 0) or Null if the value can't be read (Check <> 0).

You also have to change the condition from IsNull(Check) to either Check <> 0 or IsNull(val) if you want to call GetStringValue when the DWORD value was not present.

于 2013-02-10T12:31:41.477 回答
0

因为

  1. @Ansgar 给出了很好的解释(+1)
  2. user1691832 仍在试验 Null 检查
  3. 文档倾向于避免谈论返回值和可能的错误

一些代码表明应该检查数值返回值以及如何执行此操作:

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
于 2013-02-10T13:42:19.523 回答