In a previous post I looked at recording the driver version of the ODBC driver used by the IBM client.
Since then I have expanded this a bit to log the ODBC driver version, the file version of the Client Access driver and check any DSNs and make them read only.
Here is the code to setup the database tables, views and stored procedures:
CREATE TABLE [dbo].[ODBC_Log](
[MachineName] [varchar](20) NOT NULL,
[Driver] [varchar](50) NOT NULL,
[DriverVersion] [decimal](10, 5) NULL,
[Logged] [datetime] NOT NULL,
[FileVersion] [varchar](50) NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[ODBC_Log] ADD CONSTRAINT [DF_ODBC_Log_Logged] DEFAULT (getdate()) FOR [Logged]
GO
CREATE TABLE [dbo].[DSN_Log](
[MachineName] [varchar](20) NOT NULL,
[DSNName] [varchar](50) NOT NULL,
[DSNDriver] [varchar](50) NOT NULL,
[DSNReadOnly] [bit] NOT NULL,
[Logged] [datetime] NOT NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[DSN_Log] ADD CONSTRAINT [DF_DSN_Log_Logged] DEFAULT (getdate()) FOR [Logged]
GO
Create View [dbo].[vw_OutDatedDrivers]
AS
SELECT
[MachineName]
,[Driver]
,[DriverVersion]
,[Logged]
,[FileVersion]
FROM
[dbo].[ODBC_Log]
where
(
Driver = 'C:\Windows\System32\cwbodbc.dll' AND
(
FileVersion <> '11.64.0.0' AND
FileVersion <> '11.0.0.0' AND
FileVersion <> ''
)
)
OR
(
Driver = 'C:\Windows\SysWOW64\cwbodbc.dll' AND
(
FileVersion <> '11.0.0.0' AND
FileVersion <> ''
)
)
OR
(
(
Driver <> 'C:\Windows\SysWOW64\cwbodbc.dll' AND
Driver <> 'C:\Windows\System32\cwbodbc.dll'
) AND
(
DriverVersion > 0 AND
DriverVersion <> 3.51
)
)
GO
Create View [dbo].[vw_Current_ODBC_Driver]
AS
Select
MachineName,
Driver,
DriverVersion,
FileVersion,
Logged
From (
Select
MachineName,
Driver,
DriverVersion,
FileVersion,
Logged,
RANK()Over(PARTITION BY MachineName, Driver ORDER BY Logged DESC) [Rank]
From
dbo.ODBC_Log
) Results
Where [Rank] = 1
GO
Create View [dbo].[vw_Current_DSN]
AS
Select
MachineName,
DSNName,
DSNDriver,
DSNReadOnly,
Logged
From (
Select
MachineName,
DSNName,
DSNDriver,
DSNReadOnly,
Logged,
RANK()Over(PARTITION BY MachineName, DSNName, DSNDriver ORDER BY Logged DESC) [Rank]
From
dbo.DSN_Log
) Results
Where [Rank] = 1
GO
Create View [dbo].[vw_OutOfDate_ODBC_Driver]
AS
SELECT [MachineName]
,[Driver]
,[DriverVersion]
,[Logged]
FROM [UserManagement].[dbo].[vw_Current_ODBC_Driver]
Where DriverVersion between 0.001 and 3.5
GO
CREATE PROCEDURE [dbo].[p_ODBC_Log]
@MachineName varchar(20),
@Driver varchar(50),
@DriverVersion decimal(10,5)
AS
BEGIN
SET NOCOUNT ON;
If Not Exists(Select * From vw_Current_ODBC_Driver Where MachineName = @MachineName And Driver = @Driver And DriverVersion = @DriverVersion)
Begin
INSERT INTO dbo.ODBC_Log(MachineName, Driver, DriverVersion)
VALUES(@MachineName, @Driver, @DriverVersion)
End
END
GO
CREATE PROCEDURE [dbo].[p_ODBC_FileLog]
@MachineName varchar(20),
@Driver varchar(50),
@FileVersion varchar(50)
AS
BEGIN
SET NOCOUNT ON;
If Not Exists(Select * From vw_Current_ODBC_Driver Where MachineName = @MachineName And Driver = @Driver And FileVersion = @FileVersion)
Begin
INSERT INTO dbo.ODBC_Log(MachineName, Driver, FileVersion)
VALUES(@MachineName, @Driver, @FileVersion)
End
END
GO
CREATE PROCEDURE [dbo].[p_DSN_Log]
@MachineName varchar(20),
@DSNName varchar(50),
@DSNDriver varchar(50),
@DSNReadOnly bit
AS
BEGIN
SET NOCOUNT ON;
If Not Exists(Select * From vw_Current_DSN Where MachineName = @MachineName And DSNName = @DSNName And DSNDriver = @DSNDriver)
Begin
INSERT INTO dbo.DSN_Log(MachineName, DSNName, DSNDriver, DSNReadOnly)
VALUES(@MachineName, @DSNName, @DSNDriver, @DSNReadOnly)
End
else
Begin
Update dbo.DSN_Log
Set
DSNReadOnly = @DSNReadOnly,
Logged = GETDATE()
Where MachineName = @MachineName
And DSNName = @DSNName
And DSNDriver = @DSNDriver
End
END
GO
Here is the script:
Const HKEY_CURRENT_USER = &H80000001
Const HKEY_LOCAL_MACHINE = &H80000002
Const adDouble = 5 'http://www.w3schools.com/ado/met_comm_createparameter.asp
Const adVarChar = 200
Const adParamInput = 1
Const adBoolean = 11
Const ExpectedODBCVersionID = 3.51 'ODBC Version
Const Expected32BitVersion = "11.0.0.0" 'Equivilent to IBM Client Access V5R4
Const Expected64BitVersion = "11.64.0.0" 'Equivilent to IBM Client Access V5R4
Const strComputer = "." 'Local Machine
Const strConn = "Provider=sqloledb;packet size=4096;user id=[USERNAME];data source=[SQLSERVER]\[INSTANCE];persist security info=False;initial catalog=UserManagement;password=[PASSWORD]" 'Database connection
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2") 'WMI service for local machine
Set colComputers = objWMIService.ExecQuery("Select * from Win32_ComputerSystem") 'List of machine names for current machine
For Each objComputer in colComputers
strMachineName = objComputer.Name
Next
Set oReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv") 'Registry for current machine
oReg.GetStringValue HKEY_LOCAL_MACHINE, "SOFTWARE\ODBC\ODBCINST.INI\Client Access ODBC Driver", "DriverODBCVer", dwValue_Client86 '32bit Client Access driver
oReg.GetStringValue HKEY_LOCAL_MACHINE, "SOFTWARE\ODBC\ODBCINST.INI\Client Access ODBC Driver (32-bit)", "DriverODBCVer", dwValue_Client '64bit Client Access driver
oReg.GetStringValue HKEY_LOCAL_MACHINE, "SOFTWARE\ODBC\ODBCINST.INI\iSeries Access ODBC Driver", "DriverODBCVer", dwValue_iSeries 'iSeries Access driver
oReg.GetStringValue HKEY_LOCAL_MACHINE, "SOFTWARE\Wow6432Node\ODBC\ODBC.INI\Client Access ODBC Driver", "DriverODBCVer", dwValue_Client86_64 '32bit Client Access driver
oReg.GetStringValue HKEY_LOCAL_MACHINE, "SOFTWARE\Wow6432Node\ODBC\ODBC.INI\Client Access ODBC Driver (32-bit)", "DriverODBCVer", dwValue_Client_64 '64bit Client Access driver
oReg.GetStringValue HKEY_LOCAL_MACHINE, "SOFTWARE\Wow6432Node\ODBC\ODBC.INI\iSeries Access ODBC Driver", "DriverODBCVer", dwValue_iSeries_64 'iSeries Access driver
'Converts string values to Double for comparison and logging
ConvertToDouble dwValue_Client86
ConvertToDouble dwValue_Client
ConvertToDouble dwValue_iSeries
ConvertToDouble dwValue_Client86_64
ConvertToDouble dwValue_Client_64
ConvertToDouble dwValue_iSeries_64
'Inserts values into Database
InsertLog strMachineName, "Client Access ODBC Driver", dwValue_Client86
InsertLog strMachineName, "Client Access ODBC Driver (32-bit)", dwValue_Client
InsertLog strMachineName, "iSeries Access ODBC Driver", dwValue_iSeries
InsertLog strMachineName, "Client Access ODBC Driver - 64bit", dwValue_Client86_64
InsertLog strMachineName, "Client Access ODBC Driver (32-bit) - 64bit", dwValue_Client_64
InsertLog strMachineName, "iSeries Access ODBC Driver - 64bit", dwValue_iSeries_64
'Gets driver file version if ODBC driver exists
If dwValue_Client86 > 0 or dwValue_iSeries > 0 Then
dwValue_System32 = GetVersion("C:\Windows\System32\cwbodbc.dll")
InsertFileLog strMachineName, "C:\Windows\System32\cwbodbc.dll", dwValue_System32
End If
If dwValue_Client > 0 Then
dwValue_SysWOW64 = GetVersion("C:\Windows\SysWOW64\cwbodbc.dll")
InsertFileLog strMachineName, "C:\Windows\SysWOW64\cwbodbc.dll", dwValue_SysWOW64
End If
On Error Resume Next
'Gets a list of DSNs in the registry of the current user
CHECKDSN HKEY_LOCAL_MACHINE, "SOFTWARE\ODBC\ODBC.INI\"
CHECKDSN HKEY_CURRENT_USER, "SOFTWARE\ODBC\ODBC.INI\"
CHECKDSN HKEY_LOCAL_MACHINE, "SOFTWARE\Wow6432Node\ODBC\ODBC.INI\"
CHECKDSN HKEY_CURRENT_USER, "SOFTWARE\Wow6432Node\ODBC\ODBC.INI\"
'*******************************************************************************
' Helper Methods
'*******************************************************************************
SUB CHECKDSN (HKEY, PATH)
oReg.EnumValues HKEY, PATH & "ODBC DATA SOURCES", arrValueNames, arrValueTypes
For i = 0 to Ubound(arrValueNames)
strValueName = arrValueNames(i)
oReg.GetStringValue HKEY, PATH & "ODBC DATA SOURCES", strValueName, strValue
IF strValue = "Client Access ODBC Driver" OR _
strValue = "Client Access ODBC Driver (32-bit)" OR _
strValue = "iSeries Access ODBC Driver" THEN
oReg.GetStringValue HKEY, PATH & strValueName, "ConnectionType", strDSNReadOnlyValue
blnDSNReadOnly = FALSE
IF strDSNReadOnlyValue = "1" OR strDSNReadOnlyValue = "2" THEN
blnDSNReadOnly = TRUE
ELSE
oReg.SetStringValue HKEY, PATH & strValueName, "ConnectionType", "2"
END IF
InsertDSNLog strMachineName, strValueName, strValue, blnDSNReadOnly
END IF
Next
END SUB
Sub ConvertToDouble(byref value)
If isnull(value) or value = "" then
value = 0
Else
value = cdbl(value)
End If
End Sub
Sub InsertLog(MachineName, DriverName, Version)
'If Version = 0 Then Exit Sub
Set objCommand = CreateObject("ADODB.Command")
Set objParam = CreateObject("ADODB.Parameter")
objCommand.ActiveConnection = strConn
objCommand.commandtext = "p_ODBC_Log"
objCommand.CommandType = 4 'defines cmd type as stored proc
Set objParm = objCommand.CreateParameter("@MachineName", adVarChar, adParamInput, 20,MachineName)
objCommand.Parameters.Append objParm
Set objParm = objCommand.CreateParameter("@Driver", adVarChar, adParamInput, 50,DriverName)
objCommand.Parameters.Append objParm
Set objParm = objCommand.CreateParameter("@DriverVersion", adDouble, adParamInput,,Version)
objCommand.Parameters.Append objParm
objCommand.Execute
End Sub
Sub InsertFileLog(MachineName, DriverName, Version)
'If Version = 0 Then Exit Sub
Set objCommand = CreateObject("ADODB.Command")
Set objParam = CreateObject("ADODB.Parameter")
objCommand.ActiveConnection = strConn
objCommand.commandtext = "p_ODBC_FileLog"
objCommand.CommandType = 4 'defines cmd type as stored proc
Set objParm = objCommand.CreateParameter("@MachineName", adVarChar, adParamInput, 20,MachineName)
objCommand.Parameters.Append objParm
Set objParm = objCommand.CreateParameter("@Driver", adVarChar, adParamInput, 50,DriverName)
objCommand.Parameters.Append objParm
Set objParm = objCommand.CreateParameter("@FileVersion", adVarChar, adParamInput, 50,Version)
objCommand.Parameters.Append objParm
objCommand.Execute
End Sub
Sub InsertDSNLog(MachineName, DSNName, DSNDriver, DSNReadOnly)
'If Version = 0 Then Exit Sub
Set objCommand = CreateObject("ADODB.Command")
Set objParam = CreateObject("ADODB.Parameter")
objCommand.ActiveConnection = strConn
objCommand.commandtext = "p_DSN_Log"
objCommand.CommandType = 4 'defines cmd type as stored proc
Set objParm = objCommand.CreateParameter("@MachineName", adVarChar, adParamInput, 20,MachineName)
objCommand.Parameters.Append objParm
Set objParm = objCommand.CreateParameter("@DSNName", adVarChar, adParamInput, 50,DSNName)
objCommand.Parameters.Append objParm
Set objParm = objCommand.CreateParameter("@DSNDriver", adVarChar, adParamInput, 50,DSNDriver)
objCommand.Parameters.Append objParm
Set objParm = objCommand.CreateParameter("@DSNReadOnly", adBoolean, adParamInput, ,DSNReadOnly)
objCommand.Parameters.Append objParm
objCommand.Execute
End Sub
function GetVersion(Path)
output = ""
on error resume next
output = CreateObject("Scripting.FileSystemObject").GetFileVersion(Path)
GetVersion = output
end function