Solved

installed programs

Posted on 2001-07-17
9
296 Views
Last Modified: 2008-02-01
How can i export the list of installed programs in control panel, add/remove programs to a text file (using vb6)

If possible i want this to work in NT, 200 and 96/98



0
Comment
Question by:jkblymn
  • 5
  • 2
  • 2
9 Comments
 
LVL 8

Expert Comment

by:Dave_Greene
Comment Utility
Ok, this isn't as easy as it should be, but here is what you have to do

read from the registry here

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\

You ONLY want to print the sub-folder data which has a "Display Name" string.


0
 
LVL 1

Expert Comment

by:johnczimm
Comment Utility
This will dump the info to a list box

On a form add a listbox (list1)
Add this code:

Option Explicit

Private Sub Form_Load()
Dim sDisplay As String
Dim sKey As String
Dim hKey As Long, Cnt As Long, sSave As String
   
    List1.AddItem "RegEnumKeyEx: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
    'Open a registry key
    RegOpenKey HKEY_LOCAL_MACHINE, "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", hKey
   
    Do
        'Create a buffer
        sSave = String(255, 0)
        'Enumerate the keys
        If RegEnumKeyEx(hKey, Cnt, sSave, 255, 0, vbNullString, ByVal 0&, ByVal 0&) <> 0 Then Exit Do
        'Print the result to the form
        sKey = StripTerminator(sSave)
        sDisplay = RemoteReg(HKEY_LOCAL_MACHINE, "172.2.50.39", "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" & sKey, "DisplayName")
'        sDisplay = Mid(sDisplay, 1, Len(sDisplay) - 1)
       
        List1.AddItem "   " & sKey & " (" & sDisplay & ")"
        Cnt = Cnt + 1
    Loop
    List1.AddItem "Total Items: " & Cnt
    'Close the registry key
    RegCloseKey hKey
   
   
    List1.AddItem ""
    List1.AddItem "RegEnumValue: HKEY_CLASSES_ROOT\Installer\Products"
    'Open a new key
    RegOpenKey HKEY_CLASSES_ROOT, "Installer\Products", hKey
    Cnt = 0
    Do
        'Create a buffer
        sSave = String(255, 0)
        'enumerate the values
        If RegEnumKeyEx(hKey, Cnt, sSave, 255, 0, vbNullString, ByVal 0&, ByVal 0&) <> 0 Then Exit Do
        'pritn the results to the form
        sKey = StripTerminator(sSave)
        sDisplay = RemoteReg(HKEY_CLASSES_ROOT, "172.2.50.39", "Installer\Products\" & sKey, "ProductName") 'Replace 172.2.50.39 with your IP address
        List1.AddItem "   " & sKey & " (" & sDisplay & ")"
        Cnt = Cnt + 1
    Loop
    List1.AddItem "Total Items: " & Cnt

    'Close the registry
    RegCloseKey hKey

End Sub




Add a Module and add this code:

Option Explicit


Global Const REG_SZ As Long = 1
Global Const REG_DWORD As Long = 4

Global Const HKEY_CLASSES_ROOT = &H80000000
Global Const HKEY_CURRENT_USER = &H80000001
Global Const HKEY_LOCAL_MACHINE = &H80000002
Global Const HKEY_USERS = &H80000003
Global Const HKEY_CURRENT_CONFIG = &H80000005

Global Const ERROR_NONE = 0
Global Const ERROR_BADDB = 1
Global Const ERROR_BADKEY = 2
Global Const ERROR_CANTOPEN = 3
Global Const ERROR_CANTREAD = 4
Global Const ERROR_CANTWRITE = 5
Global Const ERROR_OUTOFMEMORY = 6
Global Const ERROR_INVALID_PARAMETER = 7
Global Const ERROR_ACCESS_DENIED = 8
Global Const ERROR_INVALID_PARAMETERS = 87
Global Const ERROR_NO_MORE_ITEMS = 259

Global Const KEY_ALL_ACCESS = &H3F

Global Const REG_OPTION_NON_VOLATILE = 0

Declare Function RegConnectRegistry Lib "advapi32.dll" Alias _
"RegConnectRegistryA" (ByVal lpMachineName As String, ByVal hKey As Long, _
phkResult As Long) As Long

Declare Function RegCloseKey Lib "advapi32.dll" _
(ByVal hKey As Long) As Long

Declare Function RegCreateKeyEx Lib "advapi32.dll" Alias _
"RegCreateKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, _
ByVal Reserved As Long, ByVal lpClass As String, ByVal dwOptions _
As Long, ByVal samDesired As Long, ByVal lpSecurityAttributes _
As Long, phkResult As Long, lpdwDisposition As Long) As Long

Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias _
"RegOpenKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, _
ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As _
Long) As Long

Declare Function RegQueryValueExString Lib "advapi32.dll" Alias _
"RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As _
String, ByVal lpReserved As Long, lpType As Long, ByVal lpData _
As String, lpcbData As Long) As Long

Declare Function RegQueryValueExLong Lib "advapi32.dll" Alias _
"RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As _
String, ByVal lpReserved As Long, lpType As Long, lpData As _
Long, lpcbData As Long) As Long

Declare Function RegQueryValueExNULL Lib "advapi32.dll" Alias _
"RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As _
String, ByVal lpReserved As Long, lpType As Long, ByVal lpData _
As Long, lpcbData As Long) As Long

Declare Function RegSetValueExString Lib "advapi32.dll" Alias _
"RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName As String, _
ByVal Reserved As Long, ByVal dwType As Long, ByVal lpValue As _
String, ByVal cbData As Long) As Long

Declare Function RegSetValueExLong Lib "advapi32.dll" Alias _
"RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName As String, _
ByVal Reserved As Long, ByVal dwType As Long, lpValue As Long, _
ByVal cbData As Long) As Long

Declare Function RegOpenKey Lib "advapi32.dll" Alias _
"RegOpenKeyA" (ByVal hKey As Long, ByVal lpSubKey As String, _
phkResult As Long) As Long

Declare Function RegEnumKeyEx Lib "advapi32.dll" Alias _
"RegEnumKeyExA" (ByVal hKey As Long, ByVal dwIndex As Long, _
ByVal lpName As String, lpcbName As Long, ByVal lpReserved As Long, _
ByVal lpClass As String, lpcbClass As Long, lpftLastWriteTime As Any) As Long

Declare Function RegEnumValue Lib "advapi32.dll" Alias _
"RegEnumValueA" (ByVal hKey As Long, ByVal dwIndex As Long, _
ByVal lpValueName As String, lpcbValueName As Long, ByVal lpReserved As Long, _
lpType As Long, lpData As Byte, lpcbData As Long) As Long

'This function is used to stripoff all the unnecessary chr$(0)'s
Public Function StripTerminator(sInput As String) As String
    Dim ZeroPos As Integer
    'Search the first chr$(0)
    ZeroPos = InStr(1, sInput, vbNullChar)
    If ZeroPos > 0 Then
        StripTerminator = Left$(sInput, ZeroPos - 1)
    Else
        StripTerminator = sInput
    End If
End Function
 
Public Function SetValueEx(ByVal hKey As Long, sValueName As String, _
                           lType As Long, vValue As Variant) As Long
  Dim lValue As Long
  Dim sValue As String
  Select Case lType
 
      Case REG_SZ
          sValue = vValue & Chr$(0)
          SetValueEx = RegSetValueExString(hKey, sValueName, 0&, _
                                           lType, sValue, Len(sValue))
      Case REG_DWORD
          lValue = vValue
          SetValueEx = RegSetValueExLong(hKey, sValueName, 0&, _
                       lType, lValue, 4)
      End Select
End Function

Function QueryValueEx(ByVal lhkey As Long, ByVal szValueName As String, _
                    vValue As Variant) As Long
  Dim cch As Long
  Dim lrc As Long
  Dim lType As Long
  Dim lValue As Long
  Dim sValue As String

  On Error GoTo QueryValueExError

  ' Determine the size and type of data to be read
  lrc = RegQueryValueExNULL(lhkey, szValueName, 0&, lType, 0&, cch)
  'If lrc <> ERROR_NONE Then Error 5

  Select Case lType
      ' For strings
      Case REG_SZ:
          sValue = String(cch, 0)
          lrc = RegQueryValueExString(lhkey, szValueName, 0&, lType, sValue, cch)
          If lrc = ERROR_NONE Then
              vValue = Left$(sValue, cch)
          Else
              vValue = Empty
          End If
      ' For DWORDS
      Case REG_DWORD:
          lrc = RegQueryValueExLong(lhkey, szValueName, 0&, lType, lValue, cch)
          If lrc = ERROR_NONE Then vValue = lValue
      Case Else
          'all other data types not supported
          lrc = -1
  End Select

QueryValueExExit:
  QueryValueEx = lrc
  Exit Function
QueryValueExError:
  Resume QueryValueExExit
 
End Function

Public Sub SetKeyValue(sKeyName As String, sValueName As String, _
vValueSetting As Variant, lValueType As Long)
  Dim lRetVal As Long         'result of the SetValueEx function
  Dim hKey As Long         'handle of open key

  'open the specified key
  lRetVal = RegOpenKeyEx(HKEY_CURRENT_USER, sKeyName, 0, _
                         KEY_ALL_ACCESS, hKey)
  lRetVal = SetValueEx(hKey, sValueName, lValueType, vValueSetting)
  RegCloseKey (hKey)
End Sub

Public Function RemoteReg(txtTopLevelKey As String, txtRemMachName As String, txtKeyName As String, txtKeyValue As String) As String
Dim lRetVal As Long         'used to hold return value for all API calls

Dim sRemMachName As String  'used by RegConnectRegistry
Dim lTopLevelKey As Long    'used by RegConnectRegistry
Dim lHKeyhandle As Long     'used by RegConnectRegistry & RegOpenKeyEx

Dim sKeyName As String      'used by RegOpenKeyEx
Dim lhkey As Long           'used by RegOpenKeyEx & RegQueryValueEx & RegCloseKey

Dim sValueName As String    'used by RegQueryValueEx
Dim vValue As String        'used by RegQueryValueEx

'               sKeyName = "Software\Microsoft\Windows NT\CurrentVersion\WinLogon" 'Gets user entered subkey name"
'               sValueName = "DefaultUserName"        'Gets user entered value name
'               sKeyName = "System\CurrentControlSet\Control" 'Gets user entered subkey name"
'               sValueName = "CurrentUser"        'Gets user entered value name
'               lTopLevelKey = HKEY_LOCAL_MACHINE
 
    lTopLevelKey = txtTopLevelKey
    sRemMachName = txtRemMachName         'Gets user entered name of remote machine
    sKeyName = txtKeyName
    sValueName = txtKeyValue
   
   
    DoEvents
   
    'Get handle of a top level registry key on remote machine
    lRetVal = RegConnectRegistry(sRemMachName, lTopLevelKey, lHKeyhandle)
   
    If lRetVal = 0 Then
       
        lRetVal = RegOpenKeyEx(lHKeyhandle, sKeyName, 0, KEY_ALL_ACCESS, lhkey)     'Get handle of the key which contains the value you need to check
       
        lRetVal = QueryValueEx(lhkey, sValueName, vValue)   'Get the value
       
        RegCloseKey (lhkey)     'Always a good idea to clean up
       
        If lRetVal = 0 Then    'QueryValueEx succeeded
            RemoteReg = Mid(vValue, 1, Len(vValue) - 1)
        Else
            RemoteReg = "Unobtainable"
        End If
    Else
        RemoteReg = "Inaccessible"
    End If
   
End Function

0
 

Author Comment

by:jkblymn
Comment Utility
johnczimm - thanks - that works well

If possible though i'd like to restrict the list to just what is in control panel, add/remove programs. (at the moment it displays loads of other stuff

eg.

ie5bakex
ie_extra
st5unst
ie4data
....etc etc

 If thats possible i'll increase the points - otherwise i'll award them to you

0
 
LVL 8

Expert Comment

by:Dave_Greene
Comment Utility
This isn't a code solution but it is what you are looking for  

<You ONLY want to print the sub-folder data which has a "Display Name" string.>

0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 
LVL 1

Accepted Solution

by:
johnczimm earned 150 total points
Comment Utility
Use the same Module from my last comment. Put a TreeView (TreeView1) control on the form and replace the code in the Form_Load with the following code:

Dim sDisplay As String
Dim sVersion As String
Dim sKey As String
Dim hKey As Long, Cnt As Long, sSave As String
Dim vValue As String
Dim lRetVal As Long         'used to hold return value for all API calls
Dim lhkey As Long           'used by RegOpenKeyEx & RegQueryValueEx & RegCloseKey
Dim lHKeyhandle As Long     'used by RegConnectRegistry & RegOpenKeyEx

    TreeView1.Nodes.Add , , "ROOT", "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
    'Open a registry key
    RegOpenKey HKEY_LOCAL_MACHINE, "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", hKey
   
    Do
        'Create a buffer
        sSave = String(255, 0)
        'Enumerate the keys
        If RegEnumKeyEx(hKey, Cnt, sSave, 255, 0, vbNullString, ByVal 0&, ByVal 0&) <> 0 Then Exit Do
        'Print the result to the form
        sKey = StripTerminator(sSave)
       
        lRetVal = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" & sKey, 0, KEY_ALL_ACCESS, lhkey)     'Get handle of the key which contains the value you need to check

        lRetVal = QueryValueEx(lhkey, "DisplayName", vValue)
       
        If lRetVal = 0 Then    'QueryValueEx succeeded
            sDisplay = Mid(vValue, 1, Len(vValue) - 1)
        Else
            sDisplay = "Unobtainable"
        End If
       
        lRetVal = QueryValueEx(lhkey, "DisplayVersion", vValue)
       
        If lRetVal = 0 Then    'QueryValueEx succeeded
            sVersion = Mid(vValue, 1, Len(vValue) - 1)
        Else
            sVersion = "Unobtainable"
        End If
       
        RegCloseKey (lhkey)     'Always a good idea to clean up
       
        Cnt = Cnt + 1
       
        If Not sDisplay = "Unobtainable" Then
            If Mid(sKey, 1, 1) = "{" Then
                TreeView1.Nodes.Add "ROOT", tvwChild, "K" & Cnt, sDisplay
                If Not sVersion = "Unobtainable" Then
                    TreeView1.Nodes.Add "K" & Cnt, tvwChild, "V" & Cnt, "Version: " & sVersion
                End If
            Else
                TreeView1.Nodes.Add "ROOT", tvwChild, "K" & Cnt, sKey
               
                If Not sDisplay = "Unobtainable" And sKey <> sDisplay Then
                    TreeView1.Nodes.Add "K" & Cnt, tvwChild, "D" & Cnt, sDisplay
                End If
               
                If Not sVersion = "Unobtainable" Then
                    TreeView1.Nodes.Add "K" & Cnt, tvwChild, "V" & Cnt, "Version: " & sVersion
                End If
            End If
        End If
   
    Loop
    TreeView1.Nodes("ROOT").Text = TreeView1.Nodes("ROOT").Text & " (Total Items: " & Cnt & ")"
    TreeView1.Nodes("ROOT").Expanded = True
    'Close the registry key
    RegCloseKey hKey
0
 
LVL 8

Expert Comment

by:Dave_Greene
Comment Utility
Nice work John!

Getting lazy in my old age  :)
0
 

Author Comment

by:jkblymn
Comment Utility
Nice code - Thanks!
0
 
LVL 8

Expert Comment

by:Dave_Greene
Comment Utility
Let me see if I can shorten the process...  :)
0
 
LVL 8

Expert Comment

by:Dave_Greene
Comment Utility
Well, I wouldn't get too excited about a faster version.. I was going to try the Registry object, but don't have time now...  good luck, happy coding  :)
0

Featured Post

6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

Join & Write a Comment

Have you ever wanted to restrict the users input in a textbox to numbers, and while doing that make sure that they can't 'cheat' by pasting in non-numeric text? Of course you can do that with code you write yourself but it's tedious and error-prone …
This article describes some techniques which will make your VBA or Visual Basic Classic code easier to understand and maintain, whether by you, your replacement, or another Experts-Exchange expert.
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now