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

0

2 Answers 2

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.

Sign up to request clarification or add additional context in comments.

Comments

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.

7 Comments

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 : pastebin.com/MHCX1sjp
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 ^^
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 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 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?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.