【问题标题】:PowerShell pass a switch to a function with Invoke-CommandPowerShell 使用 Invoke-Command 将开关传递给函数
【发布时间】:2014-06-03 09:32:16
【问题描述】:

我在使用 Invoke-Command 将开关 -CleanFolders 传递给函数时遇到了一些困难。我找到了this,但我真的不知道如何实现它,因为它不是针对函数的。

像这样调用我的函数可以正常工作:

Delete-OldFiles $Target $OlderThanDays $Server -CleanFolders
Invoke-Command -ComputerName "$Server" -Authentication Credssp -Credential $Credentials -ScriptBlock ${Function:Delete-OldFiles} -ArgumentList ($Target, $OlderThanDays, $Server)

但这根本不起作用:

Invoke-Command -ComputerName "$Server" -Authentication Credssp -Credential $Credentials -ScriptBlock ${Function:Delete-OldFiles} -ArgumentList ($Target, $OlderThanDays, $Server, -CleanFolders)

完整脚本:

#__________________________________________________________________________________________________________________________________
$ImportFile = "S:\Input\Scheduled Task\Auto_Clean.csv"
$Password = cat "S:\Input\pwd.txt" | ConvertTo-SecureString -Force
$UserName = "domain\me"

#__________________________________________________________________________________________________________________________________
# Scriptblock for running the function in a job
$JobFunc = {
# Function that removes files older than x days in all subfolders
Function Delete-OldFiles {
<# 
.SYNOPSIS   
    Script to delete files and folders older than x days

.DESCRIPTION
    Remove files older than x days in all subfolders and write success and failure actions to the logfile in "\\DEUSTHEIDIT02\Log\Scheduled Task\Auto_Clean\". 
    By default, empty foldes will be left behind and not deleted.

.PARAMETER Target 
    The path that will be recusively scanned for old files

.PARAMETER OlderThanDays
    Filter for age of file, entered in days. Use 0 for all files to be removed

.PARAMETER CleanFolders
    If this switch is specified folders that are older than 'OlderThanDays' and are empty will be removed. Default behaviour of this script is to leave empty folders behind.

.EXAMPLE
    Delete-OldFiles -Target "\\grouphc.net\bnl\DEPARTMENTS\Brussels\CBR\SHARE\Target" -OlderThanDays "10"
    Delete-OldFiles "\\grouphc.net\bnl\DEPARTMENTS\Brussels\CBR\SHARE\Target" "10"
    Delete-OldFiles "E:\DEPARTMENTS\CBR\SHARE\Target" "10"

Description:
    Deletes all files older than 10 days in the Target folder and all of its subfolders and write success and failure to the log.

.EXAMPLE
    Delete-OldFiles "\\grouphc.net\bnl\DEPARTMENTS\Brussels\CBR\SHARE\Target" "10" -CleanFolders

Description:
    Deletes all files older than 10 days and all empty folders in the Target folder and all of its subfolders and write success and failure to the log.

.NOTES
    REQUIREMENTS Remote server:
    PowerShell 2.0
    As admin run 'Set-ExecutionPolicy RemoteSigned'
    As amdin run 'Enable-WSManCredSSP -Role Server -Force'

    REQUIREMENTS Script server:
    Enable-WSManCredSSP -Role Client -DelegateComputer *.grouphc.net -Force

    CHANGELOG
    2014/05/06 Script born 
    2014/05/07 Added total runtime of the script to the logfile
    2014/05/12 Added timestamps, fail and success messages to the logfile
    2014/05/13 Added PowerShell 2.0 compatibility for Windows Server 2003
    2014/05/13 Added remove empty directories
    2014/05/14 Added comment section on top
    2014/05/15 Added parameters to pass variables $Target and $OlderThanDays
    2014/05/19 Added CSV input file for easy management
    2014/05/20 Created function Delete-OldFiles and Delete-OldFolders
    2014/05/22 Rewrote script for calling functions
    2014/05/23 Added switch -CleanFolders
    2014/06/02 Added password authentication for double hop
    2014/06/03 Added loging capability to different files with timestamps

.AUTHOR 
   Me #>
[CmdletBinding(SupportsShouldProcess=$True)] # Add -WhatIf support for dry run
Param(
    [Parameter(Mandatory=$True,Position=1)]
    [ValidateScript({Test-Path $_})]
    [String]$Target,
    [Parameter(Mandatory=$True,Position=2)]
    [Int]$OlderThanDays,
    [Parameter(Mandatory=$False,Position=3)]
    [String]$Server,
    [switch]$CleanFolders
      )

#__________________________________________________________________________________________________________________________________
# Create logfile with the correct name
# Gets date and reformats to be used in log filename
$TempDate = (get-date).ToString("dd-MM-yyyy")
# Reformats $Target so it can be used in the log filename
$TempFolderPath = $Target -replace '\\','_'
$TempFolderPath = $TempFolderPath -replace ':',''
$TempFolderPath = $TempFolderPath -replace ' ',''
# Combines the date and the path scanned into the log filename
$script:LogFile = "\\DEUSTHEIDIT02\Log\Scheduled Task\Auto_Clean\$Server - $TempFolderPath - $TempDate.log"

#__________________________________________________________________________________________________________________________________
# Check the version of PowerShell
if ($PSVersionTable.PSVersion.Major -ge "3") {

    # PowerShell 3+ Remove files older than (FASTER)
    Get-ChildItem -Path $Target -Recurse -File | 
    Where-Object { $_.CreationTime -lt (Get-Date).AddDays(-$OlderThanDays) } | 

        ForEach {
        $Item = $_.FullName
        Remove-Item $Item -Recurse -Force -ErrorAction SilentlyContinue

            # Log succes/failure
            $Timestamp = (Get-Date).ToShortDateString()+" | "+(Get-Date).ToLongTimeString()      
            if (Test-Path $Item) { 
                "$Timestamp | FAILLED: $Server $Item (IN USE)"
            } 
            else { 
                "$Timestamp | REMOVED: $Server $Item" 
            }  
        } | Tee-Object $LogFile -Append }

Else {               

    # PowerShell 2 Remove files older than
    Get-ChildItem -Path $Target -Recurse | 
    Where-Object { !$_.PSIsContainer -and $_.CreationTime -lt (Get-Date).AddDays(-$OlderThanDays) } | 

        ForEach {
        $Item = $_.FullName
        Remove-Item $Item -Recurse -Force -ErrorAction SilentlyContinue

            # Log succes/failure
            $Timestamp = (Get-Date).ToShortDateString()+" | "+(Get-Date).ToLongTimeString()   
            if (Test-Path $Item) { 
                Write-Host "$Timestamp | FAILLED: $Server $Item (IN USE)"
               "$Timestamp | FAILLED: $Server $Item (IN USE)"
            } 
            else { 
                  Write-Host "$Timestamp | REMOVED: $Server $Item"
                 "$Timestamp | REMOVED: $Server $Item"
            }  
        } | Out-File $LogFile -Append } 

#__________________________________________________________________________________________________________________________________
    # Switch -CleanFolders deletes empty folders older than x days
    if ($CleanFolders) {

        # Check the version of PowerShell
        if ($PSVersionTable.PSVersion.Major -ge "3") {

            # PowerShell 3+ Remove empty folders older than (FASTER)
            Get-ChildItem -Path $Target -Recurse -Force -Directory  -ErrorAction SilentlyContinue |
            Where-Object { $_.CreationTime -lt (Get-Date).AddDays(-$OlderThanDays) } | 
            Where-Object { (Get-ChildItem -Path $_.FullName -Recurse -Force -File) -eq $null } | 

                ForEach {
                $Item = $_.FullName
                Remove-Item $Item -Recurse -Force -ErrorAction SilentlyContinue

                    # Log succes/failure
                    $Timestamp = (Get-Date).ToShortDateString()+" | "+(Get-Date).ToLongTimeString()
                    if (Test-Path $Item) { 
                        "$Timestamp | FAILLED: $Server $Item (IN USE)" 
                    } 
                    else { 
                        "$Timestamp | REMOVED: $Server $Item" 
                    }  
                } | Tee-Object $LogFile -Append
        }     

        else {

            # PowerShell 2 Remove empty folders older than 
            Get-ChildItem -Path $Target -Recurse -Force -ErrorAction SilentlyContinue | 
            Where-Object { $_.PSIsContainer -and (Get-ChildItem -Path $_.FullName -Recurse -Force | Where-Object { !$_.PSIsContainer }) -eq $null } | 
            Where-Object { $_.CreationTime -lt (Get-Date).AddDays(-$OlderThanDays) } | 

                ForEach {
                $Item = $_.FullName
                Remove-Item $Item -Recurse -Force -ErrorAction SilentlyContinue

                    # Log succes/failure
                    $Timestamp = (Get-Date).ToShortDateString()+" | "+(Get-Date).ToLongTimeString()      
                    if (Test-Path $Item) { 
                        Write-Host "$Timestamp | FAILLED: $Server $Item (IN USE)"
                        "$Timestamp | FAILLED: $Server $Item (IN USE)" 
                    } 
                    else { 
                        Write-Host "$Timestamp | REMOVED: $Server $Item"
                        "$Timestamp | REMOVED: $Server $Item" 
                    }  
                } |  Out-File $LogFile -Append 
        } 
    }
}
}

#__________________________________________________________________________________________________________________________________
# Read input file and ignore all lines starting with #
$File = (Import-Csv -Path $ImportFile -Header "Server", "Target", "OlderThanDays" | Where { $_.Server -NotMatch "#" } )

#__________________________________________________________________________________________________________________________________

# If the UNC Path is provided we will run the script locally else it wil be run on the remote server as a job
Foreach ($_ in $File) {

        # Set easy names
        $Server = $_.Server
        $Target = $_.Target
        $OlderThanDays = $_.OlderThanDays

        if ($Server -eq "UNC")
        {
            Write-Host "UNC Path detected: $Target, $OlderThanDays" -ForegroundColor Yellow
            Start-Job -ScriptBlock {Param($Target, $OlderThanDays, $Server) Delete-OldFiles $Target $OlderThanDays $Server} -InitializationScript $JobFunc -ArgumentList ($Target, $OlderThanDays, $Server) -Name DelFiles
            # Remove empty folders to: Delete-OldFiles $Target $OlderThanDays $Server -CleanFolders
        }
        else
        {
            Write-Host "Local path detected: $Server, $Target, $OlderThanDays" -ForegroundColor Cyan

            $Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName,$Password

            $Credentials = New-Object System.Management.Automation.PSCredential -ArgumentList $UserName,$Password
            Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock {$JobFunc; Delete-OldFiles $Target $OlderThanDays $Server} -ArgumentList ($Target, $OlderThanDays, $Server) #-AsJob -JobName DelFiles

            #Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock {Delete-OldFiles $args[0] $args[1] $args[2] -CleanFolders:$args[3]} -ArgumentList ($Target, $OlderThanDays, $Server, $true) -AsJob -JobName DelFiles
            # Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock ${Function:Delete-OldFiles} -ArgumentList ($Target, $OlderThanDays, $Server)

            #Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock ${Function:Delete-OldFiles} -ArgumentList ($Target, $OlderThanDays, $Server) -AsJob -JobName DelFiles
            #Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock {Delete-OldFiles $Target, $OlderThanDays, $Server} -ArgumentList ($Target, $OlderThanDays, $Server) #-AsJob -JobName DelFiles
            #Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock {Function:Delete-OldFiles} -ArgumentList ($Target, $OlderThanDays, $Server) #-AsJob -JobName DelFiles
            #Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock ${Function:Delete-OldFiles} -ArgumentList ($Target, $OlderThanDays, $Server)
            #Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock {$JobFunc} -ArgumentList ($Target, $OlderThanDays, $Server) -AsJob -JobName DelFiles
            #Invoke-Command -ComputerName "$Server.grouphc.net" -Authentication Credssp -Credential $Credentials -ScriptBlock ${Function:Delete-OldFiles} -ArgumentList ($Target, $OlderThanDays, $Server)
        }  
}

感谢您的帮助。

【问题讨论】:

    标签: powershell


    【解决方案1】:

    试试这样:

    $sb = {
      function Delete-OldFiles {
        #...
      }
    
      Delete-OldFiles $args[0] $args[1] $args[2] -CleanFolders:$args[3]
    }
    
    Invoke-Command -ComputerName $Server -Authentication Credssp `
      -Credential $Credentials -ScriptBlock $sb `
      -ArgumentList ($Target, $OlderThanDays, $Server, $true)
    

    【讨论】:

    • 这似乎只有在我将这个if ($CleanFolders) 更改为这个if ($CleanFolders=$True) 时才有效,但它总是有效...
    • @DarkLite1 您发布的代码中没有条件。请使用其余代码更新您的问题。此外,= 是 PowerShell 中的 assignment 运算符,而不是 comparison 运算符。那将是-eq
    • @DarkLite1 在声明 if ($CleanFolders) 中评估开关 -CleanFolders 对我来说效果很好。
    • 你说得对,我已经对代码进行了全面更新,因为我没有复制粘贴所有内容。现在你可以看到完整的源代码了。问题是函数不能被Invoke-Command执行,因为它在脚本块$JobFuncnow,它只适用于Start-Job,我似乎找不到Invoke-Command 的正确语法。很抱歉造成混乱...
    • @DarkLite1 你不能定义一个包含函数和函数调用的脚本块并将该脚本块用于Start-JobInvoke-Command 吗?查看更新的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-08
    • 1970-01-01
    • 1970-01-01
    • 2016-09-24
    • 1970-01-01
    相关资源
    最近更新 更多