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
问题根源
- 分块添加脚本的语法解析缺陷:你把PowerShell脚本拆成数十个小片段用
AddScript逐个添加,PowerShell引擎无法识别分散代码块的上下文关联——比如foreach循环、@{}哈希表的起始和结束被拆成单独命令,引擎判断为语法不完整。 - 命令参数格式错误: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
相关产品推荐
相关产品推荐

