.net - 尝试连接到网络共享时句柄无效

标签 .net vb.net winapi

我有一个程序需要将数据放在网络共享上。在某些情况下,用户无法通过其帐户访问,并且需要提供凭据才能登录。

我的想法是让程序弹出 Windows 凭据屏幕,以便用户可以登录(就像用户通过 Windows 资源管理器打开共享时一样)。

我找到了 WNetUseConnection允许在不映射共享的情况下登录共享的 API,并且它有提供提示的选项。

这是我正在使用的代码:

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 handle is invalid (code 2091649073639).



有没有办法让这个工作?

最佳答案

您发布的代码似乎有几个问题:

  • 您的 P/Invoke 类型需要调整。以下是 native Windows 类型及其相应的 VB .Net 对应项:
  • HWND -> IntPtr
  • LPDWORD -> IntPtr
  • DWORD -> UInt32 (我也见过 Integer 使用过)

  • 使用 IntPtr允许运行时使用 32 位或 64 位指针,具体取决于机器架构。 DWORD s 总是 32 位,即使在 64 位机器上。另见:Visual C++: How large is a DWORD with 32- and 64-bit code?
  • P/Invoke 签名具有反转的用户名和密码参数。密码参数实际上应该是第一个。在您的情况下无关紧要,因为系统会提示用户输入此信息。但是,当您稍后尝试传递这些值时可能很重要...
  • 远程共享不应有尾随反斜杠
    .lpRemoteName = "\\server\folder\"
    应该
    .lpRemoteName = "\\server\folder"
  • 最后,我不得不添加 buffer参数以使代码工作。没有它,WNetUseConnection函数总是返回 ERROR_MORE_DATA ,这意味着缓冲区太小。

  • 这是我使用的完整代码(在 Windows 8 64 位、Windows 7 32 位上测试):
    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
    

    关于.net - 尝试连接到网络共享时句柄无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19859770/

    相关文章:

    winapi - 如何弹出USB可移动磁盘/卷,类似于Windows资源管理器中的 "Eject"功能?

    c# - 如何在 .net 反序列化期间防止 XML 外部实体 (XXE) 攻击

    c# - 泛型基类覆盖非泛型基类函数模式? (。网)

    c# - 为什么在 x64 版本上对 System.Numerics 函数进行断点编辑参数时会出现 FatalExecutionEngineError?

    asp.net - 如何在 GridView 上过滤数据/连接

    c# - 插入带有 Dapper 的 IEnumerable<T> 集合时出现 "class is not supported by Dapper."错误

    c++ - 按下了什么键?键盘 Hook

    c++ - WIndows API 中的 'L' 和 'LPCWSTR'

    c# - 如何将 DynamicProxy "really"向下转换回其原始类型(通过 WCF 发送)

    .net - 用于 block 上传的 Azure PutBlockAsync 和 PutBlockListAsync