Update: I believe I have found the simplest and most consistent method, methods 2 & 3 may or may not work consistently I've found.
Method 1 - Calling Net Use (Works consistently and across domains)
The Net Use Command allows you to store credentials to shares through the command prompt and you are able to call this from .NET very easily.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim proc As New Process
proc.StartInfo.FileName = "net"
proc.StartInfo.UseShellExecute = True
proc.EnableRaisingEvents = False
Dim server As String = "Server"
Dim user As String = "User"
Dim pass As String = "Pass"
If EnsureConnection(server) Then
proc.StartInfo.Arguments = "use \\" & server & "\IPC$ /u:" & server & "\" & user & " " & pass
proc.Start()
End If
End Sub
Function EnsureConnection(server As String)
'Give more or less ping attempts depending on how reliable your connection is.
'I have found that one ping can give false negative easily even on reliable connections
If My.Computer.Network.Ping(server) Then
Return True
ElseIf My.Computer.Network.Ping(server) Then
Return True
Else
Return False
End If
End Function
This method will store the credentials on the machine until the machine shuts down or reboots and the user will be authenticated outside of the program as well. If that is not desirable you could always use the '/delete' switch of the command to delete it as soon as the program is done with it.
Method 2 - Using functions in MPR.DLL
I eventually found this answer to another question. This is the method that worked for me. This is what it looks like integrated into my project:
Imports System.IO
Imports System.Runtime.InteropServices
Public Class Form1
Dim user As String
Dim pass As String
Dim path As String
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Cursor = Cursors.WaitCursor
user = "UsernameString"
pass = "PasswordString"
path = "\\10.0.15.87\c$"
MPRAuth()
DirSearch(path)
Cursor = Cursors.Default
End Sub
Private Sub MPRAuth()
Dim nr As New NETRESOURCE
nr.dwType = RESOURCETYPE_DISK
nr.lpRemoteName = path
If WNetAddConnection2(nr, pass, user, 0) <> NO_ERROR Then
Throw New Exception("WNetAddConnection2 failed.")
End If
If WNetCancelConnection2(path, 0, True) <> NO_ERROR Then
Throw New Exception("WNetCancelConnection2 failed.")
End If
End Sub
Public Sub DirSearch(ByVal sDir As String)
Try
For Each dir As String In Directory.GetDirectories(sDir)
Try
For Each file In Directory.GetFiles(dir, "*.exe")
MsgBox(file)
Next
Catch ex As Exception
Debug.WriteLine(ex.Message)
End Try
DirSearch(dir)
Next
Catch ex As Exception
Debug.WriteLine(ex.Message)
End Try
End Sub
<StructLayout(LayoutKind.Sequential)>
Private Structure NETRESOURCE
Public dwScope As UInteger
Public dwType As UInteger
Public dwDisplayType As UInteger
Public dwUsage As UInteger
<MarshalAs(UnmanagedType.LPTStr)>
Public lpLocalName As String
<MarshalAs(UnmanagedType.LPTStr)>
Public lpRemoteName As String
<MarshalAs(UnmanagedType.LPTStr)>
Public lpComment As String
<MarshalAs(UnmanagedType.LPTStr)>
Public lpProvider As String
End Structure
Private Const NO_ERROR As UInteger = 0
Private Const RESOURCETYPE_DISK As UInteger = 1
<DllImport("mpr.dll", CharSet:=CharSet.Auto)>
Private Shared Function WNetAddConnection2(ByRef lpNetResource As NETRESOURCE, <[In](), MarshalAs(UnmanagedType.LPTStr)> ByVal lpPassword As String, <[In](), MarshalAs(UnmanagedType.LPTStr)> ByVal lpUserName As String, ByVal dwFlags As UInteger) As UInteger
End Function
<DllImport("mpr.dll", CharSet:=CharSet.Auto)>
Private Shared Function WNetCancelConnection2(<[In](), MarshalAs(UnmanagedType.LPTStr)> ByVal lpName As String, ByVal dwFlags As UInteger, <MarshalAs(UnmanagedType.Bool)> ByVal fForce As Boolean) As UInteger
End Function
End Class
Method 3 - NetworkCredential and CredentialCache
This method converts the ip to a URI and caches the credentials. I was unable to make this method work with a server on a different domain than me.
Imports System.Net
Dim builder As New UriBuilder("10.0.15.87")
Dim uri As Uri = builder.Uri
Dim netCred = New NetworkCredential("UsernameString", "PasswordString", "DomainString")
Dim netCache = New CredentialCache()
netCache.Add(uri, "Basic", netCred)
DirSearch("\\10.0.15.87\c$")
Method 2 is a lot less involved than Method 2 and it worked fine for me so long as the server I was attempting to connect to was on the same domain as me. When I tried to connect to server not on the domain I got the error 'User name or password is incorrect' which is not true, so I'm not sure where the issue was - perhaps someone else knows. Method 2 has worked flawless for me so far for any server no matter the domain or if have manually authenticated to it before running the code. Hope this helps others!