Compiled EXE and registry read access error
Does anyone know why this doesn't work? I found the VBScript below that access the registry and extracts the Install key for windows. The VBScript produces the correct results on WinXP and Win7 64bit.
I tried dumping this into a form and compiling it into an EXE. The VB Code is below. As you can see the code is pretty much the same. The VB code runs fine on WinXP but on Win7 I'm getting an Unable to read registry key error.
I assume it is probably a premissions issue but I'm not sure. I'm running the EXE as an Administrator (right click and run as) and that is the same way I run the VBScript.
Does anyone know why the EXE with pretty much the same code cannot read a registery value that VBScript can?
VBScript
Code:
Set WshShell = CreateObject("WScript.Shell")
key = "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\"
digitalId = WshShell.RegRead(key & "DigitalProductId")
ProductName = "Product Name : " & WshShell.RegRead(key & "ProductName") & vbNewLine
ProductId = "Product Id : " & WshShell.RegRead(key & "ProductId") & vbNewLine
ProductKey = "Install Key : " & Converted(digitalId)
ProductId = ProductName & ProductId & ProductKey
MsgBox ProductId
Function Converted(id)
Const OFFSET = 52
i = 28
Chars = "BCDFGHJKMPQRTVWXY2346789"
Do
Cur = 0
x = 14
Do
Cur = Cur * 256
Cur = id(x + OFFSET) + Cur
id(x + OFFSET) = (Cur \ 24) And 255
Cur = Cur Mod 24
x = x -1
Loop While x >= 0
i = i - 1
Converted = Mid(Chars, Cur + 1, 1) & Converted
If (((29 - i) Mod 6) = 0) And (i <> -1) Then
i = i -1
Converted = "-" & Converted
End If
Loop While i >= 0
End Function
VB6 Code
Code:
Option Explicit
Private Sub Form_Load()
Me.AutoRedraw = True
Me.Print DecryptKey
End Sub
Private Function DecryptKey()
Const OFFSET = 52
Dim WshShell As Object
Dim key As String
Dim digitalid
Dim i
Dim Chars
Dim Cur
Dim x
Dim Converted
Set WshShell = CreateObject("WScript.Shell")
key = "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\"
digitalid = WshShell.RegRead(key & "DigitalProductId")
Set WshShell = Nothing
i = 28
Chars = "BCDFGHJKMPQRTVWXY2346789"
Do
Cur = 0
x = 14
Do
Cur = Cur * 256
Cur = digitalid(x + OFFSET) + Cur
digitalid(x + OFFSET) = (Cur \ 24) And 255
Cur = Cur Mod 24
x = x - 1
Loop While x >= 0
i = i - 1
Converted = Mid(Chars, Cur + 1, 1) & Converted
If (((29 - i) Mod 6) = 0) And (i <> -1) Then
i = i - 1
Converted = "-" & Converted
End If
Loop While i >= 0
DecryptKey = Converted
End Function
Re: Compiled EXE and registry read access error
your code appears to work perfectly for me, running as limited user in w7-32
Re: Compiled EXE and registry read access error
@ MarkT
Are you receiving Run-time error '-2147024894 (80070002)';
Unable to open registry key "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DigitalProductId" for reading?
I just tried the code on my Win7 64 bit machine logged in as admin and I received the above error.
Edit:
Looking at the UAC I noticed that it set to "Never notify" while I was trying to run the above code.
Re: Compiled EXE and registry read access error
Yes that is the error. Do you get the same thing if you try running the vbscript version?
Re: Compiled EXE and registry read access error
Quote:
Originally Posted by
MarkT
Yes that is the error. Do you get the same thing if you try running the vbscript version?
No, the vbs works displaying the Product Name, Product Id, Install Key. One thing I did notice on XP is that the Visual Basic code only retrieves the "Product Id" while the script returns all the information as above. Is that suppose to happen?
Edit:
While searching for a solution to the problem on Win7 I founds lots of posts talking about how to retrieve registry info under Win7 using VB.NET.
Re: Compiled EXE and registry read access error
Quote:
Originally Posted by
Nightwalker83
No, the vbs works displaying the Product Name, Product Id, Install Key. One thing I did notice on XP is that the Visual Basic code only retrieves the "Product Id" while the script returns all the information as above. Is that suppose to happen?
Edit:
While searching for a solution to the problem on Win7 I founds lots of posts talking about how to retrieve registry info under Win7 using VB.NET.
The VB code posted was cut from larger app which among other things returns the Product Name and Product ID values listed above. The sample VB code is just stripped down to return the product key to show the associated error so yes that is what is suppose to happen.
I would also note that the VB code can read the Product Name and Product ID from the registry without error use similar code as the vbscript posted. The only difference between the key values is Product Name and Product ID are REG_SZ datatypes and the install key is a REG_BINARY datatype. I just find it odd the vbscript can read the key and the vb which is pretty much the same can't.
If I were to do this in .NET I would probably go with C#.
Re: Compiled EXE and registry read access error
Quote:
Originally Posted by
MarkT
If I were to do this in .NET I would probably go with C#.
Cool! That would suit me since I haven't done vb.net.
Re: Compiled EXE and registry read access error
Quote:
With OEM or retail license keys they're stored in the DigitalProductId registry key on x86 systems or DigitalProductId4 on x64 systems, accessed by adding KEY_WOW64_64KEY to samDesired when calling RegOpenKeyEx().
You're probably running the 64-bit WSH.
That's some raggedy code too, whew. Slightly cleaned up:
Code:
Option Explicit
Private Sub Main()
Dim WshShell As Object
Dim key As String
Dim digitalid() As Variant
Dim ProductName As String
Dim ProductId As String
Dim ProductKey As String
Set WshShell = CreateObject("WScript.Shell")
key = "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\"
digitalid = WshShell.RegRead(key & "DigitalProductId")
ProductName = "Product Name : " & WshShell.RegRead(key & "ProductName") & vbNewLine
ProductId = "Product Id : " & WshShell.RegRead(key & "ProductId") & vbNewLine
ProductKey = "Install Key : " & Converted(digitalid)
ProductId = ProductName & ProductId & ProductKey
MsgBox ProductId
End Sub
Function Converted(ByRef id() As Variant) As String
Const OFFSET As Integer = 52
Const Chars As String = "BCDFGHJKMPQRTVWXY2346789"
Dim i As Integer
Dim x As Integer
Dim Cur As Integer
For i = 1 To 25
Cur = 0
For x = 14 To 0 Step -1
Cur = 256 * Cur + id(OFFSET + x)
id(OFFSET + x) = (Cur \ 24) And 255
Cur = Cur Mod 24
Next
Converted = Mid$(Chars, Cur + 1, 1) & Converted
If i < 25 And i Mod 5 = 0 Then Converted = "-" & Converted
Next
End Function
Re: Compiled EXE and registry read access error
Stupid question but did you test that code? It just displays the form but nothing else. That is unless I am missing something?
Re: Compiled EXE and registry read access error
See Sub Main()?
The code goes into a static module, not a Form.
Works on XP, Vista, and Windows 7 - but they have to be 32-bit as written.
Re: Compiled EXE and registry read access error
Quote:
Originally Posted by
dilettante
See Sub Main()?
The code goes into a static module, not a Form.
Works on XP, Vista, and Windows 7 - but they have to be 32-bit as written.
Ah ok! Although, when I move the subMain into the module and run the code it complains that the sub or function is not defined. This is because the function is still located in the form. However, moving the function to the module results in the error as in the original post.
Note:
This is for the 64bit version of Win7 not the 32bit version which works fine. By the way, error occurred for me while I was running the code via the VB IDE.
Re: Compiled EXE and registry read access error
See the quote above regarding 64-bit Windows. You have to account for registry redirection to get the 64-bit registry hive from a 32-bit program.
1 Attachment(s)
Re: Compiled EXE and registry read access error
Ok, here's a reworked version:
Code:
Option Explicit
Private Sub Main()
Dim RegRead As RegRead
Dim DigitalId As Variant
Dim ProductName As String
Dim ProductId As String
Dim ProductKey As String
Set RegRead = New RegRead
With RegRead
.OpenKey HKLM, "SOFTWARE\Microsoft\Windows NT\CurrentVersion", KEY64
ProductName = "Product Name : " & .QueryValue("ProductName") & vbNewLine
ProductId = "Product Id : " & .QueryValue("ProductId") & vbNewLine
DigitalId = .QueryValue("DigitalProductId")
.CloseKey
ProductKey = "Install Key : " & Converted(DigitalId)
End With
ProductId = ProductName & ProductId & ProductKey
MsgBox ProductId
End Sub
Function Converted(ByRef Id As Variant) As String
Const OFFSET As Integer = 52
Const Chars As String = "BCDFGHJKMPQRTVWXY2346789"
Dim I As Integer
Dim X As Integer
Dim Cur As Integer
For I = 1 To 25
Cur = 0
For X = 14 To 0 Step -1
Cur = 256 * Cur + Id(OFFSET + X)
Id(OFFSET + X) = (Cur \ 24) And 255
Cur = Cur Mod 24
Next
Converted = Mid$(Chars, Cur + 1, 1) & Converted
If I < 25 And I Mod 5 = 0 Then Converted = "-" & Converted
Next
End Function
This uses a registry access Class, stripped down for just reading and extended to handle 64-bit registry access from a 32-bit program. The attachment includes the Class module.
Tested on XP, Vista, and Windows 7 32-bit, and on Vista 64-bit.
I don't have XP or Windows 7 64-bit handy here right now.