请教: AU3 操作Access 的问题, 密码错误脚本异常退出! (已解决)
本帖最后由 user3000 于 2012-4-29 17:48 编辑已自行找到解决方法, 具体情况请参阅15楼的上一楼!
用AU3 语句试图访问有密码的数据库时,如果密码是错误的, 将会产生致命性崩溃错误, 如同引用数组时, 下标越界了!
搜索论坛内, 相关信息很少; 至少我只有在这个帖子顶楼的最后面看到这么一句:" 注意:如果旧密码不对的时候,会出错。到现在我还没有找到解决办法。同时也希望那位高手能完善这段代码。"
可惜, 没有任何相关回音.
相关帖子: 用ADO更改ACCESS数据库密码
http://www.autoitx.com/forum.php?mod=viewthread&tid=10930&highlight=Access%2B%C3%DC%C2%EB
最近研究了点数据库操作相关的知识, 发现帮助里相关的 Access 操作已经跟不上'形势'了!
第1个, 它没有考虑打开有密码的数据库! 我发现有坛友说, access 数据库加密码等于没有? 很容易被破解?
第2个, 我以前用的时候, 就发现该UDF实现不了精确查找, 它的函数中唯一能返回以行为单位是 _accessQueryLike ;
可是, 它工作方式是类似 StringInStr, 只要那一行的那字段(列)包含了查找字符串, 就将全都会被返回! 所以, 不能当作精确查找!
比如下面这个表, 如果是查找游戏名为天龙八部的游戏, 所有数据行都会被返回!
游戏名称 游戏类型
天龙八部 单机游戏
天龙八部2 单机游戏
天龙八部2 网络游戏
天龙八部3 网络游戏
这几天就有了一种冲动, 想把 access.au3 的函数全部更新一下, 增加支持密码操作, 增加精确查找等操作...
精确查找操作的函数已经几乎完成了, 但现在发现了如标题所说的错误, 这实在让人深受打击, 不能解决这问题, 做出来的UDF可以说存在致命性缺陷了!
还有, access的安全性确实低到让人可以不考虑给它上密码的程度吗?!
请跟帖发言的朋友提出有意义或有用的意见或建议, 严禁发无意义的话语, 否则不要怪我给他-20的评分了! 本帖最后由 netegg 于 2012-4-27 21:24 编辑
密码的问题不清楚,不过精确查找貌似access本身就没有,换句话说,所谓的精确查找更确切说是脱离access后的数据操作
另外,你给的那个例子说明的是什么,指定字段内查找?这个原来的access udf里有啊_accessQueryStr 本帖最后由 user3000 于 2012-4-27 23:42 编辑
回复 2# netegg
_accessQueryStr 除了确认该字符串在数据库存在外, 完全没有别的用处吧?
它是: 数据存在, 则返回字符串本身!
我说的精确查找应当如我下面的函数:
(考虑不周, 已取消隐藏, 请用心给予回复!)
#Region
#cs
;函数名 _accessQueryStrEX, 作用: 按已知字段值, 获取该行特定字段的数据.
应该还要加上字段名的判断, 如果第4个参数, 设置了不存在的字段字, 会返回空值!
;参数说明: 1,$DB_Path数据库文件(非脚本目录下需列出绝对路径)
2, $DB_Table要查询的数据表名
3, $Finds 查询条件, 有格式要求. 接受数组, 类似: Local $Finds = ['pcname', 'pc001', 'pcoo2']
或字符串, 类似:Local $Finds = 'PCName|PC001|PC002'
其中: PCName 为字段(列)名 , pc001 和 pc002 为该字段下某一行的数值)
4,$return_Columns = '*' 要求查询后返回的字段(列)的数据,默认是所有字段
如上面的查询条件, 将返回跟 pc001 及 pc002 有关的那行(所有字段)的所有数据.
5, $password = Default 数据库的密码, 默认是不用密码的方式打开数据库.
6, $CloseDB = True 查询结束是否关闭已打开的数据库. 默认操作是关闭. ; 不知道有用不?
查询成功:
返回一数组:$Array
$Array 查询到的数据串数量
$Array... $Array 有关字段名的字符串, 以 '|' 字符分隔,
$Array... $Array 有关各行数据的字符串, 也是以 '|' 分开.
查询失败:
返回 -1 并设置 @errer
@errer 1打开数据库失败
@errer 2设置的查找条件有误?
@errer 3第3个参数错误, 符合格式要求
N 维2#ce
#endregion
$query = _accessQueryStrEX(@ScriptDir & "\sys1.mdb", 'group1', 'PCName|ooo|PC001|pc002|pc003', 'PcName,IPaddress', 123)
If Not @error Then
MsgBox(0, 'number', $query)
For $i = 1 To $query
MsgBox(0, $query[$i], $query[$i])
Next
Else
MsgBox(0, 'err', @error)
EndIf
Func _accessQueryStrEX($DB_Path, $DB_Table, $Finds, $return_Columns = '*', $password = Default, $CloseDB = True)
$oADO = _OpenDaTaBase($DB_Path, $password)
$rs = ObjCreate("ADODB.recordset")
$rs.ActiveConnection = $oADO
If IsObj($rs) = 0 Then Return SetError(1, 0, -1)
Local $find, $row
If IsArray($Finds) Then
$row = UBound($Finds)
If $row = 1 Then Return SetError(3, 0, -1) ; 错误的查找条件参数
$find = ' where ' & $Finds & " in ('" & $Finds & "'"
For $i = 2 To UBound($Finds) - 1
$find &= ",'" & $Finds[$i] & "'"
Next
$find &= ')'
ElseIf StringInStr($Finds, '|') Then
$s = StringSplit($Finds, '|')
$row = $s
$find = ' where ' & $s & " in ('" & $s & "'"
For $i = 3 To $s
$find &= ",'" & $s[$i] & "'"
Next
$find &= ')'
Else
Return SetError(3, 0, -1) ; 错误的查找条件参数
; Chr(42 * 星号, 代表查询并返回所有列
EndIf
$sql = "select " & $return_Columns & " from " & $DB_Table & $find
$rs.Open($sql, $oADO)
If $rs.bof Or $rs.eof Then Return SetError(2, 0, -1) ; 查找失败, 可能是查找的条件不正确
Local $return[$row], $count = 0
While Not $rs.BOF And Not $rs.EOF
$count += 1
If $count == $row Then ExitLoop
;If @error Then ExitLoop
For $x In $rs.Fields
If $x.name <> '' And $x.value <> '' Then
$return[$count] &= $x.name & Chr(124) ; Chr(124) 垂直线
$return[$count] &= $x.value & Chr(124)
EndIf
Next
$return[$count] = StringTrimRight($return[$count], 1)
$return[$count] = StringTrimRight($return[$count], 1)
$rs.MOVENEXT
WEnd
$return = $count
If $CloseDB Then
$rs.Close
$oADO.Close
EndIf
Return $return
EndFunc ;==>_accessQueryStrEX
;#cs
Func _adoProvider() ; 获取当前系统的 Access 数据库驱动版本
Local $oProvider = "Microsoft.Jet.OLEDB.4.0; "
Local $objCheck = ObjCreate("Access.application")
If IsObj($objCheck) Then
Local $oVersion = $objCheck.Version
If StringLeft($oVersion, 2) == "12" Then $oProvider = "Microsoft.ACE.OLEDB.12.0; "
EndIf
Return $oProvider
EndFunc ;==>_adoProvider
;#ce
Func _OpenDaTaBase($DB_Path, $password = Default)
Local $oADO = 'ADODB.Connection'
If IsObj($oADO) Then
$oADO = ObjGet('', $oADO)
Else
$oADO = ObjCreate("ADODB.Connection")
$oADO.Provider = _adoProvider()
If $password = Default Then
$oADO.Open($DB_Path)
Else
$oADO.Open("Data Source=" & $DB_Path & ";Jet Oledb:Database Password=" & $password)
EndIf
EndIf
Return $oADO
EndFunc ;==>_OpenDaTaBase
以下是可作测试用的带密码的数据库文件:
你看看_accessQueryStr的第四个参数 回复学习一下 回复netegg
_accessQueryStr 除了确认该字符串在数据库存在外, 完全没有别的用处吧?
它是: 数据存在,...
user3000 发表于 2012-4-27 21:58 http://www.autoitx.com/images/common/back.gif
user3000兄,没想到下面加了“必须参与讨论者才可观看”,只是好奇,抱歉 本帖最后由 netegg 于 2012-4-27 23:00 编辑
作为闲话,这样做的好处是什么,如果有必要的话,_accessSaveXML就一切ok(可能需要正则或者其他方式处理下)
试了下,_accessQueryStr确实有点鸡肋 _accessQueryStr这个没什么用,返回本身的,我都不用那个udf了,我是下别人的源码来改 本帖最后由 风行者 于 2012-4-27 23:31 编辑
对于ACCESS数据库加密码只要将access.au3内部函数_dbOpen和 _accessCreateDB 改一改就可以,没必要写新函数
不过还是建议改用sqlite 回复 7# netegg
我觉得 UDF 的意义在于使用的普遍性及方便性!不方便, 没有人会去用它! 没有普遍性, UDF则不值得花时间去编写!
当一个没有数据库操作基础的人尝试操作数据库时,一个良好的UDF, 必然是他一条大道, 可以帮他节省大量时间和精力;有心人甚于可以通过这条路'入门' 相关的数据库基础操作!
如果已经懂得用 _accessSaveXML 来搞定问题, 我想他应该也有修改相关UDF来达到自己的目的了吧!
我这样做, 也是想给自己实践的机会吧? 把 AU3 及 acceess 的操作尽可能完美的结合在一起. 希望能为中文版 AU3 作出一点贡献吧! 回复 10# user3000
这话我同意,所以我才说我说的是闲话,只是多个方法而已,具体如何操作当然是使用者的事情 对于ACCESS数据库加密码只要将access.au3内部函数_dbOpen和 _accessCreateDB 改一改就可以,没必要写新函数 ...
风行者 发表于 2012-4-27 23:30 http://www.autoitx.com/images/common/back.gif
改了 就是 新的了
会改的人, 估计都不会用这些函数, 而是直接自己写代码, 弄出符合自己使用的函数!
论坛里不少帖子都是这样! 如果能整理融合到新版的 AU3 中, 不是更能方便后人? 回复 12# user3000
这个也同意,但是udf首先考虑的不应该是结果,而是排错,除非能把所有的错误情况都写齐了,否则起到的作用可能并不是方便,而是更迷惑
当然自己用是另一码事 找到解决问题的方法了!
其实就在帮助里的" OLE/COM 参考".
不多说了, 有兴趣者请自行查阅该帮助! 只不过很多内容没汉化!
以前也正因为这个原因所以没怎么用心看该帮助! 打算抽点时间把这内容全汉化, 再放到中文资料版块去!
以下例子, 可以完全做到操作对象的容错!
(是借用别人的代码加入了检错代码)
Global $g_eventerror = 0, $oswf
$oMyError = ObjEvent("AutoIt.Error", "MyErrFunc")
; 建立捕捉错误事件, 如果不建立, 运行至代码 $oswf.width = @DesktopWidth 脚本将崩溃!
_Form()
$oswf.width = @DesktopWidth
If $g_eventerror Then ConsoleWrite("上一行代码运行, 有错误发生了(1).")
$oswf.height = @DesktopHeight
If $g_eventerror Then ConsoleWrite("上一行代码运行, 有错误发生了(2).")
While 1
Switch GUIGetMsg()
Case -3
Exit
EndSwitch
WEnd
Func _Form()
$hForm = GUICreate("form", 600, 400)
GUISetBkColor(0x000000)
$oswf = ObjCreate("ShockwaveFlash.ShockwaveFlash.10")
$octrl = GUICtrlCreateObj($oswf, 0, 0, 400, 300)
GUISetState()
$oswf.movie = "http://player.youku.com/player.php/sid/XMzYyOTM2MDA0/isAutoPlay/true/v.swf"
Sleep(3000)
GUISetState(@SW_MAXIMIZE)
EndFunc ;==>_Form
Func MyErrFunc() ; 该函数完全抄自帮助文件
$HexNumber = Hex($oMyError.number, 8)
MsgBox(0, "", "We intercepted a COM Error !" & @CRLF & _
"Number is: " & $HexNumber & @CRLF & _
"Windescription is: " & $oMyError.windescription)
$g_eventerror = 1 ; something to check for when this function returns
EndFunc ;==>MyErrFunc 本帖最后由 user3000 于 2012-6-16 06:44 编辑
此为为提供免费下载链接的回复帖, 请论坛管理员高抬贵手!
页:
[1]
2