PowerShell Script for Remote File Copy with Extension Filtering and IIS Restart Automation


3 views

To create a robust PowerShell script that accepts multiple parameters, we'll use the param block. Here's how to declare all the required parameters with proper data types:

param (
    [Parameter(Mandatory=$true)]
    [string]$SourceFolder,
    
    [Parameter(Mandatory=$true)]
    [string[]]$Extensions,
    
    [Parameter(Mandatory=$true)]
    [string]$DestinationFolder,
    
    [Parameter(Mandatory=$true)]
    [bool]$RestartIIS,
    
    [Parameter(Mandatory=$false)]
    [PSCredential]$Credential
)

For copying files to a remote server, we'll use Copy-Item with credentials. The New-PSDrive cmdlet helps establish a temporary connection:

$driveParams = @{
    Name = "TempRemoteDrive"
    PSProvider = "FileSystem"
    Root = "\\$($DestinationFolder.Split('\')[2])\$($DestinationFolder.Split('\')[3])"
    Credential = $Credential
    Persistent = $false
}

$remoteDrive = New-PSDrive @driveParams

try {
    foreach ($ext in $Extensions) {
        Get-ChildItem -Path $SourceFolder -Filter "*.$ext" | ForEach-Object {
            $destPath = $_.FullName.Replace($SourceFolder, $remoteDrive.Root)
            Copy-Item -Path $_.FullName -Destination $destPath -Force
        }
    }
}
finally {
    Remove-PSDrive -Name $remoteDrive.Name
}

To handle IIS restart when required, we'll use the Import-Module WebAdministration and appropriate cmdlets:

if ($RestartIIS) {
    try {
        Import-Module WebAdministration
        Restart-WebAppPool -Name "*"
        Write-Host "All application pools have been restarted successfully."
    }
    catch {
        Write-Error "Failed to restart IIS: $_"
    }
}

For handling multiple folder copies, create a controller script that calls your main script:

$folders = @(
    @{
        Source = "C:\Folder1"
        Extensions = @("txt","log")
        Destination = "\\server1\share1"
        RestartIIS = $false
    },
    @{
        Source = "D:\Folder2"
        Extensions = @("csv","xml")
        Destination = "\\server2\share2"
        RestartIIS = $true
    }
)

$cred = Get-Credential

foreach ($folder in $folders) {
    & ".\Copy-FilesWithExtensions.ps1" 
        -SourceFolder $folder.Source 
        -Extensions $folder.Extensions 
        -DestinationFolder $folder.Destination 
        -RestartIIS $folder.RestartIIS 
        -Credential $cred
}

Add comprehensive error handling and logging to make the script production-ready:

Start-Transcript -Path "C:\Logs\FileCopy_$(Get-Date -Format 'yyyyMMddHHmmss').log"

try {
    # Main script logic here
}
catch {
    Write-Error "Script failed: $_"
    if ($_.Exception.InnerException) {
        Write-Error "Inner exception: $($_.Exception.InnerException.Message)"
    }
}
finally {
    Stop-Transcript
}

html

When automating file deployment in Windows environments, we often need to:

  • Filter files by specific extensions
  • Handle remote server transfers
  • Optionally restart IIS services
  • Support multiple source folders

For remote file operations, these are essential:

Copy-Item
New-PSSession
Invoke-Command
Restart-WebAppPool
Get-ChildItem
Test-Path

Here's how to structure the parameter block:

param (
    [Parameter(Mandatory=$true)]
    [string[]]$SourceFolders,
    
    [Parameter(Mandatory=$true)]
    [string[]]$Extensions,
    
    [Parameter(Mandatory=$true)]
    [string]$Destination,
    
    [Parameter()]
    [switch]$RestartIIS,
    
    [Parameter()]
    [pscredential]$Credential
)
# FileCopyWithIIS.ps1
param (
    [Parameter(Mandatory=$true)]
    [string[]]$SourceFolders,
    
    [Parameter(Mandatory=$true)]
    [string[]]$Extensions = @("*.dll","*.config"),
    
    [Parameter(Mandatory=$true)]
    [string]$Destination = "\\server\share\destination",
    
    [Parameter()]
    [switch]$RestartIIS,
    
    [Parameter()]
    [pscredential]$Credential
)

try {
    # Create remote session if credentials provided
    if ($Credential) {
        $session = New-PSSession -ComputerName ($Destination -split '\\')[2] -Credential $Credential
    }

    foreach ($folder in $SourceFolders) {
        if (-not (Test-Path $folder)) {
            Write-Warning "Source folder $folder not found"
            continue
        }

        $files = Get-ChildItem -Path $folder -Include $Extensions -Recurse -File
        
        foreach ($file in $files) {
            $destPath = $Destination + $file.FullName.Substring($folder.Length)
            $destDir = [System.IO.Path]::GetDirectoryName($destPath)
            
            if (-not (Test-Path $destDir)) {
                New-Item -ItemType Directory -Path $destDir -Force | Out-Null
            }
            
            Copy-Item -Path $file.FullName -Destination $destPath -Force
        }
    }

    if ($RestartIIS) {
        if ($session) {
            Invoke-Command -Session $session -ScriptBlock {
                Import-Module WebAdministration
                Restart-WebAppPool -Name "DefaultAppPool"
            }
        }
        else {
            Import-Module WebAdministration
            Restart-WebAppPool -Name "DefaultAppPool"
        }
    }
}
catch {
    Write-Error "Error occurred: $_"
}
finally {
    if ($session) { Remove-PSSession $session }
}

For batch processing:

$params = @{
    SourceFolders = @("C:\App1\Bin","D:\App2\Assets")
    Extensions = @("*.dll","*.pdb","*.config")
    Destination = "\\prod-server\deploy"
    RestartIIS = $true
    Credential = Get-Credential
}

.\FileCopyWithIIS.ps1 @params
  • Always use encrypted credentials
  • Validate destination paths
  • Implement proper error handling
  • Consider using JEA for constrained endpoints

For large deployments:

# Use robocopy for bulk operations
foreach ($folder in $SourceFolders) {
    robocopy $folder $Destination $Extensions /S /Z /MT:16 /R:1 /W:1
}