【问题标题】:Passing an argument from command line to PowerShell script将参数从命令行传递到 PowerShell 脚本
【发布时间】:2020-05-18 00:00:18
【问题描述】:

有人为我整理了一个 powershell 脚本。我是个编程爱好者。我无法联系到该用户进行我想要的更改,因此我自己修改了脚本。

基本上我想传递一个参数,两个文件夹目录,以便脚本可以从源和目标生成哈希数据,然后比较它们。该脚本可以正常工作。但我想检查多个来源和目的地。

我做了一些谷歌搜索,发现以下应该可以工作:

powershell.exe -Command 'C:\temp\hashcheck.ps1' -SourceDir "D:\Temp\Public" -DestDir "D:\Temp\Public2"

其中“sourcedir”和“destdir”是我要传递的字符串的名称。但是当我从管理员命令提示符运行它时,它给了我错误“意外的令牌'-SourceDir'”

在 powershell 脚本中已经有几个参数参数,但我添加了“sourcedir”和“destdir”,如下所示:

            param (

                [Parameter(Mandatory=$True)]
                [String]
                $BaseDirectory,

                [Parameter(Mandatory=$True)]
                [String]
                $SourceDir,

                [Parameter(Mandatory=$True)]
                [String]
                $DestDir,

                [Parameter(Mandatory=$True)]
                [ValidateScript({!(Test-Path -path $_ -Type Leaf) })]
                [String]
                $OutputFilePath

            )

然后在这些命令中传递该参数:

        # Run this for Source
        Get-TreeCheckSum -BaseDirectory "$SourceDir" -OutputFilePath C:\temp\PublicSource.xml -Verbose

        # Run this for Destination
        Get-TreeCheckSum -BaseDirectory "$DestDir" -OutputFilePath C:\temp\PublicDestination.xml -Verbose

感谢您的帮助。这可能是一个简单的解决方案,但正如我所说,我完全是 powershell 的业余爱好者。提前致谢。

编辑:这是完整的代码,也许会更有意义。我基本上想将“#Run this for source”和“#Run this for Destination”部分下的文件夹名称传递给“BaseDirectory”

        # Created by P33500k for fun..
        # Use at your own risk follow directions at end to run the commands
        function Get-TreeCheckSum {
            [CmdletBinding()]
            param (

                [Parameter(Mandatory=$True)]
                [String]
                $BaseDirectory,

                [Parameter(Mandatory=$True)]
                [ValidateScript({!(Test-Path -path $_ -Type Leaf) })]
                [String]
                $OutputFilePath


            )

            begin {
                # Define $results as an array of objects
                $results = @()


            }

            process {
                Write-Verbose "Getting all files in $BaseDirectory..."
                # check files
                $allfiles = Get-ChildItem -path $BaseDirectory -Force -File -Recurse | select-object Name,FullName,Length

                Write-Verbose "Found $($allfiles.count) files in $BaseDirectory..."

                $n = 0
                Foreach ($File in $allfiles) {
                    $n++
                    Write-Progress -Activity "CheckSumming $BaseFolder" -Status "Checksumming $($File.FullName)" -PercentComplete (($n / ($allfiles | measure-object | Select-object -ExpandProperty Count)) * 100)
                    Write-Verbose "Checksumming $($file.fullname)"
                    $tempobj = New-Object -TypeName psobject -Property @{
                        'FullPath' = $file.FullName
                        'FileName' = $file.Name
                        'Size' = $file.Length
                        'Hash' = (Get-FileHash -Path $file.fullname | select-object -ExpandProperty Hash)
                        'RelativePath' = ($file.fullname.substring($BaseDirectory.Length))
                    }
                    $results += $tempobj
                    $tempobj = $null
                }
                Write-Verbose "Hashing Complete for file set in $BaseDirectory"

            }

            end {
                Write-Verbose "Writing Output File to $OutputFilePath"
                $results | Export-Clixml -Path $OutputFilePath
            }
        }

        # Run this for Source
        Get-TreeCheckSum -BaseDirectory "D:\Temp\Public" -OutputFilePath C:\temp\PublicSource.xml -Verbose

        # Run this for Destination
        Get-TreeCheckSum -BaseDirectory "D:\Temp\Public2" -OutputFilePath C:\temp\PublicDestination.xml -Verbose


        # Run this code for comparing

        # Global variables for comparing
        $Filesnotondestination = ".\FilesNotonDestination.txt"
        $Filesnotonsource = ".\FilesNotonSource.txt"
        $FailedHashes = ".\Failedchecksums.txt"

        $Source = import-clixml C:\temp\PublicSource.xml
        $Destination = import-clixml C:\temp\PublicDestination.xml

        Write-Host "Comparing objects.."
        $compare = Compare-Object -ReferenceObject $Source -DifferenceObject $Destination -Property RelativePath -IncludeEqual
        Write-Host "Writing file names to files only on source.."
        $compare | Where-object {$_.SideIndicator -eq "<="} | Select-object -expandproperty RelativePath | Set-content -path $Filesnotondestination
        Write-Host "Writing file names to files only on destination.."
        $compare | Where-object {$_.SideIndicator -eq "=>"} | Select-object -expandproperty RelativePath | Set-content -path $Filesnotonsource
        Write-Host "Comparing files on both source and destination... "
        $verify = $compare | Where-object {$_.SideIndicator -eq "=="}
        Write-Host "Found $($verify.count) files that are in both paths.." 
        $n = 0
        foreach ($v in $verify) {
            $n++
            Write-progress -Activity "Comparing file hashes.." -Status "Processing File: $($v.relativepath)" -PercentComplete (($n / ($verify | measure-object | Select-object -ExpandProperty Count)) * 100)
            #Write-Host "Comparing $($v.relativepath).."
            #Write-Host $v.relativepath
            Foreach ($s in $source) {
                If ($s.relativepath -eq $v.relativepath) {
                    $sourceh = $s.hash
                    #Write-Host "Source Hash: $Sourceh"
                }
            }
            Foreach ($d in $Destination) {
                If ($d.relativepath -eq $v.relativepath) {
                    $desth = $d.hash
                    #Write-Host "Destination Hash: $desth"
                }
            }
            If ($desth -eq $sourceh) {
                #Write-Host "File hashed match"
            }
            Else {
                Write-Warning "$($v.relativepath) - File Hashes Do Not Match"
                Add-content -path $FailedHashes -value "$(get-date) - $($v.relativepath) failed checksum: $sourceh not equal to $desth"
            }
        }

【问题讨论】:

    标签: windows powershell command-line parameter-passing


    【解决方案1】:

    尝试像这样直接调用脚本:

    C:\temp\hashcheck.ps1 -SourceDir "D:\Temp\Public" -DestDir "D:\Temp\Public2"
    

    【讨论】:

    • 谢谢 epap。但由于某种原因,它现在想将参数传递给“BaseDirectory”……
    【解决方案2】:

    您不想调用 BaseDirectory 参数。因此,将源 ps1 脚本更改为

    Param (
      [string]$BaseDirectory,
      # The Rest of the script
    

    它不再要求基本目录,因为它不再是强制性的。

    现在调用脚本 其余参数。

    【讨论】:

    • 谢谢。现在当我运行它时,它会提示 SourceDir 和 DestDir,它没有传递参数。
    • 请点击灰色的大勾号接受答案,并通过 ^ 查看按钮进行投票。感谢您的帮助。
    • 感谢您的帮助,但仍然无法正常工作。它要求手动输入参数“SourceDir”和“DestDir”,即使我使用 -SourceDir 和 -DestDir 传递它。有什么想法吗?
    • 任何标记为强制的,必须提供。如果您不想强制使用已定义的参数,请不要强制使用,因为 Wasif Hasan 的有用答案显示。删除所有这些 [Parameter(Mandatory=$True)]。
    猜你喜欢
    • 2016-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-08
    相关资源
    最近更新 更多