从传递参数的 vbs 调用 power shell 脚本时出错
Error on calling power shell script from vbs passing arguments
我有一个非常简单的 VBScript,它执行 PowerShell 脚本并试图传递几个参数。
无论我尝试过什么,它都失败了并且不接受参数:
Dim WshShell
Dim cmdStr
Const ForReading = 1, ForWriting = 2 ,ForAppending = 8
curYear = Year(Date)
curMon = Month(Date)
curDay = Day(Date)
curHr = Hour(Time)
curMin = Minute(Time)
curSec = Second(Time)
datestg = curYear & curMon & curDay & curHr & curMin & curSec
Set WshShell = WScript.CreateObject("WScript.Shell")
Dim inputDir
inputDir = InputBox("Input Directory ( can be full file path ) : ", "Message Box")
inputDirLen = Len(inputDir)
If inputDirLen > 0 Then
lastchar = Mid(inputDir, inputDirLen-1, 1)
If lastchar <> "\" Then
inputDir = inputDir & "\"
End If
End If
outFileMask = InputBox("Output file name mask ( files will be created in previously entered directory ) : ", "Message Box")
newDate = InputBox("Desired Date ( format of the date should be yyyy-mm-ddThh:mm:ss ) : ", "Message Box")
cmdStr = "%comspec% /c dir " & inputDir & "*.xml > dir.lst"
cmdrc = wshShell.Run(cmdStr, , True)
'create file system object
Set fs = CreateObject("Scripting.FileSystemObject")
Set fso = CreateObject("Scripting.FileSystemObject")
dirFileName = "dir.lst"
outFileName = inputDir & outFileMask & "_" & datestg &".xml"
Set infile = fs.OpenTextFile(dirFileName, ForReading)
Set fileOut = fso.CreateTextFile(outFileName, True)
Set objShell = CreateObject("WScript.Shell")
objShell.Run("powershell -NoExit -File .\psscript.ps1 " & infile)
infile.Close
fileOut.Close
WScript.Quit
这甚至在 objshell.Run
上失败了。如果我拿走任何 arg,那么它将 运行,但由于参数中的空值,PowerShell 脚本将失败。
这是完整的 PowerShell 脚本:
$inputPath = $args[0]
$newDate = $args[1]
$outputPath = $args[2]
[xml]$xmlDoc = Get-Content $inputPath
foreach ($element in $xmlDoc.element1) {
$element.DateTime = $newDate
}
$xmlDoc.Save($outputPath)
您的 VBScript 正在打开带有 XML 文件列表的文件,然后尝试将该句柄传递给 PowerShell 脚本。那是行不通的。
您可以在这里做几件事:
读取 VBScript 中的 XML 文件列表并循环调用 PowerShell 脚本:
Set sh = CreateObject("WScript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")
outFileName = inputDir & outFileMask & "_" & datestg &".xml"
Set infile = fs.OpenTextFile(dirFileName, ForReading)
Do Until infile.AtEndOfStream
line = infile.ReadLine
sh.Run "powershell -File .\your.ps1 " & line & " " & newDate & " " & outFileName
Loop
infile.Close
但是,这意味着您要为每次迭代生成一个新进程,这在性能方面很糟糕。
将带有 XML 文件列表的文件传递给 PowerShell 脚本:
Set sh = CreateObject("WScript.Shell")
outFileName = inputDir & outFileMask & "_" & newDate &".xml"
dirFileName = sh.CurrentDirectory & "\" & dirFileName
sh.Run "powershell -File .\your.ps1 " & dirFileName & " " & newDate & " " & outFileName
您想传递 dirFileName
文件的完整路径,因为不能保证 VBScript 和 PowerShell 代码具有相同的工作目录。传递列表而不是单个文件还需要更改您的 PowerShell 代码:
$inputPath = $args[0]
$newDate = $args[1]
$outputPath = $args[2]
Get-Content $inputPath | ForEach-Object {
[xml]$xmlDoc = Get-Content $_.FullName
foreach ($element in $xmlDoc.element1) {
$element.DateTime = $newDate
}
$xmlDoc.Save($outputPath)
}
传递输入目录并让 PowerShell 执行列表:
Set sh = CreateObject("WScript.Shell")
outFileName = inputDir & outFileMask & "_" & newDate &".xml"
sh.Run "powershell -File .\your.ps1 " & inputDir & " " & newDate & " " & outFileName
同样,这还需要更改您的 PowerShell 代码:
$inputPath = $args[0]
$newDate = $args[1]
$outputPath = $args[2]
Get-ChildItem $inputPath -Filter '*.xml' | ForEach-Object {
[xml]$xmlDoc = Get-Content $_.FullName
foreach ($element in $xmlDoc.element1) {
$element.DateTime = $newDate
}
$xmlDoc.Save($outputPath)
}
您也可以在 PowerShell 中完成所有操作并完全放弃 VBScript(这可以说是最简洁的方法):
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true)]
[ValidateScript(Test-Path -LiteralPath $_)]
[String]$inputPath,
[Parameter(Mandatory=$true)]
[ValidatePattern('^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$')]
[String]$newDate,
[Parameter(Mandatory=$true)]
[String]$outFileMask
)
$datestg = (Get-Date).ToString('yyyyMMddHHmmss')
$outFileName = Join-Path $inputPath, "${outFileMask}_${datestg}.xml"
Get-ChildItem $inputPath -Filter '*.xml' | ForEach-Object {
[xml]$xmlDoc = Get-Content $_.FullName
foreach ($element in $xmlDoc.element1) {
$element.DateTime = $newDate
}
$xmlDoc.Save($outFileName)
}
但是请注意,使用这些方法中的所有,PowerShell 将在每次迭代时覆盖输出文件。如果要处理多个 XML 文件并希望将它们写入不同的输出文件,则需要在循环中创建单独的输出文件名。
我有一个非常简单的 VBScript,它执行 PowerShell 脚本并试图传递几个参数。
无论我尝试过什么,它都失败了并且不接受参数:
Dim WshShell
Dim cmdStr
Const ForReading = 1, ForWriting = 2 ,ForAppending = 8
curYear = Year(Date)
curMon = Month(Date)
curDay = Day(Date)
curHr = Hour(Time)
curMin = Minute(Time)
curSec = Second(Time)
datestg = curYear & curMon & curDay & curHr & curMin & curSec
Set WshShell = WScript.CreateObject("WScript.Shell")
Dim inputDir
inputDir = InputBox("Input Directory ( can be full file path ) : ", "Message Box")
inputDirLen = Len(inputDir)
If inputDirLen > 0 Then
lastchar = Mid(inputDir, inputDirLen-1, 1)
If lastchar <> "\" Then
inputDir = inputDir & "\"
End If
End If
outFileMask = InputBox("Output file name mask ( files will be created in previously entered directory ) : ", "Message Box")
newDate = InputBox("Desired Date ( format of the date should be yyyy-mm-ddThh:mm:ss ) : ", "Message Box")
cmdStr = "%comspec% /c dir " & inputDir & "*.xml > dir.lst"
cmdrc = wshShell.Run(cmdStr, , True)
'create file system object
Set fs = CreateObject("Scripting.FileSystemObject")
Set fso = CreateObject("Scripting.FileSystemObject")
dirFileName = "dir.lst"
outFileName = inputDir & outFileMask & "_" & datestg &".xml"
Set infile = fs.OpenTextFile(dirFileName, ForReading)
Set fileOut = fso.CreateTextFile(outFileName, True)
Set objShell = CreateObject("WScript.Shell")
objShell.Run("powershell -NoExit -File .\psscript.ps1 " & infile)
infile.Close
fileOut.Close
WScript.Quit
这甚至在 objshell.Run
上失败了。如果我拿走任何 arg,那么它将 运行,但由于参数中的空值,PowerShell 脚本将失败。
这是完整的 PowerShell 脚本:
$inputPath = $args[0]
$newDate = $args[1]
$outputPath = $args[2]
[xml]$xmlDoc = Get-Content $inputPath
foreach ($element in $xmlDoc.element1) {
$element.DateTime = $newDate
}
$xmlDoc.Save($outputPath)
您的 VBScript 正在打开带有 XML 文件列表的文件,然后尝试将该句柄传递给 PowerShell 脚本。那是行不通的。
您可以在这里做几件事:
读取 VBScript 中的 XML 文件列表并循环调用 PowerShell 脚本:
Set sh = CreateObject("WScript.Shell") Set fso = CreateObject("Scripting.FileSystemObject") outFileName = inputDir & outFileMask & "_" & datestg &".xml" Set infile = fs.OpenTextFile(dirFileName, ForReading) Do Until infile.AtEndOfStream line = infile.ReadLine sh.Run "powershell -File .\your.ps1 " & line & " " & newDate & " " & outFileName Loop infile.Close
但是,这意味着您要为每次迭代生成一个新进程,这在性能方面很糟糕。
将带有 XML 文件列表的文件传递给 PowerShell 脚本:
Set sh = CreateObject("WScript.Shell") outFileName = inputDir & outFileMask & "_" & newDate &".xml" dirFileName = sh.CurrentDirectory & "\" & dirFileName sh.Run "powershell -File .\your.ps1 " & dirFileName & " " & newDate & " " & outFileName
您想传递
dirFileName
文件的完整路径,因为不能保证 VBScript 和 PowerShell 代码具有相同的工作目录。传递列表而不是单个文件还需要更改您的 PowerShell 代码:$inputPath = $args[0] $newDate = $args[1] $outputPath = $args[2] Get-Content $inputPath | ForEach-Object { [xml]$xmlDoc = Get-Content $_.FullName foreach ($element in $xmlDoc.element1) { $element.DateTime = $newDate } $xmlDoc.Save($outputPath) }
传递输入目录并让 PowerShell 执行列表:
Set sh = CreateObject("WScript.Shell") outFileName = inputDir & outFileMask & "_" & newDate &".xml" sh.Run "powershell -File .\your.ps1 " & inputDir & " " & newDate & " " & outFileName
同样,这还需要更改您的 PowerShell 代码:
$inputPath = $args[0] $newDate = $args[1] $outputPath = $args[2] Get-ChildItem $inputPath -Filter '*.xml' | ForEach-Object { [xml]$xmlDoc = Get-Content $_.FullName foreach ($element in $xmlDoc.element1) { $element.DateTime = $newDate } $xmlDoc.Save($outputPath) }
您也可以在 PowerShell 中完成所有操作并完全放弃 VBScript(这可以说是最简洁的方法):
[CmdletBinding()] Param( [Parameter(Mandatory=$true)] [ValidateScript(Test-Path -LiteralPath $_)] [String]$inputPath, [Parameter(Mandatory=$true)] [ValidatePattern('^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}$')] [String]$newDate, [Parameter(Mandatory=$true)] [String]$outFileMask ) $datestg = (Get-Date).ToString('yyyyMMddHHmmss') $outFileName = Join-Path $inputPath, "${outFileMask}_${datestg}.xml" Get-ChildItem $inputPath -Filter '*.xml' | ForEach-Object { [xml]$xmlDoc = Get-Content $_.FullName foreach ($element in $xmlDoc.element1) { $element.DateTime = $newDate } $xmlDoc.Save($outFileName) }
但是请注意,使用这些方法中的所有,PowerShell 将在每次迭代时覆盖输出文件。如果要处理多个 XML 文件并希望将它们写入不同的输出文件,则需要在循环中创建单独的输出文件名。