werckmeister

Dear all,

win32 api offered a function returning a BY_HANDLE_FILE_INFORMATION structure.

The returned structure contained various file information, including:

nFileIndexHigh and nFileIndexLow

These were unique identifiers for a file under NTFS which did not change over lifetime of the file, e.g. if the file was moved to another directory.

I can not find these indices or a similar persistent identifier under .Net.

http://msdn2.microsoft.com/en-us/library/aa302340.aspx#win32map_fileiofunctions says that GetFileInformationByHandle was migrated to System.IO.FileInfo properties, however, the properties defined therein do not seem to contain the above mentioned info.

My efforts to implement GetFileInformationByHandle manually via P/Invoke were disastrous .... to be honest I do not really know how to correctly port the required data structures to VB

FileStream.Handle is obsolete, however still returns a handle.

However, when I run the code below, I get the following AcccessViolationException.

Thanks for any proposal how to proceed. Maybe there is another unique file identifier available that I can get rid of the API calls

Kind regards

Markus

------------------------------------------------- failure report -----------------------------------------------------------------------

System.AccessViolationException was unhandled
Message="Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
Source="WindowsApplication1"
StackTrace:
at WindowsApplication1.Form1.GetFileInformationByHandle(SafeFileHandle FileHandle, lpFileInformation BY_HANDLE_FILE_INFORMATION)
[...]

at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(ApplicationContext context)
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
at WindowsApplication1.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 81
at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()


----------------------------------------------------------- code ----------------------------------------------------------

Imports System.IO.FileStream

Imports System.IO

Imports Microsoft.Win32

Public Structure lpFileInformation

Public dwFileAttributes As String

Public ftCreationTime As Date 'was FILETIME

Public ftLastAccessTime As Date 'was FILETIME

Public ftLastWriteTime As Date 'was FILETIME

Public dwVolumeSerialNumber As String 'was DWORD

Public nFileSizeHigh As Integer 'was DWORD

Public nFileSizeLow As Integer 'was DWORD

Public nNumberOfLinks As Integer 'was DWORD

Public nFileIndexHigh As Integer 'was DWORD

Public nFileIndexLow As Integer 'was DWORD

End Structure

[ ... ] - finally in main:

Declare Auto Function GetFileInformationByHandle Lib "kernel32" (ByVal FileHandle As IntPtr, ByVal BY_HANDLE_FILE_INFORMATION As lpFileInformation) As Integer

Dim fh_obsolete As IntPtr

Dim stream2 As New FileStream("C:\Testfile.txt", FileMode.Open, FileAccess.Read, FileShare.Read)

Dim fi As WindowsApplication1.Form1.lpFileInformation

fh_obsolete = stream2.Handle

GetFileInformationByHandle(fh_obsolete, fi)



Re: Visual Basic Express Edition VB .net version of GetFileInformationByHandle()

ReneeC

"ByVal BY_HANDLE_FILE_INFORMATION As lpFileInformation) As Integer"

I'm not sure whether this is the problem or not but I believe you want to change that Byval to a byref.

Also, check your datatypes. I believe you have them right but some API calls don't take strings.






Re: Visual Basic Express Edition VB .net version of GetFileInformationByHandle()

JohnWein

Try again on the BY_HANDLE_FILE_INFORMATION structure. DWORDs are not strings. FILETIMEs are not dates (Well they are but not a .Net Date)

Pass the Structure ByRef.





Re: Visual Basic Express Edition VB .net version of GetFileInformationByHandle()

werckmeister

Thanks a lot to Renee and John,

you saved my day.

The working declarations look as follows:

Public Structure FILETIME

Public dwLowDateTime As Integer 'was DWORD

Public dwHighDateTime As Integer 'was DWORD

End Structure

Public Structure lpFileInformation

Public dwFileAttributes As Integer 'was DWORD

Public ftCreationTime As FILETIME

Public ftLastAccessTime As FILETIME

Public ftLastWriteTime As FILETIME

Public dwVolumeSerialNumber As Integer 'was DWORD

Public nFileSizeHigh As Integer 'was DWORD

Public nFileSizeLow As Integer 'was DWORD

Public nNumberOfLinks As Integer 'was DWORD

Public nFileIndexHigh As Integer 'was DWORD

Public nFileIndexLow As Integer 'was DWORD

End Structure

Declare Auto Function GetFileInformationByHandle Lib "kernel32" (ByVal FileHandle As IntPtr, ByRef BY_HANDLE_FILE_INFORMATION As lpFileInformation) As Integer