Function not going to completion

This topic contains 4 replies, has 3 voices, and was last updated by Profile photo of Jack Neff Jack Neff 3 months, 3 weeks ago.

Viewing 5 posts - 1 through 5 (of 5 total)
  • Author
    Posts
  • #41717
    Profile photo of Peter Marsh
    Peter Marsh
    Participant

    Boy, this time I'm really stumped. I am building an advanced function that will go through an archive folder tree and extract every file that has the archive bit set, then write them to output for inspection (and table of contents). This is only the first of four functions I need to build: the next three are a conditional copy for only files ready to archive, then one to clear the archive bit in all files, and last a function to report the total file count and size in GB so I know when it's time to do the copy to a DVD. I am very close to success, and I have made the core code work for three of these functions. However, all attempts to get an advanced function to perform correctly have been in vain. I have tried everything I can think of, but I'm probably missing something very simple.
    Here is thee main code for my "Get-FilesReadyToArchive"

     Get-childItem -Path C:\users\peter\Documents\TestArchive -Recurse | where-Object -Property Attributes -EQ archive | Select-Object @{name='File Name';expression={$_.name}},`
    @{name='File Size (KB)';expression={$_.length/1e3}}, @{name='Parent Directory';expression={$_.directoryname}} 

    This works:

     PS C:\> Get-childItem -Path C:\users\peter\Documents\TestArchive -Recurse | where-Object -Property Attributes -EQ archive | Select-Object @{name='File Name';expression={$_.name}},`
    @{name='File Size (KB)';expression={$_.length/1e3}}, @{name='Parent Directory';expression={$_.directoryname}} 
    
    File Name                                                                            File Size (KB) Parent Directory                                           
    ———                                                                                  ————– —————-                                           
    test_Alyeska pay stubs 2001 (2).TIF                                     1148.51 C:\users\peter\Documents\TestArchive\Bird\Owl              
    test_Income Tax Returns -1995; Jason and Jessica.PDF      253.405 C:\users\peter\Documents\TestArchive\Dog\Terrier           
    test_Akro Mills catalog.pdf                                                18832.799 C:\users\peter\Documents\TestArchive \Fish\Trout    
    

    Now here is the full script, that just runs with no output:

     
    function Get-FilesReadyToArchive
    {
        [CmdletBinding()]
        Param
        (
            # Determine path to head directory of archive tree
            [Parameter(Mandatory=$true, 
                       ValueFromPipeline=$true,
                       ValueFromPipelineByPropertyName=$true)] 
            [string]$Path
        )
    
        Begin
        {$AFiles=Get-ChildItem -Path $Path -Recurse
        }
        Process{ foreach($file in $AFiles){ $file | 
                  Where-Object -Property attributes -EQ archive | Select-Object
                 @{name='File Name';expression={$_.name}},
                 @{name='File Size (KB)';expression={$_.length/1e3}},
                 @{name='Parent Directory';expression={$_.directoryname}} | Out-GridView
                 
            }
            }    
        End {
            }
    

    This iteration shows a "Foreach" cmdlet. I have tried putting the "Child-Item" cmdlet in the process block, using no "foreach" command, adding explicit write-out commands at the end of the pipeline, and just about everything else. I've found lots of mistakes I've been making, but this one has me stumped.... Peter

    #41726
    Profile photo of Jack Neff
    Jack Neff
    Participant

    Your posted code is missing a closing curly brace to end the function block.

    When you say "just runs with no output" how are you running this? Pressing play or F5 in ISE? If so, you would only be loading the function into memory, you're not actually executing the function. In the command line section of ISE type the name of your function and give it a Path and stuff will come out (assuming the path isn't empty).

    After adding the curly brace and loading it to memory, I ran it on a folder that had 10 files inside and 10 grids popped up. Expected output based on what I see. Keep in mind the Process block will iterate for each $Path you pass to your advanced function.

    Also, if you don't need the Begin or End blocks, don't add them. Your function will still work.

    #41728
    Profile photo of random commandline
    random commandline
    Participant

    You need to move a property to the right of Select-Object cmdlet. Without it, Out-Gridview will not display your values. Also, your function is missing a closing curly brace.

    $file | 
                  Where-Object -Property attributes -EQ archive | 
                  Select-Object @{name='File Name';expression={$_.name}},
                 @{name='File Size (KB)';expression={$_.length/1e3}},
                 @{name='Parent Directory';expression={$_.directoryname}} | Out-GridView
    
    #41946
    Profile photo of Peter Marsh
    Peter Marsh
    Participant

    Gentlemen: Thanks for your input. I did have a closing curly brace – just missed in when I cut & pasted. And I was using the F5 function in the ISE to run the code, then typing the function name at the prompt in the PS panel. But I believe I have discovered the problem! While trying different versions of code, I had saved the first version of the script as ..ver2 so I could refer back to see what I had already tried. Then in ..ver2 I would try different techniques to get the working code to perform in the function. Well I shot myself in the foot. I had two different scripts with the same function name: Get-FilesReadyToArchive. It's no wonder the Powershell engine was confused, and just kept churning.

    I have made many modifications to the code, which now works:

    function Get-FilesReadyToArchive
    {
        [CmdletBinding()]
        Param
        (
            # Determine path to head directory of archive tree
            [Parameter(Mandatory=$true, 
                       ValueFromPipeline=$true,
                       ValueFromPipelineByPropertyName=$true)] 
            [string]$Path
        )
    
        Begin
        {
        }
        Process{$AFiles=Get-ChildItem -Path $Path -Recurse
        
        foreach($file in $Afiles){
            if((Get-ItemProperty -Path $file.FullName).Attributes -band [io.fileattributes]::archive)
            {$hash=[ordered]@{'File Name'=($file).name
                        'File Size (KB)'=($file).Length/1e3
                        'Last Write Time'=($file).LastWriteTime
                        'Parent Directory'=($file).DirectoryName}
               
                 $glob=New-Object -TypeName PSObject -Property $hash
                  Write-Output $glob}
                 
            }
    }}
    >/pre>
        
    I still use the "get-childitem" cmdlet with a "foreach" statement, but the original "where-object" cmdlet was not reporting files that were BOTH archive and readonly. So I borrowed an idea from the Scripting Guy (Jan27th,2011) and used "get-itemproperty" with an if construct which returns every file that has the archive bit set. Thanks for the help..
    #41958
    Profile photo of Jack Neff
    Jack Neff
    Participant

    Well done! Thanks for following up and posting the final code.

Viewing 5 posts - 1 through 5 (of 5 total)

You must be logged in to reply to this topic.