Author Posts

April 17, 2016 at 2:20 am

Hi Folks,

I've stuck on a section of a script I am creating.

Here is a simplified version of the problem I am hitting. I wish to run the command for a duration of a minute with a 10 second interval between each iteration.

$timeout = New-TimeSpan -Minutes 1
$stopwatch = [diagnostics.stopwatch]::StartNew()

While  ($stopwatch.elapsed -lt $timeout) {Get-ChildItem | ForEach-Object {
        [PSCustomObject] @{
            'Name'= $_.Name
            'Timestamp'= (get-date).ToLongTimeString()
            'Type'= $_.Attributes
            } 
         }         
    Start-Sleep -Seconds 10          
} 

The issue I have is there is a 10 second sleep anything is returned. Then I get the output from two iterations at once.

Name                Timestamp      Type
----                ---------      ----
DNS Lookup          11:18:16  Directory
iplookup.ps1        11:18:16    Archive
networkcommands.txt 11:18:16    Archive
pingAllDCs.ps1      11:18:16    Archive
wifiChannel.ps1     11:18:16    Archive
DNS Lookup          11:18:26  Directory
iplookup.ps1        11:18:26    Archive
networkcommands.txt 11:18:26    Archive
pingAllDCs.ps1      11:18:26    Archive

I'd like the first iteration to output straightaway. I tried a Do . . While loop but that behaved the same.

I next tried changing the flow by putting the execution code in a function. This did not work.

Function TestCode{
    Get-ChildItem | ForEach-Object {
            [PSCustomObject] @{
                'Name'= $_.Name
                'Timestamp'= (get-date).ToLongTimeString()
                'Type'= $_.Attributes
                } 
    }
}

$timeout = New-TimeSpan -Minutes 1
$stopwatch = [diagnostics.stopwatch]::StartNew()
testcode

While  ($stopwatch.elapsed -lt $timeout) {      
    Start-Sleep -Seconds 10
    testcode          
} 

Moving Start-Sleep -Seconds 10 outside the While loops above is no use either as it's ignored and the loop continiously cycles

Thanks,

Michael

April 17, 2016 at 3:15 am

Are you having the same problem with your simplified example?

I copied and pasted it into the ISE and it worked as expected; it output the directory contents immediately, followed by a 10 second delay, then output the contents again.

April 17, 2016 at 3:43 am

Hi Matt,

Yes I have the problem with my simplified script (both samples) in the ISE/WMF 5.0 on Windows 10.

After your post I went on to my AWS server and the code ran fine. I thought it was a problem with my logic and it didn't dawn on me to check enviromentals.

I've a little bit of profile customisation on my Windows 10 box nothing major but I'll need to eliminate that.

Thanks for testing.

Regards,

Michael

April 17, 2016 at 5:04 am

Just fired up the Windows 10 laptop and I can replicate the behaviour (I previously tested on Win8.1 with PS v4.0).

The problem appears to be something to do with the object creation (or the output of the object) rather than the sleep. If you don't create an object and just do Write-Output $_.Name it works as expected. I have tried other methods of creating the object and they don't get output until after the second iteration.

April 17, 2016 at 7:17 am

Yes I think you're right.

My guess is that the Custom Object object isn't fully initialized and the script moves on.

If I slow it down (even by 1 millisecond) it works fine.

$timeout = New-TimeSpan -Minutes 1
$stopwatch = [diagnostics.stopwatch]::StartNew()

While  ($stopwatch.elapsed -lt $timeout) {Get-ChildItem | ForEach-Object {
        [PSCustomObject] @{
            'Name'= $_.Name
            'Timestamp'= (get-date).ToLongTimeString()
            'Type'= $_.Attributes
            } 
            Start-Sleep -milliseconds 1 # Take a breather!
         }         
    Start-Sleep -Seconds 10       
}