Welche Anwendung greift auf die Datei zu?

  • VB.NET
  • .NET (FX) 4.0

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von Maik Hinze.

    Welche Anwendung greift auf die Datei zu?

    Hallo,
    ich habe ein kleines Problem, meine anwendung die ich programmiere soll bei einem Bestimmten ereigniss eine Datei löschen. Es kann aber vorkommen das diese Datei von einer Anderen Anwendung in diesem Zeitpung genutzt wird. Mir wird denn natürlich auch der fehler ausgegeben das meine Anwendung dann nicht auf die Datei zugreifen kann weil sie ja von einem anderen Prozess genutzt wird, das wars auch schon. Windows hingegen informiert mich, wenn ich diese genutze datei manuell löschen will welcher Prozess auf diese Datei zugreift. Und genau diese Information brauche ich, leider finde ich per SoFu nichts in der richtung. Ich will das wenn die datei gerade genutzt wird mir rückgeben lassen von welchem Prozess sie genutzt wird.

    Hat da jemand vielleicht erfahrung bzw. kann mir da jemand weiterhelfen?

    MfG Maik

    Maik Hinze schrieb:

    aber das ist echt zu blöd das es keinen anderen weg gibt
    Vorschlag:
    Schreib eine geeignete Lib für diesen Zweck und stelle sie hier öffentlich zur Verfügung, dann hat der Nächste dieses Problem nicht mehr ;)

    Du darfst gerne hier abschreiben:
    processhacker.sourceforge.net/downloads.php
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    //EDIT 2

    Also habs jetzt endlich raus :)

    Hier ist die Classe:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Collections.Generic
    2. Imports System.Runtime.InteropServices
    3. Imports System.Diagnostics
    4. Imports System.Text
    5. Imports System.Threading
    6. Public Class FileLocked
    7. ''' <summary>
    8. ''' Return a list of processes that hold on the given file.
    9. ''' </summary>
    10. Public Shared Function GetProcessesLockingFile(filePath As String) As List(Of Process)
    11. Dim procs = New List(Of Process)()
    12. For Each process__1 In Process.GetProcesses()
    13. Dim files = GetFilesLockedBy(process__1)
    14. If files.Contains(filePath) Then
    15. procs.Add(process__1)
    16. End If
    17. Next
    18. Return procs
    19. End Function
    20. ''' <summary>
    21. ''' Return a list of file locks held by the process.
    22. ''' </summary>
    23. Public Shared Function GetFilesLockedBy(process As Process) As List(Of String)
    24. Dim outp = New List(Of String)()
    25. Dim ts As ThreadStart = New ThreadStart(
    26. Sub()
    27. Try
    28. outp = UnsafeGetFilesLockedBy(process)
    29. Catch
    30. End Try
    31. End Sub
    32. )
    33. Try
    34. Dim t = New Thread(ts)
    35. t.IsBackground = True
    36. t.Start()
    37. t.Join()
    38. 'If Not t.Join(250) Then
    39. ' Try
    40. ' t.Abort()
    41. ' Catch
    42. ' End Try
    43. 'End If
    44. Catch
    45. End Try
    46. Return outp
    47. End Function
    48. #Region "Inner Workings"
    49. Private Shared Function UnsafeGetFilesLockedBy(process As Process) As List(Of String)
    50. Try
    51. Dim [handles] = GetHandles(process)
    52. Dim files = New List(Of String)()
    53. For Each handle In [handles]
    54. Dim file = GetFilePath(handle, process)
    55. If file IsNot Nothing Then
    56. files.Add(file)
    57. End If
    58. Next
    59. Return files
    60. Catch
    61. Return New List(Of String)()
    62. End Try
    63. End Function
    64. Const CNST_SYSTEM_HANDLE_INFORMATION As Integer = 16
    65. Const STATUS_INFO_LENGTH_MISMATCH As UInteger = &HC0000004UI
    66. Private Shared Function GetFilePath(sYSTEM_HANDLE_INFORMATION As Win32API.SYSTEM_HANDLE_INFORMATION, process As Process) As String
    67. If sYSTEM_HANDLE_INFORMATION.GrantedAccess = &H12019F OrElse
    68. sYSTEM_HANDLE_INFORMATION.GrantedAccess = &H1A019F OrElse
    69. sYSTEM_HANDLE_INFORMATION.GrantedAccess = &H120189 OrElse
    70. sYSTEM_HANDLE_INFORMATION.GrantedAccess = &H100000 Then
    71. Return Nothing
    72. End If
    73. Dim m_ipProcessHwnd As IntPtr = Win32API.OpenProcess(Win32API.ProcessAccessFlags.All, False, process.Id)
    74. Dim ipHandle As IntPtr = IntPtr.Zero
    75. Dim objBasic = New Win32API.OBJECT_BASIC_INFORMATION()
    76. Dim ipBasic As IntPtr = IntPtr.Zero
    77. Dim objObjectType = New Win32API.OBJECT_TYPE_INFORMATION()
    78. Dim ipObjectType As IntPtr = IntPtr.Zero
    79. Dim objObjectName = New Win32API.OBJECT_NAME_INFORMATION()
    80. Dim ipObjectName As IntPtr = IntPtr.Zero
    81. Dim strObjectTypeName As String = ""
    82. Dim strObjectName As String = ""
    83. Dim nLength As Integer = 0
    84. Dim nReturn As Integer = 0
    85. Dim ipTemp As IntPtr = IntPtr.Zero
    86. If Not Win32API.DuplicateHandle(m_ipProcessHwnd, sYSTEM_HANDLE_INFORMATION.Handle, Win32API.GetCurrentProcess(), ipHandle, 0, False, _
    87. Win32API.DUPLICATE_SAME_ACCESS) Then
    88. Return Nothing
    89. End If
    90. ipBasic = Marshal.AllocHGlobal(Marshal.SizeOf(objBasic))
    91. Win32API.NtQueryObject(ipHandle, CInt(Win32API.ObjectInformationClass.ObjectBasicInformation), ipBasic, Marshal.SizeOf(objBasic), nLength)
    92. objBasic = DirectCast(Marshal.PtrToStructure(ipBasic, objBasic.[GetType]()), Win32API.OBJECT_BASIC_INFORMATION)
    93. Marshal.FreeHGlobal(ipBasic)
    94. ipObjectType = Marshal.AllocHGlobal(objBasic.TypeInformationLength)
    95. nLength = objBasic.TypeInformationLength
    96. While CUInt(InlineAssignHelper(nReturn, Win32API.NtQueryObject(ipHandle, CInt(Win32API.ObjectInformationClass.ObjectTypeInformation), ipObjectType, nLength, nLength))) = Win32API.STATUS_INFO_LENGTH_MISMATCH
    97. Marshal.FreeHGlobal(ipObjectType)
    98. ipObjectType = Marshal.AllocHGlobal(nLength)
    99. End While
    100. objObjectType = DirectCast(Marshal.PtrToStructure(ipObjectType, objObjectType.[GetType]()), Win32API.OBJECT_TYPE_INFORMATION)
    101. If Is64Bits() Then
    102. ipTemp = New IntPtr(Convert.ToInt64(objObjectType.Name.Buffer.ToString(), 10) >> 32)
    103. Else
    104. ipTemp = objObjectType.Name.Buffer
    105. End If
    106. strObjectTypeName = Marshal.PtrToStringUni(ipTemp, objObjectType.Name.Length >> 1)
    107. Marshal.FreeHGlobal(ipObjectType)
    108. If strObjectTypeName <> "File" Then
    109. Return Nothing
    110. End If
    111. 'nLength = objBasic.NameInformationLength
    112. nLength = &H1000
    113. ipObjectName = Marshal.AllocHGlobal(nLength)
    114. While CUInt(InlineAssignHelper(nReturn, Win32API.NtQueryObject(ipHandle, CInt(Win32API.ObjectInformationClass.ObjectNameInformation), ipObjectName, nLength, nLength))) = Win32API.STATUS_INFO_LENGTH_MISMATCH
    115. Marshal.FreeHGlobal(ipObjectName)
    116. ipObjectName = Marshal.AllocHGlobal(nLength)
    117. End While
    118. objObjectName = DirectCast(Marshal.PtrToStructure(ipObjectName, objObjectName.[GetType]()), Win32API.OBJECT_NAME_INFORMATION)
    119. If Is64Bits() Then
    120. ipTemp = New IntPtr(Convert.ToInt64(objObjectName.Name.Buffer.ToString(), 10) >> 32)
    121. Else
    122. ipTemp = objObjectName.Name.Buffer
    123. End If
    124. If ipTemp <> IntPtr.Zero Then
    125. Dim baTemp As Byte() = New Byte(nLength - 1) {}
    126. Try
    127. Marshal.Copy(ipTemp, baTemp, 0, nLength)
    128. strObjectName = Marshal.PtrToStringUni(If(Is64Bits(), New IntPtr(ipTemp.ToInt64()), New IntPtr(ipTemp.ToInt32())))
    129. Catch generatedExceptionName As AccessViolationException
    130. Return Nothing
    131. Finally
    132. Marshal.FreeHGlobal(ipObjectName)
    133. Win32API.CloseHandle(ipHandle)
    134. End Try
    135. End If
    136. Dim path As String = GetRegularFileNameFromDevice(strObjectName)
    137. Try
    138. Return path
    139. Catch
    140. Return Nothing
    141. End Try
    142. End Function
    143. Private Shared Function GetRegularFileNameFromDevice(strRawName As String) As String
    144. Dim strFileName As String = strRawName
    145. For Each strDrivePath As String In Environment.GetLogicalDrives()
    146. Dim sbTargetPath As New StringBuilder(Win32API.MAX_PATH)
    147. If Win32API.QueryDosDevice(strDrivePath.Substring(0, 2), sbTargetPath, Win32API.MAX_PATH) = 0 Then
    148. Return strRawName
    149. End If
    150. Dim strTargetPath As String = sbTargetPath.ToString()
    151. If strFileName.StartsWith(strTargetPath) Then
    152. strFileName = strFileName.Replace(strTargetPath, strDrivePath.Substring(0, 2))
    153. Exit For
    154. End If
    155. Next
    156. Return strFileName
    157. End Function
    158. Private Shared Function GetHandles(process As Process) As List(Of Win32API.SYSTEM_HANDLE_INFORMATION)
    159. Dim nStatus As UInteger
    160. Dim nHandleInfoSize As Integer = &H10000
    161. Dim ipHandlePointer As IntPtr = Marshal.AllocHGlobal(nHandleInfoSize)
    162. Dim nLength As Integer = 0
    163. Dim ipHandle As IntPtr = IntPtr.Zero
    164. While (InlineAssignHelper(nStatus, Win32API.NtQuerySystemInformation(CNST_SYSTEM_HANDLE_INFORMATION, ipHandlePointer, nHandleInfoSize, nLength))) = STATUS_INFO_LENGTH_MISMATCH
    165. nHandleInfoSize = nLength
    166. Marshal.FreeHGlobal(ipHandlePointer)
    167. ipHandlePointer = Marshal.AllocHGlobal(nLength)
    168. End While
    169. Dim baTemp As Byte() = New Byte(nLength - 1) {}
    170. Marshal.Copy(ipHandlePointer, baTemp, 0, nLength)
    171. Dim lHandleCount As Long = 0
    172. If Is64Bits() Then
    173. lHandleCount = Marshal.ReadInt64(ipHandlePointer)
    174. ipHandle = New IntPtr(ipHandlePointer.ToInt64() + 8)
    175. Else
    176. lHandleCount = Marshal.ReadInt32(ipHandlePointer)
    177. ipHandle = New IntPtr(ipHandlePointer.ToInt32() + 4)
    178. End If
    179. Dim shHandle As Win32API.SYSTEM_HANDLE_INFORMATION
    180. Dim lstHandles As New List(Of Win32API.SYSTEM_HANDLE_INFORMATION)()
    181. For lIndex As Long = 0 To lHandleCount - 1
    182. shHandle = New Win32API.SYSTEM_HANDLE_INFORMATION()
    183. If Is64Bits() Then
    184. shHandle = DirectCast(Marshal.PtrToStructure(ipHandle, shHandle.[GetType]()), Win32API.SYSTEM_HANDLE_INFORMATION)
    185. ipHandle = New IntPtr(ipHandle.ToInt64() + Marshal.SizeOf(shHandle) + 8)
    186. Else
    187. ipHandle = New IntPtr(ipHandle.ToInt64() + Marshal.SizeOf(shHandle))
    188. shHandle = DirectCast(Marshal.PtrToStructure(ipHandle, shHandle.[GetType]()), Win32API.SYSTEM_HANDLE_INFORMATION)
    189. End If
    190. If shHandle.ProcessID <> process.Id Then
    191. Continue For
    192. End If
    193. lstHandles.Add(shHandle)
    194. Next
    195. Return lstHandles
    196. End Function
    197. Private Shared Function Is64Bits() As Boolean
    198. Return If(Marshal.SizeOf(GetType(IntPtr)) = 8, True, False)
    199. End Function
    200. Friend Class Win32API
    201. <DllImport("ntdll.dll")> _
    202. Public Shared Function NtQueryObject(ObjectHandle As IntPtr, ObjectInformationClass As Integer, ObjectInformation As IntPtr, ObjectInformationLength As Integer, ByRef returnLength As Integer) As Integer
    203. End Function
    204. <DllImport("kernel32.dll", SetLastError:=True)> _
    205. Public Shared Function QueryDosDevice(lpDeviceName As String, lpTargetPath As StringBuilder, ucchMax As Integer) As UInteger
    206. End Function
    207. <DllImport("ntdll.dll")> _
    208. Public Shared Function NtQuerySystemInformation(SystemInformationClass As Integer, SystemInformation As IntPtr, SystemInformationLength As Integer, ByRef returnLength As Integer) As UInteger
    209. End Function
    210. <DllImport("kernel32.dll")> _
    211. Public Shared Function OpenProcess(dwDesiredAccess As ProcessAccessFlags, <MarshalAs(UnmanagedType.Bool)> bInheritHandle As Boolean, dwProcessId As Integer) As IntPtr
    212. End Function
    213. <DllImport("kernel32.dll")> _
    214. Public Shared Function CloseHandle(hObject As IntPtr) As Integer
    215. End Function
    216. <DllImport("kernel32.dll", SetLastError:=True)> _
    217. 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, _
    218. dwOptions As UInteger) As <MarshalAs(UnmanagedType.Bool)> Boolean
    219. End Function
    220. <DllImport("kernel32.dll")> _
    221. Public Shared Function GetCurrentProcess() As IntPtr
    222. End Function
    223. Public Enum ObjectInformationClass As Integer
    224. ObjectBasicInformation = 0
    225. ObjectNameInformation = 1
    226. ObjectTypeInformation = 2
    227. ObjectAllTypesInformation = 3
    228. ObjectHandleInformation = 4
    229. End Enum
    230. <Flags()> _
    231. Public Enum ProcessAccessFlags As UInteger
    232. All = &H1F0FFF
    233. Terminate = &H1
    234. CreateThread = &H2
    235. VMOperation = &H8
    236. VMRead = &H10
    237. VMWrite = &H20
    238. DupHandle = &H40
    239. SetInformation = &H200
    240. QueryInformation = &H400
    241. Synchronize = &H100000
    242. End Enum
    243. <StructLayout(LayoutKind.Sequential)> _
    244. Public Structure OBJECT_BASIC_INFORMATION
    245. ' Information Class 0
    246. Public Attributes As Integer
    247. Public GrantedAccess As Integer
    248. Public HandleCount As Integer
    249. Public PointerCount As Integer
    250. Public PagedPoolUsage As Integer
    251. Public NonPagedPoolUsage As Integer
    252. Public Reserved1 As Integer
    253. Public Reserved2 As Integer
    254. Public Reserved3 As Integer
    255. Public NameInformationLength As Integer
    256. Public TypeInformationLength As Integer
    257. Public SecurityDescriptorLength As Integer
    258. Public CreateTime As System.Runtime.InteropServices.ComTypes.FILETIME
    259. End Structure
    260. <StructLayout(LayoutKind.Sequential)> _
    261. Public Structure OBJECT_TYPE_INFORMATION
    262. ' Information Class 2
    263. Public Name As UNICODE_STRING
    264. Public ObjectCount As Integer
    265. Public HandleCount As Integer
    266. Public Reserved1 As Integer
    267. Public Reserved2 As Integer
    268. Public Reserved3 As Integer
    269. Public Reserved4 As Integer
    270. Public PeakObjectCount As Integer
    271. Public PeakHandleCount As Integer
    272. Public Reserved5 As Integer
    273. Public Reserved6 As Integer
    274. Public Reserved7 As Integer
    275. Public Reserved8 As Integer
    276. Public InvalidAttributes As Integer
    277. Public GenericMapping As GENERIC_MAPPING
    278. Public ValidAccess As Integer
    279. Public Unknown As Byte
    280. Public MaintainHandleDatabase As Byte
    281. Public PoolType As Integer
    282. Public PagedPoolUsage As Integer
    283. Public NonPagedPoolUsage As Integer
    284. End Structure
    285. <StructLayout(LayoutKind.Sequential)> _
    286. Public Structure OBJECT_NAME_INFORMATION
    287. ' Information Class 1
    288. Public Name As UNICODE_STRING
    289. End Structure
    290. <StructLayout(LayoutKind.Sequential, Pack:=1)> _
    291. Public Structure UNICODE_STRING
    292. Public Length As UShort
    293. Public MaximumLength As UShort
    294. Public Buffer As IntPtr
    295. End Structure
    296. <StructLayout(LayoutKind.Sequential)> _
    297. Public Structure GENERIC_MAPPING
    298. Public GenericRead As Integer
    299. Public GenericWrite As Integer
    300. Public GenericExecute As Integer
    301. Public GenericAll As Integer
    302. End Structure
    303. <StructLayout(LayoutKind.Sequential, Pack:=1)> _
    304. Public Structure SYSTEM_HANDLE_INFORMATION
    305. ' Information Class 16
    306. Public ProcessID As Integer
    307. Public ObjectTypeNumber As Byte
    308. Public Flags As Byte
    309. ' 0x01 = PROTECT_FROM_CLOSE, 0x02 = INHERIT
    310. Public Handle As UShort
    311. Public Object_Pointer As Integer
    312. Public GrantedAccess As UInt32
    313. End Structure
    314. Public Const MAX_PATH As Integer = 260
    315. Public Const STATUS_INFO_LENGTH_MISMATCH As UInteger = &HC0000004UI
    316. Public Const DUPLICATE_SAME_ACCESS As Integer = &H2
    317. End Class
    318. Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, value As T) As T
    319. target = value
    320. Return value
    321. End Function
    322. #End Region
    323. End Class


    Und hier noch ein kleines Beispiel wie es angewendet wird:

    VB.NET-Quellcode

    1. Try
    2. Dim handleList As New System.Collections.Generic.List(Of Process)
    3. handleList = FileLocked.GetProcessesLockingFile("DateiPfad")
    4. For Each t In handleList
    5. proc = t.ProcessName
    6. Next
    7. Catch ex As Exception
    8. End Try
    9. If proc.Length > 0 Then
    10. MsgBox(proc)
    11. Process.GetProcessesByName(proc)(0).Kill()
    12. proc = ""
    13. Else
    14. MsgBox("Datei ist sauber")
    15. End If


    Leider stürzt dabei die Anwendung einfach ab( vielleicht könnt ihr das ja mal testen wie oft es bei euch abstürzt) und wenn sie funktioniert dauert es ewig, da ist Handle von Mark Russinov wesentlich schneller. Aber besser als nicht wenn man keine externen Anwendugen nutzen möchte :) Danke trotzdem.

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „Maik Hinze“ ()