0

インストールされているプログラムのリストを返すVBスクリプトを微調整しようとして、多くの時間を無駄にしたことを認めたくありません。どこが間違っていたかを理解しようとしています。

私が遭遇した問題は、オンラインで見つけたすべての「リストプログラム」タイプのスクリプトが、「DisplayName」フィールドを持つすべてのキーをテキストファイルに入力することです。たくさんの検索にもかかわらず、add/removeまたはappwiz.cplに入力されたリストだけを返すものを見つけることができませんでした。これは、私が見つけた「GrabEverything」タイプのスクリプトの例です。

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」と「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

あなたの質問がここにあるのか、私にはよくわかりません。Nullどの値(または)を期待しますNot Nullか?レジストリから読み取られた値、またはレジストリ値の読み取りに使用する関数の戻り値?これらの2つの値は、まったく異なる意味を持っています。

さらに、最後のコードスニペットの関数呼び出しは完全に正しくありません(ただし、機能します)。

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

GetDWORDValueパラメータ、、を使用して関数をhDefKey呼び出しsSubkeyNameていsValueNameますが、実際の値(uValue)のoutパラメータを省略しています。ただし、関数の戻り値はレジストリ値のデータではなくSystemComponent、整数のステータスコードであるかどうかを示します。操作が成功したかどうか。レジストリ値から読み取られたデータは、通常、関数の4番目のパラメーターに格納されます。このパラメーターが欠落しているため、デフォルトでになりNullます。つまり、ランタイム環境は関数呼び出しを次のように拡張します。

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

strKey & strSubkeyの値は、および/またはstrEntry1c存在するか存在しないかに応じてCheck、0(値が正常に読み取られた)、1(値が存在しない)、または2(キーが存在しない)のいずれかになります。ただし、データを保持する変数がないため(4番目のパラメーターは) 、レジストリから読み取られたものはすべて削除されますNull。このため、条件IsNull(Check)は常に評価されFalseGetStringValue呼び出されることはありません。

4番目のパラメーターとして実際の変数を関数呼び出しに追加する場合:

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

その変数の値は、レジストリから読み取られた値(Check = 0)、またはNull値を読み取れない場合()のいずれかになりますCheck <> 0

また、条件をIsNull(Check)から、Check <> 0またはDWORD値が存在しないときIsNull(val)に呼び出す場合はに変更する必要があります。GetStringValue

于 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 に答える