You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell脚本在ISE/VS Code正常运行,Visual Studio调用时报括号缺失错误

问题:VB.NET通过Runspace调用PowerShell脚本提示“缺少闭合}”

我用Visual Studio和VB.NET开发的程序,调用PowerShell脚本时遇到异常:其他脚本用相同逻辑能正常执行,但这段脚本在PowerShell ISE、VS Code里运行正常,一到Visual Studio用Runspace调用就提示“缺少闭合}”。我检查过括号是配对的,手动加额外的}也没用,想知道是不是Visual Studio有特殊要求,求解决办法。

原PowerShell脚本

Set-ExecutionPolicy RemoteSigned -force
Import-Module pwps_dab -force
$AdminPwd = ConvertTo-SecureString '123456789' -AsPlainText -Force
New-pwlogin -UserName 'Admin' -Password $AdminPwd -DatasourceName 'perpw1.com.au:Per_Pwise_new'
            
$FolderPath = 'Archives\1800 - 1899\1899\'
$PWfolders = Get-PWFolders -FolderPath $FolderPath -Verbose
$ProjectAccessString  = '----r------'
$DocumentAccessString = '----r--R---'
foreach($folder in $PWfolders){
    $UAC = $Folder | Get-PWFolderSecurity | Where-Object -Property InheritingFrom -eq 'none (folder own permissions)'
    foreach($item in $UAC){
        $Splat_Update = @{
        InputFolder = $folder
        MemberType = $item.Type
        MemberName = $item.Name
    }
    If ($item.SecurityType -eq 'Document'){
        $Splat_Update.DocumentSecurity = $true
        $Splat_Update.MemberAccessString = $DocumentAccessString
    } else {
        $Splat_Update.FolderSecurity = $true
        $Splat_Update.MemberAccessString = $ProjectAccessString
    }
    Update-PWFolderSecurity @Splat_Update -Verbose
    Update-PWFolderSecurity -InputFolder $folder -MemberType 'g' -MemberAccess 'fc' -MemberName 'Administrator' -DocumentSecurity -FolderSecurity
    }
}

原VB.NET调用代码

Public Sub UpdateUACtoReadOnly(ByVal sFolderPath As String)
    Try
        Using MyRunSpace As Runspace = RunspaceFactory.CreateRunspace()
            MyRunSpace.Open()
            Using MyPipeline As Pipeline = MyRunSpace.CreatePipeline()
                MyPipeline.Commands.AddScript("Set-ExecutionPolicy RemoteSigned -force")
                MyPipeline.Commands.AddScript("Import-Module pwps_dab -force")
                MyPipeline.Commands.AddScript("$AdminPwd = ConvertTo-SecureString '123456789' -AsPlainText -Force")
                MyPipeline.Commands.AddScript("New-pwlogin -UserName 'Admin' -Password $AdminPwd -DatasourceName 'perpw1.com.au:Per_Pwise_new'")

                MyPipeline.Commands.AddScript("$FolderPath = 'Archives\1800 - 1899\1899\'")
                MyPipeline.Commands.AddScript("$PWfolders = Get-PWFolders -FolderPath $FolderPath -Verbose")
                MyPipeline.Commands.AddScript("$ProjectAccessString  = '----r------'")
                MyPipeline.Commands.AddScript("$DocumentAccessString = '----r--R---'")
                MyPipeline.Commands.AddScript("foreach($folder in $PWfolders){")
                MyPipeline.Commands.AddScript("$UAC = $Folder | Get-PWFolderSecurity | Where-Object -Property InheritingFrom -eq 'none (folder own permissions)'")
                MyPipeline.Commands.AddScript("foreach($item in $UAC){")
                MyPipeline.Commands.AddScript("$Splat_Update = @{")
                MyPipeline.Commands.AddScript("InputFolder = $folder")
                MyPipeline.Commands.AddScript("MemberType = $item.Type")
                MyPipeline.Commands.AddScript("MemberName = $item.Name")
                MyPipeline.Commands.AddScript("}")
                MyPipeline.Commands.AddScript("If ($item.SecurityType -eq 'Document'){")
                MyPipeline.Commands.AddScript("$Splat_Update.DocumentSecurity = $true")
                MyPipeline.Commands.AddScript("$Splat_Update.MemberAccessString = $DocumentAccessString")
                MyPipeline.Commands.AddScript("} else {")
                MyPipeline.Commands.AddScript("$Splat_Update.FolderSecurity = $true")
                MyPipeline.Commands.AddScript("$Splat_Update.MemberAccessString = $ProjectAccessString")
                MyPipeline.Commands.AddScript("}")
                MyPipeline.Commands.AddScript("Update-PWFolderSecurity @Splat_Update -Verbose")
                MyPipeline.Commands.AddScript("Update-PWFolderSecurity - InputFolder $folder -MemberType 'g' -MemberAccess 'fc' -MemberName 'Administrator' -DocumentSecurity -FolderSecurity")
                MyPipeline.Commands.AddScript("}")
                MyPipeline.Commands.AddScript("}")

                MyPipeline.Invoke()
                MyPipeline.Dispose()
            End Using
            MyRunSpace.Close()
        End Using
    Catch ex As Exception
        MsgBox("Error in Running Powershell Script:UpdateUACtoReadOnly" & Environment.NewLine & Environment.NewLine & ex.Message, MsgBoxStyle.Critical)
        End
    Finally

    End Try
End Sub

问题根源

  1. 分块添加脚本的语法解析缺陷:你把PowerShell脚本拆成数十个小片段用AddScript逐个添加,PowerShell引擎无法识别分散代码块的上下文关联——比如foreach循环、@{}哈希表的起始和结束被拆成单独命令,引擎判断为语法不完整。
  2. 命令参数格式错误:VB.NET代码里有一行命令的参数前多了空格:Update-PWFolderSecurity - InputFolder ...,正确写法是-InputFolder,多余空格会触发语法错误。

修复方案

方案1:合并为完整脚本字符串(推荐)

把所有PowerShell代码拼成一个完整字符串,一次性用AddScript添加,让引擎能正确解析完整语法结构:

Public Sub UpdateUACtoReadOnly(ByVal sFolderPath As String)
    Try
        Using MyRunSpace As Runspace = RunspaceFactory.CreateRunspace()
            MyRunSpace.Open()
            Using MyPipeline As Pipeline = MyRunSpace.CreatePipeline()
                ' 拼接完整PowerShell脚本
                Dim psScript As String = "Set-ExecutionPolicy RemoteSigned -force" & vbCrLf &
                                        "Import-Module pwps_dab -force" & vbCrLf &
                                        "$AdminPwd = ConvertTo-SecureString '123456789' -AsPlainText -Force" & vbCrLf &
                                        "New-pwlogin -UserName 'Admin' -Password $AdminPwd -DatasourceName 'perpw1.com.au:Per_Pwise_new'" & vbCrLf &
                                        "$FolderPath = 'Archives\1800 - 1899\1899\'" & vbCrLf &
                                        "$PWfolders = Get-PWFolders -FolderPath $FolderPath -Verbose" & vbCrLf &
                                        "$ProjectAccessString  = '----r------'" & vbCrLf &
                                        "$DocumentAccessString = '----r--R---'" & vbCrLf &
                                        "foreach($folder in $PWfolders){" & vbCrLf &
                                        "    $UAC = $Folder | Get-PWFolderSecurity | Where-Object -Property InheritingFrom -eq 'none (folder own permissions)'" & vbCrLf &
                                        "    foreach($item in $UAC){" & vbCrLf &
                                        "        $Splat_Update = @{" & vbCrLf &
                                        "        InputFolder = $folder" & vbCrLf &
                                        "        MemberType = $item.Type" & vbCrLf &
                                        "        MemberName = $item.Name" & vbCrLf &
                                        "    }" & vbCrLf &
                                        "    If ($item.SecurityType -eq 'Document'){" & vbCrLf &
                                        "        $Splat_Update.DocumentSecurity = $true" & vbCrLf &
                                        "        $Splat_Update.MemberAccessString = $DocumentAccessString" & vbCrLf &
                                        "    } else {" & vbCrLf &
                                        "        $Splat_Update.FolderSecurity = $true" & vbCrLf &
                                        "        $Splat_Update.MemberAccessString = $ProjectAccessString" & vbCrLf &
                                        "    }" & vbCrLf &
                                        "    Update-PWFolderSecurity @Splat_Update -Verbose" & vbCrLf &
                                        "    Update-PWFolderSecurity -InputFolder $folder -MemberType 'g' -MemberAccess 'fc' -MemberName 'Administrator' -DocumentSecurity -FolderSecurity" & vbCrLf &
                                        "    }" & vbCrLf &
                                        "}"
                MyPipeline.Commands.AddScript(psScript)
                MyPipeline.Invoke()
                MyPipeline.Dispose()
            End Using
            MyRunSpace.Close()
        End Using
    Catch ex As Exception
        MsgBox("Error in Running Powershell Script:UpdateUACtoReadOnly" & Environment.NewLine & Environment.NewLine & ex.Message, MsgBoxStyle.Critical)
        End
    Finally
    End Try
End Sub

方案2:修复分块代码的语法问题(不推荐)

如果坚持分块添加,需保证每个AddScript的代码是语法完整单元,同时修复参数空格问题:

' 修复错误的命令行(去掉-和InputFolder之间的空格)
MyPipeline.Commands.AddScript("Update-PWFolderSecurity -InputFolder $folder -MemberType 'g' -MemberAccess 'fc' -MemberName 'Administrator' -DocumentSecurity -FolderSecurity")

额外建议

  • 优先用完整脚本字符串的方式调用,避免分块带来的语法解析问题,也便于调试。
  • 先在PowerShell环境中验证脚本正确性,再移植到VB.NET。
  • 调试时可捕获PowerShell的详细错误输出,方便定位问题。

内容的提问来源于stack exchange,提问作者Rob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 00:22:05