Hallo!
Es ist ein häufig vorkommendes Problem, dass man mit VB geschriebene Software auf Rechnern laufen lassen muss, auf denen man keine Adminrechte besitzt. Hierzu benötigt man also "portable" Versionen der eigenen Software, da eine Installation und Registrierung von Komponenten (vorwiegend ActiveX) nicht möglich ist. VB stellt im Projekt-Unterverzeichnis ..\Paket\Support zwar sämtliche nötigen Komponenten für das Projekt zur Verfügung, aber ein einfaches Kopieren dieser Komponenten auf einen USB-Stick oder eine CD reicht meist nicht aus, um eine portable Version zu erzeugen, wenn Komponenten enthalten sind, die eine Registrierung erfordern (z.B. ActiveX-Komponenten - *.OCX). Startet man solch ein Programm, erhält man die Fehlermeldung "Die Komponente 'XYZ' oder eine ihrer Abhängigkeiten ist nicht richtig registriert: Eine Datei fehlt oder ist ungültig." XYZ ist dann der Name der nicht registrierten ActiveX-Komponente. Ohne Administratorrechte ist eine Registrierung (z.B. mit regsvr32) leider nicht möglich, da die Komponenten im Registry-Zweig HKEY_CLASSES_ROOT registriert werden müssen, auf den eingeschränkte Benutzer keinen Schreibzugriff besitzen (auf diese Weise erfährt man aber immerhin, welche Komponenten überhaupt registriert werden müssen).
Das Problem kann dadurch umgangen werden, dass man die Registrierungs-Informationen nicht in HKEY_CLASSES_ROOT schreibt, sondern in den Registry-Zweig des lokalen Users, auf den er vollen Zugriff besitzt, nämlich HKEY_CURRENT_USER\Software\Classes. Damit die Informationen vom Programm dann auch dort ausgelesen werden und nicht aus dem Standard-Pfad unter HKEY_CLASSES_ROOT, muss dieser Standard-Pfad auf den benutzereigenen Pfad HKEY_CURRENT_USER\Software\Classes quasi "umgebogen" werden. Ein solcher Verweis kann mit der API-Funktion RegOverridePredefKey erstellt werden, die ab Windows 2000 verfügbar ist. Für das laufende Programm ist der Pfad zu den OCX-Registrierungen dann nicht mehr unter HKEY_CLASSES_ROOT zu finden, sondern unter HKEY_CURRENT_USER.
Zuerst einmal benötigt man also ein eigenständiges VB-Programm (Project1.vbp), das die Registrierung im Pfad des angemeldeten Users vornimmt. Es ersetzt praktisch "regsvr32" und wird zusammen mit den zu registrierenden DLLs und der eigentlichen VB-Software (aus dem Projekt-Unterverzeichnis ..\Paket\Support) z.B. auf einen USB-Stick kopiert. Dieses Programm muss nur einmal aufgerufen werden und nimmt die lokale Registrierung der nötigen Komponenten vor. Danach kann das eigentliche Programm immer wieder direkt gestartet werden.
Das Programm zur lokalen Registrierung der ActiveX-Komponenten (Aufruf ohne Admin-Rechte)
In der eigentlichen VB-Software (Project2.vbp), die die zuvor registrierten Komponenten benutzt, muss der Registry-Pfad natürlich ebenfalls auf HKEY_CURRENT_USER "umgebogen" werden. Und zwar BEVOR die entsprechende Komponente angesprochen wird. Also am besten im Load-Ereignis der Haupt-Form. Der "umgebogene" Key hat nur innerhalb des Programms Gültigkeit. Außerhalb wird weiterhin der originale Key verwendet. Wenn das Programm beendet wird, sollte (am besten im Unload-Ereignis) dennoch die Funktion RestoreOverrideKey() aufgerufen werden. Denn innerhalb der VB-Entwicklungsumgebung wird der "umgebogene" Key beim Beenden des Programms nicht automatisch zurückgesetzt, was dazu führen würde, dass die Entwicklungsumgebung auf falsche Keys zugreift und es u.U. zu Fehlermeldungen kommt.
Das eigentliche Benutzerprogramm, das Komponenten benutzt, die registriert werden müssen
Werden nun die Programmdateien zusammen mit den benötigten ActiveX-Komponenten und dem Registrierungs-Programm in ein Verzeichnis auf CD oder USB-Stick kopiert, kann man jedes VB-Programm auch ohne Registrierung und ohne Admin-Rechte starten. Erfolgreich getestet mit Windows XP und Windows 7.
Gruß, Volker
Edit by hal2000:
- Code-Tags in VB-Tags geändert
Edit by volkeru:
- Deklaration der unbenutzten Variablen "TempPath" entfernt
- Funktion RestoreOverrideKey eingeführt
Edit by LaMa5:
- die Farbe ROT ist ausschließlich für moderative Zwecke vorbehalten (Boardregeln §4.3c)
--> Farbgebung angepasst
Es ist ein häufig vorkommendes Problem, dass man mit VB geschriebene Software auf Rechnern laufen lassen muss, auf denen man keine Adminrechte besitzt. Hierzu benötigt man also "portable" Versionen der eigenen Software, da eine Installation und Registrierung von Komponenten (vorwiegend ActiveX) nicht möglich ist. VB stellt im Projekt-Unterverzeichnis ..\Paket\Support zwar sämtliche nötigen Komponenten für das Projekt zur Verfügung, aber ein einfaches Kopieren dieser Komponenten auf einen USB-Stick oder eine CD reicht meist nicht aus, um eine portable Version zu erzeugen, wenn Komponenten enthalten sind, die eine Registrierung erfordern (z.B. ActiveX-Komponenten - *.OCX). Startet man solch ein Programm, erhält man die Fehlermeldung "Die Komponente 'XYZ' oder eine ihrer Abhängigkeiten ist nicht richtig registriert: Eine Datei fehlt oder ist ungültig." XYZ ist dann der Name der nicht registrierten ActiveX-Komponente. Ohne Administratorrechte ist eine Registrierung (z.B. mit regsvr32) leider nicht möglich, da die Komponenten im Registry-Zweig HKEY_CLASSES_ROOT registriert werden müssen, auf den eingeschränkte Benutzer keinen Schreibzugriff besitzen (auf diese Weise erfährt man aber immerhin, welche Komponenten überhaupt registriert werden müssen).
Das Problem kann dadurch umgangen werden, dass man die Registrierungs-Informationen nicht in HKEY_CLASSES_ROOT schreibt, sondern in den Registry-Zweig des lokalen Users, auf den er vollen Zugriff besitzt, nämlich HKEY_CURRENT_USER\Software\Classes. Damit die Informationen vom Programm dann auch dort ausgelesen werden und nicht aus dem Standard-Pfad unter HKEY_CLASSES_ROOT, muss dieser Standard-Pfad auf den benutzereigenen Pfad HKEY_CURRENT_USER\Software\Classes quasi "umgebogen" werden. Ein solcher Verweis kann mit der API-Funktion RegOverridePredefKey erstellt werden, die ab Windows 2000 verfügbar ist. Für das laufende Programm ist der Pfad zu den OCX-Registrierungen dann nicht mehr unter HKEY_CLASSES_ROOT zu finden, sondern unter HKEY_CURRENT_USER.
Zuerst einmal benötigt man also ein eigenständiges VB-Programm (Project1.vbp), das die Registrierung im Pfad des angemeldeten Users vornimmt. Es ersetzt praktisch "regsvr32" und wird zusammen mit den zu registrierenden DLLs und der eigentlichen VB-Software (aus dem Projekt-Unterverzeichnis ..\Paket\Support) z.B. auf einen USB-Stick kopiert. Dieses Programm muss nur einmal aufgerufen werden und nimmt die lokale Registrierung der nötigen Komponenten vor. Danach kann das eigentliche Programm immer wieder direkt gestartet werden.
Das Programm zur lokalen Registrierung der ActiveX-Komponenten (Aufruf ohne Admin-Rechte)
Visual Basic-Quellcode
- 'Autor: Volker Ulle
- 'E-Mail: vulle@web.de
- '------------- Anfang Projektdatei Project1.vbp -------------
- 'Project1 ist ein eigenständiges Programm und dient nur vorab
- 'zur lokalen Registrierung der Komponenten.
- '--------- Anfang Formular "Form1" alias Form1.frm ---------
- 'Diese Form wird nicht angezeigt, sondern dient lediglicht
- 'zur Registrierung von Libraries (ActiveX (OCX), DLL etc.)
- 'im Zweig HKEY_CURRENT_USER der Registry, auf die auch
- 'eingeschränkte Benutzer Schreibrechte besitzen.
- 'In diesem Beispiel werden COMCTL32.OCX und MSCOMM32.OCX
- 'registriert.
- Private Sub Form_Load()
- Dim sRet As String
- If Register_DLL("COMCTL32.OCX") = 0 Then
- sRet = sRet + vbCrLf + "COMCTL32.OCX"
- End If
- If Register_DLL("MSCOMM32.OCX") = 0 Then
- sRet = sRet + vbCrLf + "MSCOMM32.OCX"
- End If
- If sRet <> "" Then
- MsgBox "Folgende DLLs wurden erfolgreich im lokalen Benutzerkonto registriert: " + vbCrLf + sRet
- End If
- End
- End Sub
- '---------- Ende Formular "Form1" alias Form1.frm ----------
- '--------- Anfang Modul "Module1" alias Module1.bas ---------
- 'Registrierung einer (ActiveX-)Komponente
- Option Explicit
- Private Const ERROR_SUCCESS As Long = 0
- Private Const HKEY_CLASSES_ROOT As Long = &H80000000
- Private Const HKEY_CURRENT_USER As Long = &H80000001
- 'Registry-Keys
- Private Declare Function RegOpenKey Lib "advapi32.dll" Alias "RegOpenKeyA" ( _
- ByVal hKey As Long, _
- ByVal lpSubKey As String, _
- phkResult As Long) As Long
- Private Declare Function RegOverridePredefKey Lib "advapi32" ( _
- ByVal hKey As Long, _
- ByVal hNewHKey As Long) As Long
- Private Declare Function RegCloseKey Lib "advapi32.dll" ( _
- ByVal hKey As Long) As Long
- 'DLL-Registrierung
- Private Declare Function LoadLibrary Lib "kernel32.dll" Alias "LoadLibraryA" ( _
- ByVal lpLibFileName As String) As Long
- Private Declare Function FreeLibrary Lib "kernel32.dll" ( _
- ByVal hLibModule As Long) As Long
- Private Declare Function GetProcAddress Lib "kernel32.dll" ( _
- ByVal hModule As Long, _
- ByVal lpProcName As String) As Long
- Private Declare Function CallWindowProc Lib "user32.dll" Alias "CallWindowProcA" ( _
- ByVal lpPrevWndFunc As Long, _
- ByVal hwnd As Long, _
- ByVal msg As Long, _
- ByVal wParam As Long, _
- ByVal lParam As Long) As Long
- Public Function Register_DLL(DLLName As String) As Integer
- Dim lRet As Long
- Dim hKey As Long
- Dim hModule As Long
- Dim pAdr As Long
- Dim S As String
- Register_DLL = 0
- S = App.Path
- If Right(S, 1) <> "\" Then S = S & "\"
- S = S & DLLName
- 'Override HKEY_CLASSES_ROOT:
- If RegOpenKey(HKEY_CURRENT_USER, "Software\\Classes", hKey) = ERROR_SUCCESS Then
- lRet = RegOverridePredefKey(HKEY_CLASSES_ROOT, hKey)
- RegCloseKey hKey
- If lRet = ERROR_SUCCESS Then
- 'Call the normal registration entry:
- hModule = LoadLibrary(S)
- If hModule Then
- pAdr = GetProcAddress(hModule, "DllRegisterServer")
- If pAdr Then
- CallWindowProc pAdr, 0, 0, 0, ByVal 0
- Else
- Register_DLL = 4
- End If
- Else
- MsgBox "DLL-Error " + CStr(Err.LastDllError) + " beim Registrieren von " + DLLName
- Register_DLL = 1
- End If
- FreeLibrary hModule
- Else
- Register_DLL = 2
- End If
- Else
- Register_DLL = 3
- End If
- End Function
- '--------- Ende Modul "Module1" alias Module1.bas ---------
- '-------------- Ende Projektdatei Project1.vbp --------------
In der eigentlichen VB-Software (Project2.vbp), die die zuvor registrierten Komponenten benutzt, muss der Registry-Pfad natürlich ebenfalls auf HKEY_CURRENT_USER "umgebogen" werden. Und zwar BEVOR die entsprechende Komponente angesprochen wird. Also am besten im Load-Ereignis der Haupt-Form. Der "umgebogene" Key hat nur innerhalb des Programms Gültigkeit. Außerhalb wird weiterhin der originale Key verwendet. Wenn das Programm beendet wird, sollte (am besten im Unload-Ereignis) dennoch die Funktion RestoreOverrideKey() aufgerufen werden. Denn innerhalb der VB-Entwicklungsumgebung wird der "umgebogene" Key beim Beenden des Programms nicht automatisch zurückgesetzt, was dazu führen würde, dass die Entwicklungsumgebung auf falsche Keys zugreift und es u.U. zu Fehlermeldungen kommt.
Das eigentliche Benutzerprogramm, das Komponenten benutzt, die registriert werden müssen
Visual Basic-Quellcode
- '------------- Anfang Projektdatei Project2.vbp -------------
- '--------- Anfang Formular "Form1" alias Form1.frm ---------
- Private Sub Form_Load()
- If OverrideKey Then
- MsgBox "Key override failed!"
- End
- End If
- End Sub
- Private Sub Form_Unload(Cancel As Integer)
- RestoreOverrideKey
- End Sub
- '--------- Ende Formular "Form1" alias Form1.frm ---------
- '--------- Anfang Modul "Module1" alias Module1.bas ---------
- Option Explicit
- Private Const ERROR_SUCCESS As Long = 0
- Private Const HKEY_CLASSES_ROOT As Long = &H80000000
- Private Const HKEY_CURRENT_USER As Long = &H80000001
- 'Registry-Keys
- Private Declare Function RegOpenKey Lib "advapi32.dll" Alias "RegOpenKeyA" ( _
- ByVal hKey As Long, _
- ByVal lpSubKey As String, _
- phkResult As Long) As Long
- Private Declare Function RegOverridePredefKey Lib "advapi32" ( _
- ByVal hKey As Long, _
- ByVal hNewHKey As Long) As Long
- Private Declare Function RegCloseKey Lib "advapi32.dll" ( _
- ByVal hKey As Long) As Long
- Public Function OverrideKey() As Integer
- Dim lRet As Long
- Dim hKey As Long
- OverrideKey = 1
- 'Override HKEY_CLASSES_ROOT:
- If RegOpenKey(HKEY_CURRENT_USER, "Software\\Classes", hKey) = ERROR_SUCCESS Then
- lRet = RegOverridePredefKey(HKEY_CLASSES_ROOT, hKey)
- RegCloseKey hKey
- If lRet = ERROR_SUCCESS Then
- OverrideKey = 0
- End If
- End If
- End Function
- Public Function RestoreOverrideKey() As Integer
- Dim lRet As Long
- RestoreOverrideKey = 1
- 'Restore Override of HKEY_CLASSES_ROOT:
- lRet = RegOverridePredefKey(HKEY_CLASSES_ROOT, 0&)
- If lRet = ERROR_SUCCESS Then
- RestoreOverrideKey = 0
- End If
- End Function
- '--------- Ende Modul "Module1" alias Module1.bas ---------
- '-------------- Ende Projektdatei Project2.vbp --------------
Werden nun die Programmdateien zusammen mit den benötigten ActiveX-Komponenten und dem Registrierungs-Programm in ein Verzeichnis auf CD oder USB-Stick kopiert, kann man jedes VB-Programm auch ohne Registrierung und ohne Admin-Rechte starten. Erfolgreich getestet mit Windows XP und Windows 7.
Gruß, Volker
Edit by hal2000:
- Code-Tags in VB-Tags geändert
Edit by volkeru:
- Deklaration der unbenutzten Variablen "TempPath" entfernt
- Funktion RestoreOverrideKey eingeführt
Edit by LaMa5:
- die Farbe ROT ist ausschließlich für moderative Zwecke vorbehalten (Boardregeln §4.3c)
--> Farbgebung angepasst
Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „LaMa5“ ()