从vbs传递参数调用Power Shell脚本时出错

时间:2019-02-01 16:18:40

标签: powershell vbscript

我有一个非常简单的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)

1 个答案:

答案 0 :(得分:1)

您的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)
    }
    

但是请注意,使用这些方法的 all ,PowerShell将在每次迭代时覆盖输出文件。如果要处理多个XML文件,并希望将它们写入不同的输出文件,则需要在循环中创建单独的输出文件名。