有一种比较笨的方法,可以从注册表中读出DSN的所有信息。

解决方案 »

  1.   

    对,读注册表.
    [HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI\ECDCMusic]
    "Driver"="C:\\WINNT\\System32\\odbcjt32.dll"
    "DBQ"="C:\\Program Files\\Adaptec\\Shared\\ECDC Engine\\ECDCMusic.mdb"
    "DefaultDir"="C:\\Program Files\\Adaptec\\Shared\\ECDC Engine\\"
    "Description"="Personal music CD titles"
    "DriverId"=dword:00000019
    "FIL"="MS Access"
    "SafeTransactions"=dword:00000000
    "UID"=""[HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI\ECDCMusic\Engines][HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI\ECDCMusic\Engines\Jet]
    "ImplicitCommitSync"=""
    "Threads"=dword:00000003
    "UserCommitSync"="Yes"
      

  2.   

    ' 这个模块用于读和写注册表关键字。
    ' 不同于VB 的内部注册表访问方法,它可以
    ' 通过字符串的值来读和写任何注册表关键字。
    '---------------------------------------------------------------
    '-注册表 API 声明...
    '---------------------------------------------------------------
    Private Declare Function RegCloseKey Lib "advapi32" (ByVal hKey As Long) As Long
    Private Declare Function RegCreateKeyEx Lib "advapi32" 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, ByRef lpSecurityAttributes As SECURITY_ATTRIBUTES, ByRef phkResult As Long, ByRef lpdwDisposition As Long) As Long
    Private Declare Function RegOpenKeyEx Lib "advapi32" Alias "RegOpenKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, ByVal samDesired As Long, ByRef phkResult As Long) As Long
    Private Declare Function RegQueryValueEx Lib "advapi32" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, ByRef lpType As Long, ByVal lpData As String, ByRef lpcbData As Long) As Long
    Private Declare Function RegSetValueEx Lib "advapi32" Alias "RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal Reserved As Long, ByVal dwType As Long, ByVal lpData As String, ByVal cbData As Long) As Long
    Private Declare Function RegDeleteKey Lib "advapi32.dll" Alias "RegDeleteKeyA" (ByVal hKey As Long, ByVal lpSubKey As String) As Long
    Private Declare Function RegDeleteValue Lib "advapi32.dll" Alias "RegDeleteValueA" (ByVal hKey As Long, ByVal lpValueName As String) As Long'---------------------------------------------------------------
    '- 注册表 Api 常数...
    '---------------------------------------------------------------
    ' Reg Data Types...
    Const REG_SZ = 1                         ' Unicode空终结字符串
    Const REG_EXPAND_SZ = 2                  ' Unicode空终结字符串
    Const REG_DWORD = 4                      ' 32-bit 数字' 注册表创建类型值...
    Const REG_OPTION_NON_VOLATILE = 0       ' 当系统重新启动时,关键字被保留' 注册表关键字安全选项...
    Const READ_CONTROL = &H20000
    Const KEY_QUERY_VALUE = &H1
    Const KEY_SET_VALUE = &H2
    Const KEY_CREATE_SUB_KEY = &H4
    Const KEY_ENUMERATE_SUB_KEYS = &H8
    Const KEY_NOTIFY = &H10
    Const KEY_CREATE_LINK = &H20
    Const KEY_READ = KEY_QUERY_VALUE + KEY_ENUMERATE_SUB_KEYS + KEY_NOTIFY + READ_CONTROL
    Const KEY_WRITE = KEY_SET_VALUE + KEY_CREATE_SUB_KEY + READ_CONTROL
    Const KEY_EXECUTE = KEY_READ
    Const KEY_ALL_ACCESS = KEY_QUERY_VALUE + KEY_SET_VALUE + _
                           KEY_CREATE_SUB_KEY + KEY_ENUMERATE_SUB_KEYS + _
                           KEY_NOTIFY + KEY_CREATE_LINK + READ_CONTROL
                         
    ' 注册表关键字根类型...
    Public Const HKEY_CLASSES_ROOT = &H80000000
    Public Const HKEY_CURRENT_USER = &H80000001
    Public Const HKEY_LOCAL_MACHINE = &H80000002
    Public Const HKEY_USERS = &H80000003
    Public Const HKEY_PERFORMANCE_DATA = &H80000004' 返回值...
    Public Const ERROR_NONE = 0
    Public Const ERROR_BADKEY = 2
    Public Const ERROR_ACCESS_DENIED = 8
    Public Const ERROR_SUCCESS = 0'---------------------------------------------------------------
    '- 注册表安全属性类型...
    '---------------------------------------------------------------
    Private Type SECURITY_ATTRIBUTES
        nLength As Long
        lpSecurityDescriptor As Long
        bInheritHandle As Boolean
    End Type'ICON
    Public Const RT_BITMAP = 2&
    Public Const RT_ICON = 3&
    Public Const RT_CURSOR = 1&
    Private Type GUID
        Data1 As Long
        Data2 As Integer
        Data3 As Integer
        Data4(7) As Byte
    End Type'-------------------------------------------------------------------------------------------------
    'sample usage - Debug.Print UpodateKey(HKEY_CLASSES_ROOT, "keyname", "newvalue")
    '-------------------------------------------------------------------------------------------------
    Public Function UpdateKey(KeyRoot As Long, KeyName As String, SubKeyName As String, SubKeyValue As String) As Boolean
        Dim rc As Long                                      ' 返回代码
        Dim hKey As Long                                    ' 处理一个注册表关键字
        Dim hDepth As Long                                  '
        Dim lpAttr As SECURITY_ATTRIBUTES                   ' 注册表安全类型
        
        lpAttr.nLength = 50                                 ' 设置安全属性为缺省值...
        lpAttr.lpSecurityDescriptor = 0                     ' ...
        lpAttr.bInheritHandle = True                        ' ...    '------------------------------------------------------------
        '- 创建/打开注册表关键字...
        '------------------------------------------------------------
        rc = RegCreateKeyEx(KeyRoot, KeyName, _
                            0, REG_SZ, _
                            REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, lpAttr, _
                            hKey, hDepth)                   ' 创建/打开//KeyRoot//KeyName
        
        If (rc <> ERROR_SUCCESS) Then GoTo CreateKeyError   ' 错误处理...
        
        '------------------------------------------------------------
        '- 创建/修改关键字值...
        '------------------------------------------------------------
        If (SubKeyValue = "") Then SubKeyValue = " "        ' 要让RegSetValueEx() 工作需要输入一个空格...
        
        ' 创建/修改关键字值
        rc = RegSetValueEx(hKey, SubKeyName, _
                           0, REG_SZ, _
                           SubKeyValue, LenB(StrConv(SubKeyValue, vbFromUnicode)))
                           
        If (rc <> ERROR_SUCCESS) Then GoTo CreateKeyError   ' 错误处理
        '------------------------------------------------------------
        '- 关闭注册表关键字...
        '------------------------------------------------------------
        rc = RegCloseKey(hKey)                              ' 关闭关键字
        
        UpdateKey = True                                    ' 返回成功
        Exit Function                                       ' 退出
    CreateKeyError:
        UpdateKey = False                                   ' 设置错误返回代码
        rc = RegCloseKey(hKey)                              ' 试图关闭关键字
    End Function
      

  3.   

    '-------------------------------------------------------------------------------------------------
    'sample usage - Debug.Print GetKeyValue(HKEY_CLASSES_ROOT, "COMCTL.ListviewCtrl.1\CLSID", "")
    '-------------------------------------------------------------------------------------------------
    Public Function GetKeyValue(KeyRoot As Long, KeyName As String, SubKeyRef As String) As String
        Dim i As Long                                           ' 循环计数器
        Dim rc As Long                                          ' 返回代码
        Dim hKey As Long                                        ' 处理打开的注册表关键字
        Dim hDepth As Long                                      '
        Dim sKeyVal As String
        Dim lKeyValType As Long                                 ' 注册表关键字数据类型
        Dim tmpVal As String                                    ' 注册表关键字的临时存储器
        Dim KeyValSize As Long                                  ' 注册表关键字变量尺寸
        
        ' 在 KeyRoot {HKEY_LOCAL_MACHINE...} 下打开注册表关键字
        '------------------------------------------------------------
        rc = RegOpenKeyEx(KeyRoot, KeyName, 0, KEY_ALL_ACCESS, hKey) ' 打开注册表关键字
        
        If (rc <> ERROR_SUCCESS) Then GoTo GetKeyError          ' 处理错误...
        
        tmpVal = String$(1024, 0)                             ' 分配变量空间
        KeyValSize = 1024                                       ' 标记变量尺寸
        
        '------------------------------------------------------------
        ' 检索注册表关键字的值...
        '------------------------------------------------------------
        rc = RegQueryValueEx(hKey, SubKeyRef, 0, _
                             lKeyValType, tmpVal, KeyValSize)    ' 获得/创建关键字的值
                            
        If (rc <> ERROR_SUCCESS) Then GoTo GetKeyError          ' 错误处理
          
        tmpVal = Left$(tmpVal, InStr(tmpVal, Chr(0)) - 1)    '------------------------------------------------------------
        ' 决定关键字值的转换类型...
        '------------------------------------------------------------
        Select Case lKeyValType                                  ' 搜索数据类型...
        Case REG_SZ, REG_EXPAND_SZ                              ' 字符串注册表关键字数据类型
            sKeyVal = tmpVal                                     ' 复制字符串的值
        Case REG_DWORD                                          ' 四字节注册表关键字数据类型
            For i = Len(tmpVal) To 1 Step -1                    ' 转换每一位
                sKeyVal = sKeyVal + Hex(Asc(Mid(tmpVal, i, 1)))   ' 一个字符一个字符地生成值。
            Next
            sKeyVal = Format$("&h" + sKeyVal)                     ' 转换四字节为字符串
        End Select
        
        GetKeyValue = sKeyVal                                   ' 返回值
        rc = RegCloseKey(hKey)                                  ' 关闭注册表关键字
        Exit Function                                           ' 退出
        
    GetKeyError:    ' 错误发生过后进行清除...
        GetKeyValue = vbNullString                              ' 设置返回值为空字符串
        rc = RegCloseKey(hKey)                                  ' 关闭注册表关键字
    End Function
    Public Function DeleteKey(KeyRoot As Long, KeyName As String) As Boolean
        Dim i As Long                                           ' 循环计数器
        Dim rc As Long                                          ' 返回代码
        Dim hKey As Long                                        ' 处理打开的注册表关键字
        Dim hDepth As Long                                      '
        Dim sKeyVal As String
        Dim lKeyValType As Long                                 ' 注册表关键字数据类型
        Dim tmpVal As String                                    ' 注册表关键字的临时存储器
        Dim KeyValSize As Long                                  ' 注册表关键字变量尺寸
        
        ' 在 KeyRoot {HKEY_LOCAL_MACHINE...} 下打开注册表关键字
        '------------------------------------------------------------
        rc = RegOpenKeyEx(KeyRoot, KeyName, 0, KEY_ALL_ACCESS, hKey) ' 打开注册表关键字
        
        If (rc <> ERROR_SUCCESS) Then GoTo GetKeyError          ' 处理错误...
        
        tmpVal = String$(1024, 0)                             ' 分配变量空间
        KeyValSize = 1024                                       ' 标记变量尺寸
        
        '------------------------------------------------------------
        ' 删除注册表关键字...
        '------------------------------------------------------------
        rc = RegDeleteKey(hKey, "")
                            
        If (rc <> ERROR_SUCCESS) Then GoTo GetKeyError          ' 错误处理
          
        DeleteKey = True                                        ' 返回值
        rc = RegCloseKey(hKey)                                  ' 关闭注册表关键字
        Exit Function                                           ' 退出
        
    GetKeyError:    ' 错误发生过后进行清除...
        DeleteKey = False
        rc = RegCloseKey(hKey)                                  ' 关闭注册表关键字End Function
      

  4.   

    如何制作数据库产品的安装版 
     黄春雨
    齐欢华中理工大学摘要:本文介绍了一种制作数据库软件安装版的方法。
    关键词:安装版、Create Install、dsn
    How To Make Database Installation Product
    Abstract: This paper introduces a way to make database installation product.
    Keywords: installation, Create Install、dsn
    现在所使用的比较流行的制作由PB+ODBC+后台数据库开发的信息管理系统的安装版的工具通常是PB所附带的Install Shield。由于均是由同一家公司所开发的产品,因此有相当强的针对性,而且可以方便的配制数据库运行环境和ODBC,所以制作出来的安装版产品不仅功能齐全而且界面也非常符合Windows程序的规范。但是,存在的一个问题就是:由于市面上介绍Install Shield使用的资料非常的少,加之Install Shield的使用也是比较复杂的,因此许多人在使用时可能会遇到相当的困难。而且,笔者个人认为即使有资料学习起来也是比较麻烦的。在实际开发的过程中,笔者发现了一种较为简单的制作如PB + Sybase + ODBC产品的安装版的方法(这种情况是最为复杂的)。
    在制作中所使用的安装工具是Create Install。这是一个免费程序,可以从网址www.Gentee.com处下载。在下面将会看到,只要所使用的安装制作工具具有最基本的一些功能(如:拷贝文件、写INI格式的文件等)就可以了,并不一定必需是Create Install。(就笔者所看,大多数安装版制作工具均具有这些基本功能。)这种产品安装版制作方法的基本思想就是将一台可以运行所开发产品的电脑上的软件环境完全移植到客户的电脑上去,这样就可以保证使用者安装后可以正确的使用产品了。下面就以Create Install为例讲述如何制作PB + Sybase + ODBC情况下的安装版。
    首先必需将所要安装的产品以及相应的数据库文件(对于Sybase的db数据库,一定不要将 log日志文件拷如,否则会出问题)拷贝到一个目录中(这个目录下的文件将全部被打包),然后在该台微机上安装合适的软件,最好将Sybase安装在C:盘上(这样做主要是考虑到用户硬盘上可能只有C:盘一个盘符的情况)。这样便完成了配置一台微机的基本工作。制作安装版时将这个目录选为打包的目录(源目录)就可以了。
    接着,便是对注册表的写入。这里介绍一种较为简便的写入注册表的方法。首先,在
    Windows开始菜单中选择‘运行’,然后 
    在编辑框中输入:regedit,点‘回车’即
    会出现Windows注册表编辑器。然后单
    击键‘HKEY_LOCAL_MACHINE’前的
    ‘+’号,展开该键后再同样展开其下面
    的键‘Software’。这时便会看到有一个
    键的名称是‘Sybase’,接着直接单击它;
    再选择‘注册表’菜单下的‘导出注册表
    文件’,然后输入文件名称并选择将文件
    保存到开始选择的产品所在的目录下,在
    这里便会得到一个以‘reg’为后缀的注 
    图(一) 册表文件,这个文件就是安装了SQL Anywhere后所写入注册表的全部信息。最后需要将Windows安装目录下的regedit.exe文件也一同拷贝到源目录下。再写入用户的注册表时则只需在安装版制作工具中选择安装完成后运行‘Regedit myregfile.reg’即可。具体在Create Install中的使用如图(一)所示:
    但需要注意的是由于这里注册表的内容是完全符合所配置的电脑上的数据库环境的,因此,还需要在安装制作工具中选择将安装的数据库文件所在的目录全部拷贝到使用者的相同盘符下,并且目录名称不能改动(这里建议安装在c:盘下)。
    至此已基本上完成了数据库驱动环境移植的问题,在客户的电脑上已经配置了可以使用的数据库了。对于其他数据库,如:Excel等同样可以如此进行。
    PB所生成的可执行文件的运行,需要一些动态链接文件(DLL)和INI文件的支持。因此,必须将以下文件拷贝到可执行文件所在的目录下。共有以下几个文件:
    pbodb60.dll、pbodb60.ini Pb ODBC 专用接口 (sql anywhere必须  装)
    pbor7360.dll Pb oracle7.3 专用接口
    pbsyc60.dll Pb Sybase 专用接口
    Pbdwe60.dll Pbfnt60.ini
    Pblab60.ini Pbrtc60.dll
    Pbtra60.dll Pbvm60.dll
    将这些文件拷贝到源目录下后,就可以保证可执行文件的正确运行了。但是还有一个需要注意的问题就是ODBC的安装问题。如果客户的微机上没有正确的安装ODBC,所开发的数据库产品同样无法通过ODBC正确的连接数据库。为了安全起见,还应该将以下这些用于配置ODBC的文件拷贝到Windows安装目录下的System目录内:
    Ds16gt.dll、Ds32gt.dll 、Odbc16gt.dll、Odbc32.dll、
    Odbc32gt.dll、Odbcad32.exe、 Odbccp32.cpl、Odbccp32.dll、
    Odbccr32.dll、Odbcint.dll、Odbctrac.dll;
    同样可以在安装制作工具中选择拷贝这些文件,这样便避开了修改Autoexec文件中Path的问题。但是如果了解修改Path知识的,可以将以上这些文件全部拷贝到安装目录下的一个子目录下,然后修改Path。
    真正难以解决的问题还是如何动态配置DSN的问题。PB程序通过ODBC与数据库相连接便需要配置DSN,但是用户安装数据库的目录是不确定的,这不同于上门做项目安装时可以手动配制,因此必须要在程序中进行自动配置。这里有两种自动配置DSN的方法。
    第一种方法是将数据库文件所在的目录写入注册表的方法。在安装版生成软件具有写注册表的功能时可以使用这种方法(很多这类软件具有这个功能)。首先在配置安装版的时候便选择将用户所选择的安装目录的路径写入到某一个键值中,同时也要确保数据库文件(dB文件)在此目录下,接着在程序中便可以读入数据库记录文件所在路径并动态配置DSN了。将写入Profile的代码改为如下的即可:
    String try
    RegistryGet("HKEY_LOCAL_MACHINE\Software\MyApp.Settings\Fonts","Installpath",&
    RegString!, try) 
    //读出写入注册表某一键值中的应用程序所安装的路径
    SQLCA.DBMS = "ODBC"
    SQLCA.AutoCommit = False
    Sqlca.dbparm="connectstring='UID=dba;PWD=sql;Start= dbeng50.exe;DatabaseFile=" + try + "\xwb.db;AutoStop=yes;Driver={Sybase SQL Anywhere 5.0}'")
    Connect;
    其中UID是数据库的用户名,PWD是数据库的密码。
    第二种方法则较为简单:将数据库文件所在的目录信息写入到一个INI文件中然后再读出来。同样可以在配置安装版的时候便选择将用户选择的安装目录的路径按一定的格式写入到某个INI文件中去,接着在程序中读出相应的信息就可以了。将写入Profile的代码改为如下的即可完成动态配置DSN:
    String try
    try=profilestring("c:\ win.ini","ok","InstPath","none")
    //读入数据库记录文件所在的路径
    SQLCA.DBMS = "ODBC"
    SQLCA.AutoCommit = False
    Sqlca.dbparm="connectstring='UID=dba;PWD=sql;Start= dbeng50.exe;DatabaseFile=" + try + "\xwb.db;AutoStop=yes;Driver={Sybase SQL Anywhere 5.0}'")
    Connect;
    其中try=profilestring("c:\win.ini","ok","InstPath","none")中的"ok"是段名,"InstPAth"是键的名称,而"none"则表示当没有取出数据时没有默认值。具体的INI文件的格式是:
    [ok]
    InstPath=c:\myinstall //具体路径值由Create Install的系统变量写入
    这里同样需要注意的是将INI文件存放位置的问题。考虑到用户盘符的问题,笔者建议存放在c:盘根目录下。具体在Create Install中的配置如图(二)所示:
    图(二)
    至此便完成了将开发的数据库产品制作成安装版的全部工作,然后只需点击‘创建安装程序’按钮生成安装文件即可。由于在这种安装产品的制作方法中为了简便而采取了许多措施,因此它所生成的产品在安装过程的界面效果上也较为简单(和Install Shield所生成的相比)。但是它所完成的功能却是完整的,在时间较紧而且对Install Shield不是很了解的情况下这也不失为一种可以选择的制作数据库软件安装版的方法。