powershell

    Why Powershell

    Sketchnote on the many virtues of Powershell

    Pester script parameter passing not working

    Problem

    I was trying to parameterize a Pester script. The script looked like this:

    param (
       [string]$ComputerName,
       [string]$IPAddress
    )
    
    write-dbg "$ComputerName: "
    write-dbg "$IPAddress: "
    
    Describe "$ComputerName is visible" {
    
        "It is ping-able" {
           {test-connection $ComputerName -count 1} | Should Not Throw
    
           $(test-connection $ComputerName -count 1 | Measure-Object).count | Should Be 1
        }
    
    }
    

    …but passing the parameters wasn’t working.

    Solution

    The problem was that I was calling the script as follows

    $ Invoke-Pester  @{PAth = c:\pester\diagnostics\simple\StandardDomainContoller.tests.ps1; Parameters=@{ComputerName = "server1.here.co.uk";IPAddress = "17.6.5.1""}}
    

    …and the Path variable needs quotes:

    $ Invoke-Pester  @{PAth = 'c:\pester\diagnostics\simple\StandardDomainContoller.tests.ps1'; Parameters=@{ComputerName = "server1.here.co.uk";IPAddress = "17.6.5.1""}}
    

    What I learned about powershell in 2017, according to my twitter archive

    Nov 24, 2017

    #TodayILearned that:

    $Content = get-content somefile.txt | out-string

    …preserves the line breaks in the text file

    via social.technet.microsoft.com/Forums/sc…

    Nov 21, 2017

    #TodayILearned

    set backupdir=C:\temp\vim set directory=C:\temp\vim

    via @hellojs_org at blog.hellojs.org/configure…

    Nov 8, 2017

    #TodayILearned that the batch command equivalent of the bash sleep is Timeout

    May 24, 2017

    #TodayILearned that you can replace a pattern in Powershell: “images\Leopold_I_of_Belgium 226x300” -replace “[0-9][0-9]x[0-9][0-9]”,""

    Mar 31, 2017

    #TodayILearned that if you put a ValidateSet on a #Powershell cmdlet parameter, then ISE Tab-completion will pick it up. Very handy!

    Mar 21, 2017

    #TodayILearned you can omit the Get- from Powershell commands…‘tho just because you can…doesnt mean you should!

    community.idera.com/powershel…

    Jan 20, 2017

    #TodayILearned that you can set a CSV in a here-string and turn it into an object.

    Handy for small test datasets in @PSPester

    Jan 3, 2017

    #TodayILearned that ‘show-command’ in Powershell creates a nice little GUI window for a function or cmdlet community.idera.com/powershel…

    What I learned about powershell in 2016, according to my twitter archive

    Sep 27, 2016

    #TodayILearned you have to:

    export-modulemember -alias * -function *

    to define aliases in a Powershell module

    maxtblog.com/2010/07/powershell-modules-how-to-create-aliases-for-my-functions/

    Sep 23, 2016

    #TodayILearned that in vim to scroll down but keep the cursor in the same place, you can do Ctrl-e

    Sep 15, 2016

    #TodayILearned that Powershell’s get-unique cmdlet is case sensitive.

    Aug 22, 2016

    #TodayILearned that Powershell’s get-help -parameter option takes a parameter of the parameter. Obvious, really :)

    Aug 11, 2016

    #TodayILearned this vim

    :vimgrep /^functio/ %

    :copen

    then move to the left

    Aug 10, 2016

    #TodayILearned that PowerShell’s get-help has a really, really useful -window option (via @maxtrinidad , shortly b4 losing my internet :( )

    Jul 5, 2016

    #TodayILearned that if you’re Pester-testing a bit of a #Powershell module, and you want to Mock something you need -Module option

    I think.

    Jun 15, 2016

    #TodayILearned this is v handy if you RunAs different users $Host.UI.RawUI.WindowTitle = $env:username

    #Powershell

    Mar 7, 2016

    #TodayILearned that Powershell ISE snippets live in

    C:\Users\matt\Documents\WindowsPowerShell\Snippets

    ..if your name happens to be matt

    pester: Cannot bind argument to parameter 'Actual' because it is an empty string.

    I’m just getting started with Pester and I got this error

       Cannot bind argument to parameter 'Actual' because it is an empty string.
       at line: 18 in C:\Program Files\WindowsPowerShell\Modules\pester\3.3.5\Functions\Assertions\Be.ps1
    

    So, when it’s working it does this:

    get-HugoNameAndValue -FrontMatterLine "Weighting: 103"
    DEBUG: 09:15:37.6806 Start: get-HugoNameAndValue
    DEBUG: - FrontMatterLine=Weighting: 103
    DEBUG: - get-HugoNameAndValue.ps1: line 5
    DEBUG: $PositionOfFirstColon: 9
    DEBUG: $PropertyName : {Weighting}
    DEBUG: $PropertyValue : { 103}
    DEBUG: $PropertyValue : {103}
    
    PropertyName PropertyValue
    ------------ -------------
    Weighting    103          
    
    

    When I ran it from Pester I got this

    GetHugoNameAndValue 06/21/2016 08:45:19 $ invoke-pester
    Describing get-HugoNameAndValue
    DEBUG: 08:45:56.3377 Start: get-HugoNameAndValue
    DEBUG: - FrontMatterLine=Weighting: 103
    DEBUG: - get-HugoNameAndValue.ps1: line 5
    DEBUG: $PositionOfFirstColon: 9
    DEBUG: $PropertyName : {Weighting}
    DEBUG: $PropertyValue : { 103}
    DEBUG: $PropertyValue : {103}
     [-] returns name and value 189ms
       Cannot bind argument to parameter 'Actual' because it is an empty string.
       at line: 18 in C:\Program Files\WindowsPowerShell\Modules\pester\3.3.5\Functions\Assertions\Be.ps1
    Tests completed in 189ms
    Passed: 0 Failed: 1 Skipped: 0 Pending: 0
    

    My Pester code was:

    $here = Split-Path -Parent $MyInvocation.MyCommand.Path
    $sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path).Replace(".Tests.", ".")
    . "$here\$sut"
    
    Describe "get-HugoNameAndValue" {
        It "returns name and value" {
            $Hugo = get-HugoNameAndValue -FrontMatterLine "Weighting: 103"
            $value = $Hugo.Value
            $value | Should Be '103'
        }
    }
    

    The problem here was simply that I’d got the name of the Property wrong. It was ‘PropertyName’ not just ‘Name’

    So I changed the Pester

    $here = Split-Path -Parent $MyInvocation.MyCommand.Path
    $sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path).Replace(".Tests.", ".")
    . "$here\$sut"
    
    Describe "get-HugoNameAndValue" {
        It "returns name and value" {
            $Hugo = get-HugoNameAndValue -FrontMatterLine "Weighting: 103"
            $value = $Hugo.PropertyValue
            $value | Should Be '103'
        }
    }
    

    ….and then it worked

    invoke-pester
    Describing get-HugoNameAndValue
    DEBUG: 09:22:21.2291 Start: get-HugoNameAndValue
    DEBUG: - FrontMatterLine=Weighting: 103
    DEBUG: - get-HugoNameAndValue.ps1: line 5
    DEBUG: $PositionOfFirstColon: 9
    DEBUG: $PropertyName : {Weighting}
    DEBUG: $PropertyValue : { 103}
    DEBUG: $PropertyValue : {103}
     [+] returns name and value 99ms
    Tests completed in 99ms
    Passed: 1 Failed: 0 Skipped: 0 Pending: 0
    

    pester: Cannot bind argument to parameter 'Actual' because it is an empty string.

    I’m just getting started with Pester and I got this error

       Cannot bind argument to parameter 'Actual' because it is an empty string.
       at line: 18 in C:\Program Files\WindowsPowerShell\Modules\pester\3.3.5\Functions\Assertions\Be.ps1
    

    So, when it’s working it does this:

    get-HugoNameAndValue -FrontMatterLine "Weighting: 103"
    DEBUG: 09:15:37.6806 Start: get-HugoNameAndValue
    DEBUG: - FrontMatterLine=Weighting: 103
    DEBUG: - get-HugoNameAndValue.ps1: line 5
    DEBUG: $PositionOfFirstColon: 9
    DEBUG: $PropertyName : {Weighting}
    DEBUG: $PropertyValue : { 103}
    DEBUG: $PropertyValue : {103}
    
    PropertyName PropertyValue
    ------------ -------------
    Weighting    103          
    
    

    When I ran it from Pester I got this

    GetHugoNameAndValue 06/21/2016 08:45:19 $ invoke-pester
    Describing get-HugoNameAndValue
    DEBUG: 08:45:56.3377 Start: get-HugoNameAndValue
    DEBUG: - FrontMatterLine=Weighting: 103
    DEBUG: - get-HugoNameAndValue.ps1: line 5
    DEBUG: $PositionOfFirstColon: 9
    DEBUG: $PropertyName : {Weighting}
    DEBUG: $PropertyValue : { 103}
    DEBUG: $PropertyValue : {103}
     [-] returns name and value 189ms
       Cannot bind argument to parameter 'Actual' because it is an empty string.
       at line: 18 in C:\Program Files\WindowsPowerShell\Modules\pester\3.3.5\Functions\Assertions\Be.ps1
    Tests completed in 189ms
    Passed: 0 Failed: 1 Skipped: 0 Pending: 0
    

    My Pester code was:

    $here = Split-Path -Parent $MyInvocation.MyCommand.Path
    $sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path).Replace(".Tests.", ".")
    . "$here\$sut"
    
    Describe "get-HugoNameAndValue" {
        It "returns name and value" {
            $Hugo = get-HugoNameAndValue -FrontMatterLine "Weighting: 103"
            $value = $Hugo.Value
            $value | Should Be '103'
        }
    }
    

    The problem here was simply that I’d got the name of the Property wrong. It was ‘PropertyName’ not just ‘Name’

    So I changed the Pester

    $here = Split-Path -Parent $MyInvocation.MyCommand.Path
    $sut = (Split-Path -Leaf $MyInvocation.MyCommand.Path).Replace(".Tests.", ".")
    . "$here\$sut"
    
    Describe "get-HugoNameAndValue" {
        It "returns name and value" {
            $Hugo = get-HugoNameAndValue -FrontMatterLine "Weighting: 103"
            $value = $Hugo.PropertyValue
            $value | Should Be '103'
        }
    }
    

    ….and then it worked

    invoke-pester
    Describing get-HugoNameAndValue
    DEBUG: 09:22:21.2291 Start: get-HugoNameAndValue
    DEBUG: - FrontMatterLine=Weighting: 103
    DEBUG: - get-HugoNameAndValue.ps1: line 5
    DEBUG: $PositionOfFirstColon: 9
    DEBUG: $PropertyName : {Weighting}
    DEBUG: $PropertyValue : { 103}
    DEBUG: $PropertyValue : {103}
     [+] returns name and value 99ms
    Tests completed in 99ms
    Passed: 1 Failed: 0 Skipped: 0 Pending: 0
    

    extracting post details from wordpress xml dump with powershell

    Get the xml into a variable

    [xml]$xmla = get-content D:\repair_websites\salisburywiltshireandstonehenge.wordpress.2015-10-03.xml                       
    

    Extract the details

    select-xml -xml $xmla -xpath "//channel/item" | select -expandproperty node | ? post_type -ne "attachment" | select title  
    

    gives the following:

    title                        
    -----                        
    Road names beginning with 'N'
    Road names beginning with 'O'
    Road names beginning with 'P'
    Road names beginning with 'Q'
    Road names beginning with 'R'
    Road names beginning with 'S'
    Road names beginning with 'T'
    Road names beginning with 'U'
    Road names beginning with 'V'
    Road names beginning with 'W'
    

    The properties of the expanded node are:

    wordpress-xml-powershell-properties

    For example:

    select-xml -xml $xmla -xpath "//channel/item" | select -expandproperty node | ? post_type -ne "attachment" | ? title -like "*Ramone*"
    

    outputs:

    title          : 3rd June 1977 - the Ramones visit Stonehenge. Johnny stays on the bus
    link           : /on-this-day/june/3rd-june-1977-the-ramones-visit-stonehenge-johnny-stays-on-the-bus
    pubDate        : Tue, 04 Nov 2014 12:33:09 +0000
    creator        : creator
    guid           : guid
    description    : 
    encoded        : {content:encoded, excerpt:encoded}
    post_id        : 9267
    post_date      : 2014-11-04 12:33:09
    post_date_gmt  : 2014-11-04 12:33:09
    comment_status : open
    ping_status    : closed
    post_name      : 3rd-june-1977-the-ramones-visit-stonehenge-johnny-stays-on-the-bus
    status         : publish
    post_parent    : 6624
    menu_order     : 3
    post_type      : page
    post_password  : 
    is_sticky      : 0
    postmeta       : {wp:postmeta, wp:postmeta, wp:postmeta, wp:postmeta}
    

    To get the actual content of the post:

    select-xml -xml $xmla -xpath "//channel/item" | select -expandproperty node | ? post_type -ne "attachment" | ? title -like "*Ramone*" | select -ExpandProperty encoded | fl
    

    …gives:

    #cdata-section : <a href="/images/Joey-Ramone-visited-Stonehenge.jpg"><img src="/images/Joey-Ramone-visited-Stonehenge.jpg" alt="Joey Ramone - 'visited' 
                     Stonehenge" width="320" height="455" class="alignright size-full wp-image-9702" /></a>On either the 3rdIn 'On the Road with 
                     the Ramones', Monte A. Melnick says that the visit occurred 
    
                     <blockquote>'On the '77 tour we had a day off and noticed Stonehenge was on the way'[URL <a href="http://books.google.co.uk/books?
                     id=N7m8AwAAQBAJ&lpg=RA1-PR24&dq=ramones%20stonehenge&pg=RA1-PR25#v=onepage&q=ramones%20stonehenge&f=false">'On the Road with the 
                     Ramones', by By Monte A. Melnick, Frank Meyer</a>].</blockquote>
    
                     This would have been when the Ramones were travelling back from Penzance to Canterbury - the free day being June 3rd [<a href="http://en.wikipedia.org/wiki/List_of_Ramones_concerts#1977">Wikipedia List Of Ramones Concerts</a>] or possibly the 
                     4th June 1977, the Ramones visited Stonehenge.
    
                     Pic: By en:User:Dawkeye [<a href="http://www.gnu.org/copyleft/fdl.html">GFDL</a>, <a href="http://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA-3.0</a> or <a href="http://creativecommons.org/licenses/by-sa/2.5">CC-BY-SA-2.5</a>], <a href="http://commons.wikimedia.org/wiki/File%3AJoeyramone.jpg">via Wikimedia Commons</a>
    
                     More:
    
                     <a href="http://books.google.co.uk/books?id=c7lgKVmD0yMC&lpg=PA170&dq=ramones%20stonehenge&pg=PA171#v=onepage&q=ramones%20stonehen
                     ge&f=false" title="http://books.google.co.uk/books?id=c7lgKVmD0yMC&lpg=PA170&dq=ramones%20stonehenge&pg=PA171#v=onepage&q=ramones%
                     20stonehenge&f=false">I Slept with Joey Ramone: A Family Memoir By Mickey Leigh</a>
    
                     <a href="http://books.google.co.uk/books?id=N7m8AwAAQBAJ&lpg=RA1-PR24&dq=ramones%20stonehenge&pg=RA1-PR25#v=onepage&q=ramones%20st
                     onehenge&f=false" title="http://books.google.co.uk/books?id=N7m8AwAAQBAJ&lpg=RA1-PR24&dq=ramones%20stonehenge&pg=RA1-PR25#v=onepag
                     e&q=ramones%20stonehenge&f=false">On the Road with the Ramones By Monte A. Melnick, Frank Meyer</a>
    
                     <a href="http://books.google.co.uk/books?ei=AxPJU5u3Jae60QXB1ICQBQ&id=QTjaAAAAMAAJ&dq=ramones+stonehenge&focus=searchwithinvolume&
                     q=+stonehenge" title="http://books.google.co.uk/books?ei=AxPJU5u3Jae60QXB1ICQBQ&id=QTjaAAAAMAAJ&dq=ramones+stonehenge&focus=search
                     withinvolume&q=+stonehenge">A Time to Rock: A Social History of Rock and Roll by David P. Szatmary</a>
    
    
    #cdata-section : 
    

    powershell equivalent of linux 'ps -aux | sort -k3n'

    I’m not entirely sure how I managed to not find out about Win32_PerfFormattedData_PerfProc_Process before now. I think the ‘sort -k3n’ does a sort by CPU-usage, but I’m sure there’s a better way of doing it than that.

    gwmi Win32_PerfFormattedData_PerfProc_Process -ComputerName $ComputerName | 
      Sort-Object -Property PercentProcessorTime -desc | 
      select idprocess, name, IODataBytesPersec, PercentPrivilegedTime,PercentProcessorTime, PercentUserTime, workingset | 
      Select-Object -first 11 | 
      ft -AutoSize
    

    gives:

    idprocess name      IODataBytesPersec PercentPrivilegedTime PercentProcessorTime PercentUserTime workingset
    --------- ----      ----------------- --------------------- -------------------- --------------- ----------
            0 _Total               849620                   100                  100              18 5667786752
            0 Idle                      0                   100                  100               0       4096
         5552 sqlservr             236135                     0                   18              18 3040718848
         3680 TmListen             344690                     6                    6               0   10211328
        10012 PccNTMon               7574                     6                    6               0    4706304
          496 services                  0                     0                    0               0   11198464
          744 svchost#3                 0                     0                    0               0   69857280
          568 svchost#2                 0                     0                    0               0   14368768
          792 svchost#1                 0                     0                    0               0   24203264
         2132 svchost                   0                     0                    0               0    5054464
         5888 Ssms#1                    0                     0                    0               0  190734336
    

    powershell equivalent of linux 'ps -aux | sort -k3n'

    I’m not entirely sure how I managed to not find out about Win32_PerfFormattedData_PerfProc_Process before now. I think the ‘sort -k3n’ does a sort by CPU-usage, but I’m sure there’s a better way of doing it than that.

    gwmi Win32_PerfFormattedData_PerfProc_Process -ComputerName $ComputerName | 
      Sort-Object -Property PercentProcessorTime -desc | 
      select idprocess, name, IODataBytesPersec, PercentPrivilegedTime,PercentProcessorTime, PercentUserTime, workingset | 
      Select-Object -first 11 | 
      ft -AutoSize
    

    gives:

    idprocess name      IODataBytesPersec PercentPrivilegedTime PercentProcessorTime PercentUserTime workingset
    --------- ----      ----------------- --------------------- -------------------- --------------- ----------
            0 _Total               849620                   100                  100              18 5667786752
            0 Idle                      0                   100                  100               0       4096
         5552 sqlservr             236135                     0                   18              18 3040718848
         3680 TmListen             344690                     6                    6               0   10211328
        10012 PccNTMon               7574                     6                    6               0    4706304
          496 services                  0                     0                    0               0   11198464
          744 svchost#3                 0                     0                    0               0   69857280
          568 svchost#2                 0                     0                    0               0   14368768
          792 svchost#1                 0                     0                    0               0   24203264
         2132 svchost                   0                     0                    0               0    5054464
         5888 Ssms#1                    0                     0                    0               0  190734336
    

    powershell error: 'Cannot perform operation because operation 'ReportWrongProviderType' is invalid'

    I got the following error from a Powershell script I wrote to run SQLExress backups on a remote server.

    The script runs on a Standard Edition server as a SQL Agent job. It creates and then runs a T-sql script on the remote server to backup all the databases to a folder on the remote server.

    The error occurred when I migrated the job from a Windows 2003 server running SQL 2008 R2 to a Windows 2012 Server running SQL 2012

    Message
    A job step received an error at line 18 in a PowerShell script. 
    The corresponding line is "invoke-sqlcmd -outputsqlerrors $True -ServerInstance $ServerInstance -QueryTimeout 3600 -InputFile d:\dbawork\admin\bin\sp_BackupDatabases.sql > $SqlOutputLog". 
    Correct the script and reschedule the job. 
    The error information returned by PowerShell is: "Cannot perform operation because operation "ReportWrongProviderType" is invalid. Remove operation "ReportWrongProviderType", or investigate why it is not valid.
    

    The problem was that the Powershell didn’t like the log output being re-directed to a UNC path.

    So I changed this:

    $SqlOutputLog =  "\\server1\d$\sql_backup\remote_backups\log\" + $ServerInstance.replace("\", "_") + "_sql_output.log"
    invoke-sqlcmd -outputsqlerrors $True -ServerInstance $ServerInstance -QueryTimeout 3600 -InputFile d:\dbawork\admin\bin\sp_BackupDatabases.sql > $SqlOutputLog
    

    to this

    
    $SqlOutputLog =  "d:\sql_backup\remote_backups\log\" + $ServerInstance.replace("\", "_") + "_sql_output.log"
    invoke-sqlcmd -outputsqlerrors $True -ServerInstance $ServerInstance -QueryTimeout 3600 -InputFile d:\dbawork\admin\bin\sp_BackupDatabases.sql > $SqlOutputLog
    

    i.e. I changed ‘\\server1\d$’ to ’d:'

    I’m not sure what the root cause here was, to be honest. If time ever allows I’ll do some investigation.

    how to see veeam backups in powershell

    This allows you to see veeam backups for a specified server over the last week.

    The code

    Enter-PSSession yourveeamserver 
    Add-PSSnapin VeeamPSSnapIn 
    Get-VBRBackupSession | ? JobName -like "*yourtargetserver*" | ? endtime -gt $(get-date).adddays(-7) | 
        select jobname, jobtype, creationtime, endtime, result, state | sort-object -property jobname, endtime | 
        ft -AutoSize 
    

    Explanation

    Explaining this a little…..

    This line ‘remotes’ to the veeam server. Getting Powershell remoting set-up is another subject. I’d recommend the Powershell help topic about_remote_troubleshooting, if it doesn’t ‘just work’.

    Enter-PSSession yourveeamserver 
    

    This loads all the veeam cmdlets into memory

    Add-PSSnapin VeeamPSSnapIn 
    

    This line depends on your Veeam job having the name of the server you’re interested in, in the title. You can run a command to show which job backs up which database. I’ll perhaps post that soon.

    Get-VBRBackupSession | ? JobName -like "*yourtargetserver*" | ? endtime -gt $(get-date).adddays(-7) | 
        select jobname, jobtype, creationtime, endtime, result, state | sort-object -property jobname, endtime | 
        ft -AutoSize 
    

    list AD users in powershell

    This shows all the users with ‘dba’ in their username. Obviously you could leave out the filter clause altogether to get a complete list of AD users

    Get-ADUser -Filter {samaccountname -like "*dba*"} -SearchBase "dc=mycomp,dc=co,dc=uk" |
        select samaccountname, name
    
    
    samaccountname                                                      name   
    --------------                                                      ----   
    dba_john                                                            John Hollins
    dba_terry                                                           Terry Dixon
    
    

    You have to ActiveDirectory Powershell module loaded

    how to get a list of images uploaded to wordpress.com website

    • Go to your media library and switch to the ‘List View’

    • Then under ‘Screen Options’ bump up the ‘Number of items per page’ to a big number

    Screen shot of wordpress media screen

    • Right click to ‘View Page Source, then save it somewhere on your computer

    • Run the following in PowerShell

    foreach ($line in select-string filename .\upload.php | Sort-Object -Property line ) {
        $line.line.split(">")[3].split("<")[0]
    }
    

    This gives you a list that looks like this:

    Screen shot of powershell list

    how to get a list of images uploaded to wordpress.com website

    • Go to your media library and switch to the ‘List View’

    • Then under ‘Screen Options’ bump up the ‘Number of items per page’ to a big number

    Screen shot of wordpress media screen

    • Right click to ‘View Page Source, then save it somewhere on your computer

    • Run the following in PowerShell

    foreach ($line in select-string filename .\upload.php | Sort-Object -Property line ) {
        $line.line.split(">")[3].split("<")[0]
    }
    

    This gives you a list that looks like this:

    Screen shot of powershell list

    Powershell function to get Sqlserver errorlog recent lines

    I’ve started knocking up a function to return the last few lines of a sqlserver errorlog.

    This is a little way from being finished….but I’ve already found it quite handy

    function get-sqlerrorlog { 
    
      [CmdletBinding()]	
      Param( 
          [String] [alias("computer")] $ComputerName,
          [Int] [alias("lines")] $NumberOfLines = 5
      )
    
      write-verbose "Running function $([string]$MyInvocation.MyCommand.name)"
      
      Write-verbose "`$ErrorLogFolder: $ErrorLogFolder"
    
      $ErrorLogFolder = dir sqlserver:\sql\$ComputerName 
    
      # Todo: need to work out how it works more > 1 named instance. This just picks 1st
      [string]$ErrorLogFolder = $($ErrorLogFolder | select -first 1).errorlogpath
      Write-verbose "`$ErrorLogFolder: $ErrorLogFolder"
    
      $ErrorLogFolder = $ErrorLogFolder.replace(':', '$')
      Write-verbose "`$ErrorLogFolder: $ErrorLogFolder"
    
      $ErrorLogFolder = '\\' + $ComputerName + '\' + $ErrorLogFolder
      Write-verbose "`$ErrorLogFolder: $ErrorLogFolder"
    
      # Todo: it might be that the get-content could be speeded up by retrieving less lines
      # Todo: seperate this bit out into seperate function ?  
      get-content "$ErrorLogFolder\ERRORLOG" | select -last $NumberOfLines                                                                
     
    }
    set-alias gsel get-sqlerrorlog
    
    

    getting a list of aliases ordered by the aliasee

    This is fairly trivial…and I’ve no idea if ‘aliasee’ is a real word or not, but I found this quite useful today:

    get-alias | select ResolvedCommand, name | sort -property resolvedcommand
    

    On my laptop, this gives:


    ResolvedCommand Name --------------- ---- Add-Content ac Add-PSSnapin asnp Clear-Content clc Clear-History clhy Clear-Host cls Clear-Host clear Clear-Item cli Clear-ItemProperty clp Clear-Variable clv Compare-Object diff Compare-Object compare Connect-PSSession cnsn Convert-Path cvpa Copy-Item cp Copy-Item copy Copy-Item cpi Copy-ItemProperty cpp Disable-PSBreakpoint dbp Disconnect-PSSession dnsn Enable-PSBreakpoint ebp Enter-PSSession etsn Exit-PSSession exsn Export-Alias epal Export-Csv epcsv Export-PSSession epsn ForEach-Object foreach ForEach-Object % Format-Custom fc Format-List fl Format-Table ft Format-Wide fw Get-Alias gal get-cal cal Get-ChildItem dir Get-ChildItem ls Get-ChildItem gci Get-Command gcm Get-Content cat Get-Content gc Get-Content type get-functions getf Get-History history Get-History ghy Get-History h Get-Item gi Get-ItemProperty gp Get-Job gjb Get-Location pwd Get-Location gl Get-Member gm Get-Module gmo get-os gos Get-Process gps Get-Process ps Get-PSBreakpoint gbp Get-PSCallStack gcs Get-PSDrive gdr Get-PSSession gsn Get-PSSnapin gsnp Get-Service gsv Get-Unique gu Get-Variable gv Get-WmiObject gwmi Group-Object group help man Import-Alias ipal Import-Csv ipcsv Import-Module ipmo Import-PSSession ipsn Invoke-Command icm Invoke-Expression iex Invoke-History r Invoke-History ihy Invoke-Item ii Invoke-Locate.ps1 locate Invoke-NullCoalescing ?? Invoke-RestMethod irm Invoke-WebRequest wget Invoke-WebRequest iwr Invoke-WebRequest curl Invoke-WmiMethod iwmi Measure-Object measure mkdir md Move-Item move Move-Item mv Move-Item mi Move-ItemProperty mp New-Alias nal New-Item ni New-Module nmo New-PSDrive mount New-PSDrive ndr New-PSSession nsn New-PSSessionConfigurationFile npssc New-Variable nv Out-GridView ogv Out-Host oh Out-Printer lp Pop-Location popd powershell_ise.exe ise Push-Location pushd Receive-Job rcjb Receive-PSSession rcsn Remove-Item rmdir Remove-Item del Remove-Item rd Remove-Item rm Remove-Item erase Remove-Item ri Remove-ItemProperty rp Remove-Job rjb Remove-Module rmo Remove-PSBreakpoint rbp Remove-PSDrive rdr Remove-PSSession rsn Remove-PSSnapin rsnp Remove-Variable rv Remove-WmiObject rwmi Rename-Item rni Rename-Item ren Rename-ItemProperty rnp Resolve-Path rvpa Resume-Job rujb Select-Object select Select-String sls Set-Alias sal Set-Content sc set-debug db Set-Item si Set-ItemProperty sp Set-Location sl Set-Location chdir Set-Location cd Set-PSBreakpoint sbp Set-Variable sv Set-Variable set Set-WmiInstance swmi Sort-Object sort Start-Job sajb Start-Process start Start-Process saps Start-Service sasv Start-Sleep sleep Stop-Job spjb Stop-Process kill Stop-Process spps Stop-Service spsv Suspend-Job sujb Tee-Object tee Trace-Command trcm Update-LocateDB.ps1 updatedb Wait-Job wjb Where-Object where Where-Object ? Write-Output write Write-Output echo

    how to rdp to several desktops one after the other

    For reasons that aren’t necessarily relevant, I wanted to use Remote Desktop to visit a list of servers1. I tried doing this:

    foreach ($S in "server01", "server02, "server03") { 
        mstsc /f /V:$S
    }
    

    This works….but it immediately starts rdp sessions to each of the servers. This is fine in this example, where there are only 3 servers, but in real life I’ve got a list of twenty or so and I don’t really want to open 20-odd rdp sessions at once.

    What I did instead to force it do the rdp’s sequentially was this:

    foreach ($S in "server01", "server02, "server03") { 
        mstsc /f /V:$S
        $ThrowAway = read-host "Hit Return"
    }
    

    1. I'd really rather not do this, but I can't find a safe and seen-to-be-safe way of doing what I want to do through PowerShell or any other automated tool 

    how to extract tweets about...

    This was the Powershell code I used to create the all the podcasts I’ve ever tweeted about post.

    I downloaded the tweets from Twitter itself - I think there was a link somewhere within ‘Settings’

    The .csv file looks like this:

    Tweets csv file

    So the code is:

    $PodTweets = Import-Csv c:temptweets.csv | ? text -like "*podcast*"
    
    $TweetsAsHtml = foreach ($P in $PodTweets)
    {
    #   write-output $P.timestamp.Substring(0,10)
    
       # Splitting the tweet text into words to allow for the processing of urls
       $TweetTextAsArray = $P.text.split(" ")
    
       $TextWithLink=""
    
       foreach ($Word in $TweetTextAsArray)
       {
            if ($Word -like "http:*")
            {
                # if there is an expanded_url, then use that instead
                if ($P.expanded_urls -ne "")
                {
                    $Word = $P.expanded_urls
    
                    # for some reason the expanded url is sometimes repeated in the download
                    if ($Word -like "*,*")
                    {
                        $Word = $Word.split(",")[0]
                    }
                }
    
                # re-format the URL as a link
                $Word = "`<a href=`"$Word`"`>$Word`<`/a`>"
            }
            $TextWithLink = "$TextWithLink$Word "
    
    
        }
    
        # create an object and output that
        $properties = @{'TweetDate'=$P.timestamp.Substring(0,10);
                        'TweetText'=$TextWithLink}
    
        $ReformattedTweets = New-Object -Type PSObject -Prop $properties
    
        write-output $ReformattedTweets
    
    }
    
    $TweetsAsHtml | fl | out-file -encoding ascii -FilePath x.txt -width 1000
    

    system databases not included in powershell sqlserver provider 'databases' folder

    I hadn’t noticed this before.

    If you do a dir listing of the databases for an instance within the Powershell Sqlserver provider, it doesn’t show the system databases

    PS C:powershell> dir SQLSERVER:\SQL\my_pcinst2012\databases
    
    Name                 Status          Recovery Model CompatLvl Collation                      Owner
    ----                 ------          -------------- --------- ---------                      -----
    AdventureWorks2012   Normal          Simple               110 SQL_Latin1_General_CP1_CI_AS   matty
    TSQL2012             Normal          Full                 110 Latin1_General_CI_AS           matty
    

    To get a listing for the system databases you can do the following. I would imagine there’s a better way (perhaps some equivalent to ls -a?)…but I can’t think of it at the minute1

    PS C:powershell> foreach ($DB in ("master", "msdb", "model", "tempdb")) {gi SQLSERVER:\SQL\my_pcinst2012\databases\$DB }
    
    Name                 Status          Recovery Model CompatLvl Collation                      Owner
    ----                 ------          -------------- --------- ---------                      -----
    master               Normal          Simple               110 Latin1_General_CI_AS           sa
    msdb                 Normal          Simple               110 Latin1_General_CI_AS           sa
    model                Normal          Simple               110 Latin1_General_CI_AS           sa
    tempdb               Normal          Simple               110 Latin1_General_CI_AS           sa
    

    1. The ‘better way’ is to use gci -force. That includes all the system databases. ↩︎

    Powershell pattern matching to check if a string is hex

    Hexadecimal-counting I’ve been playing with pattern matching in Powershell.

    I was trying to use ‘-match’ to ‘Check if the string is a hexadecimal number’ for the ‘Perl one-liners in Powershell’ page I’ve been working on.

    I can’t pretend to entirely understand or explain pattern matching in Powershell, or in linux, but this seems to work.

    $X = "21e" ; $Y = $X.length ; $X -match "[0123456789abcde]{$Y}"
    

    This says match the string against ‘any combination of the characters within the square brackets (i.e. the hex digits) to the same length as the original string’.

    So, the square brackets contain the allowable characters.

    The curly brackets give the number of characters.

    I tried just doing:

    $X = "21e" ; $X -match "[0123456789abcde]{$X.length}"
    

    …but this didn’t seem to work.

    Tests

    I tried the following strings - they all seemed to come up with the right answer: ``` $ $X = "21e" ; $Y = $X.length ; $X -match "[0123456789abcde]{$Y}" True $ $X = "21edjhsd" ; $Y = $X.length ; $X -match "[0123456789abcde]{$Y}" False $ $X = "21e34782348237847832748723" ; $Y = $X.length ; $X -match "[0123456789abcde]{$Y}" True $ $X = "21e34782348237847832748723f" ; $Y = $X.length ; $X -match "[0123456789abcde]{$Y}" False $ $X = "21e34782348237847832748723acbdaaa" ; $Y = $X.length ; $X -match "[0123456789abcde]{$Y}" True $ $X = " " ; $Y = $X.length ; $X -match "[0123456789abcde]{$Y}" False ```

    ….although I’m not sure whether this is right or wrong:

    $ $X = "" ; $Y = $X.length ; $X -match "[0123456789abcde]{$Y}"
    True
    
← Newer Posts Older Posts →