Get File Owner of a UNC file when run on a Windows 2000 Server

Posted on 2005-03-15
Medium Priority
Last Modified: 2012-06-21
I have the need to be able to retrieve the file owner from a host of files that live throughout our network.  We are provided the UNC names and need to return the file owner.  I can get this working on my workstation, although its very slow, using a mapped drive but not with a unc name.  As a last resort the mapped drive is OK.  The problem is that I need to run this from a server (windows 2000 Server) and that even using a mapped drive, no owner is returned.  

Question is 1) How can I get the file owner from a unc filename, and 2) how can I get it to run on the server?

The code is:

imports system.management

    Public Function GetFileOwner(ByVal strFile As String) As String
        Dim oManagementObject As New ManagementObject("Win32_LogicalFileSecuritySetting.path='" & strFile & "'")
        Dim oManagementBaseObject As ManagementBaseObject
        'oManagementObject.Path = ""
        Dim oDescriptor As ManagementBaseObject
        Dim oOwner As ManagementBaseObject
        Dim Owner As PropertyDataCollection
        Dim strOwner As String
            'Get the security descriptor for this object
            oManagementBaseObject = oManagementObject.InvokeMethod("GetSecurityDescriptor", Nothing, Nothing)
            oDescriptor = oManagementBaseObject.Properties("Descriptor").Value()
            'Get the Ownerobject
            oOwner = oDescriptor.Properties("Owner").Value
            'Read the Properties to a Propertydatacollection Object
            Owner = oOwner.Properties
            strOwner = Owner("Name").Value
        Catch e As Exception
            ' Problem getting information
            strOwner = ""
        End Try
        Return (strOwner)
    End Function
Question by:vbtl
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
LVL 41

Accepted Solution

graye earned 2000 total points
ID: 13562014
I'd consider using the APIs....   Here is an example that works for both local and UNC paths

Imports System.Runtime.InteropServices

Module FileOwner

    Private Declare Function GetFileSecurity Lib "advapi32.dll" Alias "GetFileSecurityA" ( _
    ByVal lpFileName As String, ByVal RequestedInformation As Integer, _
    ByRef pSecurityDescriptor As Byte, ByVal nLength As Integer, ByRef lpnLengthNeeded _
    As Integer) As Integer

    Private Declare Function GetSecurityDescriptorOwner Lib "advapi32.dll" (ByRef _
    pSecurityDescriptor As Byte, ByRef pOwner As Integer, ByRef lpbOwnerDefaulted As _
    Integer) As Integer

    Private Declare Function LookupAccountSid Lib "advapi32.dll" Alias "LookupAccountSidA" ( _
    ByVal lpSystemName As String, ByVal Sid As Integer, ByVal name As String, _
    ByRef cbName As Integer, ByVal ReferencedDomainName As String, ByRef _
    cbReferencedDomainName As Integer, ByRef peUse As Integer) As Integer

    <DllImport("advapi32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
    Function ConvertSidToStringSid( _
    ByVal psid As IntPtr, _
    ByRef ssp As IntPtr) As Boolean
    End Function

    Private Const SD_SIZE = 48
    Private Const NAME_SIZE = 64

    Function GetFileOwner(ByVal szfilename As String) As String
        Dim bSuccess As Integer     ' Status variable
        Dim sizeSD As Integer       ' Buffer size to store Owner's SID
        Dim pOwner As Integer       ' Pointer to the Owner's SID
        Dim name As String          ' Name of the file owner
        Dim domain_name As String   ' Name of the first domain for the owner
        Dim name_len As Integer     ' Required length for the owner name
        Dim domain_len As Integer   ' Required length for the domain name
        Dim sdBuf() As Byte         ' Buffer for Security Descriptor
        Dim nLength As Integer      ' Length of the Windows Directory
        Dim deUse As Integer        ' Pointer to a SID_NAME_USE indicating type of account
        Dim sid_ptr, sidstring_ptr As IntPtr
        Dim SidString, MachineName As String
        Dim LastError As Integer

        sizeSD = SD_SIZE
        ReDim sdBuf(sizeSD - 1)

        bSuccess = GetFileSecurity(szfilename, OWNER_SECURITY_INFORMATION, sdBuf(0), sizeSD, sizeSD)
        If (bSuccess = 0) Then
            Debug.WriteLine("File=" & szfilename & ", GetFileSecurity=" & Err.LastDllError)
            Return "Error"
        End If

        bSuccess = GetSecurityDescriptorOwner(sdBuf(0), pOwner, 0)
        If (bSuccess = 0) Then
            Debug.WriteLine("File=" & szfilename & ", GetSecurityDescriptorOwner=" & Err.LastDllError)
            Return "Error"
        End If

        ' we often need a bit of breathing room between these two API calls

        ' are we doing this remotely? (detected source of mapped drive letters?)
        If szfilename.StartsWith("\\") Then
            MachineName = szfilename.Split("\")(2)
            MachineName = ""
        End If

        name_len = NAME_SIZE
        domain_len = NAME_SIZE
        name = Space(name_len)
        domain_name = Space(domain_len)
        bSuccess = LookupAccountSid(MachineName, pOwner, name, name_len, domain_name, domain_len, deUse)
        If (bSuccess = 0) Then
            LastError = Marshal.GetLastWin32Error()
            ' if we fail on error 1332, then use the SID in the name
            If LastError <> 1332 Then
                Debug.WriteLine("File=" & szfilename & ", LookupAccountSid= " & LastError.ToString)
                Return "Error"
                sid_ptr = New IntPtr(pOwner)
                If ConvertSidToStringSid(sid_ptr, sidstring_ptr) = False Then
                    LastError = Marshal.GetLastWin32Error()
                    Debug.WriteLine("File=" & szfilename & ", ConvertSidToStringSid= " & LastError.ToString)
                    Return "Error"
                    SidString = Marshal.PtrToStringAuto(sidstring_ptr)
                    domain_len = 0
                    name = SidString
                    name_len = Len(name)
                End If
            End If
        End If

        If domain_len > 0 Then
            Return Left(domain_name, domain_len) & "\" & Left(name, name_len)
            Return Left(name, name_len)
        End If
    End Function

End Module

Author Comment

ID: 13600017
Like it!  Thanks

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Article by: Kraeven
Introduction Remote Share is a simple remote sharing tool, enabling you to see, add and remove remote or local shares. The application is written in VB.NET targeting the .NET framework 2.0. The source code and the compiled programs have been in…
It’s quite interesting for me as I worked with Excel using vb.net for some time. Here are some topics which I know want to share with others whom this might help. First of all if you are working with Excel then you need to Download the Following …
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …
Do you want to know how to make a graph with Microsoft Access? First, create a query with the data for the chart. Then make a blank form and add a chart control. This video also shows how to change what data is displayed on the graph as well as form…

777 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question