none
Alert Based on Last write time RRS feed

  • Question

  • I am writing a script based on the last write time. For the most part it works; however, the script sends out an email everytime the script runs. Ideally, I would like to have the email sent only when the last file written is older than 10 hours.

    Below is a copy of the script and I am using a task to call the script. Thanks in advance for the help.

    $dir='\\test\testfiles\' 
    $sendmail=$false
    #$sendmail=$true
    
    
    $JCFILES = gci -path $dir | where-object {
    $_.extension -eq ".pdf" -and ($_.LastWriteTime -lt (get-date).addhours(10) )} 
    $JCFILELIST=$JCFILES | sort LastWriteTime | select -last 1 
    
    #	  	  if ($JCFILES){
    
    $strbody=$JCFILELIST
    $sendmail=$true
    #}		
    
    #$strbody
    if($sendmail -eq $true){
    $smtpServer = "9.9.9.9"
    $msg = new-object Net.Mail.MailMessage
    $smtp = new-object Net.Mail.SmtpClient($smtpServer)
    $msg.From = "ELECTRONIC_FOLDER@jcc.com"
    $msg.To.Add("jcc@jcc.com")
    $msg.Subject = "Please check theElectronic Process"
    $msg.Body = "The file below was the last file to process.`n"
    $msg.Body += $strbody
    $smtp.Send($msg)
    
    }


    Tuesday, August 12, 2014 8:41 PM

Answers

  • Then you want this:

    $file=Get-ChildItem -path \\test\testfiles\* -Include *.pdf |
        Sort LastWriteTime -desc |
        Select-Object -first 1
        Where-Object{ $_.LastWriteTime -gt ([DateTime]::Now.AddHours(-10)) } |
    
    if($file.LastWriteTime -gt ([DateTime]::Now.AddHours(-10))){
        # file newer than 10     
    }else{ 
        # file older than 10
        $mailprops=@{
            SmtpServer='9.9.9.9'
            From='ELECTRONIC_FOLDER@jcc.com'
            To='jcc@jcc.com'
            Subject='Please check the Electronic Process'
    	}
        $body="This file was the last file to process: $($file.Fullname) at $($file.LastWriteTime)"
        Send-MailMessage @mailprops -Body $body
    }else{
        Write-Host 'No files' -ForegroundColor green
    }
    

    If the newest file is older than 10 hours then send the report.

    You need to think about the logic very carefully.  Double negatives and negative logic need to be learned.  It takes a bit of concentration the first time

    You were close but still a bit ambiguous.




    ¯\_(ツ)_/¯

    • Marked as answer by goosebags Thursday, August 14, 2014 4:30 PM
    Thursday, August 14, 2014 3:52 PM

All replies

  • What have you tried?  Did you ask the writer of this script for help?

    ¯\_(ツ)_/¯

    Tuesday, August 12, 2014 9:56 PM
  • Is this what you are trying to do?

    $file=Get-ChildItem -path \\test\testfiles\* -Include *.pdf |
        Where-Object{ $_.LastWriteTime -lt ([DateTime]::Now.AddHours(-10)) } |
        Sort LastWriteTime -desc |
        Select-Object -first 1
    
    if($file){
        $mailprops=@{
            SmtpServer='9.9.9.9'
            From='ELECTRONIC_FOLDER@jcc.com'
            To='jcc@jcc.com'
            Subject='Please check the Electronic Process'
    	}
        $body="This file was the last file to process: $($file.Fullname) at $($file.LastWriteTime)"
        Send-MailMessage @mailprops -Body $body
    }else{
        Write-Host 'No files' -ForegroundColor green
    }



    ¯\_(ツ)_/¯




    • Edited by jrv Tuesday, August 12, 2014 10:18 PM
    Tuesday, August 12, 2014 10:13 PM
  • Yes, this was very helpful; however I am still having an issue with the alert being sent out even if files are still being written to the directory. The script just grabs the last file to be written that is older than ten hours. Ideally the script works like this:

    Script runs - sees the last file written to the directory was less then ten hours ago. No alert sent.

    Script runs - sees the last file written is older than 10 hours. Alert is sent.

     
    Thursday, August 14, 2014 3:34 PM
  • Then you want this:

    $file=Get-ChildItem -path \\test\testfiles\* -Include *.pdf |
        Sort LastWriteTime -desc |
        Select-Object -first 1
        Where-Object{ $_.LastWriteTime -gt ([DateTime]::Now.AddHours(-10)) } |
    
    if($file.LastWriteTime -gt ([DateTime]::Now.AddHours(-10))){
        # file newer than 10     
    }else{ 
        # file older than 10
        $mailprops=@{
            SmtpServer='9.9.9.9'
            From='ELECTRONIC_FOLDER@jcc.com'
            To='jcc@jcc.com'
            Subject='Please check the Electronic Process'
    	}
        $body="This file was the last file to process: $($file.Fullname) at $($file.LastWriteTime)"
        Send-MailMessage @mailprops -Body $body
    }else{
        Write-Host 'No files' -ForegroundColor green
    }
    

    If the newest file is older than 10 hours then send the report.

    You need to think about the logic very carefully.  Double negatives and negative logic need to be learned.  It takes a bit of concentration the first time

    You were close but still a bit ambiguous.




    ¯\_(ツ)_/¯

    • Marked as answer by goosebags Thursday, August 14, 2014 4:30 PM
    Thursday, August 14, 2014 3:52 PM
  • Worked perfect - thanks for the help!
    Thursday, August 14, 2014 4:30 PM
  • Then you want this:

    $file=Get-ChildItem -path \\test\testfiles\* -Include *.pdf |
        Sort LastWriteTime -desc |
        Select-Object -first 1
        Where-Object{ $_.LastWriteTime -gt ([DateTime]::Now.AddHours(-10)) } |
    
    if($file.LastWriteTime -gt ([DateTime]::Now.AddHours(-10))){
        # file newer than 10     
    }else{ 
        # file older than 10
        $mailprops=@{
            SmtpServer='9.9.9.9'
            From='ELECTRONIC_FOLDER@jcc.com'
            To='jcc@jcc.com'
            Subject='Please check the Electronic Process'
    	}
        $body="This file was the last file to process: $($file.Fullname) at $($file.LastWriteTime)"
        Send-MailMessage @mailprops -Body $body
    }else{
        Write-Host 'No files' -ForegroundColor green
    }

    If the newest file is older than 10 hours then send the report.

    You need to think about the logic very carefully.  Double negatives and negative logic need to be learned.  It takes a bit of concentration the first time

    You were close but still a bit ambiguous.




    ¯\_(ツ)_/¯

    Is this the 3-way logic: True/False/Null?

    I had to do a double-take when I saw 2 else's 

    Anyway, it looks like lines 3 and 4 are reversed in order. Is that a typo?


    Sam Boutros, Senior Consultant, Software Logic, KOP, PA http://superwidgets.wordpress.com (Please take a moment to Vote as Helpful and/or Mark as Answer, where applicable)

    Sunday, August 17, 2014 12:13 PM
  • That does look a bit odd.  

    As a aside, I'd recommend using (Get-Date) instead of [DateTime]::Now.

    Granted they both return the same result, but if you use (Get-Date), it makes it much easier to test the script by using a proxy function for Get-Date that will return whatever arbitrary datetime you want.


    [string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "

    Sunday, August 17, 2014 12:23 PM
    Moderator
  • That does look a bit odd.  

    As a aside, I'd recommend using (Get-Date) instead of [DateTime]::Now.

    Granted they both return the same result, but if you use (Get-Date), it makes it much easier to test the script by using a proxy function for Get-Date that will return whatever arbitrary datetime you want.


    [string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "

    No- this is the broken web site.  When things are pasted lines can get duplicated.  This is how it was originally pasted:

    $file=Get-ChildItem -path \\test\testfiles\* -Include *.pdf |
        Sort LastWriteTime -desc |
        Select-Object -first 1
    
    if($file.LastWriteTime -lt ([DateTime]::Now.AddHours(-10))){
        # file older than 10
        $mailprops=@{
            SmtpServer='9.9.9.9'
            From='ELECTRONIC_FOLDER@jcc.com'
            To='jcc@jcc.com'
            Subject='Please check the Electronic Process'
    	}
        $body="This file was the last file to process: $($file.Fullname) at $($file.LastWriteTime)"
        Send-MailMessage @mailprops -Body $body
    }else{
        Write-Host 'No files' -ForegroundColor green
    }

    Well - it was a typo caused by copying the older edit then forgetting to recopy before pasting.

    The use of [datetime]::Now is correct and much easier to manage when adding hours.  It is also more explicit visually.  Using Get-Date and converting to a string is just counter-productive.

    This can all be done much easier but was posted this way to be more explicit.

    1) get newest file
    2) test against date

    Only two steps are needed.


    ¯\_(ツ)_/¯



    • Edited by jrv Sunday, August 17, 2014 1:23 PM
    Sunday, August 17, 2014 1:21 PM
  • If [datetime]::Now is "correct" and Get-Date is "wrong", when would Get-Date ever be "correct"?

    I don't understand the comment about converting to string.  Both [datetime]::Now and Get-Date are going to return a [datetime].  If the application requires conversion to [string] then it will have to be done in either case.


    [string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "

    Sunday, August 17, 2014 1:42 PM
    Moderator
  • If [datetime]::Now is "correct" and Get-Date is "wrong", when would Get-Date ever be "correct"?

    I don't understand the comment about converting to string.  Both [datetime]::Now and Get-Date are going to return a [datetime].  If the application requires conversion to [string] then it will have to be done in either case.


    [string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "

    Too many people type "Get-Date 'dd-MM-yyyy' and try to use it as a date object. 

    I never said it was wrong. I only posted that that I preferred [datetime] because it is more explicit,  reads better and is more flexible.  If you prefer Get-Date the use it.  I just don't understand what you have against [datetime]  It is a legitimate part of PowerShell and is a built-in accelerator because all descendants of "System" are immediately useful as it the were declared accelerators.

    [System.datetimne], [system.string], system.int32]

    All are available and intended for use.

    Note that what I said was that - and I quotes - "Using Get-Date and converting to a string is just counter-productive."  Other posts over the last week have used the conversion to string and then tried to do date arithmetic.  I was reacting to that recent experience.


    ¯\_(ツ)_/¯

    Sunday, August 17, 2014 2:07 PM
  • I prefer Get-Date, because I disagree with the assessment that [datatime]::Now is more flexible.

    If I write a script that does datetime calculations, and takes actions based on comparison of the current datetime to some external timestamp (like a file lastwritetime), or does something different based on the day of the month or week, and use Get-Date then I can test how that script will work on any given arbitrary date by using a proxy function in the session - e.g.

    function Get-Date {[datetime]'08/18/2014 01:00:00'}
    and then just run the script.  If I use [datetime]::Now then the only way to control with it returns is to change the system clock, which could have all kinds of unintended consequences outside of that session.


    [string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "


    Sunday, August 17, 2014 2:43 PM
    Moderator
  • I prefer Get-Date, because I disagree with the assessment that [datatime]::Now is more flexible.

    If I write a script that does datetime calculations, and takes actions based on comparison of the current datetime to some external timestamp (like a file lastwritetime), or does something different based on the day of the month or week, and use Get-Date then I can test how that script will work on any given arbitrary date by using a proxy function in the session - e.g.

    function Get-Date {[datetime]'08/18/2014 01:00:00'}
    and then just run the script.  If I use [datetime]::Now then the only way to control with it returns is to change the system clock, which could have all kinds of unintended consequences outside of that session.


    [string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "


    What?  I have no idea where that fits in:

    Get-Date is just a wrapper around [datetime]

    {[datetime]'08/18/2014 01:00:00'

    {[datetime]::Today

    ({[datetime]'08/18/2014 01:00:00').ToString('yyyy-dd-MM HH:mm')

    Whatever you need is there.  Ther ei s no reason to not use it and not reason to not use your preferences.  They are virtually identical.

    [datetime]|gm -static

    It is  mostly a matter of preference however I find that visually that [datetime] I smore explicit and more flexible.  If you don't, then don't use it.


    ¯\_(ツ)_/¯

    Sunday, August 17, 2014 2:58 PM
  • One more just for fun:

    $c=[cultureinfo]::CreateSpecificCulture('en-GB')
    [datetime]::Now.ToString($c)


    ¯\_(ツ)_/¯

    Sunday, August 17, 2014 3:04 PM
  • The point is that Get-Date is a cmdlet, and as such it can be overridden with a proxy function for testing.

    [datetime]::Now cannot, and using it costs you that option.


    [string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "

    Sunday, August 17, 2014 3:12 PM
    Moderator
  • I just use the debugger for that.  If that is what you need then there is nothing stopping you.  Mostly it is unnecessary for anything that I do just like it would be in C# or any compiled language. Use trace  or debug.

    Very few people use proxy functions in that way if at all.  In a more complex scrip that needs massive testing then I might agree but that assumes that the current time needs to be tested.


    ¯\_(ツ)_/¯

    Sunday, August 17, 2014 3:17 PM
  • Oh - and you can proxy net classes too. [datetime] can be easily proxyed.


    ¯\_(ツ)_/¯

    Sunday, August 17, 2014 3:18 PM
  • Can a dotnet class be proxied as easily as a cmdlet?

    Proxy functions for cmdlets are pretty standard fare.  I don't think I've ever seen an example of the code needed to proxy a dotnet class.


    [string](0..33|%{[char][int](46+("686552495351636652556262185355647068516270555358646562655775 0645570").substring(($_*2),2))})-replace " "


    Sunday, August 17, 2014 3:20 PM
    Moderator
  • Depends on you.  If you do not know the underlying classes and how to use a wrapper or how to create an accelerator then no.  Of course the OP here and most here qould not know what a proxy function is.

    Anyway this is way off the topic.  We can easily just replace the [datetime]::Now with Get-Date and it will still work.


    ¯\_(ツ)_/¯

    Sunday, August 17, 2014 3:25 PM