Results 1 to 6 of 6

Thread: Process Locking file , i cant solve error.

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Nov 2013
    Posts
    21

    Process Locking file , i cant solve error.

    Trying to figure out why this code does not work.
    I am on windows 10 and this code does exactly what i need, but it does not work that well for me, i keep getting error here at this code line

    Code:
    strObjectTypeName = Marshal.PtrToStringUni(ipTemp, objObjectType.Name.Length >> 1)


    The error message
    Code:
    An unhandled exception of type 'System.AccessViolationException' occurred in mscorlib.dll
    
    Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.




    Here is the full class

    Code:
    Imports System.Collections.Generic
    Imports System.Runtime.InteropServices
    Imports System.Diagnostics
    Imports System.Text
    Imports System.Threading
    
    Namespace FileLockInfo
        Public Class FileLocked
    
    
            ''' <summary>
            ''' Return a list of processes that hold on the given file.
            ''' </summary>
            Public Shared Function GetProcessesLockingFile(filePath As String) As List(Of Process)
                Dim procs = New List(Of Process)()
    
                For Each process__1 In Process.GetProcesses()
                    Dim files = GetFilesLockedBy(process__1)
                    If files.Contains(filePath) Then
                        procs.Add(process__1)
                    End If
                Next
                Return procs
            End Function
    
            ''' <summary>
            ''' Return a list of file locks held by the process.
            ''' </summary>
            Public Shared Function GetFilesLockedBy(process As Process) As List(Of String)
                Dim outp = New List(Of String)()
    
                Dim ts As ThreadStart = New ThreadStart(
                    Sub()
                        Try
                            outp = UnsafeGetFilesLockedBy(process)
                        Catch
                        End Try
                    End Sub
                )
    
                Try
                    Dim t = New Thread(ts)
                    t.IsBackground = True
                    t.Start()
                    t.Join()
                    'If Not t.Join(250) Then
                    '    Try
                    '        t.Abort()
                    '    Catch
                    '    End Try
                    'End If
                Catch
                End Try
    
                Return outp
            End Function
    
    #Region "Inner Workings"
            Private Shared Function UnsafeGetFilesLockedBy(process As Process) As List(Of String)
                Try
                    Dim [handles] = GetHandles(process)
                    Dim files = New List(Of String)()
    
                    For Each handle In [handles]
                        Dim file = GetFilePath(handle, process)
                        If file IsNot Nothing Then
                            files.Add(file)
                        End If
                    Next
    
                    Return files
                Catch
                    Return New List(Of String)()
                End Try
            End Function
    
            Const CNST_SYSTEM_HANDLE_INFORMATION As Integer = 16
            Const STATUS_INFO_LENGTH_MISMATCH As UInteger = &HC0000004UI
            Private Shared Function GetFilePath(sYSTEM_HANDLE_INFORMATION As Win32API.SYSTEM_HANDLE_INFORMATION, process As Process) As String
                If sYSTEM_HANDLE_INFORMATION.GrantedAccess = &H12019F OrElse
                    sYSTEM_HANDLE_INFORMATION.GrantedAccess = &H1A019F OrElse
                    sYSTEM_HANDLE_INFORMATION.GrantedAccess = &H120189 OrElse
                    sYSTEM_HANDLE_INFORMATION.GrantedAccess = &H100000 Then
                    Return Nothing
                End If
    
                Dim m_ipProcessHwnd As IntPtr = Win32API.OpenProcess(Win32API.ProcessAccessFlags.All, False, process.Id)
                Dim ipHandle As IntPtr = IntPtr.Zero
                Dim objBasic = New Win32API.OBJECT_BASIC_INFORMATION()
                Dim ipBasic As IntPtr = IntPtr.Zero
                Dim objObjectType = New Win32API.OBJECT_TYPE_INFORMATION()
                Dim ipObjectType As IntPtr = IntPtr.Zero
                Dim objObjectName = New Win32API.OBJECT_NAME_INFORMATION()
                Dim ipObjectName As IntPtr = IntPtr.Zero
                Dim strObjectTypeName As String = ""
                Dim strObjectName As String = ""
                Dim nLength As Integer = 0
                Dim nReturn As Integer = 0
                Dim ipTemp As IntPtr = IntPtr.Zero
    
                If Not Win32API.DuplicateHandle(m_ipProcessHwnd, sYSTEM_HANDLE_INFORMATION.Handle, Win32API.GetCurrentProcess(), ipHandle, 0, False, _
                 Win32API.DUPLICATE_SAME_ACCESS) Then
                    Return Nothing
                End If
    
                ipBasic = Marshal.AllocHGlobal(Marshal.SizeOf(objBasic))
                Win32API.NtQueryObject(ipHandle, CInt(Win32API.ObjectInformationClass.ObjectBasicInformation), ipBasic, Marshal.SizeOf(objBasic), nLength)
                objBasic = DirectCast(Marshal.PtrToStructure(ipBasic, objBasic.[GetType]()), Win32API.OBJECT_BASIC_INFORMATION)
                Marshal.FreeHGlobal(ipBasic)
    
                ipObjectType = Marshal.AllocHGlobal(objBasic.TypeInformationLength)
                nLength = objBasic.TypeInformationLength
                While CUInt(InlineAssignHelper(nReturn, Win32API.NtQueryObject(ipHandle, CInt(Win32API.ObjectInformationClass.ObjectTypeInformation), ipObjectType, nLength, nLength))) = Win32API.STATUS_INFO_LENGTH_MISMATCH
                    Marshal.FreeHGlobal(ipObjectType)
                    ipObjectType = Marshal.AllocHGlobal(nLength)
                End While
    
                objObjectType = DirectCast(Marshal.PtrToStructure(ipObjectType, objObjectType.[GetType]()), Win32API.OBJECT_TYPE_INFORMATION)
                If Is64Bits() Then
                    ipTemp = New IntPtr(Convert.ToInt64(objObjectType.Name.Buffer.ToString(), 10) >> 32)
                Else
                    ipTemp = objObjectType.Name.Buffer
                End If
    
                strObjectTypeName = Marshal.PtrToStringUni(ipTemp, objObjectType.Name.Length >> 1)
                Marshal.FreeHGlobal(ipObjectType)
                If strObjectTypeName <> "File" Then
                    Return Nothing
                End If
    
                'nLength = objBasic.NameInformationLength
                nLength = &H1000
                ipObjectName = Marshal.AllocHGlobal(nLength)
                While CUInt(InlineAssignHelper(nReturn, Win32API.NtQueryObject(ipHandle, CInt(Win32API.ObjectInformationClass.ObjectNameInformation), ipObjectName, nLength, nLength))) = Win32API.STATUS_INFO_LENGTH_MISMATCH
                    Marshal.FreeHGlobal(ipObjectName)
                    ipObjectName = Marshal.AllocHGlobal(nLength)
                End While
                objObjectName = DirectCast(Marshal.PtrToStructure(ipObjectName, objObjectName.[GetType]()), Win32API.OBJECT_NAME_INFORMATION)
    
                If Is64Bits() Then
                    ipTemp = New IntPtr(Convert.ToInt64(objObjectName.Name.Buffer.ToString(), 10) >> 32)
                Else
                    ipTemp = objObjectName.Name.Buffer
                End If
    
                If ipTemp <> IntPtr.Zero Then
    
                    Dim baTemp As Byte() = New Byte(nLength - 1) {}
                    Try
                        Marshal.Copy(ipTemp, baTemp, 0, nLength)
    
                        strObjectName = Marshal.PtrToStringUni(If(Is64Bits(), New IntPtr(ipTemp.ToInt64()), New IntPtr(ipTemp.ToInt32())))
                    Catch generatedExceptionName As AccessViolationException
                        Return Nothing
                    Finally
                        Marshal.FreeHGlobal(ipObjectName)
                        Win32API.CloseHandle(ipHandle)
                    End Try
                End If
    
                Dim path As String = GetRegularFileNameFromDevice(strObjectName)
                Try
                    Return path
                Catch
                    Return Nothing
                End Try
            End Function
    
            Private Shared Function GetRegularFileNameFromDevice(strRawName As String) As String
                Dim strFileName As String = strRawName
                For Each strDrivePath As String In Environment.GetLogicalDrives()
                    Dim sbTargetPath As New StringBuilder(Win32API.MAX_PATH)
                    If Win32API.QueryDosDevice(strDrivePath.Substring(0, 2), sbTargetPath, Win32API.MAX_PATH) = 0 Then
                        Return strRawName
                    End If
                    Dim strTargetPath As String = sbTargetPath.ToString()
                    If strFileName.StartsWith(strTargetPath) Then
                        strFileName = strFileName.Replace(strTargetPath, strDrivePath.Substring(0, 2))
                        Exit For
                    End If
                Next
                Return strFileName
            End Function
    
            Private Shared Function GetHandles(process As Process) As List(Of Win32API.SYSTEM_HANDLE_INFORMATION)
                Dim nStatus As UInteger
                Dim nHandleInfoSize As Integer = &H10000
                Dim ipHandlePointer As IntPtr = Marshal.AllocHGlobal(nHandleInfoSize)
                Dim nLength As Integer = 0
                Dim ipHandle As IntPtr = IntPtr.Zero
    
                While (InlineAssignHelper(nStatus, Win32API.NtQuerySystemInformation(CNST_SYSTEM_HANDLE_INFORMATION, ipHandlePointer, nHandleInfoSize, nLength))) = STATUS_INFO_LENGTH_MISMATCH
                    nHandleInfoSize = nLength
                    Marshal.FreeHGlobal(ipHandlePointer)
                    ipHandlePointer = Marshal.AllocHGlobal(nLength)
                End While
    
                Dim baTemp As Byte() = New Byte(nLength - 1) {}
                Marshal.Copy(ipHandlePointer, baTemp, 0, nLength)
    
                Dim lHandleCount As Long = 0
                If Is64Bits() Then
                    lHandleCount = Marshal.ReadInt64(ipHandlePointer)
                    ipHandle = New IntPtr(ipHandlePointer.ToInt64() + 8)
                Else
                    lHandleCount = Marshal.ReadInt32(ipHandlePointer)
                    ipHandle = New IntPtr(ipHandlePointer.ToInt32() + 4)
                End If
    
                Dim shHandle As Win32API.SYSTEM_HANDLE_INFORMATION
                Dim lstHandles As New List(Of Win32API.SYSTEM_HANDLE_INFORMATION)()
    
                For lIndex As Long = 0 To lHandleCount - 1
                    shHandle = New Win32API.SYSTEM_HANDLE_INFORMATION()
                    If Is64Bits() Then
                        shHandle = DirectCast(Marshal.PtrToStructure(ipHandle, shHandle.[GetType]()), Win32API.SYSTEM_HANDLE_INFORMATION)
                        ipHandle = New IntPtr(ipHandle.ToInt64() + Marshal.SizeOf(shHandle) + 8)
                    Else
                        ipHandle = New IntPtr(ipHandle.ToInt64() + Marshal.SizeOf(shHandle))
                        shHandle = DirectCast(Marshal.PtrToStructure(ipHandle, shHandle.[GetType]()), Win32API.SYSTEM_HANDLE_INFORMATION)
                    End If
                    If shHandle.ProcessID <> process.Id Then
                        Continue For
                    End If
    
                    lstHandles.Add(shHandle)
                Next
                Return lstHandles
    
            End Function
    
            Private Shared Function Is64Bits() As Boolean
                Return If(Marshal.SizeOf(GetType(IntPtr)) = 8, True, False)
            End Function
    
            Friend Class Win32API
                <DllImport("ntdll.dll")> _
                Public Shared Function NtQueryObject(ObjectHandle As IntPtr, ObjectInformationClass As Integer, ObjectInformation As IntPtr, ObjectInformationLength As Integer, ByRef returnLength As Integer) As Integer
                End Function
    
                <DllImport("kernel32.dll", SetLastError:=True)> _
                Public Shared Function QueryDosDevice(lpDeviceName As String, lpTargetPath As StringBuilder, ucchMax As Integer) As UInteger
                End Function
    
                <DllImport("ntdll.dll")> _
                Public Shared Function NtQuerySystemInformation(SystemInformationClass As Integer, SystemInformation As IntPtr, SystemInformationLength As Integer, ByRef returnLength As Integer) As UInteger
                End Function
    
                <DllImport("kernel32.dll")> _
                Public Shared Function OpenProcess(dwDesiredAccess As ProcessAccessFlags, <MarshalAs(UnmanagedType.Bool)> bInheritHandle As Boolean, dwProcessId As Integer) As IntPtr
                End Function
                <DllImport("kernel32.dll")> _
                Public Shared Function CloseHandle(hObject As IntPtr) As Integer
                End Function
                <DllImport("kernel32.dll", SetLastError:=True)> _
                Public Shared Function DuplicateHandle(hSourceProcessHandle As IntPtr, hSourceHandle As UShort, hTargetProcessHandle As IntPtr, ByRef lpTargetHandle As IntPtr, dwDesiredAccess As UInteger, <MarshalAs(UnmanagedType.Bool)> bInheritHandle As Boolean, _
        dwOptions As UInteger) As <MarshalAs(UnmanagedType.Bool)> Boolean
                End Function
                <DllImport("kernel32.dll")> _
                Public Shared Function GetCurrentProcess() As IntPtr
                End Function
    
                Public Enum ObjectInformationClass As Integer
                    ObjectBasicInformation = 0
                    ObjectNameInformation = 1
                    ObjectTypeInformation = 2
                    ObjectAllTypesInformation = 3
                    ObjectHandleInformation = 4
                End Enum
    
                <Flags()> _
                Public Enum ProcessAccessFlags As UInteger
                    All = &H1F0FFF
                    Terminate = &H1
                    CreateThread = &H2
                    VMOperation = &H8
                    VMRead = &H10
                    VMWrite = &H20
                    DupHandle = &H40
                    SetInformation = &H200
                    QueryInformation = &H400
                    Synchronize = &H100000
                End Enum
    
                <StructLayout(LayoutKind.Sequential)> _
                Public Structure OBJECT_BASIC_INFORMATION
                    ' Information Class 0
                    Public Attributes As Integer
                    Public GrantedAccess As Integer
                    Public HandleCount As Integer
                    Public PointerCount As Integer
                    Public PagedPoolUsage As Integer
                    Public NonPagedPoolUsage As Integer
                    Public Reserved1 As Integer
                    Public Reserved2 As Integer
                    Public Reserved3 As Integer
                    Public NameInformationLength As Integer
                    Public TypeInformationLength As Integer
                    Public SecurityDescriptorLength As Integer
                    Public CreateTime As System.Runtime.InteropServices.ComTypes.FILETIME
                End Structure
    
                <StructLayout(LayoutKind.Sequential)> _
                Public Structure OBJECT_TYPE_INFORMATION
                    ' Information Class 2
                    Public Name As UNICODE_STRING
                    Public ObjectCount As Integer
                    Public HandleCount As Integer
                    Public Reserved1 As Integer
                    Public Reserved2 As Integer
                    Public Reserved3 As Integer
                    Public Reserved4 As Integer
                    Public PeakObjectCount As Integer
                    Public PeakHandleCount As Integer
                    Public Reserved5 As Integer
                    Public Reserved6 As Integer
                    Public Reserved7 As Integer
                    Public Reserved8 As Integer
                    Public InvalidAttributes As Integer
                    Public GenericMapping As GENERIC_MAPPING
                    Public ValidAccess As Integer
                    Public Unknown As Byte
                    Public MaintainHandleDatabase As Byte
                    Public PoolType As Integer
                    Public PagedPoolUsage As Integer
                    Public NonPagedPoolUsage As Integer
                End Structure
    
                <StructLayout(LayoutKind.Sequential)> _
                Public Structure OBJECT_NAME_INFORMATION
                    ' Information Class 1
                    Public Name As UNICODE_STRING
                End Structure
    
                <StructLayout(LayoutKind.Sequential, Pack:=1)> _
                Public Structure UNICODE_STRING
                    Public Length As UShort
                    Public MaximumLength As UShort
                    Public Buffer As IntPtr
                End Structure
    
                <StructLayout(LayoutKind.Sequential)> _
                Public Structure GENERIC_MAPPING
                    Public GenericRead As Integer
                    Public GenericWrite As Integer
                    Public GenericExecute As Integer
                    Public GenericAll As Integer
                End Structure
    
                <StructLayout(LayoutKind.Sequential, Pack:=1)> _
                Public Structure SYSTEM_HANDLE_INFORMATION
                    ' Information Class 16
                    Public ProcessID As Integer
                    Public ObjectTypeNumber As Byte
                    Public Flags As Byte
                    ' 0x01 = PROTECT_FROM_CLOSE, 0x02 = INHERIT
                    Public Handle As UShort
                    Public Object_Pointer As Integer
                    Public GrantedAccess As UInt32
                End Structure
    
                Public Const MAX_PATH As Integer = 260
                Public Const STATUS_INFO_LENGTH_MISMATCH As UInteger = &HC0000004UI
                Public Const DUPLICATE_SAME_ACCESS As Integer = &H2
            End Class
            Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, value As T) As T
                target = value
                Return value
            End Function
    #End Region
        End Class
    End Namespace



    And here is how i call it

    Code:
        Private Sub Whoislockingf_Click(sender As Object, e As EventArgs) Handles Whoislockingf.Click
            For Each P As Process In FileLockInfo.FileLocked.GetProcessesLockingFile("F:\Testfile") 'Example place of file that is locked by anbother process
                ListBox1.Items.Add(P.ProcessName)
            Next
        End Sub


    I think i just missing something easy. but i dont know where,
    I compile it as 64 bit and have tried "Any CPU" but same results.


    If anyone could try it out and maby figure this one out any help would be appreciated!

  2. #2
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,038

    Re: Process Locking file , i cant solve error.

    The threading you are using seems a bit off, but it also seems irrelevant to the question at hand.

    If you were to strip out all the threading, and also strip out the loops such that you are calling a simpler method for just the first P in the collection, do you still get the error?

    My thinking is that you are currently complicating the situation with the threading, which boils down to just this:

    Code:
    Dim files = New List(Of String)()
    
                    For Each handle In [handles]
                        Dim file = GetFilePath(handle, process)
                        If file IsNot Nothing Then
                            files.Add(file)
                        End If
                    Next
    so it would be good to try that without the threading to ensure that you still get the error. I expect that you will, but it would be more interesting if you did not.
    My usual boring signature: Nothing

  3. #3

    Thread Starter
    Junior Member
    Join Date
    Nov 2013
    Posts
    21

    Re: Process Locking file , i cant solve error.

    Hey thanks for the input, i tried that and now the listbox seems to add something, but it stops and i still get that error after a few seconds of the listbox filling up, with what results i can not see.

  4. #4
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    39,038

    Re: Process Locking file , i cant solve error.

    So, the loop runs for a while...then stops? That's some interesting information. Not GOOD news, in my opinion, but interesting.

    Had it failed on the first iteration, that would be relatively simple and straightforward to address. It sounds like that did not happen. The first iteration sounds like it worked fine.

    One further test you might try is to add a GC.Collect statement such that you force garbage collection after each iteration of the loop. This is a horrible thing to do in real code, but as a test, it might be revealing. My thinking is that you appear to have a memory issue going on, based on the error message. You are also doing a fair amount of direct memory work, which is not generally done in .NET. I'm wondering whether or not that memory action (the alloc calls) is getting things into a confused state.

    Of course, this test would be solely informational. After all, if GC.Collect caused the error to go away, that's not really a solution, because the cure would be pretty bad.
    My usual boring signature: Nothing

  5. #5

    Thread Starter
    Junior Member
    Join Date
    Nov 2013
    Posts
    21

    Re: Process Locking file , i cant solve error.

    Yes, it looks like it was wanting to work, but in the end failed, i tried skiping that error and apparently it seems it lists all processes in use by windows, that is not the solution i was going for though.
    But i think i will have to put this one on ice for a while untill i have time to figure it out.

    Thank you for trying to help!

  6. #6
    Angel of Code Niya's Avatar
    Join Date
    Nov 2011
    Posts
    8,600

    Re: Process Locking file , i cant solve error.

    Whats with all the Is64Bits calls? This is EXACTLY the point of the IntPtr type, so you don't have to do those checks. IntPtr will always be the correct size, no need to check if you're running 32 bit or 64 bit.
    Treeview with NodeAdded/NodesRemoved events | BlinkLabel control | Calculate Permutations | Object Enums | ComboBox with centered items | .Net Internals article(not mine) | Wizard Control | Understanding Multi-Threading | Simple file compression | Demon Arena

    Copy/move files using Windows Shell | I'm not wanted

    C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter

    There's just no reason to use garbage like InputBox. - jmcilhinney

    The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width