mrsiro > 07-01-15, 10:32 AM
MTNQ > 12-01-15, 04:46 PM
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" & strPathLinkTable _
& "; Jet OLEDB:System Database=" & strMdwPath, "UserID", "Password"
Call ShowUserRosterMultipleUsers(Me)
Public Sub ShowUserRosterMultipleUsers(mfrm As Form)
On Error GoTo ErrorHandler
Dim cnn As New ADODB.Connection
Dim rst As New ADODB.Recordset
Dim fld As ADODB.Field
Dim strUser, strPathLinkTable, strMdwPath As String
Dim intUser As Integer
Dim varValue As Variant
Const conUsers = "{947bb102-5d43-11d1-bdbf-00c04fb92675}"
strPathLinkTable = GetCurrentPath("tblUser")
strMdwPath = Left(strPathLinkTable, InStrRev(strPathLinkTable, "\")) & "Security.mdw"
cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" & strPathLinkTable _
& "; Jet OLEDB:System Database=" & strMdwPath, "UserID", "Password"
Set rst = cnn.OpenSchema(Schema:=adSchemaProviderSpecific, SchemaID:=conUsers)
strUser = "COMPUTER_NAME;LOGIN_NAME;CONNECTED;SUSPECT_STAT"
With rst
Do Until .EOF
intUser = intUser + 1
For Each fld In .Fields
varValue = Nz(fld.Value, "Null")
If InStr(varValue, vbNullChar) > 0 Then
varValue = Left(varValue, InStr(varValue, vbNullChar) - 1)
End If
strUser = strUser & ";" & varValue
Next
.MoveNext
Loop
End With
mfrm!txtTongSo = intUser
With mfrm!lstUsers
.ColumnCount = 4
.RowSourceType = "Value List"
.ColumnHeads = True
.RowSource = strUser
End With
Set fld = Nothing
Set rst = Nothing
Set cnn = Nothing
Exit_ErrorHandler:
Exit Sub
ErrorHandler:
If Not fld Is Nothing Then Set fld = Nothing
If Not rst Is Nothing Then Set rst = Nothing
If Not cnn Is Nothing Then Set cnn = Nothing
MsgBox "Error: " & Err.Number & Chr(13) & Err.Description, , "Error: ShowUserRosterMultipleUsers"
Resume Exit_ErrorHandler
End Sub
Function GetCurrentPath(MyLinkedTable As String) As String
On Error GoTo ErrorHandler
GetCurrentPath = Mid(CurrentDb.TableDefs(MyLinkedTable).Connect, InStr(1, CurrentDb.TableDefs(MyLinkedTable).Connect, "=") + 1)
Exit_ErrorHandler:
Exit Function
ErrorHandler:
MsgBox "Error: " & Err.Number & Chr(13) & Err.Description, , "Error: GetCurrentPath"
Resume Exit_ErrorHandler
End Function
mrsiro > 17-01-15, 12:02 PM
MTNQ > 17-01-15, 01:21 PM
MTNQ > 26-01-15, 12:31 PM
thucgia > 08-02-15, 09:29 AM
(24-02-14, 01:21 AM)MatTroiNguQuen Đã viết: Chào bạn connguoi123! mình giải thích cách làm cụ thể như sau:
-Khi người dùng đăng nhập thành công, ta cập nhật tên máy, thời gian đăng nhập và UserOnline = True
- Khi người dùng đăng xuất hay tắt ứng dụng ta set Useronline = False (bằng cách chạy query qrUpdatetblUser)
Như vậy bạn chỉ cần lọc ra danh sách (ds) các Users có Useronline = True (Mình tạm gọi là ds 1) là biết được ai đang chạy ứng dụng cũng như tên máy và thời gian đăng nhập
Tuy nhiên trên đây là điều kiện cần nhưng chưa đủ.
Có một số trường hợp Useronline vẫn là True mặc dù người dùng đã thoát do ứng dụng được tắt không đúng cách (qrUpdatetblUser không được gọi khi thoát ứng dụng)
Ta dùng thủ tục ReturnUserRoster để lấy về tên các máy tính đang kết nối đến CSDL (ds 2)
Sau đó ta duyệt qua từng mẫu tin trong ds1 xem ComputerName có nằm trong ds2 hay không, nếu có thì set CpuOnline = True
Cuối cùng lọc ra danh sách thỏa 2 điều kiện UserOnline = True và CpuOnline = True ta có ds người dùng hiện đang truy cập CSDL
Giải thích các lệnh trong thủ tục ReturnUserRoster:
Mã PHP:Public Function ReturnUserRoster(mfrm As Form)
On Error GoTo ErrorHandler
Dim strPathLinkTable As String
Dim cnn As New ADODB.Connection
Dim rst As ADODB.Recordset
Dim rstUserOnl As New ADODB.Recordset
Dim SQL As String
'Lệnh sau đây set CpuOnline = 0 cho tất cả các mẫu tin trong bảng tblUser
CurrentDb.Execute "UPDATE tblUser SET tblUser.CpuOnline = 0 "
'Lấy về đường dẫn đến CSDL (back end):
strPathLinkTable = GetCurrentPath("tblUser")
'Thiết lập Kết nối đến CSDL:
cnn.Open "Provider= Microsoft.Jet.OLEDB.4.0; data source=" & strPathLinkTable
'Lấy về bản ghi chứa tên các máy đang truy cập đấn CSDL(ds2):
Set rst = cnn.OpenSchema(adSchemaProviderSpecific _
, , "{947bb102-5d43-11d1-bdbf-00c04fb92675}")
'Lấy về danh sách các mẫu tin có UserOnline = -1 (-1 = True): ds1
SQL = "SELECT Computername,CpuOnline FROM tblUser WHERE tblUser.UserOnline = -1 "
rstUserOnl.Open SQL, cnn, adOpenStatic, adLockOptimistic
'Với mỗi tên máy trong ds2-rst(0), ta duyệt qua ds1-rstUserOnl(0) nếu thấy trùng tên máy thì set cpuOnline = -1
Do While Not rst.EOF
If Not rstUserOnl.BOF Then rstUserOnl.MoveFirst
Do While Not rstUserOnl.EOF
If Trim(rstUserOnl(0)) = Trim(rst(0)) Then
rstUserOnl!CpuOnline = -1
rstUserOnl.Update
End If
rstUserOnl.MoveNext
Loop
rst.MoveNext
Loop
Set rstUserOnl = Nothing
Set rst = Nothing
Set cnn = Nothing
Exit_ErrorHandler:
Exit Function
ErrorHandler:
If Not rstUserOnl Is Nothing Then Set rstUserOnl = Nothing
If Not rst Is Nothing Then Set rst = Nothing
If Not cnn Is Nothing Then Set cnn = Nothing
MsgBox "Error: " & Err.Number & Chr(13) & Err.Description, , "Error: ReturnUserRoster"
Resume Exit_ErrorHandler
End Function
-Với "Demo một" RowSource của lstUserOnline mình đã lọc ra danh sách các mẫu tin thỏa cả hai điều kiện UserOnline = -1 và cpuOnline = -1 nên chỉ cần Requery là sẽ cập nhật lên form
-"Demo Hai" và "Demo Ba" dùng cho Unbound form
-Với "Demo Ba" mình không sử dụng đến cpuOnline mà lọc ra danh sách ( từ ds1 và ds2) rồi cập nhật thẳng vào lstUserOnline chứ không cập nhật vào tblUser rồi mới lấy lên lstUserOnline, nên bạn sẽ thấy cách 3 chạy nhanh hơn, tuy nhiên cách này với các bạn mới làm quen với lập trình sẽ thấy khó hiểu đôi chút
-Trong cách 3 nếu bạn bấm "Demo Hai" trước rồi mới bấm "Demo Ba" thì sẽ thấy trong lstUserOnline có tới 3 dòng có tên máy ta đang chạy. Điều đó có nghĩa là chương trình hiện tại đang có 3 kết nối đến CSDl (Recordset của form, Recordset của lstUserOnline và kết nối đang được mở ra của hàm ReturnUserRoster)
Nếu có gì chưa hiểu bạn cứ hỏi hoặc up file của bạn lên mình sẽ hướng dẫn cụ thể hơn!
Chúc bạn thành công!
MTNQ > 17-02-15, 11:21 AM
MTNQ > 17-02-15, 12:10 PM