Modyfikacja wtyczki WinSCP

Modyfikacja wtyczki WinSCP

Dodałem funkcję której mi brakowało

Case

Używam WinSCP do synchronizacji zdalnego katalogu FTP z lokalnym folderem. Pliki są automatycznie pobierane z katalogu i wczytywane do Lightrooma. Na serwer FTP pliki są wgrywane bezpośrednio z apartu podłączonego do sieci.

+---------+       FTP Upload        +------------+
|  Camera | ----------------------> | FTP Server |
+---------+  (smartphone hotspot)   +------------+
                                         |
                                         | Sync via
                                         | WinSCP
                                         v
                                   +--------------+
                                   |   Computer   |
                                   |  (Local Dir) |
                                   +--------------+
                                         |
                                         | Auto-import
                                         v
                                  +------------------+
                                  | Adobe Lightroom  |
                                  +------------------+

Zmiany

  • Dodałem opcję pobierania tylko plików króych czas modyfikacji jest starszy niż określona ilość sekund. Rozwiązuje to prawie całkowicie problem pobierania niekompletnych plików które są właśnie wgrywane na serwer.
  • Dodałem funkcję do automatycznego usuwania plików z serwera po ich pobraniu.

Kod wtyczki

Lokalizacja pliku wtyczki: ~\WinSCP\Extensions\KeepLocalUpToDate.WinSCPextension.ps1

~~~powershell

@name &Keep Local Directory up to Date and Delete Remote…

@command powershell.exe -ExecutionPolicy Bypass -File “%EXTENSION_PATH%” ^

-sessionUrl “!E” -localPath “%LocalPath%” -remotePath “%RemotePath%” ^

%Delete% %DeleteRemote% %Beep% %ContinueOnError% -interval “%Interval%” ^

-fileMask “%FileMask%” -pause -sessionLogPath “%SessionLogPath%” -minDownloadAge “%MinDownloadAge%”

@description Periodically scans for changes in a remote directory, ^

reflects them on a local directory and optionally deletes remote files

@version 14

@homepage https://winscp.net/eng/docs/library_example_keep_local_directory_up_to_date

@require WinSCP 5.16

@option - -run group “Directories”

@option RemotePath -run textbox “&Watch for changes in the remote directory:” “!/”

@option LocalPath -run textbox ^

“… &and automatically reflect them on the local directory:” “!\”

@option - -config -run group “Options”

@option Delete -config -run checkbox “&Delete local files” “” -delete

@option DeleteRemote -config -run checkbox “Delete &remote files after download” “” -deleteRemote

@option Beep -config -run checkbox “&Beep on change” “” -beep

@option ContinueOnError -config -run checkbox “Continue on &error” “” -continueOnError

@option Interval -config -run textbox “&Interval (in seconds):” “30”

@option FileMask -config -run textbox “File &mask:” “”

@option MinDownloadAge -config -run textbox “Minimum download age (in seconds):” “5”

@option - -config group “Logging”

@option SessionLogPath -config sessionlogfile

param ( $sessionUrl = “sftp://user:mypassword;fingerprint=ssh-rsa-xxxxxxxxxxx…@example.com/”, [Parameter(Mandatory = $True)] $localPath, [Parameter(Mandatory = $True)] $remotePath, [Switch] $delete, [Switch] $deleteRemote, [Switch] $beep, [Switch] $continueOnError, $sessionLogPath = $Null, $interval = 30, $fileMask = $Null, [Switch] $pause, $minDownloadAge = 5 )

function Beep() { if ($beep) { [System.Console]::Beep() } }

function HandleException ($e) { if ($continueOnError) { Write-Host -ForegroundColor Red $_.Exception.Message Beep } else { throw $e } }

function SetConsoleTitle ($status) { if ($sessionOptions) { $status = “$sessionOptions - $status” } $Host.UI.RawUI.WindowTitle = $status }

try { # Load WinSCP .NET assembly $assemblyPath = if ($env:WINSCP_PATH) { $env:WINSCP_PATH } else { $PSScriptRoot } Add-Type -Path (Join-Path $assemblyPath “WinSCPnet.dll”)

# Setup session options
$sessionOptions = New-Object WinSCP.SessionOptions
$sessionOptions.ParseUrl($sessionUrl)

$transferOptions = New-Object WinSCP.TransferOptions -Property @{ FileMask = $fileMask };

$session = New-Object WinSCP.Session

try {
    $session.SessionLogPath = $sessionLogPath

    Write-Host "Connecting..."
    SetConsoleTitle "Connecting"
    $session.Open($sessionOptions)

    while ($True) {
        Write-Host -NoNewline "Looking for changes..."
        SetConsoleTitle "Looking for changes"
        try {
            # Track successfully downloaded files
            $downloadedFiles = @()

            $differences =
            $session.CompareDirectories(
                [WinSCP.SynchronizationMode]::Local, $localPath, $remotePath, $delete,
                $False, [WinSCP.SynchronizationCriteria]::Time, $transferOptions)

            Write-Host
            if ($differences.Count -eq 0) {
                Write-Host "No changes found."   
            }
            else {
                Write-Host "Synchronizing $($differences.Count) change(s)..."
                SetConsoleTitle "Synchronizing changes"
                

                foreach ($difference in $differences) {
                    $action = $difference.Action
                    if ($action -eq [WinSCP.SynchronizationAction]::DownloadNew) {
                        $message = "Downloading new $($difference.Remote.FileName)..."
                    }
                    elseif ($action -eq [WinSCP.SynchronizationAction]::DownloadUpdate) {
                        $message = "Downloading updated $($difference.Remote.FileName)..."
                    }
                    elseif ($action -eq [WinSCP.SynchronizationAction]::DeleteLocal) {
                        $message = "Deleting local $($difference.Local.FileName)..."
                    }
                    else {
                        throw "Unexpected difference $action"
                    }

                    Write-Host -NoNewline $message

                    try {
                        # Check if the file's last modification date is older than the specified minimum age
                        $lastWriteTime = $difference.Remote.LastWriteTime
                        $currentTime = [System.DateTime]::Now
                        $timeDifference = $currentTime - $lastWriteTime

                        if ($timeDifference.TotalSeconds -gt $minDownloadAge) {
                            $difference.Resolve($session, $transferOptions) | Out-Null
                            Write-Host " Done."
                            Beep

                            # Track successfully downloaded files
                            if (($action -eq [WinSCP.SynchronizationAction]::DownloadNew) -or 
                                ($action -eq [WinSCP.SynchronizationAction]::DownloadUpdate)) {
                                $downloadedFiles += $difference.Remote
                            }
                        } else {
                            Write-Host " Skipping download of $($difference.Remote.FileName) as it was modified less than $minDownloadAge seconds ago."
                        }
                    }
                    catch {
                        Write-Host
                        HandleException $_
                    }
                }

                # Delete only the files that were successfully downloaded
                if ($deleteRemote -and $downloadedFiles.Count -gt 0) {
                    Write-Host "Deleting successfully downloaded remote files..."
                    foreach ($remoteFile in $downloadedFiles) {
                        try {
                            # Konstrukcja poprawnej ścieżki
                            $remoteFilePath = [System.IO.Path]::Combine($remotePath.TrimEnd('/'), $remoteFile.FileName).Replace('\\', '/')
                            Write-Host "Attempting to delete: $remoteFilePath"
                            $result = $session.RemoveFiles($remoteFilePath)
                            if ($result.IsSuccess) {
                                Write-Host "Deleted: $($remoteFile.FileName)"
                            } else {
                                Write-Host "Failed to delete: $($remoteFile.FileName)"
                                Write-Host -ForegroundColor Red $result.Failures[0].Message
                            }
                        }
                        catch {
                            Write-Host
                            HandleException $_
                        }
                    }
                }
            }
        }
        catch {
            Write-Host
            HandleException $_
        }

        SetConsoleTitle "Waiting"
        $wait = [int]$interval
        # Wait for 1 second in a loop, to make the waiting breakable
        while ($wait -gt 0) {
            Write-Host -NoNewLine "\`rWaiting for $wait seconds, press Ctrl+C to abort... "
            Start-Sleep -Seconds 1
            $wait--
        }

        Write-Host
        Write-Host
    }
}
finally {
    Write-Host # to break after "Waiting..." status
    Write-Host "Disconnecting..."
    # Disconnect, clean up
    $session.Dispose()
} } catch {
$continueOnError = $True
HandleException $_
SetConsoleTitle "Error" }

Pause if -pause switch was used

if ($pause) { Write-Host “Press any key to exit…” [System.Console]::ReadKey() | Out-Null }

Never exits cleanly

exit 1 ~~~


© 2024. Wszelkie prawa zastrzeżone.

Powered by Hydejack v9.2.1