2013-02-10 50 views
0

我討厭承認我浪費了大量時間試圖調整一個VB腳本,該腳本返回已安裝程序的列表,並試圖瞭解我出錯的位置。爲什麼不存在的註冊表值回到「1」而不是空值?

我遇到的問題是,我在網上找到的每個「列表程序」類型腳本都會填充每個具有「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 

因爲我找不到它,我決定把它自己。查找Windows用來排除條目的字段非常簡單。如果包含字段「ParentDisplayName」或「SystemComponent」,則註冊表中的「卸載」鍵中列出的所有鍵均被排除。我所要做的就是引入一種方法來屏蔽包含上述字段的鍵,以便它們不會被添加到ObjTextFile.WriteLine中。

我的問題是應該爲null的值是否會返回爲「1」?我真的很想知道出了什麼問題,所以我避免在將來浪費太多時間。

腳本我終於得到工作是在這裏:

(注意提交的文本文件必須以同時具有「SystemComponent」和「1」,「ParentDisplayName」不排除,但我有。不知道爲什麼它是「1」,而不是空

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) 
+0

strValue1沒有得到在循環也許它的價值重新初始化? – UnhandledExcepSean 2013-02-10 04:31:00

+1

@SpectralGhost否,調用'GetStringValue'時總會重新初始化'strValue1'。 – 2013-02-10 12:32:51

回答

2

這不是很清楚,我什麼你的我的問題在這裏。您期望哪個值爲Null(或Not Null)?從註冊表中讀取的值或用於讀取註冊表值的函數的返回值?這兩個值有完全不同的含義。

此外,上次代碼片段中的函數調用並不完全正確(儘管它會起作用)。

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

你調用該函數GetDWORDValue與參數hDefKeysSubkeyNamesValueName,但省略了out參數的實際值(uValue)函數.The返回值,但是,沒有的數據註冊表值SystemComponent,但是指示操作是否成功的整數狀態代碼。從註冊表中讀取的數據通常會存儲在函數的參數中。由於缺少此參數,則默認爲Null,即運行時環境擴展函數調用此:

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

根據strKey & strSubkey和/或strEntry1c無論做什麼或不存在的Check值將是0(成功讀取的值),1(值不存在)或2(鍵不存在)。不管從註冊表中讀取什麼,都將被丟棄,因爲沒有變量來保存數據(4 th參數是Null)。因此,條件IsNull(Check)總是評估爲False,並且GetStringValue永遠不會被調用。

如果添加的實際變量作爲4 參數的函數調用:

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

該變量的值將是無論是從註冊表(Check = 0)或Null如果讀出的值值無法讀取(Check <> 0)。

您也可以從IsNull(Check)更改的條件要麼Check <> 0IsNull(val)如果你想打電話GetStringValue當DWORD值不存在。

+0

這解釋得很好,出於某種原因,我認爲「檢查」將包含密鑰的實際值。我可能是錯誤的,但我敢肯定的第一件事情我嘗試之一是: 'strEntry1c = 「SystemComponent」 檢查= objReg.GetDWORDValue(HKLM,strKey&strSubkey,_ strEntry1c,Chk1的) IF的isNull (Chk1)然後 intRet1 = objReg.GetStringValue(HKLM,strKey&strSubkey,_ strEntry1a,strValue1)' 由於某種原因,這也不起作用,但也許我做錯了。 – KevinD 2013-02-10 13:09:02

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 
相關問題