0

I want to call function MoveFile from "Kernel32.dll".

1)First approach:

Imports System.Runtime.InteropServices

Public Class Form1

<DllImport("KERNEL32.DLL", EntryPoint:="MoveFileW", SetLastError:=True, CharSet:=CharSet.Unicode, ExactSpelling:=True, CallingConvention:=CallingConvention.StdCall)>
Public Shared Function MoveFile(ByVal src As String, ByVal dst As String) As Boolean
End Function

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

Dim src As String = "C:\Users\Baha1990\Documents\Visual Studio 2017\Projects\WindowsApp1\TEST FILE\1\MSACCESS.accdb"
Dim dst As String = "C:\Users\Baha1990\Documents\Visual Studio 2017\Projects\WindowsApp1\TEST FILE\2\MSACCESS.accdb"
Dim RetVal As Boolean = MoveFile(src, dst)

End Sub

End Class

It works pretty well

  1. Second approach:
Imports System.Runtime.InteropServices

Public Class Form1


<Runtime.InteropServices.DllImport("kernel32.dll", SetLastError:=True)> Private Shared Function LoadLibrary(ByVal lpFileName As String) As IntPtr
End Function
    
<Runtime.InteropServices.DllImport("kernel32.dll", SetLastError:=True, CharSet:=Runtime.InteropServices.CharSet.Ansi, ExactSpelling:=True)> Private Shared Function GetProcAddress(ByVal hModule As IntPtr, ByVal procName As String) As IntPtr
End Function

<UnmanagedFunctionPointer(CallingConvention.StdCall)>
Public Delegate Function _MoveFile(ByVal src As String, ByVal dst As String) As Boolean

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

Dim src As String = "C:\Users\Baha1990\Documents\Visual Studio 2017\Projects\WindowsApp1\TEST FILE\1\MSACCESS.accdb"
Dim dst As String = "C:\Users\Baha1990\Documents\Visual Studio 2017\Projects\WindowsApp1\TEST FILE\2\MSACCESS.accdb"

 Dim pDll As IntPtr = IntPtr.Zero
 pDll = LoadLibrary("kernel32.dll")
 Dim pProc2D = GetProcAddress(pDll, "MoveFileW")
 Dim MoveFile = Marshal.GetDelegateForFunctionPointer(pProc2D, GetType(_MoveFile))

Dim RetVal = MoveFile.DynamicInvoke(src, dst) 'Here I get boolean as false it should be true
or
Dim RetVal = MoveFile.Method.Invoke(What to pass here in my case?)

End Sub

End Class

So Question: What is difference between DLLImport and DynamicInvoke or Method.Invoke, and why I have fail with DynamicInvoke and what params to pass to Method.Invoke?

Ok, in second approach I figure out that in this line:

<UnmanagedFunctionPointer(CallingConvention.StdCall)>

Needs additional params, after I edited as:

<UnmanagedFunctionPointer(CallingConvention.StdCall, SetLastError:=True, CharSet:=CharSet.Unicode)>

Dim RetVal = MoveFile.DynamicInvoke(src, dst) - DynamicInvoke works perfect.

So question what to pass as params to Method.Invoke still open.

Ok, I also figured out about Method.Invoke:

Dim param = {src, dst}

Dim RetVal = MoveFile.Method.Invoke(MoveFile, param) - works perfect.

So seems all three aproach works and gives same result, but what advantage gives these methods between each other. Who can explain?

Baha Dzhan
  • 11
  • 4
  • Why not use: https://learn.microsoft.com/en-us/dotnet/api/system.io.file.move?view=netframework-4.8 ? – Tu deschizi eu inchid Apr 04 '21 at 14:34
  • @user9938 I want to understand how to call dll function from vb.net and took as an example MoveFile function from kernel32.dll. – Baha Dzhan Apr 04 '21 at 15:28
  • The managed `DllImport` adds some overhead because of the extra security checks it performes. So it can be a little slower, but safer. The other methods are missing a cast: the `GetDelegateForFunctionPointer` result is usually cast to the delegate you defined, so you don't need late bound `DynamicInvoke()`, passing an object[] param, or use reflection, as `MethodInfo.Invoke()` which calls `DynamicInvokeImpl()` anyway; you can use the delegate directly to pass the parameters as the actual types. To have some more performance, you should probably use `Reflection.Emit()` to replace `DllImport`. – Jimi Apr 04 '21 at 17:30
  • BTW, you really need to call `FreeLibrary()` after `LoadLibrary()`. – Jimi Apr 04 '21 at 18:00
  • @Jimi why `freelibrary` is obligatory after `loadlibrary`? Will cause sth bad if I won't use it? – Baha Dzhan Apr 04 '21 at 18:54
  • The official reasons are explained in the Docs. There's also PInvoke to consider. `DllInport` also uses `LoadLibrary`, so you don't want to mess with the reference count of modules loaded in your process space. Follow that simple rule: one `LoadlIbrary`, one `FreeLibrary`. If you really need to, that is. Use the standard PInvoke if you don't have a specific need to load a module that way. – Jimi Apr 04 '21 at 19:26

0 Answers0