This post provides several methods of enumerating sessions, connections and open files on a local or remote machine. Apart from the Powershell script that calls NetFileEnum there's nothing particularly new about this post, but I thought it was worth putting several different methods in one place.
This information is useful for gauging the use of file servers in particular, including the detail of which users are connected and what files they have locked.
Querying information against a single computer:
- Run 'compmgmt.msc /computer=%server%' and look in 'Shared Folders' for Shares, Sessions and 'Open Files'
- Run 'procexp.exe' (Process Explorer - SysInternals) on the machine and view the handles of the server service
- psexec \\%server% net file
- psloggedon \\server
- psexec \\%server% -c handle.exe
Querying against one or more computers:
- for %i in (server1 server2 server3 server4) do wmic /node:"%i" path win32_serverconnection get * /format:csv >> ServerConnections.txt
- for %i in (server1 server2 server3 server4) do wmic /node:"%i" path win32_serversession get * /format:csv >> ServerSessions.txt
- for %i in (server1 server2 server3 server4) do cscript //nologo listOpenFiles.vbs %i >> OpenFiles_%dateflat%.txt
- for %i in (server1 server2 server3 server4) do psexec \\%i net file
$servers = ("server1", "server2") foreach {. .\EnumOpenFiles.ps1 -s $_} write-host
Closing handles:
- The compmgmt.msc GUI
- The .remove method in the VBS below
- net session \\%client% [/delete]
- net file %id% [/close]
' VBScript
On Error Resume Next
If wscript.arguments.count = 1 Then
strserver = wscript.arguments.unnamed(0)
Else
wscript.echo "Error, no server name provided"
wscript.quit(0)
End If
Set objConnection = GetObject("WinNT://" & strServer & "/LanmanServer")
Set colResources = objConnection.Resources
For Each objResource in colResources
Wscript.Echo objResource.User & "," & objResource.LockCount & "," & objResource.Path & "," & objResource.Name
' Remove the session: colResources.Remove(objResource.Name)
Next
-
# PowerShell
# EnumOpenFiles #
#
# 28/07/2008, martinwx, Initial version
#
#
# Description:
# Call NetFileEnum() to enumerate open files on a file server
# the computer that a user is connecting from.
#
# Assumptions, this script works on the assumption that:
# The caller has administrator or server operator rights to the specified machines
#
# Usage
# Enumerate open files from the specified server:
# . .\EnumOpenFiles.ps1 -s server
#
# References
# http://msdn.microsoft.com/en-us/library/bb525378(VS.85).aspx
# http://support.microsoft.com/kb/176738
$server = $null
if (($args.count -eq 2) -or ($args.count -eq 4)) {
for ($i = 0; $i -le $args.count-1; $i+=2) {
if ($args[$i].ToLower().Contains("-s")) {
$server = $args[$i+1]
} elseif ($args[$i].ToLower().Contains("-v")) {
$verbosePreference = $args[$i+1]
}
}
}
$info = ""
if ($server -eq $null) {
write-output "No server specified, listing local files"
}
$provider = new-object Microsoft.VisualBasic.VBCodeProvider
$params = new-object System.CodeDom.Compiler.CompilerParameters
$params.GenerateInMemory = $True
$refs = "System.dll","Microsoft.VisualBasic.dll"
$params.ReferencedAssemblies.AddRange($refs)
# VB.NET EXAMPLE
$txtCode = @'
Imports System
Imports System.Runtime.InteropServices
Imports System.Net
Class EnumFiles
Const ERROR_SUCCESS As Long = 0
Private Const MAX_PREFERRED_LENGTH As Long = -1
Private Const PERM_FILE_READ = &h1
Private Const PERM_FILE_WRITE = &h2
Private Const PERM_FILE_CREATE = &h4
Private Const ACCESS_EXEC = &h08 ' Execute Permission (X)
Private Const ACCESS_DELETE = &h10 ' Delete Permission (D)
Private Const ACCESS_ATRIB = &h20 ' Change Attribute Permission (A)
Private Const ACCESS_PERM = &h40 ' Change ACL Permission (P)
Private Structure FILE_INFO_3
public fi3_id As Integer
public fi3_permissions As Integer
public fi3_num_locks As Integer
public fi3_pathname As String
public fi3_username As String
'fi3_id Specifies a DWORD value that contains the identification number assigned to the resource when it is opened.
'fi3_permissions Specifies a DWORD value that contains the access permissions associated with the opening application. This member can be one or more of the following values.
'fi3_num_locks Specifies a DWORD value that contains the number of file locks on the file, device, or pipe.
'fi3_pathname Pointer to a string that specifies the path of the opened resource.
'fi3_username Pointer to a string that specifies which user (on servers that have user-level security) or which computer (on servers that have share-level security) opened the resource. Note that Windows does not support share-level security.
End Structure
Declare Auto Function NetApiBufferFree Lib "netapi32" (ByVal Buffer As Long) As Long
Declare Function NetFileEnum Lib "netapi32.dll" ( _
ByVal servername As String, _
ByVal basepath As String, _
ByVal username As String, _
ByVal level As Integer, _
ByRef bufptr As Integer, _
ByVal prefmaxlen As Integer, _
ByRef entriesread As Integer, _
ByRef totalentries As Integer, _
ByVal resume_handle As Integer) As Integer
Function Main(Optional ByVal servername As String = Nothing) As String()
Dim result As Long
Dim ptr As IntPtr
Dim bufptr As Long 'out buffer
Dim i As Integer
Dim fi3 As FILE_INFO_3
Dim finfo As Object
Dim dwEntriesread As Long 'out
Dim dwTotalentries As Long 'out
Dim dwResumehandle As Long 'out
Dim iPermissions As Integer
Dim sPermissions As String = ""
If servername = "" Then servername = Nothing
result = NetFileEnum(servername, _
Nothing, _
Nothing, _
3, _
bufptr, _
MAX_PREFERRED_LENGTH, _
dwEntriesRead, _
dwTotalEntries, _
Nothing)
'Console.WriteLine("Entries: " + dwTotalentries.ToString() + ", " + dwEntriesRead.ToString())
Dim output(dwEntriesRead-1) As String ' Re-dim the array for the number of results
if result = 0 then
ptr = BufPtr ' Convert long to pointer
For i = 0 To dwEntriesread -1
sPermissions = ""
ptr = BufPtr ' Convert long to pointer
fi3 = CType(Marshal.PtrToStructure(ptr, GetType(FILE_INFO_3)),FILE_INFO_3) ' Marshal this record of the output buffer to the structure
BufPtr = BufPtr + Marshal.SizeOf(fi3) ' Increment for the next record
iPermissions = fi3.fi3_permissions
If (iPermissions AND PERM_FILE_READ) Then sPermissions = sPermissions + "+Read"
If (iPermissions AND PERM_FILE_WRITE) Then sPermissions = sPermissions + "+Write"
If (iPermissions AND PERM_FILE_CREATE) Then sPermissions = sPermissions + "+Create"
If (iPermissions AND ACCESS_EXEC) Then sPermissions = sPermissions + "+Execute"
If (iPermissions AND ACCESS_DELETE) Then sPermissions = sPermissions + "+Delete"
If (iPermissions AND ACCESS_ATRIB) Then sPermissions = sPermissions + "+Attr"
If (iPermissions AND ACCESS_PERM) Then sPermissions = sPermissions + "+Security"
If sPermissions.Length > 1 Then sPermissions = sPermissions.Remove(0,1)
output(i) = serverName + "," + fi3.fi3_id.ToString() + "," + fi3.fi3_pathname + "," + _
fi3.fi3_username + "," + fi3.fi3_num_locks.ToString() + "," + sPermissions
Next
Else
Output = Nothing
End If
Call NetApiBufferFree(ptr) ' Free the memory
return output
End Function
end class
'@
$cr = $provider.CompileAssemblyFromSource($params, $txtCode)
if ($cr.Errors.Count) {
$codeLines = $txtCode.Split("`n");
foreach ($ce in $cr.Errors)
{
write-output -i "Error: $($codeLines[$($ce.Line - 1)])"
write-output -i $ce
#$ce write-output
}
Throw "INVALID DATA: Errors encountered while compiling code"
}
$mAssembly = $cr.CompiledAssembly
$instance = $mAssembly.CreateInstance("EnumFiles")
#write-output "Enumerating open files from $server"
$result = $instance.main($server) # Call the VB.Net entry point
write-output -i $result
-
References:
IADsResource Property Methods
http://msdn.microsoft.com/en-us/library/aa706125(VS.85).aspx
IADsResource Interface
http://msdn.microsoft.com/en-us/library/aa706124(VS.85).aspx
List Open Sessions and Open Files
http://www.microsoft.com/technet/scriptcenter/resources/qanda/feb05/hey0216.mspx
Wayne's World of IT (WWoIT)
3 comments:
In VB code block. Passed in $server (to servername) fails to pas into NetEnum API call. It only works when servername is set to Nothing. I suspect this is a misdeclaration of the parameters in the API "declare". It shule be a pointer being passed. Can't yet prove this without loading VB6.
Have you tried to fix this yet?
Hello,
I haven't had any problems using this when passing in a remote server - which is how I originally used the script.
Please make sure you are using this syntax:
. .\EnumOpenFiles.ps1 -s server
Any compilation errors would show up when trying to run the PowerShell script (you can test this by making an error in the VB.Net code).
I've only tested this with PowerShell v1.0 by the way; it may not work correctly under 2.0?
Although it covered most of code that is needed and quite helpful for those who need this solution.Querying information against a single computer is easy but when it comes to multiple then you need to pay attention
Post a Comment