PowerShell SIG of the North Texas PC Users Group (NTPCUG)

            "Share what you know, learn what you don't"

The next NTPCUG PowerShell SIG meeting is Saturday, March 17, 2018 at 8:00 am

This month ...
The first half hour starting at 8am we cover topics and demonstrations that come up in informal discussion.

At 8:30am
Terry Dow will discuss a project he has done using the PSGraph PowerShell based interface 
to GraphViz 
    Links associated with Terry's project are
     Terry's files at
     PSGraph  at    https://github.com/KevinMarquette/PSGraph 
     GraphViz  at    http://www.graphviz.org/

At 9:00am Josh Miller will lead a discussion on the topic 
   "Locking down PowerShell to foil attackers".
    Links associated with Josh's topic are

We meet at Northaven United Methodist Church, located at 

    11211 Preston Road, Dallas TX 75230

These websites support the NTPCUG PowerShell SIG


This webpage is located at http://sites.google.com/site/powershellsig/ 

  via bevoveb's account


omments are welcome to Larry Weiss  lfw@airmail.net

searches for "PowerShell"
   Google    goosh    code.google.com   G+    Books   Scholar   News   Videos   Images 
   Bing   Yahoo   duckduckgo   archive.org   Wikipedia   

   Twitter    Facebook    Amazon   reddit    Pinterest   YouTube   flickr    audible
   GitHub    GitHub.ps1    gist    CodeProject     CodePlex    Poshcode    msgroups.net  
Microsoft resources
    Script Center                                                      https://technet.microsoft.com/en-us/scriptcenter
    PowerShell Gallery                                            https://www.powershellgallery.com/
    PowerShell Documentation                              https://msdn.microsoft.com/en-us/powershell
    PowerShell Blog                                                https://blogs.msdn.microsoft.com/powershell/
    PowerShell Script Center                                  http://technet.microsoft.com/en-us/scriptcenter/powershell.aspx
    UserVoice feedback for PowerShell                  https://windowsserver.uservoice.com/forums/301869-powershell

NTPCUG PowerShell SIG resources

Table of contents of this website
    ===community===user groups===conferences===newsgroups===wikis===
    === ... ===



    • NTPCUG PowerShell SIG members
      • Josh Miller
      • Larry Weiss
      • Chris Morgan
      • Terry Dow
      • Mark Kraus
      • Tom Sweet
      • Tuc Goodwin
      • Michael Ramsdell
      • Brian Finn
      • Chris Jujan
      • Mike Boley
      • William Allen
    • PowerShell Team members
      • xx
      • Jason Shirk
      • Joey Aiello
      • Bruce Payette
      • Steve Lee
      • Hermant Mahawar
      • xx
      • xx
    • Hristo Deshev
      • xx
      • xx
      • "Pro Windows PowerShell"
      • http://www.apress.com/9781590599402?gtmf=s
      • http://www.apress.com/author/author/view/id/3209
    • Jerry Lee Ford, Jr.
      • xx
      • xx
      • https://www.amazon.com/Windows-PowerShell-Programming-Absolute-Beginner/dp/1305260341/ref=sr_1_1?s=books&ie=UTF8&qid=1467817910&sr=1-1
      • xx
    • Steve Seguis
      • "Windows PowerShell 2 For Dummies"
    • Jonathon Medd
      • http://twitter.com/#!/jonathanmedd
      • https://twitter.com/search?q=from%3A
      • http://www.jonathanmedd.net/
      • @jonathanmedd http://twitter.com/jonathanmedd/
      • +Jonathan Medd https://plus.google.com/114991381416891894727
    • Stefan Stranger
      • https://twitter.com/sstranger
      • at MSFT
      • http://www.stranger.nl/
      • https://github.com/stefanstranger
      • https://github.com/stefanstranger/PowerShell
      • xx



    Just  don't ever do a start-transcript, and then get-content on the transcript file. - mjolinor 
    Don't put a Set-ExecutionPolicy statement inside profile.ps1 





    • "SQL Server 2012 with PowerShell V3 Cookbook"
    • "PowerShell in Depth: An administrator's guide" by Don Jones, Richard Siddaway and Jeffrey Hicks
    • "Learn PowerShell Toolmaking in a Month of Lunches" by Don Jones and Jeffrey Hicks
    • "Managing VMware Infrastructure with Windows PowerShell TFM" by Hal Rottenberg  (PS 1)
    • "Windows PowerShell 2.0 Administrator's Pocket Consultant" by William R. Stanek +
    • "Windows PowerShell Scripting Guide" by Ed Wilson                                              (PS1)
    • "Microsoft Windows PowerShell Step By Step" by Ed Wilson                                 (PS1)
    • "Windows 7 Resource Kit" by Mitch Tulloch, Ed Wilson and others                        (PS1)
    • "Windows PowerShell Unleashed - Second Edition" by Kopczynski, Handley and Marco Shaw +  (PS1)




      • dir variable: | fl *
      • dir function: | fl *
      • [int] | %{ ($_|gm -static -force);  ($_|gm -force) } | %{if ($_.membertype -like '*Property*'){$_}}
      • dir alias: | fl *
      • Get-Alias | Where-Object {$_.Definition -match "Get-ChildItem"}
      • function ??($keywords) { Get-Help * | ? { $_.description -like "*$keywords*" } | Select-Object Name, Synopsis } # This function called "??" searches PowerShell Help content for any keyword you specify.
      • Search for Localized Keywords  http://app.en25.com/e/es.aspx?s=1403&e=1758&elq=5ae823fb10c64116bb0927e050c91ee1
      • Windows PowerShell Community Documentation Review
      • Get-Process -Id $pid | Format-Custom * -Depth 5
      • (get-command set-content).parametersets[0].parameters |% {$_.name} # discover parameters to a cmdlet
      • Get-Command -type cmdlet | % {$_.Definition} | select-string '<FileSystemCmdletProviderEncoding>' # parameter value coverage across cmdlets
      • Get-Command -type cmdlet | % {$_.Definition} | select-string '-Encoding'                                           # parameter name coverage across cmdlet
      • I have lost confidence in being able to see the actual parametersets from the help text.
        I use the methods shown below to see the actual parametersets:
        (gcm get-content).Definition
        Get-Command get-content -Syntax
      • At a PowerShell prompt, this will get you a list of installed updates
        Get-WmiObject -Class "win32_quickfixengineering" |
        Select-Object -Property "Description", "HotfixID", 
        @{Name="InstalledOn"; Expression={([DateTime]($_.InstalledOn)).ToLocalTime()}}
      • PS C:\> "string".split.OverloadDefinitions
        string[] Split(Params char[] separator)
        string[] Split(char[] separator, int count)
        string[] Split(char[] separator, System.StringSplitOptions options)
        string[] Split(char[] separator, int count, System.StringSplitOptions options)
        string[] Split(string[] separator, System.StringSplitOptions options)
        string[] Split(string[] separator, int count, System.StringSplitOptions options)



      ===community===user groups===conferences===newsgroups===wikis===







      # convert file to ASCII
      [io.file]::ReadAllText('xo') | %{[io.file]::WriteAllText('xo', $_, [System.Text.Encoding]::ASCII)} # convert file to ASCII
      $filecontent = get-content $file; $filecontent | out-file $file -encoding ascii # convert file to ASCII (get-content $filename)|out-file $filename -encoding ascii # convert file to ASCII

      $data=get-content bigfile.csv
      $header=$data|select -first 15
      $body=$data|select -skip 15
      for($i=100;$i -le $body.length;$i=$i+100){
       $header|out-file "smallfile${j}.csv"
       $body|select -first $i|select -last 100|out-file -append "smallfile${j}.csv"
      get-content xo | where {$_}        # remove null content lines
      get-content xo | where {$_.trim()} # remove blank lines

      gci xo | % { $_.LastWriteTime=[DateTime]::Now } # set LastWriteTime for a file

      # replace "is red" with "was red" and "is blue" with "was blue"
      ${c:old.txt} -replace 'is (red|blue)','was $1' > new.txt 

      $Folder = $($dir.fullname -replace [Regex]::Escape($(''+$pwd+'\')),'')

      PS C:> $lastline = ${c:logfilename}[${c:logfilename}.length-1]

      then in $arrayBEGIN you have the first 64kb of the file and in $arrayEND you have the last 64kb.
      $file = New-Object IO.FileStream -ArgumentList (gi THEFILETHATYOUWANTTOREAD).fullname,"Open","Read";
      $arrayBEGIN = new-object Byte[] 64kb;
      $arrayEND = new-object Byte[] 64kb;

      PS Z:\> remove-item -literalpath "c:\2192363 Cam On Mot doa Xuan Ngoi - My
      Tam - Tuan Hung [NCT 3220591328].mp3"
      so to bring it all together you could rename the file by making a copy of it
      with the new name using the copy-item -literalpath
      Then you could delete the old one using the remove-item -literalpath

      The "PowerTip of the Day" article at
      displayed this code to generate temporary file names
        PS C:> (Get-Date -format 'yyyy-MM-dd hh-mm-ss') + '.tmp'
        2010-03-18 09-48-08.tmp
      I took the essence of the idea to do it this way, by two styles of code
        PS C:> '' + (Get-Date).Ticks + '.tmp'
        PS C:> (Get-Date).Ticks.ToString() + '.tmp'

      Replace Text "inplace" in Files
      Often, some text will need to be replaced in a text file. 
      That's easy with Get-Content and Set-Content - or not?
        Get-Content c:\somefile.txt | 
          Foreach-Object { $_ -replace 'old', 'new' } | 
            Set-Content c:\somefile.txt

      If you try this, PowerShell will complain that the file is in use and can't be written to. 
      PowerShell cannot read and write to a file at the same time. 
      Your solution: use parenthesis so that PowerShell reads the file first and
      only and then processes the content:
        (Get-Content c:\somefile.txt) | 
          Foreach-Object { $_ -replace 'old', 'new' } | 
            Set-Content c:\somefile.txt










          •   if (@($env:path -split '"').count -gt 1)
               'Warning: the value of $env:path contains doublequotes.'
               '         PowerShell ignores any path node delimited by doublequotes.'
          • $a = $env:path; $a.Split(";")

          • [System.Environment]::GetEnvironmentVariable('Path', 'Machine')
            [System.Environment]::GetEnvironmentVariable('Path', 'User')
            [System.Environment]::GetEnvironmentVariable('Path', 'Process')

          ===scheduled tasks===tasks===task===



          • $error[0]
          • The Write-Debug cmdlet is very handy for writing objects (such as text strings) to the Debug pipeline. Trying this cmdlet in the shell can be somewhat disappointing, though, because it doesn't look like the cmdlet is doing anything.
            The trick is that the Debug pipeline is shut off by default—the $DebugPreference variable is set to "SilentlyContinue." Set it to "Continue," however, and everything you send with Write-Debug will appear at the console in yellow text. This is a perfect way to add trace code to your scripts, allowing you to follow the execution of a complex script. The yellow color helps you distinguish between trace about and the script's normal output, and you can shut off the debug messages at any time without having to remove all the Write-Debug statements. Simply set $DebugPreference = "SilentlyContinue" again and the debug text will be suppressed.


          • $error[0]
          • $error.clear()
          • [System.Enum]::GetValues([System.Management.Automation.ActionPreference])
          • PS C:> dir xxxxxxx -ErrorAction SilentlyContinue
          • gi wrongInstanceName -ea silentlyContinue -WarningAction silentlyContinue
          •     # use black on white for all text including errors
                # -------------------------------------------------
                $Host.Ui.RawUi.BackGroundColor = "White"
                $Host.Ui.RawUi.ForeGroundColor = "Black"
                $host.privatedata.ErrorForegroundColor    = "Black"
                $host.privatedata.ErrorBackgroundColor    = "White"
                $host.privatedata.WarningForegroundColor  = "Black"
                $host.privatedata.WarningBackgroundColor  = "White"
                $host.privatedata.DebugForegroundColor    = "Black"
                $host.privatedata.DebugBackgroundColor    = "White"
                $host.privatedata.VerboseForegroundColor  = "Black"
                $host.privatedata.VerboseBackgroundColor  = "White"
                $host.privatedata.ProgressForegroundColor = "Black"
                $host.privatedata.ProgressBackgroundColor = "White"



          • finding all aliases to cmdlets and functions
          $FormatEnumerationLimit = 10
          $Type = @{n='Type';e={gcm $_.Name | %{$_.CommandType}}}
          dir alias: | group definition | sort name | select group,name,$Type | ft -auto
          dir alias: | group definition | sort name | select group,name,@{n='Type';e={gcm $_.Name |
              %{$_.CommandType}}} | ft -auto


          • creating a [datetime] object
            • [datetime]::ParseExact(  '20150903 12:39:12'   ,'yyyyMMdd hh:mm:ss',$null)
          • How to Express Dates in Different Fashions
          • [timespan]("8.23:24")
          • [datetime]'9/6/2011'+[timespan]("90.00:00") # add 90 days
          • $dateformat = 'dd.MM.yyyy HH:mm:ss'
            $datestring = '31.05.2010 17:00:00'
            $date1 = [System.Xml.XmlConvert]::ToDateTime($datestring, $dateformat)

          • $dateformat = 'dd.MM.yyyy HH:mm:ss'
            $datestring = '31.05.2010 17:00:00'
            $date2 = [DateTime]::ParseExact($datestring, $dateformat, $null)
            $cultureGerman = New-Object Globalization.CultureInfo "de-DE"
            $culturedateformat = "G"
            $datestring = '31.05.2010 17:00:00'
            $date3 = [DateTime]::ParseExact($datestring, $culturedateformat, $cultureGerman)

            ===formatting of command output===formatting===format===

            ===string formatting===string===formating===format===

            • PowerShell ABC's - F is for Format Operator
            • http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx
            • PowerShell -f operator (returns a string)
              • format types
                • N = numeric
                • C = currrency
                • D = decimal with leading zeros
                • P = percentage
                • X = hex

              • $a = [double] ("{0:N4}" -f 12345.54326) # using a formatted number as a number
              • x
              • x
              • x
              • x
              • x
              • {0:x}  hex in lowercase                     "{0:x}" -f 181342              2c45e
              • {0:X}  hex in uppercase                     "{0:X}" -f 181342              2C45E
              • {0:X4  hex in upper zero padded            "{0:X8}" -f 181342           0002C45E
              • {0:dn} decimal zero padded                 "{0:d8}" -f 3                00000003
              • {0:p}  percentage                           "{0:p}" -f .123              12.30 %
              • {0:c}  currency                             "{0:c}" -f 12.34              $12.34
              • {0,n}  width n, right aligned             "|{0,5}|" -f "hi"              |   hi|  
              • {0,-n} width n, left aligned             "|{0,-5}|" -f "hi"              |hi   |
              • {0:hh} hours minutes                "{0:hh}:{0:mm}" -f (Get-Date)          01:34
              • {0:mm} hours minutes                "{0:hh}:{0:mm}" -f (Get-Date)          01:34
              • {0:N0} rounded integer with commas         "{0:N0}" -f 12345.54321        12,346
              • {0:N4} round int commas 4 decimals         "{0:N4}" -f 12345.54326   12,345.5433
              • x
              • x
            • .Net format() method
              • [string]::format('{0:X4}', 10) # 000A # 4-characters of hex format  (x = lowercase, X = uppercase)


            ===Regular Expressions===RegEx===



            • .NET discovery
              • PowerShell, strings and .NET
              • .Net enumerations 
                • ((@('winrm'|get-service)[0].status).gettype().fullname)
                • [System.Enum]::GetValues([System.Management.Automation.ActionPreference])
                • [management.automation.psparser]::Tokenize('[System.Enum]::GetValues([System.ServiceProcess.ServiceControllerStatus])', [ref]$null)
                • add-type -assemblyName "System.ServiceProcess"
              • PS C:\> "string".split.OverloadDefinitions
                string[] Split(Params char[] separator)
                string[] Split(char[] separator, int count)
                string[] Split(char[] separator, System.StringSplitOptions options)
                string[] Split(char[] separator, int count, System.StringSplitOptions options)
                string[] Split(string[] separator, System.StringSplitOptions options)
                string[] Split(string[] separator, int count, System.StringSplitOptions options)
            • [System.Net.IO.File]
              • http://msdn.microsoft.com/en-us/library/system.io.file%28VS.85%29.aspx
              • See caveats below about using .NET's [IO.File]::ReadAllText method in a PowerShell script
                • I figured it out!    I had some ambiguous content in the folders I was testing with that made me think it was working correctly, when it was actually always grabbing content from the default PowerShell directory (as you told me it would when I used other than the full path when the PowerShell current directory was not the default one!)
                  For anyone wanting published documentation on what is going on, pages 356 and 357 of Bruce Payette's "PowerShell in Action" shows this in detail.  Bruce suggests using the Resolve-Path cmdlet to assist in passing the correct full path into the fast .NET method [IO.File]::ReadAllText()
                    # using the Replace operator
                    $pat = '(?s)^.*(START OF DATA.+END OF DATA).*$'
                    $txt = [IO.File]::ReadAllText((Resolve-Path $file)) -replace $pat, '$1'

            ===interface with other programs===

            • COM
              • Get all COM interfaces
                • $progId = Get-WMIObject Win32_ClassicCOMClassSetting | ? {$_.ProgId -like
                  "*"} | select Description, ProgID, InprocServer32, LocalServer32
            • CMD.exe

              • & 'TestArgs.bat' 1 2 3

              • cmd.exe /c dir p* /ad /od 
              • start-process cmd.exe -ArgumentList @('/c','dir','p*','/ad','/od') -NoNewWindow -Wait

              • & $env:COMSPEC @('/c','ping.exe','www.ibm.com')
              • ping.exe www.ibm.com
              • & ping.exe www.ibm.com
              • start-process ping.exe -ArgumentList @('www.ibm.com') -NoNewWindow -Wait
              • cmd.exe /c ping.exe www.ibm.com
              • & cmd.exe /c ping.exe www.ibm.com

              • & $env:COMSPEC @('/c','dir','a*')
              • & cmd.exe @('/c','dir','a*')

              • $c=@();$c+='*';$c+='a';$c+='d';cmd.exe /c echo $c

              • C:\bin>type ~.bat
              • @echo off % ~.bat %
                rem ~.bat placed in the %path% is used to assist PowerScript command use of cmd.exe commands
                rem for example
                rem ~ dir /b
                rem as a PowerShell command will invoke cmd.exe's built-in comand dir instead of PowerShell's alias dir
              • C:\bin>type posh.bat
                @echo off
                :: posh.bat is used to assist cmd.exe to use a PowerScript command
                :: for example
                ::  posh ps
                :: as a command at a cmd.exe prompt will invoke PowerShell to get a list of run
                ing processes
                powershell -noprofile %*
              • @powershell -file TheScript.ps1 1>TheScript.log 2>&1
              • you can run powershell.exe with the -WindowStyle hidden attribute set
              • Windows PowerShell Exit Codes
              • @echo off % setyyyy.bat %
                :: powershell -noprofile '@set yyyy='+(get-date).year >%temp%.\tempbat.bat
                :: call %temp%.\tempbat.bat
                :: del  %temp%.\tempbat.bat
                for /f %%a in ('"powershell -noprofile 'yyyy='+(get-date).year"') do set %%a
                echo yyyy=%yyyy%   
              • when a POSH alias is the same as an executable or batch file name
                • use it as "sc.exe", include the extension and it no longer conflicts with the alias
                • &(Get-Command sc -CommandType Application) /? # execute sc.exe
                  The advantage is that you don't have to know explicitly whether
                  the command is an EXE CMD or BAT file.
              • I am running a program (Sysinternals PSList command) from a PowerShell
                script, but want it to open in a new command prompt window.  Is this possible?
                PS C:> cmd.exe /c start cmd /k PSlist
                If PSlist is not in the $Path then provide the full path to it.
              • Start-Process cmd
              • powershell.exe -NonInteractive -WindowStyle Hidden -NoProfile &'F:\invokeApp.ps1'

            ===directory processing===

              • dir -recurse | where {$_.Attributes -eq 'Directory'} | %{($_.fullname).replace($pwd.path+'\','')}

              ===environment variables===





              ===RSS feeds===RSS===feeds===feed===

              Add descriptions to PowerShell variables
              Keeping track of a variable’s purpose can be accomplished by assigning a text description:
              $ip= ''
              Set-Variable ip -description 'Server IP or Name'
              When you now list your variables, you can output the variable description as well:
              dir variable:ip | Format-Table Name, Value, Description

              ===home use===home===

              Launch Windows Explorer
              # ShellExplore.ps1
              # Opening Explorer using PowerShell
              # Author Guy Thomas http://computerperformance.co.uk/
              # Version 2.5 - October 2007
              # Sets the Drive
              $Drive = "C:\windows"
              # Launches the Explorer
              $ShellExp = new-Object -comObject Shell.Application

              $letter = get-psdrive | ?{$_.Description -eq 'BOOTME'} | %{$_.name}

              How much RAM is installed
              Get-WmiObject Win32_PhysicalMemory
              Get your assigned IP address
              Get-WMIObject win32_NetworkAdapterConfiguration | Where-Object {$_.IPEnabled -eq $true } | Foreach-Object { $_.IPAddress }

              Get your actual IP address
              (New-Object System.Net.WebClient).DownloadString("http://www.whatismyip.com/automation/n09230945.asp")
              Installed software
              gp HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* |Select DisplayName, DisplayVersion, Publisher, InstallDate, HelpLink, UninstallString |ogv
              installed applications
              Get-WMIObject Win32_product | sort-object InstallDate | format-table InstallDate, name -autosize

              ages of files
              Dir | Select-Object *, Age | Foreach-Object { $_.Age = (new-timespan $_.LastWriteTime).Days; $_ } | Format-Table Name, Age

              closing a program gracefully
              Get-Process Notepad | Foreach-Object { $_.CloseMainWindow() | Out-Null }

              stopping a program by name
              get-process thunderbird | stop-process
              restart a program
              $process = 'firefox'
              $psid = (gps $process).id
              $null = stop-process -id $psid
              $null = wait-process -id $psid
              start-process $process
              BIOS information, like serial number
              Get-WmiObject Win32_BIOS

              OS info
              gwmi win32_operatingsystem | fl *

              list installed fixes
              gwmi win32_quickfixengineering | fl hotfixid

              list data drives
              gwmi win32_logicaldisk | fl freespace

              PowerShell V2 Remoting on Workgroup Joined Computers
              start times for processes
              get-process | select name,starttime | sort starttime

              setting a program's priority
              (gps explorer).priorityclass="High"

              list of main windows
              Get-Process | where {$_.MainWindowTitle} | Select ID,Name,MainWindowTitle,StartTime,@{Name="Age";Expression={(get-date) - $_.StartTime }}

              days until
              ( ([system.datetime]$args[0]).tooadate() - [int]((get-date).tooadate()-0.5) )

              running Services
              Get-WmiObject Win32_Service | Where-Object { $_.State -eq "Running" } fl Caption

              Replacing text in Word documents through PowerShell

              system log messages
              Get-EventLog -Newest 5 -LogName System | fl Message

              PowerShell remoting between two workgroup machines

              Remote Configuration in a Peer-to-Peer environment

              Transactions to Write to the Registry

              restart explorer.exe
              Stop-Process (Get-Process explorer).Id

              PowerShell and the Registry
              value for SnapToDefaultButton
              Set-ItemProperty -path 'HKCU:\Control Panel\Mouse' -name SnapToDefaultButton -value 1
              Set-ItemProperty -path 'HKCU:\Control Panel\Mouse' -name SnapToDefaultButton -value 0
              (then logoff or reboot and log back on)

              PowerShell and the Registry value for SnapToDefaultButton from cmd.exe prompt
              powershell -noprofile Set-ItemProperty -path 'HKCU:\Control Panel\Mouse' -name SnapToDefaultButton -value 1
              powershell -noprofile Set-ItemProperty -path 'HKCU:\Control Panel\Mouse' -name SnapToDefaultButton -value 0
              (then logoff or reboot and log back on)

              Packet Sniffer For Powershell  

              Create System Restore Points

              PowerShell speaks!
                $s = new-object -com SAPI.SPVOICE; $s.Speak('Hello Mr. Brand!')
              or this at a cmd.exe prompt
                powershell -noprofile "$s = new-object -com SAPI.SPVOICE; $s.Speak('Hello Gil!')"

              I just created the first draft of some PowerShell functions I've
              added to my profile.ps1 to let me leverage my cmd.exe "dir" command
              experience, yet use the PowerShell version of this functionality
              (outputing a stream of Directory and File objects).
                 function dir/od { dir $args | sort LastWriteTime }
                 function dir/o-d { dir $args | sort LastWriteTime -Descending}
                 function dir/os { dir $args | ? { !$_.PSIsContainer } | sort Length }
                 function dir/o-s { dir $args | ? { !$_.PSIsContainer } | sort Length
                 function dir/os/a-d { dir $args | ? { !$_.PSIsContainer } | sort Length }
                 function dir/o-s/a-d { dir $args | ? { !$_.PSIsContainer } | sort Length
                 function dir/ad { dir $args | ? { $_.PSIsContainer } }
                 function dir/a-d { dir $args | ? { !$_.PSIsContainer } }
                 function dir/ah { dir $args -force | ? { $_.Attributes –band
              [IO.FileAttributes]::Hidden } }
                 function dir/od/a-d { dir $args | ? { !$_.PSIsContainer } | sort LastWriteTime }
                 function dir/o-d/a-d { dir $args | ? { !$_.PSIsContainer } | sort
              LastWriteTime -Descending}

              Get-FirewallStatus.ps1 http://pshscripts.blogspot.com/2010/03/get-firewallstatusps1.html



              • <##> # (get-itemproperty "HKLM:\software\Microsoft\windows\CurrentVersion\App Paths\WRITE.EXE").'(default)'
                <##> # get-itemproperty 'HKLM:\software\Microsoft\windows\CurrentVersion\App Paths\WRITE.EXE' | select -expand '(default)'
              • # get the default value for a key
                $hklm.OpenSubKey('software\Microsoft\windows\CurrentVersion\App Paths\WRITE.EXE').GetValue($null)
              • (get-item "HKLM:\software\Microsoft\windows\CurrentVersion\App Paths\WRITE.EXE").getvalue('')

              • PowerShell and the Registry
                $RegPath = "HKCU:\Control Panel\Mouse"
                $RegProp = "SnapToDefaultButton"
                $RegValue = 1
                If (Test-Path $RegPath)
                If ((Get-ItemProperty $RegPath).$RegProp -eq $RegValue)
                "Value is already set"
                "Set value now"
                "Registry path does not exist"
                if ((Get-Item $RegPath).Property -notcontains $RegProp)
                New-ItemProperty -Path $RegPath -Property $RegProp -Value $RegValue
              • PS C:> $MachineName = 'ACERONE'
                PS C:> $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $MachineName)
                PS C:> $regKey= $reg.OpenSubKey("SYSTEM\CurrentControlset\services\Disk\", $true)
                PS C:> $regkey.GetvalueNames() | select @{n='result';e={"$_ / $($regkey.GetvalueKind($_)) / $($regkey.Getvalue($_))"}}
                DependOnGroup / MultiString / SCSI miniport
                ErrorControl / DWord / 1
                Group / String / SCSI Class
                Start / DWord / 0
                Tag / DWord / 2
                Type / DWord / 1
                DisplayName / String / Disk Driver
                ImagePath / ExpandString / system32\DRIVERS\disk.sys
                AutoRunAlwaysDisable / MultiString / Brother RemovableDisk(U)

              ===miscellaneous articles===misc===

              concerns the "hidden" property named pstypenames .
              (Hidden in the sense that GetMember requires -Force to disclose it.)
              PS C:> $a = 'Hello'
              PS C:> $a.pstypenames
              PS C:> $a = 1
              PS C:> $a.pstypenames
              PS C:> $a = 1,2,3
              PS C:> $a.pstypenames
              PS C:> $a[0].pstypenames

              PS C:> $EXPLORER=NEW-OBJECT -Comobject "Shell.Application"
              PS C:> $EXPLORER | Get-member
              PS C:> $EXPLORER.Explore("C:\")
              PS C:> $EXPLORER.Minimizeall()
              PS C:> $EXPLORER.TrayProperties ()
              PS C:> $EXPLORER.SetTime()

              Use Write-Progress to Return Feedback 

              65..90 | Foreach-Object { "$([char]($_)) : $([char]($_+32))" } # generate character ranges

              PowerShell will go through its native commands (Cmdlets, Functions, Filters, Aliases, etc.) unless it detects a path -relative or fully qualified- then it will search for a script/executable only in that directory. If no command is found, then PowerShell will search each directory in your $Env:Path and search for an executable/script file by appending an extension from a set*.
              If no command is found after all that, it will prepend 'get-' to the command and go back to search through native commands, scripts; if nothing is found then search through all dirs in your $Env:Path again!
              Even though psprovider resolves to Get-PSProvider, you'll get a performance hit.


              `New-TimeSpan' | # discovering parameter aliases
              Foreach-Object {
              (get-command $_).parameters |
              % { $_.Values |
              Where-Object { $_.Aliases.Count -gt 0 } |
              Select-Object Name, Aliases
              What's my IP ?
              PS C:> (New-Object System.Net.WebClient).DownloadString("http://www.whatismyip.c
              • PS C:\> $a = (get-date).ticks.tostring()
                PS C:\> $a
                PS C:\> get-date ([long]$a)
                Thursday, March 18, 2010 8:40:51 AM
              • foreach ($word in (get-content 'words.txt'))
                     $word = $word.Trim()
                     $correct = $false
                         $answer = Read-Host (' ' * 10 + $word)
                         $answer = $answer.Trim()
                         if ($answer -ceq $word) {$correct = $true}
                         if ($answer -ceq 'Q') {exit}
                     while (-not $correct)
              PS C:> 1..10
              PS C:> 1..10 | % {$_}
              PS C:> 1..10 | % {$_} | % {$_}
              PS C:> 1..10 | % {$_; sleep 1} | % {$_}
              PS C:> 1..10 | % {$_; sleep 1} | sort | % {$_}


              1..10 | % {$_}
              1..10 | % {$_} | % {$_}
              1..10 | % {$_; sleep 1} | % {$_}
              1..10 | % {$_; sleep 1} | sort | % {$_}

              PS C:> echo get-date
              PS C:> echo (get-date)
              Friday, March 12, 2010 4:51:41 PM

              # scriptblocks with delayed execution
              PS C:> $a = { (get-date) }
              PS C:> write-host "pre: " (& $a)
              pre:  3/10/2010 10:15:32 AM
              PS C:> sleep -sec 10
              PS C:> write-host "post: " (& $a)
              post:  3/10/2010 10:15:59 AM
              # pausetest.ps1
              $SPVOICE = new-object -com SAPI.SPVOICE;
              $SPVOICE.Speak('press any key to pause') | Out-Null
              1..100 | % {
              if ($host.ui.RawUI.KeyAvailable)
              sleep -m 500
              $SPVOICE.Speak('press any key to continue') | Out-Null
              while (-not $host.ui.RawUI.KeyAvailable) {sleep -m 500}
              sleep -m 500
              # sleep -m 500
              $SPVOICE.Speak('' + $_ + ' of 100') | Out-Null

              # pause.ps1
              1..100000 | % {
              if ($Host.UI.RawUI.KeyAvailable)
              'Press any key to continue'
              Start-Sleep -milliseconds 500
              do {Start-Sleep -milliseconds 1000} until ($Host.UI.RawUI.KeyAvailable)

              { xxx  | Out-Null }
              # the proper way to send to null in powershell

              ("\\servername has been up for: 4 day(s), 18 hour(s), 12 minute(s), 5 second(s)").Replace("\\",$null).Replace(" 
              has been up for:",$null) 
              output file encodings
              This webpage has examples
              This article discusses the topic

              Using the form of the example from the duplicate of 152205, issue 333752
              (but without using a script), I can duplicate the bug.
                PS C:> get-acl; get-acl | Format-List
              There must be some intrinsic sameness somehow to executing commands separated by semicolons, and executing commands in sequence in a script that allows this bug to be exposed by either structure.
                PS C:> &{
                >> get-acl
                >> get-acl | Format-List
                >> }
              will cause it as well.

              Recursive searching for subfolders in a folder

              $msg.body = Get-Content "c:\TheFile.htm"
              Get-Content reads each line and returns a string for each line.
              What you end up with is an array of strings.
              Try this
              $msg.body = Get-Content "c:\TheFile.htm" | Out-String

              function out-random {
                 $r = New-Object random
                 $input | sort {$r.next}
              PS C:\scripts> 1..10 | out-random

              foreach ($t in [float],[int],[string]) {"0123.45" -as $t}

              0..($s.length-1) | % { ("0x{0:x}" -f [int][char] $s[$_]) }

              [int][char] 'α' # decimal ordinal of character

              ipconfig | Select-String ":" -SimpleMatch

              select-string -Path xo "the" | ForEach-Object {$_.Line}

              Get-Process g* | ForEach-Object { $_.ProcessName }

              Set-Content tmp.tmp ([byte[]][char[]] "hey") -Encoding Byte

              & "$env:programfiles\Internet Explorer\iexplore.exe" www.powershell.com

              dir | ? {$_.lastwritetime -lt (get-date).adddays(-3)}

              powershell.exe -noprofile -command [Path to .PS1 script file]

              $null = New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT
              Include the pattern in the path. The pattern turns 'greedy' when passed to the -Filter parameter.
              Get-ChildItem -Path "E:\Temp\Release 2*_????.??.??.????"

              rename-item c:\folder\dailybackup.bak -newname ((get-date -f MMddyyhhmm) + ".bak")

              Start-Sleep -s 30

              if ([int]$_.lastwritetime.tooadate() -lt [int](get-date).tooadate() -3) {$_}

              $host.UI.RawUI.BufferSize = new-object System.Management.Automation.Host.Size(256,50)

              Get-ChildItem C:\Test -force| Where-Object {$_.mode -match "h"}

              $Message = $Message.Replace("`n", "")

              $x -replace '^', ' ' # add space to string
              $Folder = $($dir.fullname -replace [Regex]::Escape($(''+$pwd+'\')),'')
              $pattern = '^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
              do {$ip = Read-Host "Enter IP"} while ($ip -notmatch $pattern)
              Bob Landau: Here is what I used to determine whether this is a 64 bit OS or not. This as 
              you've pointed out will work in 32/64 bit OS as well as WOW
              if ($ENV:Processor_Architecture -eq 'x86' -and (test-path
              echo 'WOW layer 64 bit OS/32 bit process'
              elseif ($ENV:Processor_Architecture -eq 'x86')
              echo '32 bit OS'
              elseif ($ENV:Processor_Architecture -eq 'AMD64')
              echo '64 bit OS'
              echo 'Unknown'
              How to get the script name inside itself in Powershell?

              This code that can be added to a script to allow the script to find its own location.
                $mypath = (@(get-command $myInvocation.InvocationName)[0].Path).Split("\")
                $mypath = $mypath[0..($mypath.length - 2)] -Join "\"

              code that can be added to a script to allow the script to find its own location.
              [string]$CurrentFolder = Split-Path -Parent $MyInvocation.MyCommand.Path

              Here's my first attempt to code the UNIX "which" utility in PowerShell.
              # which.ps1
              if ($args -ne $null)
              @(get-command $args[0] | ? {$_.CommandType -ne "Alias"})[0].Path
              Actually the script should be named something like "Get-CommandPath" with alias "which".

              Check for the $PSVersionTable automatic variable. If it exists you're running v2.
               "v2 detected"
               "v1 detected"

              function Get-HelpFull and resetting the alias help to it instead of Get-Help.
              function Get-HelpFull()
              { Get-Help $args[0] -Full | more }
              Set-Alias help Get-HelpFull
              I almost always want the full version of help text, and now I can just type (using Get-Command as an example)
              help Get-Command
              instead of having to remember to type
              help Get-Command -full

              The plot thickens!  Consider:
              PS C:> $regex = [regex]'.*'
              PS C:> $regex.Matches("one")
              Groups   : {one}
              Success  : True
              Captures : {one}
              Index    : 0
              Length   : 3
              Value    : one
              Groups   : {}
              Success  : True
              Captures : {}
              Index    : 3
              Length   : 0
              Value    :
              PS C:> $regex.Matches("`none")
              Groups   : {}
              Success  : True
              Captures : {}
              Index    : 0
              Length   : 0
              Value    :
              Groups   : {one}
              Success  : True
              Captures : {one}
              Index    : 1
              Length   : 3
              Value    : one
              Groups   : {}
              Success  : True
              Captures : {}
              Index    : 4
              Length   : 0
              Value    :
              That's why this is a bug...
              It is using the Matches method of the System.Text.RegularExpressions
              object, which is supposed to iterate through the string and return all
              successful matches and their index in a MatchCollection object. What
              is happening is that it is matching the entire string and then
              returning to the string at the index past the last match, but instead
              of realizing that it's run out of string to process, it's running one
              last time on the string '' (empty), which is what's left over after
              the first match because there is no more string left. In most cases
              that would result in nothing more being returned, but in this case,
              because .* also matches zero characters, it adds an empty result to
              the MatchCollection before returning.

              I do like the side-effect that Control+C has of preserving the current command
              line on screen without executing it (and it does not get into the history).
              You can use copy/paste to reuse it later that way.
              Esc just obliterates it.

              Two commands, ASSOC and FTYPE, allow you to manage file associations  from a command prompt (or in a batch file).
              Typing ASSOC  without parameters, displays the currently defined extensions.
              Type Assoc .wav to display
              the .wav file association. Typing assoc .wav= will delete the .wav association.
              Typing FTYPE without options displays the file types that have defined open command strings.
              Ftype SoundRec

              will display the open command string for the file type SoundRec.
              Typing ftype SoundRec= will delete the open command string.
              To define a new association for .log files which you want to open with notepad:
              assoc .log=LogFile
              ftype LogFile=%Systemroot%\System32\notepad.exe %1
              For a complete explanation, type ftype /? at a command prompt.

              You can have four different profiles in Windows PowerShell.
              The profiles are listed in load order.
              The most specific profiles have precedence over less specific profiles where they apply.
              all users:
              This profile applies to all users and all shells.
              %windir%\system32\WindowsPowerShell\v1.0\ Microsoft.PowerShell_profile.ps1
              This profile applies to all users, but only to the Microsoft.PowerShell shell.
              current user (one of each for each user):
              %UserProfile%\My Documents\WindowsPowerShell\profile.ps1
              This profile applies only to the current user, but affects all shells.
              %UserProfile%\My Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
              This profile applies only to the current user and the Microsoft.PowerShell shell.
              There are multiple profile scripts that can be created according to which hosts and how many users you wish the profile to apply to. The PowerShell 2.0 help has an about_profiles goes into details. The short version (from the docs) is:
              Description Path

              ----------- ----
              Current User, Current Host $Home\[My ]Documents\WindowsPowerShell\Profile.ps1
              Current User, All Hosts $Home\[My ]Documents\Profile.ps1
              All Users, Current Host $PsHome\Microsoft.PowerShell_profile.ps1
              All Users, All Hosts $PsHome\Profile.ps1
              Name Description
              ----------- -----------
              $Profile Current User,Current Host
              $Profile.CurrentUserCurrentHost Current User,Current Host
              $Profile.CurrentUserAllHosts Current User,All Hosts
              $Profile.AllUsersCurrentHost All Users, Current Host
              $Profile.AllUsersAllHosts All Users, All Hosts
              You could save a Get-ChildItem list before and after the deletes and save off 
              the difference.  Here's a simplified example (you would substitute your removing
              logic and the exact appended text to $logfile could be customized from the
              output of compare-object to suit your preferences)
                PS C:> dir >xo # just to make sure file xo exists for this example
                PS C:> $logfile = "mylogfile.txt"  # just for my example
                PS C:> $before = Get-ChildItem     # before
                PS C:> remove-Item xo              # substitute your own logic to remove files
                PS C:> $after = Get-ChildItem      # after
                PS C:> compare-object $before $after | ? { $_.SideIndicator -eq "<=" } | %
              {$_.InputObject} >>$logfile # substitute your own text to append to $logfile
                PS C:> gc $logfile
                  Directory: C:\Documents and Settings\Larry\My Documents\WindowsPowerShell
              Mode                LastWriteTime     Length Name
              ----                -------------     ------ ----
              -a---         11/6/2009  11:53 AM      18968 xo

              Using an idea from

              $msg.Body = (Get-Content "x:\MorningChecksResults.txt" | Out-String)
              The discussion in that webpage of how Get-Content interacts in a pipeline is
              The transcript below gives you an idea what the difference is:
              An array of strings is bound to $msg by this code
              PS C:> $msg = Get-Content "Results.txt"
              PS C:> $msg[0]
              PS C:> $msg[1]
              Stopped Services on Exchange 2007 Servers
              PS C:> $msg[2]
              PS C:> $msg[-2]
              Server2 MSExchangeMTA Stopped
              PS C:> $msg[-1]
              Server3 MSExchangeMGMT Stopped
              An array of characters with embedded line delineation
              is bound to $msg by using this code
              PS C:> $msg = (Get-Content "Results.txt" | Out-String)
              PS C:> $msg[0]
              PS C:> $msg[1]
              PS C:> $msg[2]
              PS C:> ("0x{0:x}" -f [int][char] $msg[-2])
              PS C:> ("0x{0:x}" -f [int][char] $msg[-1])

              Using calculated property with Format-Table.
                l = for label, e = for expression
              dir |
              ft @{l="filename";e={$_.name}},
                  @{l="attrib";e={$_.Mode}} -autosize

              PowerShell's design of how you can specify a formal parameters, by using
              parenthesis around the set of function parameters separated my commas leads us
              to expect to carry forward that pattern into the calls.   It is just plain
                function subtract($from, $count) { $from - $count }
              and the call is
                subtract 5 4
              Even the alternative of
                function subtract { param($from, $count) $from - $count }
              uses a pattern involving parenthesis and commas.
              And further confusing is that when you invoke .NET methods, you use the more
              traditional form of passing arguments.  Once you get used to it, it does have
              the benefit of distinguishing the PowerShell function and command calls from the
              calls to the .NET methods. For example,
                subtract "0123456789".IndexOf("5",0) "0123456789".IndexOf("4",0)
              (making up a contrived example).

              select-string -Path thefilename "thepattern" | ForEach-Object {$_.Line}
              and going in the opposite direction, to see all of the MatchInfo fields, use
              select-string -Path thefilename "thepattern" | fl

              Get-WMIObject Win32_product | sort-object vendor | format-table name, version, vendor, caption -autosize | out-file installed.txt -width 250
              Get-WMIObject Win32_product | sort-object InstallDate | format-table InstallDate, name, version, vendor -autosize

              A quick list of all parameters that a given cmdlet supports along with a short description:
              Get-Help get-process -parameter * | Format-Table Name, { $_.Description[0].Text } -wrap -autosize

              ASCII encoding is not the default for Get-Content (aka cat), but is the side-effect of piping to an executable.
              From http://blogs.msdn.com/powershell/archive/2006/12/11/outputencoding-to-the-rescue.aspx
              "The reason we convert to ASCII when piping to existing executablesis that most commands today
              do not process UNICODE correctly.
              Some do, most don't." - Jeffrey Snover
              "There is no array literal notation in PowerShell" - Bruce Payette
              I am tempted sometimes to think that PowerShell has a syntax for array literals; something like this for an array of integers:
              Bruce Payette in PowerShell in Action makes a point that there is no such syntax for array literals, and that was reinforced to me today by looking at the difference in
               $a = 1,2,3
               $a, $b = 1,2,3
              The interpretation of 1,2,3 changes depending upon the composition of the left-hand-side of that assignment expression.

              Whenever an executable path contains spaces, you need to quote it. Use single quotes unless you want to resolve variables that are part of your path name. Then, you should  use double quotes. This leads to another problem. Once quoted, PowerShell treats your command as a plain string and echoes it back to you. To invoke the string, add "&" or "." like this:
              & "$env:programfiles\Internet Explorer\iexplore.exe"

              $WhatIfPreference and other "preference variables"
              describes a way to set -WhatIf by default for all operations,
              and also shows how to use the explicit switch variable syntax of
              -WhatIf:$false to override that default as needed.
                $WhatIfPreference = $true
              makes PowerShell assume a -WhatIf switch on commands.
              It turns out there are a bunch of the "preference variables" built into PowerShell.  You need to know about them just to keep from stepping on that namespace.

              <#c:#> get-help about_Preference_Variables | out-string -stream | select-string '^    \$(.*)'
                | %{ $v=($($_ -replace '    \$','').replace('.','') -split ' ')[0]; "$($v)=$((gc variable:$v -ea 0))" }

              <#c:#> # get-help about_Preference_Variables | out-string -stream | select-string '^    \$.*' |
                 %{$v=($($_ -replace '^    \$|\.','').split())[0]; "$v=$(gc variable:$v -ea 0)"}

              <#c:#> (get-help about_Preference_Variables) -split '\.|\n' | select-string '^    \$.*  ' |
               %{$v=$($_ -replace '^    \$','').split()[0]; "$v=$(gc variable:$v -ea 0)"}

              function Test-SwitchParameter { Param([Switch]$Force);if($Force){"forced!"}else{"not forced!"}}

              PS C:> "phrase" > file.log
              PS C:> c:\mksnt\grep.exe phrase file.log
              PS C:> c:\mksnt\cat.exe file.log | c:\mksnt\grep.exe phrase
              PS C:> c:\mksnt\od -x  file.log
              0000000000      FEFF    0070    0068    0072    0061    0073    0065    000D
              0000000020      000A
              PS C:>
              coding it as
              PS C:> cmd /c "grep phrase file.log"
              PS C:> cmd /c "cat file.log | grep phrase"
              produces more consistent results (with either an ASCII or UNICODE file).
                ASCII file: both forms match
                UNICODE file: both forms fail to match
              The lesson learned is not to allow PowerShell piping to reinterpret CMD.EXE piping if at all possible!

              There are some things about the language that I have not seen before, like a
               leftside -op rightside  
              expression requiring that the rightside be cast to the type of the leftside before the expression is evaluated.
                0 -eq "0000"  # evaluates true
                "0000" -eq 0  # evaluates false
              So assumptions like commutativity of operators like -eq have to be discarded.
              As we just discovered, the way PowerShell creates pipelines of PowerShell object types between all the combinations of commands of various types get in the way of a simple port of a cmd.exe "batch" file to a PowerShell script.
              Some concepts like the way a function can return an array of different types of objects as output have to be understood, especially when you create one that does this unintentionally.
              Some PowerShell concepts like how scriptblocks play a fundamental role are actually pretty neat to learn about.

              Another PowerShell concept to learn is to wrap a value as an array to cover the case where only one element is available, and otherwise a scalar instead of an array will be processed.
              PS C:> $a = 1,2,3
              PS C:> $a[0]
              PS C:> $a = 1
              PS C:> $a[0]
              Unable to index into an object of type System.Int32.
              At line:1 char:4
              + $a[ <<<< 0]
                  + CategoryInfo          : InvalidOperation: (0:Int32) [], RuntimeException
                  + FullyQualifiedErrorId : CannotIndex
              PS C:> $a = 1
              PS C:> $a = @($a)
              PS C:> $a[0]
              PS C:>
              If the value is already an array, it is still OK to wrap it as an array.
              PS C:> $a = 1,2,3
              PS C:> $a = @($a)
              PS C:> $a[0]
              PS C:>

              Here's a general and efficient way to get the contents to a limited depth
                PS C:> gci *; gci *\*; gci *\*\*
              The above limits the depth to two levels deeper than the current directory.
              The results may not be sorted optimally.
                PS C:> &{gci *; gci *\*; gci *\*\*} | sort
              gives a better formatted output that displays the deeper levels in place.
              Common mistake.
              Arguments -to a function/script- in PowerShell are space-delimited.
              # change this line
              two($value1, $value2)
              # to...
              two $value1 $value2
              $attributes= @("name")
              if ($var -eq $true) { $attributes+= "canonicalname"}
              Get-qaduser | select $attributes

              Trace-Command -Name ParameterBinding -PSHost -Expression { cmd /c echo abc | cmd /c sort }
              Trace-Command -Name ParameterBinding -PSHost -Expression { echo abc | sort }

              The only strange thing about here-strings I know about is that
              you get differences when creating here-strings interactively versus
              via a script when you try to embed blank lines into the here-string
              The interactive session discards the blank lines.
              The script preserves them, and in fact seems to create two blank lines
              in the here-string for each blank line in the script.
              Consider this transcript:
              PS C:> Get-Content hstest.ps1
              $herestringtest = @"
              line 1

              line 3

              line 5
              PS C:> . .\hstest.ps1
              PS C:> $herestringtest
              line 1

              line 3

              line 5
              PS C:> $herestringtest = @"
              >> line 1
              >> line 3
              >> line 5
              >> "@
              PS C:> $herestringtest
              line 1
              line 3
              line 5
              PS C:>

              One more strange thing about PowerShell here-strings is that I get different content for them when I create one interactively than via a script.
              By script I get a CR LF pair embedded in the here-string, and interactively I get just the LF.
              PS C:> get-content hstest.ps1
              $a = @'
              PS C:> . .\hstest.ps1
              PS C:> 0..($a.length-1) | % { ("0x{0:x}" -f [int][char] $a[$_])  }
              PS C:> $a = @'
              >> 1
              >> 2
              >> '@
              PS C:> 0..($a.length-1) | % { ("0x{0:x}" -f [int][char] $a[$_])  }
              PS C:>

              $a = {$_ * 10}
              1..10 | foreach-object -process $a
              then change the value of the variable to another scriptblock and run
              the same thing again
              $a = {"this is the number $_"}
              1..10 | foreach-object -process $a
              or shorten it to the alias and implied (positional) parameter
              1..10 | % $a

              PS C:> pwd;
              PS C:> dir | Select-Object @{e={"$_"}} | fw -c 8
              PS C:> pwd; dir | Select-Object @{e={"$_"}} | fw -c 8

              PS C:> set-location; get-childitem
              PS C:> get-location; get-childitem

              PS C:> get-location; get-childitem
              PS C:> get-location; get-childitem | more
              Get-Location | Get-Member
              $PSVersionTable = PS version information

              [char] | Get-Member -Static
              Compare-Object $(Get-Content c:\file1.txt) $(Get-Content c:\file2.txt)
              Auto-Documenting Script Variables
              Ever wanted to get a sorted list of all variables used inside a script? Use this function: simply call Get-ScriptVariables and supply a path to your PowerShell script. You will then get back a sorted list of all variable names found in that script:

              function Get-ScriptVariables($path) {
                      $result = Get-Content $path |
                      ForEach-Object { if ( $_ -match '(\$.*?)\s*=') {
                                 $matches[1]  | Where-Object { $_ -notlike '*.*' }
                      $result | Sort-Object | Get-Unique
              Get-ScriptVariables "$home\myscript.ps1"

              powershell -Command "&{help Get-Help}" >xo
              powershell -Command "&{help Get-Help} >xo"

              $^ is not bound to the value of the last command at the time that the prompt function is executed.

              > Alex K. Angelopoulos wrote:
              > Test-path won't help for this scenario, which I would describe as this:
              > you want to know whether or not a specific variable exists in the global
              > scope, without regard to whether or not it exists in the local scope.
              > For the existence test, use Get-Variable and just discard the output
              > (and suppress errors with -ea SilentlyContinue). Then check the value of
              > $? - it will be true if the variable exists in the requested scope,
              > false if not.
              > Get-Variable -Name foo -Scope Global -ea SilentlyContinue | out-null
              > $?

              Show .NET datetime formats with examples
              (Get-Date).GetDateTimeFormats() | % {$i=0} {"$i`t$_" ; $i++}
              Using format 94
              2009-08-30 10:59:50
              PS C:\> [string]::Format("{0:C}",12.99)
              PS C:\> [string]::Format("{0:###-##-####}",111223333)
              PS C:\> [string]::Format("{0:(###)###-####}",3178675309)
              Search file names only (by svkk)
              ls |? {$_.Name -match "match me"}
              Get-ChildItem | Where-Object {$_.Name -match "match me"}
              "Robert Robelo" wrote:
              Find pattern, display next line
              Select-String's MatchInfo objects have a 1-based LineNumber property which you can use.
              Get-Content returns a 0-based Object[].
              Using the MatchInfo's LineNumber values -without adjusting them- asindices for the Object[] will retrieve the line after each line thatsuccessfully matched the pattern in the log.
              $log = 'log.txt'
              $patt = 'find me'
              $indx = Select-String $patt $log | ForEach-Object {$_.LineNumber}
              (Get-Content $log)[$indx]
              # v2 CTP3 makes it easier
              Select-String $patt $log -Context 0, 1 | % {$_.Context.PostContext}
              Get-WMIObject -list

              If you want the output of a PowerShell command to be produced in ASCII encoding from a simple output redirection operator like >, you can use an embedded non-interactive PowerShell session via cmd.exe
              For example
                cmd /c "powershell -noprofile get-help about_profiles >about_profiles.txt"

              #  output to Unix LF style
              ... | Out-String | %{ $_.Replace("`r`n","`n") } | Out-File -Encoding ASCII ...  #  output to Unix LF style

              '' myScript > file.txt is just syntactic sugar for myScript | out-file -path file.txt ''  - Bruce Payette
              dir >> out.txt
              is equivalent to
              dir | out-file -append out.txt

              myScript >> file.txt  # is   myScript | out-file -filepath out.txt -append
              myScript >  file.txt  $ is   myScript | out-file -filepath file.txt

              function ($num) { [Math]::Sqrt($num) } #  fancy name!
              √ 81

              $a = $b +  $(if($x) {$y} else {$z})  # shorter way
              $a = $b + (&{if($x) {$y} else {$z}}) # longer way

              ii .  #  start Windows explorer at current directory

              New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT

              <# from http://app.en25.com/e/es.aspx?s=1403&e=26812&elq=a137d355066b464b91ff99273e8a2ec2 #>
              <# originally as Get-Enum            #>
              <#    Show-Enum IO.FileAttributes    #>
              function Show-Enums($name) {
               [Enum]::GetValues($name) |
                 Select-Object @{n="Name";e={$_}},@{n="Value";e={$_.value__}} |
                  format-table -autosize

              function get-guihelp {
                $helpfile = "C:\Windows\Help\mui\0409\WindowsPowerShellHelp.chm"
                if ( Test-Path $helpfile ) { Invoke-Item $helpfile; return}
                $helpfile = "C:\Windows\Help\WindowsPowerShellHelp.chm"
                if ( Test-Path $helpfile ) {Invoke-Item $helpfile; return}
              new-alias ghelp get-guihelp

              function Get-HelpFull-oe() {Get-Help $args[0] -Full | oe}
              Set-Alias help!   Get-HelpFull-oe
              Set-Alias myhelp  Get-HelpFull-oe
              function Get-HelpFull() {Get-Help $args[0] -Full | more}
              Set-Alias helpfull Get-HelpFull

              function prompt {
                # PS prompt displays $pwd only when last command entered is cd or Set-Location.
                # When $pwd is displayed, it displays on a line above the prompt.
                # The host window title always displays $pwd.
                $host.ui.rawui.WindowTitle = "PS $pwd"
                $p = 'PS ' + (([string] $pwd).split('\'))[0] + '> '
                if (@(Get-History).count -eq 0) {return $p}
                $s = ((Get-History -count 1|Select-Object -expandproperty commandline).split(' '))[0]
                switch ($s) {
                  'cd'           {return "PS $pwd`n" + $p}
                  'Set-Location' {return "PS $pwd`n" + $p}
                  default        {return $p}

              To get the aliases associated with a cmdlet try this pattern: for example, the command to return the aliases for Get-ChildItem is
                Get-Alias | Where-Object {$_.Definition -match "Get-ChildItem"}
                Get-Alias -Definition Get-ChildItem
                Get-Alias -Definition *
              See:  "Windows PowerShell Aliases"
              Pipe the notepad statement to Out-Null,
               this will cause the script to wait until notepad is closed by the user.
              # create a test file
              Set-Content qt.txt 'line 1'
              # copy this script and run it
              # -< script.ps1 >-
              notepad .\qt.txt | Out-Null
              cmd /c type qt.txt
              function WhatTypeIs($obj) {
                 $obj.GetType() | fl UnderlyingSystemType, BaseType

              foreach ($line in get-help about*) {$line.Name + " = " + $line.Synopsis}
              &{foreach ($line in get-help about*) {$line.Name + " = " + $line.Synopsis}} | out-file xoxo -encoding ASCII

              contrast the speed of these two ways to sort an array
                $a = ($a | Sort-Object)
              write '-----------------------'
              write '$a = "D", "C", "B", "A"'
              write '$a = ($a | Sort-Object)'
              $a = "D", "C", "B", "A"
              Measure-Command {
                1..1000 | % {
                $a = ($a | Sort-Object)   # the slower way to sort an array
              } | fw totalmilliseconds
              write '-----------------------'
              write '$a = "D", "C", "B", "A"'
              write '[Array]::Sort([Array]$a)'
              $a = "D", "C", "B", "A"
              Measure-Command {
                1..1000 | % {
                [Array]::Sort([Array]$a)  # the faster way to sort an array
              } | fw totalmilliseconds
              write '-----------------------'

              PowerShell and the Registry
              Set-ItemProperty -path "HKCU:\Control Panel\Mouse" -name "SnapToDefaultButton" -value 1
              PowerShell and the Registry
              $RegPath = "HKCU:\Control Panel\Mouse"
              $RegProp = "SnapToDefaultButton"
              $RegValue = 1
              If (Test-Path $RegPath)
              If ((Get-ItemProperty $RegPath).$RegProp -eq $RegValue)
              "Value is already set"
              "Set value now"
              "Registry path does not exist"
              if ((Get-Item $RegPath).Property -notcontains $RegProp)
              New-ItemProperty -Path $RegPath -Property $RegProp -Value $RegValue
              setting a program's priority
              (gps explorer).priorityclass="High"



              • Collections in PowerShell start at 0, not at 1. This is why $files[1] is actually extracting the second element, not the first.
              • <#c:#> (0 -eq 0)
              • True
              • <#c:#> ('0' -eq '0')
              • True
              • <#c:#> ('0' -eq 0)
              • True
              • <#c:#> (0 -eq '0')
              • True
              • <#c:#> ('0.0' -eq 0)
              • False
              • <#c:#> (0 -eq '0.0')
              • True
              • <#c:#>
              • $ExecutionContext.InvokeCommand.ExpandString('$pwd') # expand a string 
                • But watch out for double quotes that need to be preserved:
                    PS C:> $x = 'embedded "text"'
                    PS C:> $executionContext.InvokeCommand.ExpandString($x)
                    embedded text
                    PS C:> $executionContext.InvokeCommand.ExpandString(($x -replace '"','`"'))
                    embedded "text
              • ... trying get a limited set of files from a directory tree. The
                 following is what i want but it doesn't work. I get everything.
                 get-childitem -LiteralPath \rm5_0_code_h\source -include
                 *.frm,*.ctl,*.bas,*.cls,*.cs,*.cpp,*.hpp,*.sql,*.java -Recurse
                 I still get them all. what am i doing wrong?
                 get-childitem \rm5_0_code_h\source\* -include
                 *.frm,*.ctl,*.bas,*.cls,*.cs,*.cpp,*.hpp,*.sql,*.java -Recurse

              • If you suspect that something has a type of string but it doesn't seem so, try executing  $B.status.Gettype()and you'll quickly find out what type it actually is.The convenience of implicit casts to [string] on output to the console can mislead you.
              • use @() to insure array to generalize results like from DIR where only one iten may be returned
              • using -force to insure all properties, especially with $error[0].Exception | Format-List * -force )
              • error coding two($value1, $value2) instead of two value1 value2
              • coding a space before a # comment to avoid echo hi#there situations
              • coding to execute a string:  & "$env:programfiles\Internet Explorer\iexplore.exe"
              • "Get-" is appended to a command name if that command is not otherwise found and then it is reparsed
              • arrays are reference types, try:   $a = 1,2,3; $b = $a; $a[1]=999; $a; $b; $a = 1,2,3; $a; $b
              • blank lines in here-strings are treated differently in command line entry than in scripts
              • line delineation in here-strings are treated differently in command line entry than in scripts
              • limitations on length of file path
              • Write-Host $("a"*16000);Write-Host $("a"*32000) # the 32000 fails on its own until the 16000 is executed
              • [int] %i = 9.99   persists a type consraint on $i
              • [int] $i = 10; $i; $i = "aaa"; $i  won't work
              • Working with STDERR in PowerShell
              • $msg.body = Get-Content "c:\TheFile.htm" -vs- $msg.body = Get-Content "c:\TheFile.htm" | Out-String
              • Why is Get-ChildItem so Slow?
              • Compare-Object gotcha
              • Execute this to get the full list of invalid characters:  PS > [io.path]::GetInvalidFileNameChars()
              • Perhaps the "magic" of #Tab should be triggered by #^Tab instead of #Tab?
              • 3 PowerShell Array Gotchas
              • eliminate unexpected extra blank lines
                • $b = (ipconfig) -Join "`n" | uniq # eliminate unexpected extra blank lines
                • $b = ipconfig | get-Unique        # eliminate unexpected extra blank lines
              • when a POSH alias is the same as an executable or batch file name
                • use it as "sc.exe", include the extension and it no longer conflicts with the alias
                • &(Get-Command sc -CommandType Application) /? # execute sc.exe
                  The advantage is that you don't have to know explicitly whether the command is an EXE CMD or BAT file.
              • See caveats below about using .NET's [IO.File]::ReadAllText method in a PowerShell script
                • I figured it out!    I had some ambiguous content in the folders I was testing with that made me think it was working correctly, when it was actually always grabbing content from the default PowerShell directory (as you told me it would when I used other than the full path when the PowerShell current directory was not the default one!)
                  For anyone wanting published documentation on what is going on, pages 356 and 357 of Bruce Payette's "PowerShell in Action" shows this in detail.  Bruce suggests using the Resolve-Path cmdlet to assist in passing the correct full path into the fast .NET method [IO.File]::ReadAllText()
                    # using the Replace operator
                    $pat = '(?s)^.*(START OF DATA.+END OF DATA).*$'
                    $txt = [IO.File]::ReadAllText((Resolve-Path $file)) -replace $pat, '$1'
              • Script logging via Start-Transcript and End-Transcript does not log executable or batch command output
              • Tab expansion is different for Command Line host and ISE host for situations like    dir a* -force where you want to replace a* only
              • $x = "C:\","hklm:\software\microsoft\windows" | % { ,(gci $_) }
                # Looking at the objects returned
                $x[0] # FileInfo object formatted normally
                $x[1] # Microsoft.Win32.RegistryKey objects formatted normally
                $x    # FileInfo objects will format normally, but not the reg
                $x[0],$x[1] = $x[1],$x[0] # swap the array values
                $x[0] # Microsoft.Win32.RegistryKey objects formatted normally
                $x[1] # FileInfo object formatted normally
                $x # reg objects will format normally, but not the FileInfo objects
                This represents the basic issue: how can one apply consistent formatting to the output of a command/script/function when it consists of dissimilar object types?
              • And here's a variation that's even more puzzling at first encounter:
                (at the command prompt execute this sequence of commands)
                  $x = "C:\","hklm:\software\microsoft\windows" | % { ,(gci $_) }
                  $x[0];       # file objects formatted as expected
                  $x[1];       # reg objects formatted as expected
                  $x[0]; $x[1] # only the file objects formatted as expected
                  $x[1];       # reg objects formatted as expected
                  $x[0];       # file objects formatted as expected
                  $x[1]; $x[0] # only the reg objects formatted as expected
                From a traditional imperative programming language perspective you expect
                to be the same as
                   a; b;
                but PowerShell's pipelining (even in the absence of a pipe symbol) throws a curveball.
              • PS C:> $s = 1; "_$s_"; "_$($s)_" # underscore is allowed in a variable name
              • Ah, welcome to the world of 64-bit computing. Where the registry and things like Execution policy are different between 32-bit and 64-bit programs! When you run PowerShell from a 32-bit program, it calls 32-bit PowerShell.  But when you run from the taskbar it runs the 64-bit version.
                Go to Start->All Programs->Accessories->Windows PowerShell and start the Windows PowerShell (x86) version as an Administrator, and from there set your execution policy for the 32-bit version of PowerShell. That should fix your issues.

              Jason Shirk's blog article at
              talks about the Windows PowerShell Language Specification Version 2.0
              spec available at
              A little light reading!   But exactly what I've been looking for.


              • Start-Job {Copy-Item $args[0] $args[1] -recurse -force} -ArgumentList $source,$destination
              • while ($true) {ping www.google.com; sleep 10}
              • while ((ping -n 1 www.google.com).count -lt 18) {write-host -nonewline 'still down...'; sleep 2}
              • ((ping.exe localhost | ? {$_ -match 'Received' }).Split(',') | ? {$_ -match 'Received'}).Trim()

              • sc $PWD\args.ps1 '$args'; &"$PWD\args.ps1" a b c

              This webpage is located at http://sites.google.com/site/powershellsig/  

              Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko 

              Jeffrey Snover, Inventor of PowerShell
              Steve Lee, Software Engineering Manager for PowerShell
              Andy Schwartzmeyer, Software Engineer and PowerShell Linux Guru
              Joey Aiello, Program Manager for PowerShell

              ===scripting games===games===

              searches for "PowerShell"


              Comments welcome to   lfw@airmail.net

              Larry Weiss co-leader with Josh Miller of the PowerShell SIG of the North Texas PC User Group

              via bevoveb