# exe geht - exe geht nicht - eine Idee



## olek (22. März 2005)

Servus an Alle 

 Habe ein kleines VB-Programm (VB 6) geschrieben, das nun als exe vorliegt.
 Dieses führe ich auf verschiedenen PCs aus - nun folgt das komische:

 Auf einigen PCs rennt die exe tadellos auf andren PCs folgt dieser Error:
*35600, index out of bounds* 

 Die PCs auf denen die exe getestet wurde sind alle XP Prof. SP2 Kisten mit Office und anderen normalen Standardprogrammen. (keine VB Umgebung oder ähnliches).
 Auf einigen rennt die exe perfekt auf anderen taucht eben dieser Fehler auf.

 Woran könnte das liegen ?
 Habe schon etliches ausprobiert aber es kann doch nicht sein das ein und diesselbe exe auf einem pc geht und auf dem anderen wieder nicht :-(

 Bin für jeden Vorschlag sehr Dankbar!

 greets alex


----------



## Shakie (22. März 2005)

Schätzungsweise liegt es daran, dass auf manchen PCs nicht alle benötigten DLLs oder OCX-Dateien installiert sind. Überprüfe mal, welche Dateien dein Programm benötigt und schau nach, ob auf den entsprechenden PCs diese Dateien vorhanden sind.

Zum Nachgucken, welche Dateien benötigt werden kann man den "Verpackungs- und Weitergabe-Assistent" verwenden.


----------



## olek (22. März 2005)

Ich lese die Hardware über die Registry aus.
 Dabei benötige ich 2 ocx Dateien also bei mir:

 MSCOMCTL.OCX
 comctl32.ocx

 Diese beiden Dateien stehen überall im system32 Ordner auf jedem PC wo ich die exe ausprobiert habe. Trotzdem geht die exe nicht überall.

 Übrigens wo finde ich diesen "Verpackungs- und Weitergabe-Assistent" ?
 Habe ihn in VB nicht gefunden. Da gibts nur einen Visual Component Manager und einen allgemeinen Component Manager wo ich halt das Hackerl bei "Microsoft Windows Common Controls 6.0 (SP6)

 Cya Alex


----------



## Alex F. (22. März 2005)

Index out of bounds heisst normalerweise, dass du wenn du mit einem array arbeitest über die grenze hinausschiesst also bei einem array aus 4 elementen auf das 5. zugreifst 
oder dass du auf ein Item zugreifst welches es nicht gibt -> Prüfe mal ob du irgendwo eine .Item Methode verwendest.

Gruß bb


----------



## olek (22. März 2005)

Wenn es wirklich etwas mit der Grenze zu tun hätte dann würde doch das Programm überhaupt nicht funktionieren oder? ich meine es funkt ja auf einigen PCs. kann doch kein Zufall sein.

 Hier einmal der Hauptcode wobei ich nichts falsches erkennen kann:


 Private 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
 Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long
 Private Declare Function RegEnumKeyEx Lib "advapi32.dll" Alias "RegEnumKeyExA" (ByVal hKey As Long, ByVal dwIndex As Long, ByVal lpName As String, lpcbName As Long, lpReserved As Long, ByVal lpClass As String, lpcbClass As Long, lpftLastWriteTime As Any) As Long
 Private Declare Function RegQueryValueEx Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, lpData As Any, lpcbData As Long) As Long

 ' Einige RegOpenKeyEx samDesired-Konstanten
 Private Const KEY_ENUMERATE_SUB_KEYS = &H8    ' Öffnen zum Enumerieren
 Private Const KEY_READ = &H20019              ' Öffnen zum Lesen

 ' RegEnumValue lpType-Konstanten
 Private Const REG_DWORD = 4                   ' Ein 32-Bit Integerwert (Little Endian)
 Private Const REG_SZ = 1                      ' Ein VBNullChar-Zeichen Terminierter String

 ' Allgemeine (ROOT) hKey-Konstanten für die Registry Funktionen
 Private Const HKEY_LOCAL_MACHINE = &H80000002 ' Local Machine Schlüssel

 Private Const DevClassPath = "SYSTEM\ControlSet001\Control\DeviceClasses\"
 Private Const EnumPath = "System\CurrentControlSet\Enum\"
 Private Const ClassPath = "System\CurrentControlSet\Control\Class\"

 ' API Deklaration: Hostname
 Const MAX_COMPUTERNAME_LENGTH = 15
 Private Declare Function GetComputerName Lib "kernel32" _
         Alias "GetComputerNameA" (ByVal lpBuffer As String, _
         nSize As Long) As Long

 ' Wert eines Eintrags ermitteln (String)
 Private Function GetValueStr(ByVal DevicePath As String, ByVal Value As String) As String

      Dim hKey As Long, TmpStr As String * 256

      ' Schlüssel öffnen
      Call RegOpenKeyEx(HKEY_LOCAL_MACHINE, DevicePath, 0&, KEY_READ, hKey)
      If hKey <> 0 Then

         ' Eintrag lesen
         Call RegQueryValueEx(hKey, Value, 0&, REG_SZ, ByVal TmpStr, 256)
         GetValueStr = Left$(TmpStr, InStr(1, TmpStr, vbNullChar) - 1)
         RegCloseKey hKey
      End If

 End Function

 ' Wert eines Eintrags ermitteln (Long)
 Private Function GetValueLng(ByVal DevicePath As String, ByVal Value As String) As Long

      Dim hKey As Long, TmpLng As Long

      ' Schlüssel öffnen
      Call RegOpenKeyEx(HKEY_LOCAL_MACHINE, DevicePath, 0&, KEY_READ, hKey)
      If hKey <> 0 Then

         ' Eintrag lesen
         Call RegQueryValueEx(hKey, Value, 0&, REG_SZ, TmpLng, 4)
         GetValueLng = TmpLng
          RegCloseKey hKey
      End If

 End Function

 ' Enumerieren aller installierten Geräte
 Public Function EnumConntectedDevices()

      Dim hKey As Long, TmpStr As String * 256, RegClass As String * 256, i As Integer, Retval As Long

      ' Schlüssel der installierten Hardwareklassen öffnen
      Call RegOpenKeyEx(HKEY_LOCAL_MACHINE, DevClassPath, 0&, KEY_ENUMERATE_SUB_KEYS, hKey)
      If hKey <> 0 Then
           Do
                ' Hardwareklassen Enumerieren
                Retval = RegEnumKeyEx(hKey, i, TmpStr, Len(TmpStr), ByVal 0&, RegClass, Len(RegClass), ByVal 0&)
                If Retval <> 0 Then
                     Exit Do
                End If
                i = i + 1

                ' Hardwaregeräte Enumerieren
                Call EnumDevices(DevClassPath & Left$(TmpStr, InStr(1, TmpStr, vbNullChar) - 1) & "\")
           Loop
           RegCloseKey hKey
      End If

 End Function

 ' Geräte einer Klasse Enumerieren
 Private Function EnumDevices(ByVal DevicePath As String)

      Dim hKey As Long, TmpStr As String * 256, RegClass As String * 256, i As Integer, Retval As Long

      ' Schlüssel der Geräte öffnen
      Call RegOpenKeyEx(HKEY_LOCAL_MACHINE, DevicePath, 0&, KEY_ENUMERATE_SUB_KEYS Or KEY_READ, hKey)
      If hKey <> 0 Then
           Do
                ' Geräte der Hardwareklasse Enumerieren
                Retval = RegEnumKeyEx(hKey, i, TmpStr, Len(TmpStr), ByVal 0&, RegClass, Len(RegClass), ByVal 0&)
                If Retval <> 0 Then
                     Exit Do
                End If
                i = i + 1

                ' Emulierte Netzwekgeräte filtern
                If Right$(DevicePath, 39) = "{ad498944-762f-11d0-8dcb-00c04fc3358c}\" Then
                     If UCase(Left$(TmpStr, 8)) <> "##?#ROOT" And UCase(Left$(TmpStr, 6)) <> "##?#SW" Then
                          Call EnumSubDevices(DevicePath & Left$(TmpStr, InStr(1, TmpStr, vbNullChar) - 1) & "\")
                     End If
                Else
                     Call EnumSubDevices(DevicePath & Left$(TmpStr, InStr(1, TmpStr, vbNullChar) - 1) & "\")
                End If
           Loop
           RegCloseKey hKey
      End If

 End Function

 ' Instanzen der selben Hardware Enumerieren (z.B. Wave & Midi einer Soundkarte)
 Private Function EnumSubDevices(ByVal DevicePath As String)

      Dim hKey As Long, TmpStr As String * 256, RegClass As String * 256, i As Integer, Retval As Long
      Dim DevInstance As String, DevDesc As String, LI As ListItem, DExist As Boolean, j As Integer

      Call RegOpenKeyEx(HKEY_LOCAL_MACHINE, DevicePath, 0&, KEY_ENUMERATE_SUB_KEYS Or KEY_READ, hKey)

      For i = 0 To GetValueLng(DevicePath & "Control\", "ReferenceCount")
           ' Untergerät ermitteln
           Retval = RegEnumKeyEx(hKey, i, TmpStr, Len(TmpStr), ByVal 0&, RegClass, Len(RegClass), ByVal 0&)

           ' Gerät angeschlossen?
           If GetValueLng(DevicePath & Left$(TmpStr, InStr(1, TmpStr, vbNullChar) - 1) & "\Control\", "Linked") = 1 Then
                ' DeviceInstance Pfad ermitteln
                DevInstance = GetValueStr(DevicePath, "DeviceInstance")
                DevDesc = GetValueStr(EnumPath & DevInstance & "\", "DeviceDesc")
                If DevDesc = "" Then DevDesc = GetValueStr(EnumPath & DevInstance & "\", "DeviceDesc")

                ' Doppelte Einträge?
                DExist = False
                For j = 1 To ListView1.ListItems.Count
                     If ListView1.ListItems(j).SubItems(1) = DevInstance Then DExist = True
                Next j

                ' Doppelte, Storage, System und SW Geräte wollen wir nicht!
                If Not DExist And UCase(Left$(DevInstance, 2)) <> "SW" And UCase(Left$(DevInstance, 7)) <> "STORAGE" And _
                UCase(GetValueStr(EnumPath & GetValueStr(DevicePath, "DeviceInstance"), "Class")) <> "SYSTEM" Then
                     Set LI = ListView1.ListItems.Add(, , DevDesc)
                     LI.SubItems(1) = DevInstance
                End If
           End If
      Next i
      RegCloseKey hKey

 End Function


----------



## Shakie (22. März 2005)

"Verpackungs- und Weitergabe-Assistent" findest du hier: ...Dein-VB-Verzeichnis*\*Wizards*\*PDWizard*\*PDCMDLN.EXE
Überprüfe auch mal die Verwendeten DLLs, dazu in VB auf Menü "Projekt" -->"Verweise" klicken


----------



## Alex F. (23. März 2005)

Wenn es wirklich etwas mit der Grenze zu tun hätte dann würde doch das Programm überhaupt nicht funktionieren oder? 

Nein da du mit apis arbeitest und nicht alle rechner gleich sind muss das nicht sein
(könnte schon reichen wenn einer weniger speicher hat was ich nicht glaube)

2. ich habe mir deinen Code mal angeschaut:  es wäre ganz gut gewesen in welcher reihenfolge du  die Funktionen aufrufst aber egal 

3. als TIp : bau mal in alle funktionen eine kleine Fehlerbehandlung ein 
Bsp: 

Private Function GetValueStr(ByVal DevicePath As String, ByVal Value As String) As String
On Error goto GetValueStrErr
Dim hKey As Long, TmpStr As String * 256

' Schlüssel öffnen
Call RegOpenKeyEx(HKEY_LOCAL_MACHINE, DevicePath, 0&, KEY_READ, hKey)
    If hKey <> 0 Then

    ' Eintrag lesen
    Call RegQueryValueEx(hKey, Value, 0&, REG_SZ, ByVal TmpStr, 256)
    GetValueStr = Left$(TmpStr, InStr(1, TmpStr, vbNullChar) - 1)
    RegCloseKey hKey
End If
exit function 

GetValueStrErr: 

Call MSgbox "Fehler in GetValueStr" & err.number & err.description


End Function



das hilft zumindest soweit das du weisst wo du suchen musst 


Gruß bb


----------



## Filone (23. März 2005)

Ich würde meinen Hintern darauf verwetten, daß die Zeilen


```
For j = 1 To ListView1.ListItems.Count
If ListView1.ListItems(j).SubItems(1) = DevInstance Then DExist = True
Next j
```

den Fehler verursachen, denn das erste ListView-Element hat den Index 0.


----------



## Shakie (23. März 2005)

Negativ!  Die Einträge im ListView starten im Gegensatz zur ListBox mit Index 1!
_Edit:_ Könnte man den Startindex mit einer Anweisung in "Option Explicit" verändern?


----------



## JensG (23. März 2005)

Irgendwas mit dem Listview hat das aber sicher zu tun, womöglich ist es nicht gefüllt.

Am besten mittels MZ-Tools mal Zeilennummern einbauen lassen und dann für jede
Sub oder Function eine lückenlose Fehlerbehandlung einbauen. Da erspart man sich viel Zeit bei der Fehlersuche.

z.B.


```
10     On Error GoTo Fehler

20     'dein Code

Ausgang:
            
30     Exit Sub
            
Fehler:
         
40     MsgBox "Fehler Sub in Zeile " & Erl & " " & Err.Description
         
50     Resume Ausgang
60     Resume
```


----------



## Filone (24. März 2005)

> Die Einträge im ListView starten im Gegensatz zur ListBox mit Index 1!



Dann hab ich mich vertan. Sorry.


----------



## reflexor (27. März 2005)

ich hoffe hier guckt nochmal einer rein!

bei meiner *.exe wenn die auf nem anderen rechner gestartet wird kommt IMMER der fehler

_Run-time error '76': Path not found _

voll komisch


----------



## Shakie (27. März 2005)

"Path not found" bedeutet, ein Pfad (entweder eine Datei oder ein Verzeichnis) wurde nicht gefunden. Schätzungsweise liegt hier irgendwo der Fehler:

```
' Instanzen der selben Hardware Enumerieren (z.B. Wave & Midi einer Soundkarte)
Private Function EnumSubDevices(ByVal DevicePath As String)

Dim hKey As Long, TmpStr As String * 256, RegClass As String * 256, i As Integer, Retval As Long
Dim DevInstance As String, DevDesc As String, LI As ListItem, DExist As Boolean, j As Integer

Call RegOpenKeyEx(HKEY_LOCAL_MACHINE, DevicePath, 0&, KEY_ENUMERATE_SUB_KEYS Or KEY_READ, hKey)

For i = 0 To GetValueLng(DevicePath & "Control\", "ReferenceCount")
' Untergerät ermitteln
Retval = RegEnumKeyEx(hKey, i, TmpStr, Len(TmpStr), ByVal 0&, RegClass, Len(RegClass), ByVal 0&)

' Gerät angeschlossen?
If GetValueLng(DevicePath & Left$(TmpStr, InStr(1, TmpStr, vbNullChar) - 1) & "\Control\", "Linked") = 1 Then
' DeviceInstance Pfad ermitteln
DevInstance = GetValueStr(DevicePath, "DeviceInstance")
DevDesc = GetValueStr(EnumPath & DevInstance & "\", "DeviceDesc")
If DevDesc = "" Then DevDesc = GetValueStr(EnumPath & DevInstance & "\", "DeviceDesc")

' Doppelte Einträge?
DExist = False
For j = 1 To ListView1.ListItems.Count
If ListView1.ListItems(j).SubItems(1) = DevInstance Then DExist = True
Next j

' Doppelte, Storage, System und SW Geräte wollen wir nicht!
If Not DExist And UCase(Left$(DevInstance, 2)) <> "SW" And UCase(Left$(DevInstance, 7)) <> "STORAGE" And _
UCase(GetValueStr(EnumPath & GetValueStr(DevicePath, "DeviceInstance"), "Class")) <> "SYSTEM" Then
Set LI = ListView1.ListItems.Add(, , DevDesc)
LI.SubItems(1) = DevInstance
End If
End If
Next i
RegCloseKey hKey
```
Weil hier die einzigen Stellen in deinem Code sind, an denen du Pfade verwendest (die rot markierten Stellen).


----------



## reflexor (27. März 2005)

das war nicht mein code   ich ich hatte meinen code nicht geschrieben! aber bei mir habe ich das problem gefunden ich habe ein Pfad zugewiesen der auf jedem pc anders sein kann


----------



## mashine-obf (12. September 2005)

Lesezeichen


----------



## Shakie (14. September 2005)

@mashine-obf: Hä? Was willst du mit deinem Post aussagen?


----------



## mashine-obf (14. September 2005)

damit ich auf suchen (user beiträge) gehen kann und den thread gleich wieder finde 
 da der so alt ist


----------



## Shakie (14. September 2005)

Aaaaaaaaaaaaaaaha. Du könntest dir auch einfach die URL abspeichern...


----------



## mashine-obf (14. September 2005)

hast du recht aber dann hab ich nicht nur 150 lesezeichen sondern 151


----------

