VB.Net:如何获取访问共享文件夹文件的远程计算机IP及名称
问题:获取访问共享文件夹的远程计算机IP与名称
在Windows系统中使用VB.Net的FileSystemWatcher监控网络共享文件夹时,无法获取访问文件的远程计算机IP和名称,当前代码仅能返回本地系统的IP和名称,需解决该问题以获取远程访问者的信息。
现有代码
Imports System.IO Imports System.Data.OleDb Public Class Form1 Private watchers As New List(Of FileSystemWatcher) ' Dictionary to store last access times of files Private lastAccessTimes As New Dictionary(Of String, DateTime) Dim con As New OleDbConnection Dim cmd As OleDbCommand Dim flag As Integer = 0 Dim qry As String Dim dr As OleDbDataReader Dim data As String = "Provider=Microsoft.ACE.OLEDB.12.0;jet OLEDB:Database Password=open;Data Source=" & Application.StartupPath & "\Database.accdb;" Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load con.ConnectionString = data If con.State = ConnectionState.Closed Then con.Open() End If load_file_path() monitoring_access() End Sub Private Sub load_file_path() If con.State = ConnectionState.Closed Then con.Open() End If qry = "select * from Tbl_FilePath where Status=" & "'Active';" cmd = New OleDbCommand(qry, con) cmd.ExecuteNonQuery() dr = cmd.ExecuteReader If dr.HasRows Then While dr.Read DGView2.Rows.Add(dr("File_Path")) 'Me.ListBox1.Items.Add(dr("File_Path")) End While End If con.Close() End Sub Private Sub img_settings_Click(sender As Object, e As EventArgs) Handles img_settings.Click Settings.ShowDialog() End Sub Private Sub monitoring_access() ' Start monitoring folders For Each row As DataGridViewRow In DGView2.Rows Dim folderPath As String = row.Cells(0).Value.ToString() AddFolderToWatcher(folderPath) Next End Sub Private Sub AddFolderToWatcher(folderPath As String) If Directory.Exists(folderPath) Then ' Create a new instance of FileSystemWatcher for the specified path Dim watcher As New FileSystemWatcher(folderPath) AddHandler watcher.Created, AddressOf FileSystemWatcher_Event AddHandler watcher.Deleted, AddressOf FileSystemWatcher_Event AddHandler watcher.Changed, AddressOf FileSystemWatcher_Event AddHandler watcher.Renamed, AddressOf FileSystemWatcher_Event watcher.IncludeSubdirectories = True watcher.EnableRaisingEvents = True watchers.Add(watcher) Else MessageBox.Show($"Folder does not exist: {folderPath}") End If End Sub Private Sub FileSystemWatcher_Event(sender As Object, e As FileSystemEventArgs) ' Handle file system events here Dim eventType As String = GetEventType(e.ChangeType) Dim operation As String = $"{eventType}" 'Dim username As String = currentIdentity.Name Dim username As String = $"{Environment.UserName}" 'Dim user As String = GetUsername() Dim now As DateTime = DateTime.Now Dim GetDateTime As String = now.ToString("dd-MM-yyyy hh:mm:ss tt") Dim file_path As String = $"{e.FullPath}" 'CheckAccessedUser(file_path) If Not file_path.Contains("$") Or file_path.Contains("@") Then ' The filePath does not contain '$' update_DGView1(operation, username, GetDateTime, file_path) End If 'UpdateListBox(message) ' Update last access time in the dictionary lastAccessTimes(e.FullPath) = File.GetLastAccessTime(e.FullPath) ' Check if the file has been accessed (opened or viewed) Dim lastAccessTime As DateTime If lastAccessTimes.TryGetValue(e.FullPath, lastAccessTime) AndAlso File.GetLastAccessTime(e.FullPath) <> lastAccessTime Then 'message += " - Viewed" update_DGView1("Viewed", username, GetDateTime, file_path) End If End Sub Private Function GetEventType(changeType As WatcherChangeTypes) As String Select Case changeType Case WatcherChangeTypes.Created Return "Created" Case WatcherChangeTypes.Changed Return "Edited" Case WatcherChangeTypes.Deleted Return "Deleted" Case WatcherChangeTypes.Renamed Return "Renamed" Case Else Return "Unknown event" End Select End Function Private Sub update_DGView1(operation As String, user As String, GetDateTime As String, file_path As String) If DGView1.InvokeRequired Then DGView1.Invoke(Sub() update_DGView1(operation, user, GetDateTime, file_path)) Else ' Your DGView1 update code goes here DGView1.Rows.Add(operation, user, GetDateTime, file_path) End If End Sub End Class
解决方案
FileSystemWatcher本身不包含远程访问者的身份信息,需要结合Windows系统的日志、共享会话查询或文件审核来实现:
方法1:查询Windows共享会话(Net Session命令)
通过执行net session命令获取当前连接到共享的会话信息,解析结果得到远程计算机名和IP。在VB.Net中可通过Process类执行命令并读取输出:
Private Function GetRemoteSessionInfo() As Dictionary(Of String, String) Dim sessionDict As New Dictionary(Of String, String) Dim process As New Process() process.StartInfo.FileName = "net" process.StartInfo.Arguments = "session" process.StartInfo.RedirectStandardOutput = True process.StartInfo.UseShellExecute = False process.StartInfo.CreateNoWindow = True process.Start() Dim output As String = process.StandardOutput.ReadToEnd() process.WaitForExit() ' 解析输出,提取计算机名和IP Dim lines As String() = output.Split(New String() {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries) For i = 2 To lines.Length - 1 ' 跳过前两行表头 Dim parts As String() = lines(i).Split(New Char() {" "c}, StringSplitOptions.RemoveEmptyEntries) If parts.Length >= 3 Then Dim computerName As String = parts(0).TrimEnd("\") ' 去除末尾的反斜杠 Dim ipAddress As String = parts(2) sessionDict(computerName) = ipAddress End If Next Return sessionDict End Function
在FileSystemWatcher的事件触发时,调用此方法,结合事件时间范围匹配对应的会话信息。
方法2:启用文件审核并读取安全日志
- 启用文件审核:右键共享文件夹→属性→安全→高级→审核→添加,选择目标用户/组,勾选“读取”“写入”等操作的成功审核规则。
- 读取安全日志:在VB.Net中筛选事件ID为4663(文件/对象访问)和4656(句柄创建)的事件,提取远程计算机名和IP:
Imports System.Diagnostics.Eventing.Reader Private Sub GetRecentAuditLogs(targetFilePath As String, eventTime As DateTime) ' 查询指定时间范围内的文件访问日志 Dim timeFilter As String = $"*[System[TimeCreated[@SystemTime>='{eventTime.AddSeconds(-5).ToString("o")}'] and EventID=4663]]" Dim query As New EventLogQuery("Security", PathType.LogName, timeFilter) Dim reader As New EventLogReader(query) Dim eventRecord As EventRecord = reader.ReadEvent() While eventRecord IsNot Nothing ' 解析事件中的文件路径 Dim accessedPath As String = eventRecord.Properties(6).Value.ToString() If accessedPath.Equals(targetFilePath, StringComparison.OrdinalIgnoreCase) Then ' 获取远程计算机名 Dim computerName As String = eventRecord.Properties(11).Value.ToString() ' 解析计算机名到IP Dim ipAddress As String = GetIpFromComputerName(computerName) ' 获取访问用户名 Dim userName As String = eventRecord.Properties(1).Value.ToString() ' 更新DataGridView update_DGView1("Accessed", $"{userName} ({computerName}/{ipAddress})", eventTime.ToString("dd-MM-yyyy hh:mm:ss tt"), targetFilePath) Exit While End If eventRecord = reader.ReadEvent() End While End Sub Private Function GetIpFromComputerName(computerName As String) As String Try Dim hostEntry = System.Net.Dns.GetHostEntry(computerName) Return hostEntry.AddressList.FirstOrDefault(Function(ip) ip.AddressFamily = System.Net.Sockets.AddressFamily.InterNetwork)?.ToString() OrElse "Unknown" Catch ex As Exception Return "Unknown" End Try End Function
在FileSystemWatcher事件中调用此方法,传入文件路径和事件触发时间。
方法3:使用WMI查询共享连接
通过WMI的Win32_ServerConnection类获取当前共享会话信息:
Imports System.Management Private Function GetWmiSessionInfo() As List(Of Tuple(Of String, String, String)) Dim sessionList As New List(Of Tuple(Of String, String, String)) Try Dim scope As New ManagementScope("\\.\root\CIMV2") scope.Connect() Dim query As New ObjectQuery("SELECT ComputerName, UserName, ConnectionID FROM Win32_ServerConnection") Dim searcher As New ManagementObjectSearcher(scope, query) For Each mObj As ManagementObject In searcher.Get() Dim computerName As String = mObj("ComputerName")?.ToString().TrimEnd("\") Dim userName As String = mObj("UserName")?.ToString() Dim ipAddress As String = GetIpFromComputerName(computerName) sessionList.Add(Tuple.Create(computerName, ipAddress, userName)) Next Catch ex As Exception ' 处理权限或连接异常 End Try Return sessionList End Function
关键注意事项
- 权限要求:所有方法均需程序以管理员权限运行,否则无法读取系统日志、执行
net session或访问WMI。 - 事件关联:FileSystemWatcher事件与日志/会话信息的时间可能存在微小偏差,建议设置±5秒的时间范围进行匹配。
- 性能优化:避免高频查询系统资源,可设置定时器批量查询,或在事件触发时仅查询最近的会话/日志。
内容的提问来源于stack exchange,提问作者karthick ks
相关产品推荐
相关产品推荐

