If-Else Logic Structure: Commands in statement not running.

Welcome Forums General PowerShell Q&A If-Else Logic Structure: Commands in statement not running.

This topic contains 12 replies, has 5 voices, and was last updated by

 
Participant
2 days, 13 hours ago.

  • Author
    Posts
  • #157587

    Participant
    Topics: 13
    Replies: 17
    Points: 31
    Rank: Member
    $i=0
    $subpaths=(Get-ChildItem -Path $PathToArchive -Directory -Recurse | Select-Object -ExpandProperty fullname)
    $subpaths | ForEach-Object -Process {
    $test1=(Get-ChildItem -Path $_ -File);
    $test2=(Get-ChildItem -Path $_ -Directory);
    if (!$test1.Exists -and !$test2.exists)
    {Write-Host "There are no files in $_ ,empty folder!."}
    elseif($test1.exists -and $test2){$i++; Write-Host "files and directories in $_ ", "File Block #$i";
    {foreach ($file in $test1)
    {if((Get-ItemProperty -Path $file.FullName).Attributes -band [io.fileattributes]::Archive)
    {Write-Host "Archive Bit Set"}
    else {Write-Host "Archive Bit Cleared"} }
    elseif($test2.exists){ Write-Host "Directories Only in $_"}
    else{$i++; Write-Host "Files only in $_", "File Block # $i"}
    }}}}}

    This block of code is part of an advanced function. The first section extracts all the directory folders in an archive structure and makes a list of those directory names. The foreach-object cmdlet steps through each directory checking for files. The if-else logic determines whether a directory contains only files, a mix of files and directories, only directories, or is empty. This logic works. What I want to do is then determine which of the located files have the archive bit set, once I know their parent directories. The second elseif test has several commands in its script block. Besides incrementing a counter, it writes a couple of messages to the console, then I want to continue with another set of commands to step through each file in that directory and identify those that are ready to archive. I use a foreach command with another if-else test. This logic also works by itself. However, when I run the whole block, the additional commands are ignored. Can one have several commands strung together in the script block after an if/else conditional test? Can I use a foreach statement after a foreach-object cmdlet? I've beat my head against the wall for almost a week. If this approach won't work, I can explain more fully what I'm trying to do so other ideas may come to light...Sorry the code didn't retain the layout in the ISE pane.

  • #157596

    Participant
    Topics: 8
    Replies: 371
    Points: 423
    Helping Hand
    Rank: Contributor

    Mismatched parentheses found. Try formatting like this:

    $i=0
    $subpaths=(Get-ChildItem -Path $PathToArchive -Directory -Recurse | Select-Object -ExpandProperty fullname)
    $subpaths | ForEach-Object -Process {
        $test1=(Get-ChildItem -Path $_ -File)
        $test2=(Get-ChildItem -Path $_ -Directory)
        if (!$test1.Exists -and !$test2.exists){
            Write-Host "There are no files in $_ ,empty folder!."
        } elseif ($test1.exists -and $test2) {
            $i++
            Write-Host "files and directories in $_ ", "File Block #$i"
            foreach ($file in $test1) { 
                if ((Get-ItemProperty -Path $file.FullName).Attributes -band [io.fileattributes]::Archive) {
                    Write-Host "Archive Bit Set"
                } else {
                    Write-Host "Archive Bit Cleared"
                } 
            }
        } elseif ($test2.exists) { 
            Write-Host "Directories Only in $_"
        } else {
            $i++
            Write-Host "Files only in $_", "File Block # $i"
        }
    }
    
    • #157770

      Participant
      Topics: 13
      Replies: 17
      Points: 31
      Rank: Member

      Mr.Sam! Fantastic! I was going nuts... I had one wrong parenthesis that was breaking the statement execution chain at the "foreach" statement, then another one extra after that code block. I was beginning to believe my messed up regions in the ISE were affecting the code execution..

      BTW, how do you get code from your ISE to replicate exactly in the posting? I tried cut and paste, but the formatting was lost.

    • #158346

      Participant
      Topics: 0
      Replies: 35
      Points: 354
      Helping Hand
      Rank: Contributor

      You'll want to surround your code with pre opening and closing tags. You can find the tag insert for pre in the wysigyg-editor when you're writing your post.

      So like this:

      Code goes here
          indented code works too
      
  • #157653
    js

    Participant
    Topics: 22
    Replies: 613
    Points: 1,257
    Helping Hand
    Rank: Community Hero

    This would never happen in a python forum.

  • #157806

    Participant
    Topics: 8
    Replies: 371
    Points: 423
    Helping Hand
    Rank: Contributor

    When posting code, click the "text" tab (not the default "visual" tab) in the top right corner of this WYSIWYG editor to preserve formatting inside pre/pre tags..

  • #157853

    Participant
    Topics: 13
    Replies: 17
    Points: 31
    Rank: Member

    I'll do that.. Thanks. I know I got it right a few years ago before the Powershell website was upgraded...

    Thought that was the problem.

    On to the project finish!

     

  • #158330

    Participant
    Topics: 13
    Replies: 17
    Points: 31
    Rank: Member
        $i=0
        $subpaths=(Get-ChildItem -Path $PathToArchive -Directory -Recurse | Select-Object -ExpandProperty fullname)
            $subpaths | ForEach-Object -Process {
            $test1=(Get-ChildItem -Path $_ -File);
            $test2=(Get-ChildItem -Path $_ -Directory);
                if (!$test1.Exists -and !$test2.exists){
                     Write-Host "There are no files or directories in $_ ,empty folder!."
               } elseif($test1.exists -and $test2){
                     $i++
                     Write-Host  "files AND directories in $_ ", "File Block #$i" 
                        foreach ($file in $test1){
                             if((Get-ItemProperty -Path $file.FullName).Attributes -band [io.fileattributes]::Archive -and (Get-ItemProperty -Path $file.FullName -Exclude *partial*))
                                 { $hash=[ordered]@{
                                     'File Name'=($file).basename;
                                     'File Type'=($file).Extension;
                                     'File Size (KB)'=($file).Length/1e3 -as [int];
                                     'Date Created'=($file).LastWriteTime};
                                     Write-Host "Files Ready to Archive"
                                  $glub=New-Object -TypeName Psobject -Property $hash
                                  # New-Variable -Name Frag$i -Value glub}
                                                                                                                                                                                                                                                                  
                           } else {Write-Host "File Not Ready to Archive"}
                     }                                                                                                        
               } elseif($test2.exists){
                     Write-Host "Directories only in $_"
               } else{
                    $i++
                    Write-Host "Files only in $_", "File Block # $i"
                         foreach ($file in $test1){
                             if((Get-ItemProperty -Path $file.FullName).Attributes -band [io.fileattributes]::Archive -and (Get-ItemProperty -Path $file.FullName -Exclude *partial*))
                                {$hash1=[ordered]@{
                                     'File Name'=($file).BaseName;
                                     'File Type'=($file).extension;
                                     'File Size (KB)'=($file).length/1e3 -as [int];
                                     'Date Created'=($file).LastWriteTime};
                                     Write-Host "Archive Bit Set"
                                     #$glop=New-Object -TypeName Psobject -Property $hash1}
                                     
                                    # New-Variable -Name frag$i -Value glop}
                                                                  
                            } else {Write-Host "Archive Bit Cleared"}
                             }}}
                             #$glub=New-Object -TypeName Psobject -Property $hash;
                             $glop=New-Object -TypeName psobject -Property $hash1;
    
                             Write-Host $glub
                             Write-Host $glop
                             }}
    
    
    

    Ok, Another hangup. This code works and produces the following result when applies against a "test archive" on my computer:

    PS C:\> make-NewTOC52
    cmdlet make-NewTOC52 at command pipeline position 1
    Supply values for the following parameters:
    PathToArchive: C:\Users\Peter\Documents\Test_Archive\Fish
    Files only in C:\Users\Peter\Documents\Test_Archive\Fish\Carp File Block # 1
    Archive Bit Cleared
    Archive Bit Set
    Files only in C:\Users\Peter\Documents\Test_Archive\Fish\Salmon File Block # 2
    Archive Bit Set
    Archive Bit Set
    Archive Bit Cleared
    Archive Bit Set
    Archive Bit Set
    files AND directories in C:\Users\Peter\Documents\Test_Archive\Fish\Trout File Block #3
    File Not Ready to Archive
    Files Ready to Archive
    Files only in C:\Users\Peter\Documents\Test_Archive\Fish\Trout\goldfish File Block # 4
    Archive Bit Set
    @{File Name=test_Adhesive webinar; File Type=.pdf; File Size (KB)=764; Date Created=3/27/2014 11:03:29 AM}
    @{File Name=AC Power Problems; File Type=.PDF; File Size (KB)=753; Date Created=9/3/2015 9:36:26 AM}

    The directories are first extracted and stored as a string in variable $subpaths. Then each directory is examined (using the foreach-object cmdlet) to see if it contains files, directories, both or neither (empty folder.) Within this if logic I further check for files that have the archive bit set. The code finds these files and writes the appropriate messages. I am also counting each "file block" as I go. The last two line are the PSobjects $glop and $glub. These are the last two files in the archive. What I want is for these files to be collected into a single object per the hash table. That is not happening; the values appear to be only the very last files handled.

    Now if I remove the remarks to include the two "new-variable statements, I get these output error messages:

    New-Variable : A variable with name 'frag2' already exists.
    At C:\Users\Peter\Documents\Powershell_Scripts\EnhancedHTML2\2.1\new TOC.ps1:87 char:34
    + ... New-Variable -Name frag$i -Value glop
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : ResourceExists: (frag2:String) [New-Variable], SessionStateException
    + FullyQualifiedErrorId : VariableAlreadyExists,Microsoft.PowerShell.Commands.NewVariableCommand

    This indicates once again that instead of creating a single object with all the selected files in it, that is not happening. What am I doing wrong with my hash tables? Thanks

  • #158337

    Participant
    Topics: 8
    Replies: 371
    Points: 423
    Helping Hand
    Rank: Contributor

    Let's step back a little bit and explain what exactly is the purpose of the script. Exactly what is it that it's trying to do?
    Not the line by line details, but the functional purpose.

  • #158381

    Participant
    Topics: 13
    Replies: 17
    Points: 31
    Rank: Member

    That would probably be a good idea. Here goes. I had built a module that allows me to copy files that have their archive bit set to a storage medium. Now imagine a directory on your computer for, say, credit card statements. You either scan or download a year's worth of statements and save them as a single file (pdf, by necessity). At the end of the year you wish to archive them, and recover the space on your hard drive so it doesn't get filled up. BUT, you need to retain the CC Statement directory for new statements. The module I coded allowed me to not only copy such files, but to also clear their archive bit and then delete them. I also needed to create a Table of Contents to go with the storage medium. Here's the information I wanted in the TOC: 1) Path to directory holding the file(s); 2)File name; 3)File type (extension); 4)file size in KB; 5)Date created. I coded two cmdlets that did this, but they both have some shortcomings. One works fine where everything of interest is in a single folder. The files are listed alphabetically. In this case, the cmdlet doesn't show the directory path, which would be repeated for every file... superfluous information. If you know where the folder lives on the hard drive, and what its name is, that's fine. The second cmdlet does show the directory path – for every file – and while the folder names provide important context to the file names (Think how many files begin with "miscellaneous."), it's still a lot of extra information.

    Now enter Don Jones, and his two ConvertTo-EnhancedHTML cmdlets. I bought his book "Creating HTML Reports in Powershell" and it appeared that there might be a solution to my problem. However, I also realized I didn't know anything about HTML so I signed up for a course with Edx University on HTML and CSS. That has turned out to be very useful.

    In his book, Jones poses a problem: how can one collect different types of information about a computer and present it all in one single HTML document which can then be viewed in any browser? The native ConvertTo-HTML cmdlets can generate HTML for each extracted hunk of computer info, but can't combine them into a single HTML file. (BTW, his new cmdlets also include JavaScript for interactive HTML features.)

    It became evident I could concoct a Table of Contents that not only wasn't overrun with extra "directory path" information, but also included borders, color, different font sizes and formats, etc. Something that would be more suitable for general consumption. (Think the wife..) I don't need any JavaScript.

    So back to my current cmdlet project... Instead of just collecting all files recursively from my archive for copying I now need to disassemble the folder/file tree structure so I can retain the parent directories for each block of files. I'm no longer interested in the files themselves, just the five pieces of information enumerated above. So the first chore is to get all the directories in the archive. Then go to each directory one at a time to see what's inside. The If logic does that. Once a folder with archive-able files is located, I then need to sort those files by name and extension, select the last four pieces of information (name,type,size,date), stuff that into a single PSobject, and feed that to the -EnhancedHTMLFragment cmdlet. The fragment cmdlet produces a bunch of HTML, but not an entire document ready for a web page. One of the parameters for this fragment cmdlet should allow me to include a header that has the current directory path. So the table of info would have the four columns of info under the header directory.. All good so far. Once each batch of files is created by feeding them to the -enhancedHTMLfragment cmdlet, it's time to combine them all using the ConvertTo-enhancedHTML cmdlet. At the bottom of my "Make-NewTOC function, this would be the last line of code. One of the parameter inputs to this last cmdlet is a list of HTML Fragments. As you can imagine, these fragment names must be unique. This is the reason for the $i variable, and it does count the "file blocks." The new-variable cmdlet allows me to create unique fragment names. I'm hoping I can easily figure out how to pass all the fragmenst to the final -enhancedHTML command, if I don't know how many I have, but they still all have unique names...
    So that's where things stand. As I've said bits of code do work, and when I get the new function up and running, I can then play with the CSS (Cascading Style Sheet) and pretty the report up...

    • #158636

      Participant
      Topics: 1
      Replies: 21
      Points: 110
      Helping Hand
      Rank: Participant

      So, you want to end up with a table showing columns for each of your object properties (File Name, File Type, File Size, Date Created). I think your hash table is fine. The part you're missing is that each time you store those values for your object "glop", you overwrite the previous values for "glop", which is why at the end the only values are those from the last file handled. What you need to do is collect the objects into an ArrayList as they are created.

      Before you create any of the objects, make the storage array:

      $gloplist = New-Object System.Collections.ArrayList

      And then after each "$glop=..."

      $gloplist.Add($glop) | Out-Null

      Now when you echo $gloplist you should see a line for each file that was handled. $glop essentially works as a temporary object holder for each time a new file is handled. Out-Null just prevents PowerShell from printing the array to the screen every time a new object is added.

  • #159344

    Participant
    Topics: 13
    Replies: 17
    Points: 31
    Rank: Member
    $direc = (Get-ChildItem -Path C:\Users\Peter\Documents\Test_Archive\Dog\Terrier -File)
        $globlist=New-Object -TypeName System.Collections.ArrayList
        foreach($file in $direc){
            if((Get-ItemProperty -Path $file.FullName).Attributes -band [io.fileattributes]::archive -and (Get-ItemProperty -Path $file.FullName -Exclude *partial*))
            {$hash=[ordered]@{'Directory'=($file).Directory
                        'File Name'=($file).basename
                        'File Type'=($file).Extension
                        'File Size (KB)'=($file).Length/1e3 -as [int]
                        'Date Created'=($file).LastWriteTime}
               
                 $glob=New-Object -TypeName psobject -Property $hash
                 $globlist.Add($glob) 
                 Write-Output $glob}}
    

    Grokkit: I never realized how many typenames there were for New-Objects. This block of test code works in the ISE, and I can verify there are 9 objects in the $globlist array. I can also do a $_.gettype() on both the array and the PSobject and see they are either a PSCustomObject or an ArrayList. However, in the function I'm trying to build, the code doesn't work right. It seems the array is not being created, or is not being loaded with objects..

    Here is the main code section:

        $i=0
        $subpaths=(Get-ChildItem -Path $PathToArchive -Directory -Recurse | Select-Object -ExpandProperty fullname)
            $subpaths | ForEach-Object -Process {
            $test1=(Get-ChildItem -Path $_ -File);
            $test2=(Get-ChildItem -Path $_ -Directory);
                if (!$test1.Exists -and !$test2.exists){
                     Write-Host "There are no files or directories in $_ ,empty folder!."
               } elseif($test1.exists -and $test2.Exists){
                     $i++;
                     $glublist=New-Object -TypeName System.Collections.ArrayList;
                     Write-Host  "files AND directories in $_ ", "File Block #$i" 
                        foreach ($file in $test1){
                             if((Get-ItemProperty -Path $file.FullName).Attributes -band [io.fileattributes]::Archive -and (Get-ItemProperty -Path $file.FullName -Exclude *partial*))
                                  {$hash=[ordered]@{
                                     'File Name'=($file).basename;
                                     'File Type'=($file).Extension;
                                     'File Size (KB)'=($file).Length/1e3 -as [int];
                                     'Date Created'=($file).LastWriteTime};
                                  $glub=New-Object -TypeName Psobject -Property $hash;
                                  $glublist.add($glub);
                                  Write-Host "File Ready to Archive";
                                  Write-Host "Current state of $Glub";
                                  Write-Host "Here's the count: '$glublist.count'"; 
                                  #New-Variable -Name Frag$i -Value glublist
                                                                                                                                                                                                                                                                  
                           } else {Write-Host "File Not Ready to Archive"}
                           }                                                                                                        
               } elseif($test2.exists){
                     Write-Host "Directories only in $_"
               } else{
                    $i++;
    
                    Write-Host "Files only in $_", "File Block # $i"
                         foreach ($file in $test1){
                             if((Get-ItemProperty -Path $file.FullName).Attributes -band [io.fileattributes]::Archive -and (Get-ItemProperty -Path $file.FullName -Exclude *partial*))
                                {$hash1=[ordered]@{
                                     'File Name'=($file).BaseName;
                                     'File Type'=($file).extension;
                                     'File Size (KB)'=($file).length/1e3 -as [int];
                                     'Date Created'=($file).LastWriteTime};
                                     Write-Host "Archive Bit Set";
                                     $gloplist=New-Object -TypeName System.Collections.ArrayList
                                     $glop=New-Object -TypeName Psobject -Property $hash1;
                                     $gloplist.add($glop);
                                     Write-Host "Current state of $glop";
                                     Write-Host "This is the state of $gloplist"   
                                    # New-Variable -Name Crag$i -Value gloplist                                                              
                            } else {Write-Host "Archive Bit Cleared"}
                            }
    

    Can you see any obvious problem?

  • #161040

    Participant
    Topics: 1
    Replies: 21
    Points: 110
    Helping Hand
    Rank: Participant

    One obvious problem is that your $gloplist New-Object (line 42) is inside your foreach loop, which will result in $gloplist being created again each time the loop iterates. You should move this line outside the foreach loop. Does $glublist (line 10) work as expected?

You must be logged in to reply to this topic.