Search code examples
vb.netkernel32

GetTempFileName throwing 'System.AccessViolationException' vb.net


I am new to VB and is working on VB6 to VB.net migration. There is one API call which appends a prefix in temporary file name.

I have added the dll as

<DllImport("kernel32")> _
Private Shared Function GetTempFileName(ByVal lpszPath As String, ByVal lpPrefixString As String, ByVal wUnique As Long, ByVal lpTempFileName As String) As Long
End Function

When I am calling this:

test = GetTempFileName(My.Application.Info.DirectoryPath, Prefix, 0, m_sTempfile)

It throws an exception:

An unhandled exception of type 'System.AccessViolationException' occurred in Forum.exe

Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

I tried using Path.GetTempFileName() but I might need to perform several manipulation to get the file name prefixed with specific word and located to specific location. I crossed checked the values and they are NOT bad data. I tried mutiple resolutions, but none of it worked. Can someone help in this? Thanks in advance!


Solution

  • Pinvoke declarations need to be rewritten when you move them to VB.NET. Many differences, like Long needs to be Integer and if the winapi function returns a string then you need to use StringBuilder instead of String. Required because String is an immutable type.

    Proper declaration is:

    <DllImport("kernel32", SetLastError:=True, CharSet:=CharSet.Auto)> _
    Public Shared Function GetTempFileName(ByVal lpszPath As String, _
                                           ByVal lpPrefixString As String, _
                                           ByVal wUnique As Integer, _
                                           ByVal lpTempFileName As StringBuilder) As Integer
    End Function
    

    And a proper call looks like:

        Dim buffer As New StringBuilder(260)
        If GetTempFileName("c:\temp", "xyz", 0, buffer) = 0 Then
            Throw New System.ComponentModel.Win32Exception()
        End If
        Dim filename = buffer.ToString()
    

    The pinvoke.net website tends to be a half-decent resource for pinvoke declarations. Not for this one though, the VB.NET version is pretty fumbled.