HTWingNut
HTWingNut

Reputation: 277

Passing an argument from command line to PowerShell script

Someone kindly put together a powershell script for me. I'm a total amateur with programming. I haven't been able to reach this user to make a change that I'd like to to so I took it upon myself to modify the script myself.

Basically I want to pass an argument, two folder directories, so that the script can generate hash data from both source and destination and then compare them. The script works fine for that. But I want to check multiple sources and destinations.

I've done some googling and found that the following should work:

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

Where "sourcedir" and "destdir" are the names of the strings I want to pass. But when I run it from admin command prompt, it gives me error "unexpected token '-SourceDir'"

In the powershell script there are already a couple argument params but I added the "sourcedir" and "destdir" as follows:

            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

            )

and then pass that argument on in these commands:

        # 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

Thanks for any help. It's probably a simple solution, but as I said, I am complete amateur with powershell. Thanks in advance.

EDIT: Here's the full code, maybe will make more sense. I basically want to pass the folder name under "# Run this for source" and "#Run this for Destination" section assigned to "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"
            }
        }

Upvotes: 2

Views: 665

Answers (2)

Wasif
Wasif

Reputation: 15470

You don't want to call the BaseDirectory parameter. So, change the source ps1 script into

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

It will not ask for base directory as it is no longer mandatory.

Now call the script with the rest parameters.

Upvotes: 1

epap
epap

Reputation: 39

Try calling the script directly like this:

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

Upvotes: 1

Related Questions