• This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.

GetStringValue silently fails

J
#1
I have a VBScript (see below) that uses GetStringValue to read two
values from the local registry. Both of these values are REG_SZ and
their value is "" (empty string). If I run a single instance of the
script, I *usually* get the correct output:

> cscript //nologo scan.vbs
printSeparatorFile=, typeName=String, rval=0, err=0
System.EnterpriseServices.Thunk.dll=, typeName=String, rval=0, err=0

But every once in a while, the value is reported to be a sequence of 3
unprintable bytes even though the call to GetStringValue returns 0 and
Err.Number is 0. In other words, the call silently fails with a
corrupt value.

> cscript //nologo scan.vbs
printSeparatorFile=FFE869, typeName=String, rval=0, err=0
System.EnterpriseServices.Thunk.dll=FFE869, typeName=String, rval=0,
err=0

I can cause this to happen almost immediately by calling the script
from a batch file, and running two instances of the batch file (see
below) concurrently. Once in this state, it usually stays there until
I restart the WMI service. Though sometimes it seems to clear up on
its own.

I have only seen this problem with some registry values of type REG_SZ
whose value is "".

I have also run regmon 7.03 (sysinternals) to see if other processes
are accessing these registry keys & values, but it only reports
wmiprvse.exe. Interestingly, regmon shows that QueryValue returns the
correct value "", in other words, WMI is receiving the correct value,
but there is a disconnect between WMI and my VBScript.

10.14105988 wmiprvse.exe:3728 OpenKey HKLM\SOFTWARE\Microsoft\Ole
\NONREDIST SUCCESS Access: 0x1
10.14108276 wmiprvse.exe:3728 QueryValue HKLM\SOFTWARE\Microsoft\Ole
\NONREDIST\System.EnterpriseServices.Thunk.dll SUCCESS ""
10.14109898 wmiprvse.exe:3728 QueryValue HKLM\SOFTWARE\Microsoft\Ole
\NONREDIST\System.EnterpriseServices.Thunk.dll SUCCESS ""
10.14112854 wmiprvse.exe:3728 QueryKey HKLM\SOFTWARE\Microsoft\Ole
\NONREDIST ACCESS VIOLATION
10.14114475 wmiprvse.exe:3728 CloseKey HKLM\SOFTWARE\Microsoft\Ole
\NONREDIST SUCCESS

I'm running on XP SP2. I've tried rebooting, but I get the same
result.

Any suggestions?

TIA,
Josh

--------------------------------------------------------------------------------------------------------------
Batch File
--------------------------------------------------------------------------------------------------------------
FOR /L %%G IN (1,1,1000) DO cscript //nologo scan.vbs

--------------------------------------------------------------------------------------------------------------
scan.vbs
--------------------------------------------------------------------------------------------------------------
Const HKEY_LOCAL_MACHINE = &H80000002

Set objReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\.
\root\default:StdRegProv")
If Err.Number <> 0 Then
WScript.Echo "Failed to connect"
WScript.Quit 1
End If

GetValue HKEY_LOCAL_MACHINE, "SOFTWARE\Microsoft\Windows NT
\CurrentVersion\Print\Printers\Dell Laser Printer M5200\DsSpooler",
"printSeparatorFile"
GetValue HKEY_LOCAL_MACHINE, "SOFTWARE\Microsoft\Ole\NONREDIST",
"System.EnterpriseServices.Thunk.dll"

WScript.Quit 0

Function GetValue(hive, key, name)
Dim value
Dim strValue

rval = objReg.GetStringValue(hive, key, name, value)
num = Err.Number
strValue = ToHex(Trim(value))
WScript.Echo " " & name & "=" & strValue & ", typeName=" & TypeName
(value) & ", rval=" & CStr(rval) & ", err=" & CStr(num)

End Function

Function ToHex( strLine )

iLen = Len(strLine)
strEscaped = ""

If ( iLen > 0 ) Then

For i = 1 To iLen

s = Mid(strLine, i, 1)

h = Hex(AscW(s))

If Len(h) = 1 Then
strEscaped = strEscaped & "0"
End If

strEscaped = strEscaped & h
Next

End If

ToHex = strEscaped

End Function
 
P

Pegasus [MVP]

#2
"Josh" <josh.nw@xxxxxx> wrote in message
news:e10785cf-0532-4ab3-b9c9-df9500ac26c0@xxxxxx

>I have a VBScript (see below) that uses GetStringValue to read two
> values from the local registry. Both of these values are REG_SZ and
> their value is "" (empty string). If I run a single instance of the
> script, I *usually* get the correct output:
>

>> cscript //nologo scan.vbs
>
> printSeparatorFile=, typeName=String, rval=0, err=0
> System.EnterpriseServices.Thunk.dll=, typeName=String, rval=0, err=0
>
> But every once in a while, the value is reported to be a sequence of 3
> unprintable bytes even though the call to GetStringValue returns 0 and
> Err.Number is 0. In other words, the call silently fails with a
> corrupt value.
>

>> cscript //nologo scan.vbs
>
> printSeparatorFile=FFE869, typeName=String, rval=0, err=0
> System.EnterpriseServices.Thunk.dll=FFE869, typeName=String, rval=0,
> err=0
>
> I can cause this to happen almost immediately by calling the script
> from a batch file, and running two instances of the batch file (see
> below) concurrently. Once in this state, it usually stays there until
> I restart the WMI service. Though sometimes it seems to clear up on
> its own.
>
> I have only seen this problem with some registry values of type REG_SZ
> whose value is "".
>
> I have also run regmon 7.03 (sysinternals) to see if other processes
> are accessing these registry keys & values, but it only reports
> wmiprvse.exe. Interestingly, regmon shows that QueryValue returns the
> correct value "", in other words, WMI is receiving the correct value,
> but there is a disconnect between WMI and my VBScript.
>
> 10.14105988 wmiprvse.exe:3728 OpenKey HKLM\SOFTWARE\Microsoft\Ole
> \NONREDIST SUCCESS Access: 0x1
> 10.14108276 wmiprvse.exe:3728 QueryValue HKLM\SOFTWARE\Microsoft\Ole
> \NONREDIST\System.EnterpriseServices.Thunk.dll SUCCESS ""
> 10.14109898 wmiprvse.exe:3728 QueryValue HKLM\SOFTWARE\Microsoft\Ole
> \NONREDIST\System.EnterpriseServices.Thunk.dll SUCCESS ""
> 10.14112854 wmiprvse.exe:3728 QueryKey HKLM\SOFTWARE\Microsoft\Ole
> \NONREDIST ACCESS VIOLATION
> 10.14114475 wmiprvse.exe:3728 CloseKey HKLM\SOFTWARE\Microsoft\Ole
> \NONREDIST SUCCESS
>
> I'm running on XP SP2. I've tried rebooting, but I get the same
> result.
>
> Any suggestions?
>
> TIA,
> Josh
>
> --------------------------------------------------------------------------------------------------------------
> Batch File
> --------------------------------------------------------------------------------------------------------------
> FOR /L %%G IN (1,1,1000) DO cscript //nologo scan.vbs
>
> --------------------------------------------------------------------------------------------------------------
> scan.vbs
> --------------------------------------------------------------------------------------------------------------
> Const HKEY_LOCAL_MACHINE = &H80000002
>
> Set objReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\.
> \root\default:StdRegProv")
> If Err.Number <> 0 Then
> WScript.Echo "Failed to connect"
> WScript.Quit 1
> End If
>
> GetValue HKEY_LOCAL_MACHINE, "SOFTWARE\Microsoft\Windows NT
> \CurrentVersion\Print\Printers\Dell Laser Printer M5200\DsSpooler",
> "printSeparatorFile"
> GetValue HKEY_LOCAL_MACHINE, "SOFTWARE\Microsoft\Ole\NONREDIST",
> "System.EnterpriseServices.Thunk.dll"
>
> WScript.Quit 0
>
> Function GetValue(hive, key, name)
> Dim value
> Dim strValue
>
> rval = objReg.GetStringValue(hive, key, name, value)
> num = Err.Number
> strValue = ToHex(Trim(value))
> WScript.Echo " " & name & "=" & strValue & ", typeName=" & TypeName
> (value) & ", rval=" & CStr(rval) & ", err=" & CStr(num)
>
> End Function
>
> Function ToHex( strLine )
>
> iLen = Len(strLine)
> strEscaped = ""
>
> If ( iLen > 0 ) Then
>
> For i = 1 To iLen
>
> s = Mid(strLine, i, 1)
>
> h = Hex(AscW(s))
>
> If Len(h) = 1 Then
> strEscaped = strEscaped & "0"
> End If
>
> strEscaped = strEscaped & h
> Next
>
> End If
>
> ToHex = strEscaped
>
> End Function
I was unable to duplicate your observation. On the other hand here are some
general remarks:
- While WMI is a wonderful thing, it is also quite slow. You could more than
double the speed of your code if you used the RegRead method of the
WScript.Shell object.
- There is little point in having statements such as "num = Err.Number" in
isolation. If you want your program to continue on an error condition then
you must precede the above statement with an "on error resume next". If you
don't then the program will terminate immediately.
- Your function "GetValue" is not really a function, it is a subroutine. To
avoid confusion, I would call it a sub.
- I would check if RegRead successfully reads a registry value.

Below is your code modified for the RegRead method. Is it subject to the
same problem?

Dim oWshShell
Set oWshShell = WScript.CreateObject("WScript.Shell")

GetValue "HKLM\SOFTWARE\Microsoft\Windows
NT\CurrentVersion\Print\Printers\Dell Laser Printer M5200\DsSpooler\",
"printSeparatorFile"
GetValue "HKLM\SOFTWARE\Microsoft\Ole\NONREDIST\",
"System.EnterpriseServices.Thunk.dll"

Sub GetValue(value, name)
Dim strValue
On Error Resume Next
ValueData = oWshShell.RegRead(value & name)
num = Err.Number
If Not IsEmpty(ValueData) Then
strValue = ToHex(Trim(ValueData))
WScript.Echo " " & name & "=" & strValue & ", typeName=" &
TypeName(ValueData) & ", rval=" & CStr(rval) & ", err=" & CStr(num)
End If
On Error Goto 0
End Sub

Function ToHex( strLine )
iLen = Len(strLine)
strEscaped = ""
If ( iLen > 0 ) Then
For i = 1 To iLen
s = Mid(strLine, i, 1)
h = Hex(AscW(s))
If Len(h) = 1 Then strEscaped = strEscaped & "0"
strEscaped = strEscaped & h
Next
End If
ToHex = strEscaped
End Function