none
Getting Powershell to count records... RRS feed

  • Question

  • OK, I'm a VBScript kind of guy, and Powershell is neither intuitive nor straightforward.  The power is undeniable, so, I must reluctantly start using it.

    I need to create a "pretty" report based on Powershell's returned info from WMI and registry queries of a remote target.

    Lets take a solitary example, if you can help with this, I can most likely figure out the rest of the queries:

    gci -Path C:\ -r -force -ea 0 -include *.exe,*.pif,*.scr | Where-Object {-not $_.PSIsContainer -and $_.lastwritetime -gt ((Get-Date).addDays(-7)) } | select name,fullname,lastwritetime,@{N='Owner';E={($_ | Get-ACL).Owner}} | sort lastwritetime -desc | Format-List >> TargLog.txt

    As you can see, I'm placing the result as appended data to a log already in progress.  The "problem" here is there are in fact no .exe, .pif, or .scr on my test machine that have been modified in the last 7 days.  Meaning, I'd like to KNOW that and append "No Records Found", or, if records are found (and I can get a count of how many) I can format a table in Word using VBScript (or VBA) to accomodate the count and make each query nice and tidy in the finalized report.

    So, the Powershell makes a bunch of queries, appends the results to a log, VBScript will be used to pull that log apart and format it for Word, and just before closing I'll ask Word to output as .pdf.  The only thing I'm missing is a means of knowing how many records Powershell returned for a given query.

    Any help?

    Wednesday, January 14, 2015 3:53 PM

Answers

  • OK, I got something, but nothing I wanted.

    <snip>

    Here you can see the approach I'm using, I "head" each block (seperate query type) with a title framed by two asterisks each side, the premise being the VBScript post processor will recognise the framing and created a header.  But, since i can' read Katana (or whatever that is, lol) it's really broken now.

    I should note **Executables --Last Seven Days** is the header for the command you've been helping with, the other is a user query I decided to try to, using your code as a guide.

    Lost?  Yep, that'd be me.

    You can change the encoding Add-Content will use with the -Encoding parameter:

    http://ss64.com/ps/add-content.html

    PowerShell loves Unicode output.


    Don't retire TechNet! - (Don't give up yet - 13,085+ strong and growing)

    Wednesday, January 14, 2015 5:27 PM

All replies

  • Save your results in a variable (before piping to any format cmdlets) and check the count property.


    EDIT: As an example:

    $a = Get-ChildItem -Path 'C:\Scripts\PowerShell Scripts' -Include *.ps1 -Recurse
    $a.Count
    
    Output:
    299


    Don't retire TechNet! - (Don't give up yet - 13,085+ strong and growing)

    Wednesday, January 14, 2015 3:59 PM
  • Consider me extremely slow, can you give me an example based on the query I posted?

    I just don't "get" where I can place a counter.

    Thanks

    Wednesday, January 14, 2015 4:02 PM
  • PowerShell can measure output objects by piping to Measure-Object, which returns a measurement object (contains Count, Sum, Average, and some other properties). If the Count property is zero, then naturally there was no output.


    -- Bill Stewart [Bill_Stewart]

    Wednesday, January 14, 2015 4:04 PM
    Moderator
  • Consider me extremely slow, can you give me an example based on the query I posted?

    I just don't "get" where I can place a counter.

    Thanks

    I added an edit to my initial post to show an example. Here's the same idea, but filtering out older results:

    $a = Get-ChildItem -Path 'C:\Scripts\PowerShell Scripts' -Include *.ps1 -Recurse |
        Where { $_.LastWriteTime -gt (Get-Date).AddDays(-30) }
    $a.Count
    
    Output:
    3


    Don't retire TechNet! - (Don't give up yet - 13,085+ strong and growing)

    Wednesday, January 14, 2015 4:07 PM
  • I tried:

    $a gci -Path C:\ -r -force -ea 0 -include *.exe,*.pif,*.scr | Where-Object {-not $_.PSIsContainer -and $_.lastwritetime -gt ((Get-Date).addDays(-7)) } | select name,fullname,lastwritetime,@{N='Owner';E={($_ | Get-ACL).Owner}} | sort lastwritetime -desc | Format-List >> TargLog.txt
    $a.Count >>TargLog.txt

    No count displayed.

    Wednesday, January 14, 2015 4:27 PM
  • I tried:

    $a gci -Path C:\ -r -force -ea 0 -include *.exe,*.pif,*.scr | Where-Object {-not $_.PSIsContainer -and $_.lastwritetime -gt ((Get-Date).addDays(-7)) } | select name,fullname,lastwritetime,@{N='Owner';E={($_ | Get-ACL).Owner}} | sort lastwritetime -desc | Format-List >> TargLog.txt
    $a.Count >>TargLog.txt

    No count displayed.


    Do not pipe through Format-List. You're also missing the =.


    EDIT: Clarification:

    $a = Get-ChildItem -Path C:\ -Recurse -Force -ErrorAction SilentlyContinue -Include *.exe,*.pif,*.scr | 
        Where-Object {-not $_.PSIsContainer -and $_.LastWriteTime -gt ((Get-Date).addDays(-7)) } | 
            Select Name,FullName,LastWriteTime,@{N='Owner';E={($_ | Get-ACL).Owner}} | 
                Sort LastWriteTime -Descending
    
    $a | Format-List | Add-Content .\TargLog.txt
    $a.Count | Add-Content .\TargLog.txt


    EDIT2: Also, what version of PowerShell are you running? If anything less than v3, I highly recommend updating.

    Don't retire TechNet! - (Don't give up yet - 13,085+ strong and growing)

    Wednesday, January 14, 2015 4:29 PM
  • Sorry, I do have the a$ = in the real code.

    I'm just a dummy with this stuff, even the various flavors of C read like plain english to me compare to Powershell.  I'm lost.

    Wednesday, January 14, 2015 4:34 PM
  • With custom selecter:

    $a = Get-ChildItem -Path 'C:\Scripts\PowerShell Scripts\*' -Include *.ps1 -Recurse |
                Where { $_.LastWriteTime -gt [datetime]::ToDay.AddDays(-30) }
    if($a){
         $a | 
             select name,
                          fullname,
                         lastwritetime,
                        @{N='Owner';E={($_ | Get-ACL).Owner}}  | 
             sort lastwritetime -desc | 
             Format-List >> TargLog.txt
    }else{
         'no files found' >> TargLog.txt
    }


    ¯\_(ツ)_/¯




    • Edited by jrv Wednesday, January 14, 2015 5:09 PM
    Wednesday, January 14, 2015 4:36 PM
  • Sorry, I do have the a$ = in the real code.

    I'm just a dummy with this stuff, even the various flavors of C read like plain english to me compare to Powershell.  I'm lost.

    You'll get the hang of it in time, no worries.

    Have you seen this yet?

    http://technet.microsoft.com/en-us/library/ee221101.aspx

    This was a huge help for me when I started with PowerShell, since I came from a VBScript background as well.


    Don't retire TechNet! - (Don't give up yet - 13,085+ strong and growing)

    Wednesday, January 14, 2015 4:36 PM
  • Sorry, I do have the a$ = in the real code.

    I'm just a dummy with this stuff, even the various flavors of C read like plain english to me compare to Powershell.  I'm lost.

    PowerShell is structured just like 'C' (C#' and uses modern C++ and C# Net techniques wrapped in an interactive parser.  Anyone who understand C and CLI tools should be able to pick it up quickly.

    A tutorial or book is a good bootstrap even for seasoned programmers.

    (I should also note that it borrows form 'nix shells and other scripting languages.)


    ¯\_(ツ)_/¯


    • Edited by jrv Wednesday, January 14, 2015 4:39 PM
    Wednesday, January 14, 2015 4:38 PM
  • Sorry, I do have the a$ = in the real code.

    I'm just a dummy with this stuff, even the various flavors of C read like plain english to me compare to Powershell.  I'm lost.

    You'll get the hang of it in time, no worries.

    Have you seen this yet?

    http://technet.microsoft.com/en-us/library/ee221101.aspx

    This was a huge help for me when I started with PowerShell, since I came from a VBScript background as well.


    Don't retire TechNet! - (Don't give up yet - 13,085+ strong and growing)

    I am opposed to that article because it culture many bad habits. It is a useful mapping but don't buy into it structurally.  Look at modern PowerShell syntax examples and learn to not think procedurally.

    Luck and happy scripting.


    ¯\_(ツ)_/¯

    Wednesday, January 14, 2015 4:41 PM
  • I'm on version 2 0 -1 -1, and in a forest of 90,000+ machines, I'm not in control of what version I can run, nor the people that will ultimately be running the reporting tool.

    And the last code you posted (thanks for using my original code, that helps) I STILL get nothing recorded, i.e., I expected "0", but there is nothing being output.

    I guess I should have stayed with VBScript, it might have ended up being thousand of lines, but at least I wouldn't be clueless.

    Wednesday, January 14, 2015 4:59 PM
  • I'm on version 2 0 -1 -1, and in a forest of 90,000+ machines, I'm not in control of what version I can run, nor the people that will ultimately be running the reporting tool.

    And the last code you posted (thanks for using my original code, that helps) I STILL get nothing recorded, i.e., I expected "0", but there is nothing being output.

    I guess I should have stayed with VBScript, it might have ended up being thousand of lines, but at least I wouldn't be clueless.

    No, you're just running into a quirk of v2. Since nothing is returned, $a has no count property. They've adjusted this behavior in v3+. Try this:

    $a = Get-ChildItem -Path C:\ -Recurse -Force -ErrorAction SilentlyContinue -Include *.exe,*.pif,*.scr | 
        Where-Object {-not $_.PSIsContainer -and $_.LastWriteTime -gt ((Get-Date).addDays(-7)) } | 
            Select Name,FullName,LastWriteTime,@{N='Owner';E={($_ | Get-ACL).Owner}} | 
                Sort LastWriteTime -Descending
    
    If ($a) {
    
        $a | Format-List | Add-Content .\TargLog.txt
        $a.Count | Add-Content .\TargLog.txt
    
    } Else {
        
        'No results' | Add-Content .\TargLog.txt
    
    }

    Since you're stuck on v2, this resource should help you:

    http://ss64.com/ps/

    They stick to v2 commands, so people like you and me who are stuck in a v2 environment still have a cmdlet listing available.


    Don't retire TechNet! - (Don't give up yet - 13,085+ strong and growing)

    Wednesday, January 14, 2015 5:04 PM
  • the reason you are getting nothing iis simple.  Your original code has a big error and you are hidung it:

     Get-ChildItem -Path 'C:\Scripts\PowerShell Scripts'

    This needs to be:

     Get-ChildItem -Path 'C:\Scripts\PowerShell Scripts'\*'

    Without the wildcard the include will not work.

    Start by running this to see that files are found:

    Get-ChildItem -Path 'C:\Scripts\PowerShell Scripts\*' -Include *.ps1 -Recurse |
               
    Where {$_.PsIsContainer -eq $false -and $_.LastWriteTime -gt [datetime]::ToDay.AddDays(-30) }


    ¯\_(ツ)_/¯

    Wednesday, January 14, 2015 5:06 PM
  • the reason you are getting nothing iis simple.  Your original code has a big error and you are hidung it:

     Get-ChildItem -Path 'C:\Scripts\PowerShell Scripts'

    This needs to be:

     Get-ChildItem -Path 'C:\Scripts\PowerShell Scripts'\*'

    Without the wildcard the include will not work.

    Start by running this to see that files are found:

    Get-ChildItem -Path 'C:\Scripts\PowerShell Scripts\*' -Include *.ps1 -Recurse |
               
    Where {$_.PsIsContainer -eq $false -and $_.LastWriteTime -gt [datetime]::ToDay.AddDays(-30) }


    ¯\_(ツ)_/¯


    PS C:\> (Get-ChildItem -Path 'C:\Scripts\PowerShell Scripts' -Recurse -Include *.ps1).Count
    299
    
    PS C:\> (Get-ChildItem -Path 'C:\Scripts\PowerShell Scripts\*' -Recurse -Include *.ps1).Count
    299


    Don't retire TechNet! - (Don't give up yet - 13,085+ strong and growing)

    Wednesday, January 14, 2015 5:08 PM
  • This works perfectly on my system:

    $path='C:\Scripts\PowerShell Scripts\*'
    $a = Get-ChildItem $path -Include *.ps1 -Recurse |
                Where { $_.LastWriteTime -gt [datetime]::ToDay.AddDays(-30) }
    if($a){
         $a | 
             select name,
                          fullname,
                         lastwritetime,
                        @{N='Owner';E={$_.GetAccessControl().Owner}}  | 
             sort lastwritetime -desc | 
             Format-List >> TargLog.txt
    }else{
         'no files found' >> TargLog.txt
    }
    Tested in V2.!!!


    ¯\_(ツ)_/¯




    • Edited by jrv Wednesday, January 14, 2015 5:20 PM
    Wednesday, January 14, 2015 5:14 PM
  • Mike - some versions of V2 (XP) will not work correctly without the *.  This is an oid bug.


    ¯\_(ツ)_/¯

    Wednesday, January 14, 2015 5:22 PM
  • OK, I got something, but nothing I wanted.

    **User Accounts**
    楍牣獯景⹴潐敷卲敨汬䌮浯慭摮⹳湉整湲污䘮牯慭⹴潆浲瑡瑓牡䑴瑡ൡ䴊捩潲潳瑦倮睯牥桓汥⹬潃浭湡獤䤮瑮牥慮⹬潆浲瑡䜮潲灵瑓牡䑴瑡ൡ䴊捩潲潳瑦倮睯牥桓汥⹬潃浭湡獤䤮瑮牥慮⹬潆浲瑡䘮牯慭䕴瑮祲慄慴਍楍牣獯景⹴潐敷卲敨汬䌮浯慭摮⹳湉整湲污䘮牯慭⹴潆浲瑡湅牴䑹瑡ൡ䴊捩潲潳瑦倮睯牥桓汥⹬潃浭湡獤䤮瑮牥慮⹬潆浲瑡䘮牯慭䕴瑮祲慄慴਍楍牣獯景⹴潐敷卲敨汬䌮浯慭摮⹳湉整湲污䘮牯慭⹴潆浲瑡湅牴䑹瑡ൡ䴊捩潲潳瑦倮睯牥桓汥⹬潃浭湡獤䤮瑮牥慮⹬潆浲瑡䘮牯慭䕴瑮祲慄慴਍楍牣獯景⹴潐敷卲敨汬䌮浯慭摮⹳湉整湲污䘮牯慭⹴潆浲瑡湅牴䑹瑡ൡ䴊捩潲潳瑦倮睯牥桓汥⹬潃浭湡獤䤮瑮牥慮⹬潆浲瑡䘮牯慭䕴瑮祲慄慴਍楍牣獯景⹴潐敷卲敨汬䌮浯慭摮⹳湉整湲污䘮牯慭⹴潆浲瑡湅牴䑹瑡ൡ䴊捩潲潳瑦倮睯牥桓汥⹬潃浭湡獤䤮瑮牥慮⹬潆浲瑡䘮牯慭䕴瑮祲慄慴਍楍牣獯景⹴潐敷卲敨汬䌮浯慭摮⹳湉整湲污䘮牯慭⹴潆浲瑡湅牴䑹瑡ൡ䴊捩潲潳瑦倮睯牥桓汥⹬潃浭湡獤䤮瑮牥慮⹬潆浲瑡䜮潲灵湅䑤瑡ൡ䴊捩潲潳瑦倮睯牥桓汥⹬潃浭湡獤䤮瑮牥慮⹬潆浲瑡䘮牯慭䕴摮慄慴਍〱਍**Startup Commands**
    楍牣獯景⹴潐敷卲敨汬䌮浯慭摮⹳湉整湲污䘮牯慭⹴潆浲瑡瑓牡䑴瑡ൡ䴊捩潲潳瑦倮睯牥桓汥⹬潃浭湡獤䤮瑮牥慮⹬潆浲瑡䜮潲灵瑓牡䑴瑡ൡ䴊捩潲潳瑦倮睯牥桓汥⹬潃浭湡獤䤮瑮牥慮⹬潆浲瑡䘮牯慭䕴瑮祲慄慴਍楍牣獯景⹴潐敷卲敨汬䌮浯慭摮⹳湉整湲污䘮牯慭⹴潆浲瑡湅牴䑹瑡ൡ䴊捩潲潳瑦倮睯牥桓汥⹬潃浭湡獤䤮瑮牥慮⹬潆浲瑡䘮牯慭䕴瑮祲慄慴਍楍牣獯景⹴潐敷卲敨汬䌮浯慭摮⹳湉整湲污䘮牯慭⹴潆浲瑡湅牴䑹瑡ൡ䴊捩潲潳瑦倮睯牥桓汥⹬潃浭湡獤䤮瑮牥慮⹬潆浲瑡䘮牯慭䕴瑮祲慄慴਍楍牣獯景⹴潐敷卲敨汬䌮浯慭摮⹳湉整湲污䘮牯慭⹴潆浲瑡湅牴䑹瑡ൡ䴊捩潲潳瑦倮睯牥桓汥⹬潃浭湡獤䤮瑮牥慮⹬潆浲瑡䘮牯慭䕴瑮祲慄慴਍楍牣獯景⹴潐敷卲敨汬䌮浯慭摮⹳湉整湲污䘮牯慭⹴潆浲瑡湅牴䑹瑡ൡ䴊捩潲潳瑦倮睯牥桓汥⹬潃浭湡獤䤮瑮牥慮⹬潆浲瑡䘮牯慭䕴瑮祲慄慴਍楍牣獯景⹴潐敷卲敨汬䌮浯慭摮⹳湉整湲污䘮牯慭⹴潆浲瑡湅牴䑹瑡ൡ䴊捩潲潳瑦倮睯牥桓汥⹬潃浭湡獤䤮瑮牥慮⹬潆浲瑡䜮潲灵湅䑤瑡ൡ䴊捩潲潳瑦倮睯牥桓汥⹬潃浭湡獤䤮瑮牥慮⹬潆浲瑡䘮牯慭䕴摮慄慴਍〱਍**Exectutables --Last Seven Days**
    潎爠獥汵獴਍

    Here you can see the approach I'm using, I "head" each block (seperate query type) with a title framed by two asterisks each side, the premise being the VBScript post processor will recognise the framing and created a header.  But, since i can' read Katana (or whatever that is, lol) it's really broken now.

    I should note **Executables --Last Seven Days** is the header for the command you've been helping with, the other is a user query I decided to try to, using your code as a guide.

    Lost?  Yep, that'd be me.

    Wednesday, January 14, 2015 5:24 PM
  • Mike - some versions of V2 (XP) will not work correctly without the *.  This is an oid bug.


    ¯\_(ツ)_/¯

    Ah, okay.

    I had run those commands using 'v2' on my machine and they appeared to work okay.


    Don't retire TechNet! - (Don't give up yet - 13,085+ strong and growing)

    Wednesday, January 14, 2015 5:25 PM
  • OK, I got something, but nothing I wanted.

    <snip>

    Here you can see the approach I'm using, I "head" each block (seperate query type) with a title framed by two asterisks each side, the premise being the VBScript post processor will recognise the framing and created a header.  But, since i can' read Katana (or whatever that is, lol) it's really broken now.

    I should note **Executables --Last Seven Days** is the header for the command you've been helping with, the other is a user query I decided to try to, using your code as a guide.

    Lost?  Yep, that'd be me.

    You can change the encoding Add-Content will use with the -Encoding parameter:

    http://ss64.com/ps/add-content.html

    PowerShell loves Unicode output.


    Don't retire TechNet! - (Don't give up yet - 13,085+ strong and growing)

    Wednesday, January 14, 2015 5:27 PM
  • Well Mike, thanks for your help, but I'm not cut out for this stuff.

    I tried ASCII, looks the same.  I think you are overestimating how much I understand, LOL.

    I hate Powershell with a deep, loathing passion.  They give you all this power to do stuff in no space at all (funny, in a day and age where memory usage matters little!), but if you need to format the output, now you are solidly in the black arts.

    Maybe I'll just shoot myself.

    Wednesday, January 14, 2015 5:48 PM
  • OK, looks like I've got what I need. 

    The key was abandoning Mike's suggested Add-Content, something I realized was possible looking at JRVs examples where he used the standard >> append.

    The gist of it seems to be, Add-Content doesn't have a sensible default, meaning it just changes it to whatever it is happiest with, while the >> append just gave me what I wanted right out of the gate.

    And therein lies my problem with Powershell, nowhere (that I can find) does anything mention "if you use this method prepare to jump through hoops to get the output you desire". 

    So, now each of my queries ends with a count (thanks guys!), and for those where records don't return anything I have a default text stating so plainly.

    So, points to Mike and JRV, you guys crushed a problem I've been tying to puzzle my way through for days.

    Thank you very much.

    Wednesday, January 14, 2015 6:30 PM
  • PowerShell is the cuttingedge of technology but like al other technologies it requires concentrated study.  It is not possible to gues your way through how it works if you are not an experienced systems programmer.  It is easy to learn but only if we put in the effort.  VBScript is actually much harder to learn for most people.

    Now you have odd output but have not shown the code you are using to create it.  The redirectors are not really good in this case.

    $path='C:\Scripts\PowerShell Scripts\*'
    $a = Get-ChildItem $path -Include *.ps1 -Recurse |
                Where { $_.LastWriteTime -gt [datetime]::ToDay.AddDays(-30) }
    if($a){
         $a | 
             select name,
                          fullname,
                         lastwritetime,
                        @{N='Owner';E={$_.GetAccessControl().Owner}}  | 
             sort lastwritetime -desc | 
             Format-List | Out-File TargLog.txt -Encoding unicode -Append
    }else{
         'no files found'  | Out-File TargLog.txt -Encoding unicode -Append
    }

    You must start by deleting the current log file or you will get mmixed encoding as yuo can already see.

    What appears to be happening is that you have gathered a lot of shortcuts from teh web and are using themm without trying to understand what they do. A tutorial would get you out of this death spiral.


    ¯\_(ツ)_/¯


    • Edited by jrv Wednesday, January 14, 2015 6:35 PM
    Wednesday, January 14, 2015 6:35 PM
  • Mike was correct but, as I pointed out, yuo need to delete teh file and start over with a file created with teh encoding you want to use.  You cannot change encodins in the middle of a file if you don't want the contents to be like you saw.

    This is not about PowerShell. It is standard for all OSs and all programming languages.  That is why actually studying PowerShell basics is so important because o few techs have formal trianing or degress in commputer negineering or software engineering.

    Get one of the many excellent books on how to use PowerShell.  It willsave you fromall of this frustration.


    ¯\_(ツ)_/¯

    Wednesday, January 14, 2015 6:46 PM
  • OK, looks like I've got what I need. 

    The key was abandoning Mike's suggested Add-Content, something I realized was possible looking at JRVs examples where he used the standard >> append.

    The gist of it seems to be, Add-Content doesn't have a sensible default, meaning it just changes it to whatever it is happiest with, while the >> append just gave me what I wanted right out of the gate.

    And therein lies my problem with Powershell, nowhere (that I can find) does anything mention "if you use this method prepare to jump through hoops to get the output you desire". 

    So, now each of my queries ends with a count (thanks guys!), and for those where records don't return anything I have a default text stating so plainly.

    So, points to Mike and JRV, you guys crushed a problem I've been tying to puzzle my way through for days.

    Thank you very much.

    =]

    That's what I get for trying to be fancy.

    Glad it worked out for you.


    EDIT: Just as a note though, I agree with what jrv is saying above. Out-File -Append is probably going to serve you better than >> in the long run.

    Don't retire TechNet! - (Don't give up yet - 13,085+ strong and growing)

    Wednesday, January 14, 2015 6:46 PM
  • I handle the "delete" by each run being a unique file name based on the target machine name, so if run again on the same machine, the first action is to overwrite the existing file, then append until we're done.

    And yes, it took a REALLY long time to put the queries together, but once you filter by one, filtering by two is easier, filtering by three is childs play.  It's the first one that wears my old brain out!

    Thanks again, and when I'm feeling like getting bit again, I ight try the "better" Out-File method.

    Wednesday, January 14, 2015 7:00 PM
  • I thought PowerShell was annoying when I first started using it too. After you get used to it though, I promise you'll never go back to VBScript unless you really have to.

    Anyway, good luck with your endeavor.


    Don't retire TechNet! - (Don't give up yet - 13,085+ strong and growing)

    Wednesday, January 14, 2015 7:03 PM
  • On this point, yes, it absolutely WAS powershell changing the encoding without being directed to do so. 

    So, in this case the powershell basic is, "powershell will change your encoding unless you specify what you are currently using, or, if it happens to match what powershell happens to default to.

    And this is why I find interacting with you (JRV) to be difficult.  This stuff (thankfully) is second nature to you, but you are willing to treat everyone who doesn't understand it as you do, as a complete newbie who needs to rethink his entire life before engaging in programming.

    Me, I assumed powershell would keep the encoding the file was opened with by a simple directive.  Instead, powershell opened the file, placed my headers in the encoding I expected, but changed the encoding as soon as I tried to use Add.Content.  Where is this documented, and why would a change be considered "normal" anyway?

    That's not the OS, that's not all programming languages, that's not even the basic ability to know one's anus from a hole in the ground, that was Powershell making a decision all it's own.

    Thanks for the example with >> though, I literally had given up till I saw that.

    Wednesday, January 14, 2015 7:12 PM
  • On this point, yes, it absolutely WAS powershell changing the encoding without being directed to do so. 

    So, in this case the powershell basic is, "powershell will change your encoding unless you specify what you are currently using, or, if it happens to match what powershell happens to default to.

    And this is why I find interacting with you (JRV) to be difficult.  This stuff (thankfully) is second nature to you, but you are willing to treat everyone who doesn't understand it as you do, as a complete newbie who needs to rethink his entire life before engaging in programming.

    Me, I assumed powershell would keep the encoding the file was opened with by a simple directive.  Instead, powershell opened the file, placed my headers in the encoding I expected, but changed the encoding as soon as I tried to use Add.Content.  Where is this documented, and why would a change be considered "normal" anyway?

    That's not the OS, that's not all programming languages, that's not even the basic ability to know one's anus from a hole in the ground, that was Powershell making a decision all it's own.

    Thanks for the example with >> though, I literally had given up till I saw that.

    Not what is happening.  PowerShell redirectors use the default always.  If you start a file with >> then output as -encoding unicode you will have changed the ouput to the file. It is you who have done this because you do not understand that the file encoding is fixed once the file is created but text in the file can beinserted with a different encoding.

    You cnnot convert a file with append.  Yuo need to sue a file converter to change the existing text to the new encoding.

    The key is to always thinka bout what you are doing.

    >> and > are the same as Out-File and Out-Fille -Append.  If you always stick with what you staartwith you will have no issue.  Changing encoding  in midstream will not work.


    ¯\_(ツ)_/¯

    Wednesday, January 14, 2015 7:22 PM
  • I hate Powershell with a deep, loathing passion. They give you all this power to do stuff in no space at all (funny, in a day and age where memory usage matters little!), but if you need to format the output, now you are solidly in the black arts.

    Keep in mind that PowerShell outputs objects, not text.


    -- Bill Stewart [Bill_Stewart]

    Wednesday, January 14, 2015 7:29 PM
    Moderator
  • JVR, you aren't listening to me.

    I open the file (for this example TargLog.txt), I write **User Accounts** to it, as the very first action. 

    Then when trying to use Mike's Add-Content (without specifying ANY encoding change), IT CHANGED THE OUTPUT AS YOU SEE IN THE DUMP SHOW ABOVE.  Those Katana or whatever characters showed up.

    Now you say I should think about what I'm doing.  Fair enough.  If I open a file without specifying an encoding, and I'm able to write something to it and have it stick (**User Accounts**), then I expect any further writes to the file to be the same (non-mangled), and it would be pretty odd in fact to want to change the encoding mid stream, meaning, I would expect a warning, an error, or just junk output.

    I just got the junk output.  So, I replaced Add-Content with the append operator >> and only then did I get the ouput I was expecting.  Interesting how you are focussed on Out-File and Out-File -Append, the actual topic is Add-Content. 

    Like I said, I'm good now, Powershell is acting exactly as I expect it, all it took was using the proper redirection.

    Thursday, January 15, 2015 12:00 PM
  • You just said exactly what is wrong with what you are doing.  You wrote " open the file (for this example TargLog.txt), I write **User Accounts** to it, as the very first action. "

    How did you write that line? How did you open the file?  You obviously opened it with a different command or utility.  The issue is not PowerShell.  It is a lack of underestanding of how the Windows file system and file IO APIs work.  Once you understand this the rest becomes obvious.  Powershell is just a wrapper around all of this and has good defaults.  Its design is extremaly well thought out.  It is not a replacement for VBScript but is  new and more complete managememnt toolbox.  From Windows 10 on you will only be able to manage the systems with PowerShell.  Batch and VBScript(COM) will no longer be usable for new systems.  Microsoft has been waving this flag to the developer community since PowerShell was release almost 10 years ago.

    The one issue that you might complain about is the behavior of the little used "Add-Content" which defaults to ANSI if the file does not exist.  Add-Content is not really designed to be used to create and update single files.  It is a custom sort of CmdLet used to batch update files and uses the OS default and not the PowerShell default.  All of the other file IO commands default to the PowerShell encoding which is Unicode on all modern platforms and in version 3 and later.

    You can test this easily by creating a bunch of files and checking their encoding.

    function Get-FileEncoding($Path){
        [byte[]]$byte = get-content -Encoding byte -ReadCount 4 -TotalCount 4 -Path $Path 
        if( $byte[0] -eq 0xfe -and $byte[1] -eq 0xbb -and $byte[2] -eq 0xbf ){ Write-Output 'UTF8' }
        elseif ($byte[0] -eq 0xff -and $byte[1] -eq 0xfe){ Write-Output 'Unicode' } 
        elseif ($byte[0] -eq 0 -and $byte[1] -eq 0 -and $byte[2] -eq 0xfe -and $byte[3] -eq 0xff){ Write-Output 'UTF32' } 
        elseif ($byte[0] -eq 0x2b -and $byte[1] -eq 0x2f -and $byte[2] -eq 0x76) { Write-Output 'UTF7'} 
        else{ Write-Output 'ASCII' } 
    }
    
    'hello' | Out-File test1.txt
    'hello' > test2.txt
    'hello' | Add-Content test3.txt
    'hello' | Set-Content test4.txt
    notepad test5.txt # type anything and save
    
    Get-FileEncoding test1.txt
    Get-FileEncoding test2.txt
    Get-FileEncoding test3.txt
    Get-FileEncoding test4.txt
    Get-FileEncoding test5.txt
    
    # note that only add-content and set-content are different. Notepad does it the same.  It is the OS default.
    # it will be different on different OSs and has nothing to do with Powershell
    # note also that the "content" CmdLets take credentials.  This is a clue that they are differnt for a reason.
    
    
    
    

    To summarize.  It is important to research any system. PowerShell, VBScript, C++, Windows, Unix;  all require us to do research and understand the relationship of the various components.  Blaming the tool only tells us that the tech has not taken the time to do the requied research.

    When I built and ran my first global field support operation I fired many techs because they refused to do the research and which caused disasters because they guessed at answers.  These techs often blamed the tools or the documentation.  It was funny how so many other techs were able to do good work with such terrible tools.

    Don't get lost in the sauce.  Just spend a good amount of your time researching your tools.

    PowerShelll will stop being frustrating once you break down and try to learn it frothe ground up.  It aint that hard.


    ¯\_(ツ)_/¯

    Thursday, January 15, 2015 12:48 PM
  • # This WMI command will list all user accounts that have logged into the system
    "**User Accounts**" > .\JRVLog.txt
    $a = gwmi -ea 0 Win32_UserProfile | select LocalPath, SID,@{NAME='lastused';EXPRESSION={$_.ConvertToDateTime($_.lastusetime)}} | sort lastused -desc
    If ($a) {
    
    $a | Format-List >> .\JRVLog.txt
    $a.Count >> .\JRVLog.txt
    
    } Else {
        
        'No results' >> .\JRVLog.txt
    
    }
    
    "**User Accounts**" > .\JRV2Log.txt
    $a = gwmi -ea 0 Win32_UserProfile | select LocalPath, SID,@{NAME='lastused';EXPRESSION={$_.ConvertToDateTime($_.lastusetime)}} | sort lastused -desc
    If ($a) {
    
    
    $a | Format-List | Add-Content .\JRV2Log.txt
    $a.Count | Add-Content .\JRV2Log.txt
    
    } Else {
        
        'No results' >> .\JRV2Log.txt
    
    }
    Run this then examine the contents of the 2 log files.
    Thursday, January 15, 2015 6:01 PM