I have a program which needs to put data on a network share. In some cases, the user has no access through his account, and would need to provide credentials to login.
My idea was to have the program popup the windows credential screen so the user can login (like when the user would open the share through windows explorer).
I found the WNetUseConnection
API which would allow to login to the share without mapping it, and it has options to give a prompt.
This is the code I'm using:
Public Class frmMain
Private Const CONNECT_INTRERACTIVE = &H8
Private Const CONNECT_PROMPT = &H10
Private Const RESOURCETYPE_DISK = &H1
Private Structure NETRESOURCE
Public dwScope As Long
Public dwType As Long
Public dwDisplayType As Long
Public dwUsage As Long
Public lpLocalName As String
Public lpRemoteName As String
Public lpComment As String
Public lpProvider As String
End Structure
Private Declare Function WNetUseConnection Lib "mpr.dll" _
Alias "WNetUseConnectionA" ( _
ByVal hwndOwner As Long, _
ByRef lpNetResource As NETRESOURCE, _
ByVal lpUsername As String, _
ByVal lpPassword As String, _
ByVal dwFlags As Long, _
ByVal lpAccessName As String, _
ByRef lpBufferSize As Long, _
ByRef lpResult As Long) _
As Long
Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim resource As New NETRESOURCE
Dim success As Long
Dim ErrInfo As Long
With resource
.dwType = RESOURCETYPE_DISK
.lpLocalName = vbNullString
.lpRemoteName = "\\server\folder\"
.lpProvider = vbNullString
End With
ErrInfo = WNetUseConnection(Me.Handle, resource, "", "", CONNECT_INTRERACTIVE Or CONNECT_PROMPT, vbNull, vbNull, success)
Console.WriteLine(ErrInfo)
Dim errorMessage As String
errorMessage = New Win32Exception().Message
Console.WriteLine(errorMessage)
End Sub
The error I'm getting back is:
The handle is invalid (code 2091649073639).
Is there a way to get this working?
"The handle is invalid" error can appear when you are logging in, and the problem is usually related to a Windows Update problem or using the wrong credentials to log in. Rebooting your computer should allow Windows Updates to continue if that's the issue.
Select Network and Sharing Center.Go to Change advanced sharing settings. After that, expand All networks. Locate the Public folder sharing option and make sure it's checked. Then restart your computer.
The Handle is Invalid. This error message basically means that the affected user cannot get into their user account and, by extension, their computer, and that is most definitely a significant problem. Thankfully, there exist ways that can be used to try and fix this problem.
There seem to be several issues with the code you posted:
Your P/Invoke types need to be tweaked. Here are the native Windows types and their appropriate VB .Net counterparts:
HWND
-> IntPtr
LPDWORD
-> IntPtr
DWORD
-> UInt32
(I've also seen Integer
used)Using IntPtr
allows the runtime to use a 32-bit or 64-bit pointer, depending on the machine architecture. DWORD
s are always 32 bit, even on a 64-bit machine. See also: Visual C++: How large is a DWORD with 32- and 64-bit code?
The P/Invoke Signature has the username and password parameters reversed. The password parameter should actually be first. It doesn't matter in your case because the user gets prompted for this information. However, it might matter when you try to pass those values in later...
The remote share should not have the trailing backslash
.lpRemoteName = "\\server\folder\"
should be
.lpRemoteName = "\\server\folder"
Finally, I had to add the buffer
parameter to get the code to work. Without it, the WNetUseConnection
function always returned ERROR_MORE_DATA
, which means the buffer is too small.
Here is the complete code I used (tested on Windows 8 64-bit, Windows 7 32-bit):
Imports System.ComponentModel
Imports System.Text
Public Class frmMain
Private Const CONNECT_INTRERACTIVE = &H8
Private Const CONNECT_PROMPT = &H10
Private Const RESOURCETYPE_DISK = &H1
Private Structure NETRESOURCE
Public dwScope As UInt32
Public dwType As UInt32
Public dwDisplayType As UInt32
Public dwUsage As UInt32
Public lpLocalName As String
Public lpRemoteName As String
Public lpComment As String
Public lpProvider As String
End Structure
Private Declare Function WNetUseConnection Lib "mpr.dll" _
Alias "WNetUseConnectionA" ( _
ByVal hwndOwner As IntPtr, _
ByRef lpNetResource As NETRESOURCE, _
ByVal lpPassword As String, _
ByVal lpUsername As String, _
ByVal dwFlags As UInt32, _
ByVal lpAccessName As StringBuilder, _
ByRef lpBufferSize As IntPtr, _
ByRef lpResult As IntPtr) _
As UInt32
Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim resource As New NETRESOURCE
Dim success As Long
Dim ErrInfo As Long
Const BUFFERSIZE As Integer = 1024
Dim buffer As New StringBuilder(BUFFERSIZE)
With resource
.dwType = RESOURCETYPE_DISK
.lpLocalName = vbNullString
.lpRemoteName = "\\server\folder"
.lpProvider = vbNullString
End With
ErrInfo = WNetUseConnection(Me.Handle, resource, "", "", CONNECT_INTRERACTIVE Or CONNECT_PROMPT, buffer, BUFFERSIZE, success)
If ErrInfo > 0 Then
Dim winExcept As New Win32Exception()
LogMsg(winExcept.Message)
Else
LogMsg("all good")
End If
End Sub
Private Sub LogMsg(ByVal msg As String)
System.Diagnostics.Debug.WriteLine(msg)
MsgBox(msg)
End Sub
End Class
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With