Wrote a Wise package using Wise 5.52 that's basically a wrapper for a VBScript that looks for a specific reg key and then performs actions based on the value of the key (or the absence of the key).

The Wise script copies the VBScript locally and then runs it. The VBScript came from JSWare (recommended to me by VBScab, and a big thank you for that if you're reading this), and all I did was modify what reg key I was looking for, plus added some dialogs to tell me one of three results: found the key and value you were looking for; found the key but the value is different than what you were looking for; didn't find the key).

I'm testing on a 2003 Windows Server and a 2008 Windows Server. On 2003, the package works fine.

Here's where it gets weird: on 2008, if I run the Wise exe, the script tells me the reg key doesn't exist, even though it does. If I just run the VBScript (locally, from the location the Wise exe put it), the VBScript reports correctly that the reg key exists.

I also tested on a desktop environment and the Wise exe works just fine, so it's only on the 2008 server that I'm seeing the oddball results.

Any ideas why I'd be getting different results like that?
0 Comments   [ + ] Show Comments

Comments

Please log in to comment

Rating comments in this legacy AppDeploy message board thread won't reorder them,
so that the conversation will remain readable.

Answers

0
RonW,

Can you give the reg key name that you are searching for, and would be better if you post the vbscript code.
Answered 03/15/2010 by: sunny07
Senior Yellow Belt

Please log in to comment
0
Are they both 32 bit versions of Windows Server?
Answered 03/15/2010 by: SuccessSystems
Senior Yellow Belt

Please log in to comment
0
Is the Wise package an MSI or a WiseScript EXE? If the former, it would be much simpler to just use AppSearch/RegLocator to populate a property? If the latter (I'm no expert...) could you not set the script to retrieve the registry data?
Answered 03/16/2010 by: VBScab
Red Belt

Please log in to comment
0
I found out the 2008 server is 64 bit, whereas the 2003 server and my desktop are 32 bit.

Reg key I'm searching for is HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Telephony\DomainName.

Script I'm using is modified from code I got from the JSWare website:

'-- Demo script for CWMIReg class.
Dim CR, iRet, Ret, s1, T
Include "RegClass.vbs" '-- load the class.
Set CR = New CWMIReg
s1 = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Telephony\DomainName"
Ret = CR.GetValue(s1, S)
If (Len(Ret) > 0) Then
'MsgBox "GetValue" & vbCrLf & "ProductID is: " & Ret & vbCrLf & "Data type is: " & S
If Ret = "DMZ1" Then
Set objFSO = CreateObject("Scripting.FileSystemObject")
' Set a txt file so we can use its existence to set a variable in Wise and then perform an action
' based on the variable.
Set objTextFile = objFSO.CreateTextFile("C:\Windows\Temp\dmz.txt")
ElseIf Ret = "DMZ2" Then
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.CreateTextFile("C:\Windows\Temp\dmz.txt")
Else
MsgBox "Registry path exists, but value isn't DMZ1 or 2. The value is " & Ret & _
". Server is NOT in the DMZ. NOT adding subnet mask."
End If
Else
' maybe here set a different txt file that we could inventory, to indicate PCs that need some
' manual checking to determine if they're in the DMZ.
MsgBox "Registry path does not exist."
End If

Set CR = Nothing

Sub Include(FileName)
Dim sPath, FSO2, TS2, Pt1, s2
' On Error Resume Next
sPath = WScript.ScriptFullName
Pt1 = InStrRev(sPath, "\")
sPath = Left(sPath, Pt1) & FileName
Set FSO2 = CreateObject("Scripting.FileSystemObject")
Set TS2 = FSO2.OpenTextFile(sPath, 1)
s2 = TS2.ReadAll
TS2.Close
Set TS2 = Nothing
Set FSO2 = Nothing
ExecuteGlobal s2
End Sub


That script requires this script, to which I made no changes:

'-- WMI-derived Registry class for VBScript. The variables in this class all have "_" appended.
'-- Unfortunately, that makes the code a bit more difficult to read. It was done in order to
'-- avoid possible conflicts with variable names in code in scripts that use the class.
' Function Exists(Path) (Returns type of data if value, "K" if key, or "" if not found.)
' Function CreateKey(Path) Returns 0 on success. Path can have "\" at end or not.
' Function EnumKeys(Path, ArrayOut) Returns number of subkeys. ArrayOut contains subkey names.
' Function EnumVals(Path, AValsOut, ATypesOut) AVals is array of value names. ATypesOut is array of value types.
' Function GetValue(Path, Type) - Returns value data for value or key. Returns data if found.
' Function SetValue(Path, ValData, Type) - set value data.
' Function Delete(Path) ' delete key or value.
'-- private functions:
' Function EnumKeysAll(Path, ArrayOut) Return list of all subkeys in a key. Function returns number of subkeys.
' ArrayOut returns key paths.
' EnumKeysAll has been made public, in case it might be useful, but it was really written for use in deleting keys.
' Function DeleteKey deletes all subkeys in path by first calling EnumKeysAll. It then deletes parent key.
'-- ########################## BEGIN CLASS #####################################
'-- All variables in this class have "_" appended.
'-- That makes the code harder to read, but prevents possible clashes With global variables in the "parent" script.
Class CWMIReg
Private HKCR_, HKCU_, HKLM_, HKU_, Reg1_
Public Function Exists(Path_)
Dim i2_, i3_, AVals_, ATypes_, s1_, Pt1_, sName_, Path1_, IsKey_
Exists = ""
On Error Resume Next
s1_ = Path_
If Right(s1_, 1) = "\" Then '-- key.
s1_ = Left(s1_, (len(s1_) - 1))
IsKey_ = True
Else
IsKey_ = False
End If
Pt1_ = InStrRev(s1_, "\")
If Pt1_ = 0 Then Exit Function
sName_ = Right(s1_, (len(s1_) - Pt1_))
Path1_ = Left(s1_, (Pt1_ - 1))
If (IsKey_ = True) Then
i2_ = EnumKeys(Path1_, AVals_)
Else
i2_ = EnumVals(Path1_, AVals_, ATypes_)
End If
If (i2_ < 1) Then Exit Function '-- if i2_ is 0 or neg. then doesn't exist.

For i3_ = 0 to i2_ - 1
If UCase(AVals_(i3_)) = UCase(sName_) Then
If (IsKey_ = False) Then
Exists = ATypes_(i3_)
Else
Exists = "K"
End If
Exit For
End If
Next
End Function
'--------------------------------------------- GetValue -----------------------------------------------------
Public Function GetValue(Path_, TypeOut_)
Dim Path1_, sKey_, LKey_, iRet_, Val_, Pt1_, ValName_, Typ_
On Error Resume Next
If Len(TypeOut_) = 0 Then
Typ_ = Exists(Path_)
Else
Typ_ = TypeOut_
End If
If Len(Typ_) = 0 Then Exit Function
If IsNumeric(Typ_) Then
Typ_ = ConvertType(Typ_)
Else
Typ_ = UCase(Typ_)
End If
If Len(Typ_) = 0 Then Exit Function
TypeOut_ = Typ_
Pt1_ = InStr(1, Path_, "\")
If (Pt1_ > 0) Then
sKey_ = Left(Path_, (Pt1_ - 1))
Path1_ = Right(Path_, (len(Path_) - Pt1_))
LKey_ = GetHKey(sKey_)
Else
LKey_ = GetHKey(Path_)
Path1_ = ""
End If

If (Len(Path1_) = 0) Then
iRet_ = Reg1_.GetStringValue(LKey_, Path1_, "", Val_)
GetValue = Val_
Else
If (Typ_ = "K") Then
Path1_ = Left(Path1_, (len(Path1_) - 1))
iRet_ = Reg1_.GetStringValue(LKey_, Path1_, "", Val_)
GetValue = Val_
Else
Pt1_ = InStrRev(Path1_, "\")
ValName_ = Right(Path1_, (len(Path1_) - Pt1_))
Path1_ = Left(Path1_, (Pt1_ - 1))
Select Case Typ_
Case "S"
iRet_ = Reg1_.GetStringValue(LKey_, Path1_, ValName_, Val_)
Case "X"
iRet_ = Reg1_.GetExpandedStringValue(LKey_, Path1_, ValName_, Val_)
Case "B"
iRet_ = Reg1_.GetBinaryValue(LKey_, Path1_, ValName_, Val_)
Case "D"
iRet_ = Reg1_.GetDWORDValue(LKey_, Path1_, ValName_, Val_)
Case "M"
iRet_ = Reg1_.GetMultiStringValue(LKey_, Path1_, ValName_, Val_)
Case Else
Exit Function
End Select
GetValue = Val_
End If
End If
End Function
'------------------------ Enum Keys -----------------------------------
Public Function EnumKeys(Path_, AKeys_)
Dim iRet_, sKey_, LKey_, Pt1_, Path1_
On Error Resume Next
EnumKeys = -1 '-- invalid Path
Pt1_ = InStr(1, Path_, "\")
If (Pt1_ = 0) Then
sKey_ = Path_
Else
sKey_ = left(Path_, (Pt1_ - 1))
End If
LKey_ = GetHKey(sKey_)
EnumKeys = -2 '-- invalid hkey.
If (LKey_ = 0) Then Exit Function

If (sKey_ = Path_) Then
Path1_ = ""
Else
Path1_ = Right(Path_, (len(Path_) - Pt1_))
If Right(Path1_, 1) = "\" Then Path1_ = Left(Path1_, (len(Path1_) - 1))
End If
iRet_ = Reg1_.EnumKey(LKey_, Path1_, AKeys_)

Select Case iRet_
Case 0
If UBound(AKeys_) = -1 Then
EnumKeys = 0
Else
EnumKeys = UBound(AKeys_) + 1
End If
Case 2 '-- invalid key Path
EnumKeys = -3
Case -2147217405 '-- access denied H80041003
EnumKeys = -4
Case Else
EnumKeys = -5 '-- some other error.
End Select
End Function
'---------------------------------------------------- Enum Values -----------------------------
Public Function EnumVals(Path_, Vals_, Types_)
Dim sKey_, Pt1_, LKey_, iRet_, Path1_, iCnt_, Val_
On Error Resume Next
EnumVals = -1 '-- invalid Path.
Pt1_ = InStr(1, Path_, "\")
If (Pt1_ = 0) Then
sKey_ = Path_
Path1_ = ""
Else
sKey_ = Left(Path_, (Pt1_ - 1))
Path1_ = Right(Path_, (len(Path_) - Pt1_))
End If
LKey_ = GetHKey(sKey_)
EnumVals = -2 '-- invalid hkey.
If (LKey_ = 0) Then Exit Function

If Right(Path1_, 1) = "\" Then Path1_ = Left(Path1_, (len(Path1_) - 1))
iRet_ = Reg1_.EnumValues(LKey_, Path1_, Vals_, Types_)

Select Case iRet_
Case 0
If UBound(Vals_) = -1 Then
EnumVals = 0 '-- no values in key.
Else '-- values found. convert types from numeric to letters.
EnumVals = UBound(Vals_) + 1
For iCnt_ = 0 to UBound(Types_)
Val_ = Types_(iCnt_)
Types_(iCnt_) = ConvertType(Val_)
Next
End If
Case 2 '-- invalid key Path
EnumVals = -3
Case -2147217405 '-- access denied H80041003
EnumVals = -4
Case Else
EnumVals = -5 '-- some other error.
End Select
End Function
Public Function SetValue(Path_, ValData_, TypeIn_)
Dim Path1_, sKey_, LKey_, iRet_, Pt1_, ValName_, Typ_
On Error Resume Next
SetValue = -1 '-- defaults to invalid path error.
If Len(TypeIn_) = 0 Then
Typ_ = Exists(Path_)
If Len(Typ_) = 0 Then Typ_ = "S"
Else
If isNumeric(TypeIn_) Then
Typ_ = ConvertType(TypeIn_)
Else
Typ_ = UCase(TypeIn_)
End If
End If

Pt1_ = InStr(1, Path_, "\")
If (Pt1_ = 0) Then
sKey_ = Path_
Path1_ = ""
Else
sKey_ = Left(Path_, (Pt1_ - 1))
Path1_ = Right(Path_, (len(Path_) - Pt1_))
End If
LKey_ = GetHKey(sKey_)
If (LKey_ = 0) Then
SetValue = -2 '-- invalid hKey.
Exit Function
End If

If (Typ_ = "K") Or (Right(Path1_, 1) = "\") Then
If Right(Path1_, 1) = "\" Then Path1_ = Left(Path1_, (len(Path1_) - 1))
iRet_ = Reg1_.SetStringValue(LKey_, Path1_, "", ValData_)
Else
Err.clear
On Error Resume Next
Pt1_ = InStrRev(Path1_, "\")
ValName_ = Right(Path1_, (len(Path1_) - Pt1_))
Path1_ = Left(Path1_, (Pt1_ - 1))
Select Case Typ_
Case "S"
iRet_ = Reg1_.SetStringValue(LKey_, Path1_, ValName_, ValData_)
Case "X"
iRet_ = Reg1_.SetExpandedStringValue(LKey_, Path1_, ValName_, ValData_)
Case "B"
iRet_ = Reg1_.SetBinaryValue(LKey_, Path1_, ValName_, ValData_)
Case "D"
iRet_ = Reg1_.SetDWORDValue(LKey_, Path1_, ValName_, ValData_)
Case "M"
iRet_ = Reg1_.SetMultiStringValue(LKey_, Path1_, ValName_, ValData_)
Case Else
SetValue = -7
Exit Function
End Select
End If
If (Err.number = -2147217403) Then
SetValue = -6 '-- type mismatch. incoming value not valid.
Exit Function
End If
Select Case iRet_
Case 0
SetValue = 0 'success.
Case 2 '-- invalid key path
SetValue = -3
Case -2147217405 '-- access denied H80041003
SetValue = -4
Case Else
SetValue = -5 '-- some other error.
End Select
End Function
'-- create a key. Path can be with "\" at end or not, but must not have "\" if path is an HKey like "HKLM". ------------
Public Function CreateKey(Path_)
Dim sKey_, LKey_, Path1_, iRet_, Pt1_
On Error Resume Next
CreateKey = -1
Pt1_ = InStr(1, Path_, "\")
If (Pt1_ = 0) Then
sKey_ = Path_
Path1_ = ""
Else
sKey_ = Left(Path_, Pt1_ - 1)
Path1_ = Right(Path_, (len(Path_) - Pt1_))
End If
CreateKey = -2
LKey_ = GetHKey(sKey_)
If (LKey_ = 0) Then Exit Function

If Right(Path1_, 1) = "\" Then Path1_ = Left(Path1_, (len(Path1_) - 1))
iRet_ = Reg1_.CreateKey(LKey_, Path1_)

Select Case iRet_
Case 0
CreateKey = 0 '-- OK.
Case 2
CreateKey = -3
Case -2147217405 '-- access denied H80041003
CreateKey = -4
Case Else
CreateKey = -5 '-- some other error.
End Select
End Function
'-------------- Delete ---- delete a key or value. Add "\" for keys. -------------------
Public Function Delete(Path_)
Dim sKey_, LKey_, Path1_, Pt1_, ValName_, iRet_
On Error Resume Next
Delete = -1 'invalid path.
If Len(Path_) < 6 Then Exit Function
Pt1_ = InStr(1, Path_, "\")
If Pt1_ = 0 Then Exit Function
sKey_ = Left(Path_, (Pt1_ - 1))
Path1_ = Right(Path_, (len(Path_) - Pt1_))
Delete = -2 ' invalid hkey.
LKey_ = GetHKey(sKey_)
If (LKey_ = 0) Then Exit Function

If Right(Path1_, 1) = "\" Then
Path1_ = Left(Path1_, (len(Path1_) - 1))
iRet_ = DeleteKey(Path_)
Else
Pt1_ = InStrRev(Path1_, "\")
ValName_ = Right(Path1_, (len(Path1_) - Pt1_))
Path1_ = Left(Path1_, (Pt1_ - 1))
iRet_ = Reg1_.DeleteValue(LKey_, Path1_, ValName_)
End If

Select Case iRet_
Case 0
Delete = 0
Case -1 ' returned from DeleteKey
Delete = -1
Case -2 ' returned from DeleteKey
Delete = -2
Case 2
Delete = -3
Case -2147217405 '-- access denied H80041003
Delete = -4
Case 5
Delete = -6 '--keys exist under this key.
Case Else
Delete = -5 '-- some other error.
End Select

End Function
'--------------------------------------- Private Functions ----------------------------
Private Sub Class_Initialize()
On Error Resume Next
HKCR_ = &H80000000
HKCU_ = &H80000001
HKLM_ = &H80000002
HKU_ = &H80000003
Set Reg1_ = GetObject("winMgMts:root\default:StdRegProv")
If (Err.number <> 0) Then
Err.Raise 1, "WMIReg Class", "Failed to access WMI StdRegProv object. Class cannot function."
End If
End Sub
Private Sub Class_Terminate()
Set Reg1_ = Nothing
End Sub
Private Function GetHKey(sKey1_)
Select Case UCase(sKey1_)
Case "HKLM"
GetHKey = HKLM_
Case "HKCU"
GetHKey = HKCU_
Case "HKCR"
GetHKey = HKCR_
Case "HKU"
GetHKey = HKU_
Case Else
GetHKey = 0
End Select
End Function
Private Function ConvertType(TypeIn)
On Error Resume Next
Select Case TypeIn
Case 1
ConvertType = "S"
Case 2
ConvertType = "X"
Case 3
ConvertType = "B"
Case 4
ConvertType = "D"
Case 7
ConvertType = "M"
Case Else
ConvertType = ""
End Select
End Function
Private Function TestPath(PathIn)
Dim Cnt_, Pt1_, Pt2_
On Error Resume Next
Cnt_ = 0
Pt1_ = 1
Do
Pt2_ = InStr(Pt1_, PathIn, "\")
If (Pt2_ = 0) Then
Exit Do
Else
Pt1_ = Pt2_ + 1
Cnt_ = Cnt_ + 1
If (Pt1_ > Len(PathIn)) Then Exit Do
End If
Loop
TestPath = Cnt_
End Function
Public Function EnumKeysAll(Path_, AKeys_)
Dim sList_, s2_, AK1_, AK3_, AK2_(), iRet1_, i2_, UB_, iRet2_, i3_, Path1_
Path1_ = Path_
On Error Resume Next
If Right(Path1_, 1) <> "\" Then Path1_ = Path1_ & "\"
iRet1_ = EnumKeys(Path_, AK1_)
If iRet1_ > 0 Then
ReDim Preserve AK2_(iRet1_ - 1)
For i2_ = 0 to iRet1_ - 1
AK2_(i2_) = Path1_ & AK1_(i2_) & "\"
iRet2_ = EnumKeysAll(AK2_(i2_), AK3_)
If (iRet2_ > 0) Then
UB_ = UBound(AK2_)
ReDim Preserve AK2_(UB_ + iRet2_)
For i3_ = 1 to iRet2_
AK2_(UB_ + i3_) = AK3_(i3_ - 1)
Next
End If
Next
End If
AKeys_ = AK2_
EnumKeysAll = 0
EnumKeysAll = UBound(AKeys_) + 1
End Function
Private Function DeleteKey(Path_)
Dim i3_, i4_, A1_, iRet_, Pt1_, s2_, hK_, sK_
On Error Resume Next
i3_ = TestPath(Path_)
If (i3_ < 3) Then
DeleteKey = -1 '-- invalid path. Key is top level. function fails on the premise that attempted deletion was a mistake.
Exit Function
End If

Pt1_ = InStr(Path_, "\")
sK_ = Left(Path_, (Pt1_ - 1))
hK_ = GetHKey(sK_)
If (hK_ = 0) Then
DeleteKey = -2 '-- invalid hkey.
Exit Function
End If

iRet_ = EnumKeysAll(Path_, A1_)
If (iRet_ > 0) Then
For i3_ = UBound(A1_) to 0 Step -1
s2_ = A1_(i3_)
s2_ = Right(s2_, (len(s2_) - Pt1_)) '-- remove hkey string from path.
If Right(s2_, 1) = "\" Then s2_ = Left(s2_, (len(s2_) - 1))
i4_ = Reg1_.DeleteKey(hK_, s2_)
Next
End If

s2_ = Right(Path_, (len(Path_) - Pt1_))
If Right(s2_, 1) = "\" Then s2_ = Left(s2_, (len(s2_) - 1))
i3_ = Reg1_.DeleteKey(hK_, s2_)
DeleteKey = i3_
End Function
End Class
Answered 03/16/2010 by: RonW
Green Belt

Please log in to comment
0
VBScab: it's a Wisescript exe.
Answered 03/16/2010 by: RonW
Green Belt

Please log in to comment
0
OK, so why bother with a VBS? WiseScript is easily capable of reading registry data and assigning it to a script variable.
Answered 03/16/2010 by: VBScab
Red Belt

Please log in to comment
0
Ah. Good point. Now I'm doing the reg key check directly in Wise and my original issue is still happening: the script works everywhere except for the Windows Server 2008 PC I'm testing on, which is 64 bit as opposed to everything else (32 bit), so I have to think that's the issue. Is there any way I can make this work on a 64 bit machine? I'm using Wise Package Studio 5.52.
Answered 03/16/2010 by: RonW
Green Belt

Please log in to comment
0
Shouldn't you be looking under the wow6432node for 64-bit OS ?!

You'll need to check for 32-bit or 64-bit OS then query the appropriate part of the registry.

Sorry if I've got the wrong end of the stick here!

Cheers,
Rob.
Answered 03/16/2010 by: MSIPackager
Third Degree Black Belt

Please log in to comment
0
That seems to be another clue, though I'm still not sure what the answer is.
I checked the 2008 server under the key HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Telephony and there's no DomainName value there, but there is a DomainName value under HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Telephony, which is what I'm after.

But I reckon that what's happening, if I'm understanding it correctly (and let me be the first to say that maybe I'm not...) , is that when a 32-bit app (which is what I take my Wise-created exe is) queries a value at HKLM\SOFTWARE\... on a 64-bit machine, the app really reads from HKLM\SOFTWARE\Wow6432Node\...

And THAT'S why I'm being told the reg value doesn't exist. Because it doesn't under the Wow6432Node key.

So am I going to have to create this as a 64 bit app if I want it to work on a 64 bit machine? And if so, I'm guessing I can't do it w/ Wise 5.52, so what are my options?
Answered 03/16/2010 by: RonW
Green Belt

Please log in to comment
0
Your logic makes sense to me. I can't see how you'll read 64-bit registry data from a 32-bit process - especially from a wise script .exe

However I googled a bit and found a couple of interesting articles (there are lots out there!) - I don't have a 64-bit test environment to give them a try but I hope they are of some use:

http://www.symantec.com/connect/downloads/wise-installation-builder-7-64-bit-registry-script-actions
http://stackoverflow.com/questions/1229760/how-do-i-read-64-bit-registry-values-from-vbscript-running-as-a-an-msi-post-insta

Let us know how you get on....

Cheers,
Rob.
Answered 03/16/2010 by: MSIPackager
Third Degree Black Belt

Please log in to comment
0
Is it necessary to run this from a wisescript? It sounds to me like the problem is that you're attempting to access 64-bit registry nodes from a 32-bit process, so why not cut out the process? Is there some limiting factor that's preventing you from running this directly as a vbscript?
Answered 03/16/2010 by: Jsaylor
Second Degree Blue Belt

Please log in to comment
0
Thanks for doing the Googling for me, Rob. My mouse-clicking hand was JUST. SO. TIRED. [;)]

Seriously, though, the links were a help and I adapted the VBScript in the first link, so now I just need to add a bit of logic to the package that determines 32-bit vs. 64-bit and I should be good to go.

Jsaylor: Good question. But I'm running this from a Wisescript as part of a package that does some other actions, one of which will be determined by the value found from the VBScript that queries the reg.
Answered 03/16/2010 by: RonW
Green Belt

Please log in to comment
Answer this question or Comment on this question for clarity