3

I trying to write PowerShell script who can send a email when a new file his drop on a FTP (I'm not the owner of the FTP so I can't do a cron job).

I got a error because I'm using the Contains method and after some research Contains doesn't work through FTP.

I don't know a other method for doing this job. Someone can help me out in my ignorance here ?

There is the script I've write :

# Charger l'ensemble .NET de WinSCP
Add-Type -Path "WinSCPnet.dll"

# Configurer les options de session
$sessionOptions = New-Object WinSCP.SessionOptions -Property @{
    Protocol = [WinSCP.Protocol]::Ftp
    HostName = "xxxxxx"
    UserName = "xxxxxx"
    Password = "xxxxxx"
}

$sessionOptions.AddRawSettings("ProxyHost", "xxxxxx")
$sessionOptions.AddRawSettings("ProxyPort", "xxxxxx")
$sessionOptions.AddRawSettings("FtpProxyLogonType", "xxxxxx")

$session = New-Object WinSCP.Session

try
{
    # Connecter
    $session.Open($sessionOptions)

    # Votre code

    ### FONCTION ENVOI DE MAIL ###
    Function SendMail
    {
        $EXPEDITEUR = "xxxxxx"
        $DESTINATAIRE = "xxxxxx","xxxxxx"
        $SUJET = "xxxxxx"
        $SERVEUR_SMTP = "xxxxxx" 
        $CORPS_MAIL = "xxxxxx"
        #$PJ = 'c:\script\Rapport.txt' # si Pièce jointe
        #$attachment = New-Object System.Net.Mail.Attachment($PJ) #Pour la Pièce jointe
        $Mail_Message = New-Object System.Net.Mail.MailMessage #on créé l'objet
        $Mail_Message.From = $EXPEDITEUR
        $Mail_Message.Subject = $SUJET
        $Mail_Message.Body = $CORPS_MAIL
        #$Mail_Message.Attachments.Add($PJ)
        $Mail_Adresses = $Mail_Message.To
        if ($DESTINATAIRE -is "System.Array") #Si plusieurs adresses
        {
            foreach ($Adr in $DESTINATAIRE) #on rajoute chaque adresse
            {
                $Mail_Adress = New-Object System.Net.Mail.MailAddress $Adr
                $Mail_Adresses.Add($Mail_Adress)
            }
        }
        else
        {
            $Mail_Adress = New-Object System.Net.Mail.MailAddress $DESTINATAIRE
            $Mail_Adresses.Add($Mail_Adress)
        }
        $SMTPClient = New-Object Net.Mail.SmtpClient($SERVEUR_SMTP, 25) #serveur SMTP et Port
        $SMTPClient.EnableSsl = $false #si SSL activé ou non - Importer le certificat avant?
        $SMTPClient.Credentials = New-Object System.Net.NetworkCredential("xxxxxx", "xxxxxx"); #ICI Login et password du compte mail
        $SMTPClient.Send($Mail_Message) #l'envoi du mail
    }

    ### Déclaration variables ###
    $log="xxxxxx" #
    $dateverif = get-date -format "yyyy_MM_dd_-_HH_mm_ss"

    ### VERIFICATION DES COMMANDES EN ATTENTE ###
    $Date=(Get-Date).AddMinutes(-2)
    #$remotePath = "xxxxxx"
    #$H =Dir $remotePath
    #$path='xxxxxx'
    #$H=Dir $Path |
    $H=$session.Open
        Where-Object {! $_.PsIsContainer}|
        Group-Object -Property {$_.LastWriteTime -ge $date} -AsHashTable -AsString

    $oldOfs,$ofs=$ofs,' , '
    if ($H -eq $null) # Aucun fichier dans le répertoire à surveiller
    {
        echo "$dateverif Aucun fichier trouvé" >> $log
        exit 0
    }
    if ($H.Contains('True')) # Présence de fichiers de moins de 1 jour (1440 minutes)
    {
        Write-Warning "Nouveau rapport d'intervention TowerCast"
        "$($H.True)"
        echo "$dateverif NEW : Nouveau rapport d'intervention de Towercast" >> $log
        echo $H >>$log
        SendMail #Envoi du mail d'alerte
        exit 0
    }
    if ($H.Contains('False')) # Présence de fichiers de plus de 1 jour (1440 minutes)
    {
        Write-Warning "Pas de nouveau rapport"
        "$($H.False)"
        echo "$dateverif Aucun nouveau rapport" >> $log
        exit 0
    }
    $ofs=$oldOfs
}
finally
{
    $session.Dispose()
}

Thanks in advance and have a good day

Martin Prikryl
  • 147,050
  • 42
  • 335
  • 704
Ivanova
  • 55
  • 3

2 Answers2

1

From your existing code, I think you are using contains in the wrong way.

contains is to be used to confirm if a matching value is contained in an array Your code is trying to check if "True" string is contained as a file resulting from your earlier filter on the files. This will not work.

Based on your filter, instead of contains, you can use count, it should give better results:

if (($H).Count -gt 0")
{
# There are at least 1 new file in your filter
}
else
{
# No new files in your filter
}

Let me suggest to move to an easier module to connect and play with FTP Files:

PowerShell FTP Client Module from TechNet PowerShell Gallery looks very friendly.

Klausen
  • 81
  • 2
  • Thanks @Klausen I've tried to replace **contains** by **count** but If **count** is set to **0** I always get a email and if it's set to **1** I never get one. I think I've implement **count** in the wrong way ... The updated version of the script is here : https://pastebin.com/MHCX1sjp – Ivanova Sep 08 '20 at 17:04
  • About the TechNet PowerShell Gallery, I've take a look but it not seems more friendly to me. Maybe should I go further with it. But for my own knowledge I will succeed with my first method too ^^ – Ivanova Sep 08 '20 at 17:06
  • I see you tried with the number between quotation marks. This makes Powershell to treat it as text: (($H).Count -gt "0"). You should use the number without them, so it is treated as a number: (($H).Count -gt 0). Tip for troubleshooting: after you execute your code in the console, you still can go on the terminal print variables used in the session, etc for troubleshooting. This should be of help as troubleshooting for any Powershell script you make. – Klausen Sep 08 '20 at 17:11
  • @Klausen You are misinterpreting how `.Contains()` is being used in the example. It's a hashtable being grouped where `$H['True']` would list the items that meet the criteria (`$_.LastWriteTime -ge $date`) and `$H['False']` would list the ones that didn't. – notjustme Sep 08 '20 at 17:31
  • @notjustme thanks for point! Always glad to learn something new. I may have misinterpreted this code. I am not finding this documented. Could you point me to some documentation where I can read of this please? – Klausen Sep 08 '20 at 19:47
  • So have you a idea for doing this ? @Klausen – Ivanova Sep 09 '20 at 16:58
  • @notjustme If you have a idea too ? – Ivanova Sep 09 '20 at 16:59
1

You want something like this:

$H = $session.ListDirectory($path) |
     Where-Object {! $_.IsDirectory} |
     Group-Object ...

For another implementation, see WinSCP example for Watching for changes in SFTP/FTP server.

Martin Prikryl
  • 147,050
  • 42
  • 335
  • 704