【问题标题】:Converting DOS Batch file commands to VBA Function将 DOS 批处理文件命令转换为 VBA 函数
【发布时间】:2020-03-02 10:18:20
【问题描述】:

我已经创建并正在使用以下函数来映射和缩短网络驱动器的路径长度,使用 SUBST 命令与我的实现 ADO 的工具一起使用。

Function MapBasePathToDrive(FullDirectory As String, strDrive As String, blnReadAttr As Boolean) As String

    Dim objShell As Object
    Dim sCmd$
    Dim WaitOnReturn As Boolean: WaitOnReturn = True
    Dim WindowStyle As Integer: WindowStyle = 0
    Dim i&, lngErr&

    ' remove backslash for `SUBST` dos command to work
    If Right(FullDirectory, 1) = "\" Then FullDirectory = Left(FullDirectory, Len(FullDirectory) - 1)

    ' prefix & suffix directory with double-quotes
    FullDirectory = Chr(34) & FullDirectory & Chr(34)

    Set objShell = CreateObject("WScript.Shell")
    For i = 1 To 2
        If i = 1 Then
            'remove drive
            sCmd = "SUBST" & " " & strDrive & " " & "/D"
            lngErr = objShell.Run(sCmd, WindowStyle, WaitOnReturn)
        Else
            'add drive
            sCmd = "SUBST" & " " & strDrive
            lngErr = objShell.Run(sCmd & " " & FullDirectory, WindowStyle, WaitOnReturn)
        End If
    Next i

    ' remove read-only attribute from Destination folder if you plan to copy files
    If blnReadAttr Then
        sCmd = "ATTRIB " & "-R" & " " & strDrive & "\*.*" & " " & "/S /D"
        lngErr = objShell.Run(sCmd, WindowStyle, WaitOnReturn)
    End If

    ' to refresh explorer to show newly created drive
    sCmd = "%windir%\explorer.exe /n,"
    lngErr = objShell.Run(sCmd & strDrive, WindowStyle, WaitOnReturn)

    ' add backslash to drive if absent
    MapBasePathToDrive = PathWithBackSlashes(strDrive)

End Function

上述功能大部分时间都可以很好地缩短长网络路径,然后将其传递给Application.FileDialog.InitialFilename。但是,如果一个驱动器(比如 Y:) 已经被映射,那么问题就接踵而至,因为Application.FileDialog.InitialFilename 进行了折腾,最终用户无法选择所需的文件,但看到了Y:\ 的文件!

我想做什么:

  • 查看相关驱动器,例如Y: 是否可用。
  • 如果正在使用,请将Y: 的网络路径分配给下一个免费可用的驱动器。
  • 断开连接(删除)Y:
  • Y: 分配给相关目录。

我有下面的批处理文件可以做到这一点,但我不知道如何将此批处理代码转换为 VBA 函数,即类似于上面显示的函数。任何帮助将不胜感激。

@echo off 
if exist y:\ (
    for /F "tokens=1,2,3" %%G in ('net use^|Find /I "Y:"^|Find "\\"')  do ( net use * %%H >nul 2>&1)
    net use y: /delete >nul 2>&1
)
net use y: \\xx.xx.xx.xx\SomeFolder >nul 2>&1

编辑:

我修改了上面的函数来添加这段代码。问题仅在于 sCMD 字符串由于不正确的双引号而没有被 WScript.Shell 执行。

  • 谁能帮我正确的语法?
  • 如果是我需要映射的本地文件夹,语法会如何变化?

...

Sub TestDriveMapping()
    MapBasePathToDrive "\\xx.xx.xx.xx\SomeFolder", "Y:", True
End Sub

Function MapBasePathToDrive(FullDirectory As String, strDrive As String, blnReadAttr As Boolean) As String

    Dim objShell As Object
    Dim sCmd$
    Dim WaitOnReturn As Boolean: WaitOnReturn = True
    Dim WindowStyle As Integer: WindowStyle = 0
    Dim i&, lngErr&

    ' remove backslash for `NET USE` dos command to work
    If Right(FullDirectory, 1) = "\" Then FullDirectory = Left(FullDirectory, Len(FullDirectory) - 1)

    ' prefix & suffix directory with double-quotes
    FullDirectory = Chr(34) & FullDirectory & Chr(34)

    Set objShell = CreateObject("WScript.Shell")
    sCmd = ""
    sCmd = "@Echo Off " & vbCrLf
    sCmd = sCmd & " IF EXIST " & strDrive & " (" & vbCrLf
    sCmd = sCmd & "  FOR /F " & Chr(34) & "TOKENS=1,2,3" & Chr(34) & " %G IN (" & Chr(39) & "NET USE ^|Find /I " & Chr(34) & strDrive & Chr(34) & "^|Find ""\\""" & Chr(39) & ")  DO ( NET USE * %H >NUL 2>&1)" & vbCrLf
    sCmd = sCmd & "  NET USE " & strDrive & " /DELETE >NUL 2>&1" & vbCrLf
    sCmd = sCmd & " )" & vbCrLf
    sCmd = sCmd & " NET USE " & strDrive & " " & FullDirectory & " >NUL 2>&1"

    lngErr = objShell.Run(sCmd, WindowStyle, WaitOnReturn)

    ' remove read-only attribute from Destination folder if you plan to copy files
    If blnReadAttr Then
        sCmd = "ATTRIB " & "-R" & " " & strDrive & "\*.*" & " " & "/S /D"
        lngErr = objShell.Run(sCmd, WindowStyle, WaitOnReturn)
    End If

    ' to refresh explorer to show newly created drive
    sCmd = "%windir%\explorer.exe /n,"
    lngErr = objShell.Run(sCmd & strDrive, WindowStyle, WaitOnReturn)

    ' add backslash to drive if absent
    MapBasePathToDrive = PathWithBackSlashes(strDrive)

End Function

【问题讨论】:

  • 也许我过于简化了,但如果您只是想在对驱动器号进行任何操作之前检查驱动器是否正在使用,您可以使用FileSystemObject 来执行此操作。 This might help

标签: excel vba batch-file net-use subst


【解决方案1】:

请尝试下一个代码。它使用 VBScript 对象来检查和执行映射...

Sub ReMapDrive()
  Dim objNet As Object, strLocal As String, strPath As String, fso As Object
  Set fso = CreateObject("Scripting.FileSystemObject")
  Set objNet = CreateObject("WScript.Network")
  'Name the drive and its path:
  strLocal = "Y:"
  strPath = "\\xx.xx.xx.xx\SomeFolder"

    'Check if it is mapped and map it if it is not:
    If fso.FolderExists(strLocal) = True Then
        MsgBox (strLocal & " Mapped")
    Else
        objNet.MapNetworkDrive strLocal, , False
        MsgBox (strLocal & " Re-mapped")
    End If
   Set fso = Nothing: Set objNet = Nothing
End Sub

我不是代码之父。我从互联网上获得它(不知道它的出处)并且我使用它多年......我只是将它调整为适合你的工作方式(我希望)。

下一个函数将返回(在一个数组中)您映射的驱动器及其路径。我还包括了一个 sub 来看看它是如何被测试/使用的......

Sub testEnumMPapp()
 Dim arrMap As Variant, i As Long
  arrMap = enumMappedDrives
  For i = 0 To UBound(arrMap, 2)
    Debug.Print arrMap(0, i), arrMap(1, i)
  Next i
End Sub

    Private Function enumMappedDrives() As Variant
      Dim objNet As Object, fso As Object, oDrives As Object
      Dim mapRep As Variant, i As Long, k As Long
      ReDim mapRep(1, 100)
      Set fso = CreateObject("Scripting.FileSystemObject")
      Set objNet = CreateObject("WScript.Network")
      Set oDrives = objNet.EnumNetworkDrives
        If oDrives.Count > 0 Then
            For i = 0 To oDrives.Count - 1 Step 2
                mapRep(0, k) = oDrives.Item(i)
                mapRep(1, k) = oDrives.Item(i + 1)
                k = k + 1
            Next
        End If
        ReDim Preserve mapRep(1, k - 1)
        enumMappedDrives = mapRep
    End Function

【讨论】:

  • 感谢@FaneDuru。我面临的唯一问题是如何将现有Y: drive 的远程路径保存到下一个可用的可用驱动器,然后将 Y: 驱动器删除/设置为新的远程路径地址,即我想保留 Y 的现有远程路径:\ 驱动器到另一个免费可用的驱动器,然后再次断开/设置 Y:\。希望你明白我的意思。
  • @sifar:EnumNetworkDrives 属性为objNet,它将检索所有映射的驱动器。但是,我们必须找到一种方法将它们/它报告给某物。让我们说一组字母......对于这种方式,我对如何进行有一个想法。让我检查一下是否真的可以找到最后一个空字母。我不太确定是这样。或者,如果这很容易实现。现在,我有急事要做,但我保证会深入挖掘。同时,我还将发布能够检索映射驱动器列表的代码。
  • 我唯一担心的是,当我删除 Y:`, i want to retain` 上的任何现有远程共享时,先将它们分配给任何免费可用的驱动器号,然后再将新共享分配给“Y:”。
  • 不幸的是,上面的代码没有列出断开连接的驱动器。我之前用谷歌搜索并尝试过类似的代码。
  • @sifar:我会提出下一种方法:我将在一个函数中转换子枚举映射驱动器,返回一个数组。它的第一个参数是映射字母,第二个参数是映射路径。第二个将根据您希望的路径进行检查,如果匹配则使用。如果没有,新的映射将在另一个字母上完成,但不是数组中的那个。不一定是下面的字母。这对你来说方便吗?
猜你喜欢
  • 2012-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-27
  • 2011-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多