OK, as promised, here is the code that you can use to automaticall update the registry by checking the
HKEY_CLASSES_ROOT\VBSFILE\Shell\Open\Command key of an instance of
C:\WINNT\System32\WScript.exe "%1" %*
and changing it to
C:\WINNT\System32\Notepad.exe %1.
The first thing to remember is, that despite all other rumors, THE REGISTRY IS NOT THAT HARD TO WORK WITH . . . but you do need to be careful. The following code was run on WINNT40 - SP6a. The actual code that does the checking and updating uses passed in values . . . this was done so that the same piece of code could be used over again elsewhere (remember that oft spoken phrase, "Code Reuse"

. When the application want to check and possible update the key, it simply passes in the key location, the search string that will trigger a replacement, the string that will replace the data in the key, and a message that will be displayed when a replacement occurs.
AND NOW . . . THE CODE . . .
First off, declare your APIs in the general declaration
Private Const HKEY_CLASSES_ROOT = &H80000000
Private Const HKEY_CURRENT_CONFIG = &H80000005
Private Const HKEY_CURRENT_USER = &H80000001
Private Const HKEY_DYN_DATA = &H80000006
Private Const HKEY_LOCAL_MACHINE = &H80000002
Private Const HKEY_PERFORMANCE_DATA = &H80000004
Private Const HKEY_USERS = &H80000003
Private Const READ_CONTROL = &H20000
Private Const STANDARD_RIGHTS_READ = (READ_CONTROL)
Private Const STANDARD_RIGHTS_WRITE = (READ_CONTROL)
Private Const STANDARD_RIGHTS_ALL = &H1F0000
Private Const SYNCHRONIZE = &H100000
Private Const KEY_CREATE_LINK = &H20
Private Const KEY_CREATE_SUB_KEY = &H4
Private Const KEY_ENUMERATE_SUB_KEYS = &H8
Private Const KEY_EVENT = &H1
Private Const KEY_NOTIFY = &H10
Private Const KEY_QUERY_VALUE = &H1
Private Const KEY_SET_VALUE = &H2
Private Const KEY_WRITE = ((STANDARD_RIGHTS_WRITE Or KEY_SET_VALUE Or KEY_CREATE_SUB_KEY) And (Not SYNCHRONIZE))
Private Const KEY_ALL_ACCESS = ((STANDARD_RIGHTS_ALL Or KEY_QUERY_VALUE Or KEY_SET_VALUE Or KEY_CREATE_SUB_KEY Or KEY_ENUMERATE_SUB_KEYS Or KEY_NOTIFY Or KEY_CREATE_LINK) And (Not SYNCHRONIZE))
Private Const KEY_READ = ((STANDARD_RIGHTS_READ Or KEY_QUERY_VALUE Or KEY_ENUMERATE_SUB_KEYS Or KEY_NOTIFY) And (Not SYNCHRONIZE))
Private Const KEY_EXECUTE = ((KEY_READ) And (Not SYNCHRONIZE))
Private Const REG_SZ = 1
Private Const ERROR_SUCCESS = 0&
Private Type SECURITY_ATTRIBUTES
nLength As Long
lpSecurityDescriptor As Long
bInheritHandle As Long
End Type
Private Declare Function RegCreateKeyEx Lib "advapi32.dll" Alias "RegCreateKeyExA" (ByVal lngKeyHandle As Long, ByVal lpSubKey As String, ByVal Reserved As Long, ByVal lpClass As String, ByVal dwOptions As Long, ByVal samDesired As Long, lpSecurityAttributes As SECURITY_ATTRIBUTES, phkResult As Long, lpdwDisposition As Long) As Long
Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) 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 ' Note that if you declare the lpData parameter as String, you must pass it By Value
Private Declare Function RegSetValueEx Lib "advapi32.dll" Alias "RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal Reserved As Long, ByVal dwType As Long, lpData As Any, ByVal cbData As Long) As Long ' Note that if you declare the lpData parameter as String, you must pass it By Value
This routine simply sets the desired search parameters and calls the registry update code.
Public Sub CheckRegistry()
Dim strKey As String
Dim strTargetString As String
Dim strReplacementString As String
Dim strErrorMessage As String
'** Set the desired search parameters.
strKey = "VBSFILE\Shell\Open\Command"
strTargetString = "C:\WINNT\System32\WScript.exe ""%1"" %*"
strReplacementString = "C:\WINNT\System32\Notepad.exe %1"
strErrorMessage = "Disassociated VB Script from WScript.exe! VB Script will now open in notepad."
'** Pass in the search parameters to the UpdateRegistry function.
Call UpdateRegistry(strKey, strTargetString, strReplacementString, strErrorMessage)
End Sub
This routine does the actual work of opening the registry, searching for the target value, and - if found - replacing the data. NOTE THAT THIS CODE WILL ONLY WORK WITH REG DATA OF TYPE STRING . . . although with a very simple modification, that could be changed.
Private Sub UpdateRegistry(strTargetKey As String, strTargetString As String, strReplacementString As String, strErrorMessage As String)
Dim udtSec As SECURITY_ATTRIBUTES
Dim lngKeyHandle As Long
Dim lngDisposition As Long
Dim lngRetCode As Long
Dim strData As String
Dim lngBufferLength As Long
'** First off, open the desired key.
lngRetCode = RegCreateKeyEx(HKEY_CLASSES_ROOT, strTargetKey, 0, "", 0, KEY_ALL_ACCESS, udtSec, lngKeyHandle, lngDisposition)
'** IF the key was opened, then query the default value.
If lngRetCode = ERROR_SUCCESS Then
lngBufferLength = 1024
strData = Space$(lngBufferLength)
lngRetCode = RegQueryValueEx(lngKeyHandle, "", 0, REG_SZ, ByVal strData, lngBufferLength)
If lngRetCode = ERROR_SUCCESS Then
'** trim off the extra spaces in the buffer. Use lngBufferLength - 1 to account for the null space.
If lngBufferLength > 1 Then
strData = Left$(strData, lngBufferLength - 1)
End If
'** Check to see if the key matches the target key. If it does, then replace it and raise an error message.
If UCase$(Trim$(strData)) = UCase$(Trim$(strTargetString)) Then
lngBufferLength = Len(strReplacementString)
lngRetCode = RegSetValueEx(lngKeyHandle, "", 0, REG_SZ, ByVal strReplacementString, lngBufferLength)
MsgBox strErrorMessage, vbOKOnly + vbCritical, "Registry Update Warning!"
HERE, IF YOU WANTED, YOU COULD SIGNAL A LAN ADMIN OF THE CHANGE
End If
End If
End If
'** Close the open handle.
If RegCloseKey(lngKeyHandle) <> ERROR_SUCCESS Then
MsgBox "Key not closed."
End If
End Sub
Is this what you guys were looking for? Just put an EXE with this in it in the RUN key for your users or in their LOGIN scripts, and you can always be sure that VBS IS NOT associated with the scriptiong host.
Also, DSI, what problem were you having when you were trying to update the registry? Were you doing it the same way my code is?
If anyone has any questions or comments regarding this code, please feel free to let me know and I will do what I can to further explain it.
Also, I am working on a WebSite that will consist of a series of articles and examples for programming (with commented code examples) . . .anyone have any requests for information regarding advanced topics that they would like to see? Any feed back would be greatly appreciated. Thanks!
- Jeff Marler
(please note, that the page is under construction)