Powershell – Basics 3

If we look more into powershell programming

#---------------------------------------------------
# Functions
#---------------------------------------------------

# Functions are basically script blocks with names.
function write-fullname($firstName, $lastName)
{
    Write-host ($lastName + " , " + $firstName)
}

write-fullname "Kishore" "Patil"  //output: Patil, Kishore

# unlike other languages, you don't use () or ,
# Rather than using set-variable with its -scope, you can pass by ref
# Note however it turns it into an object, thus requiring the .Value syntax
function Set-fvar([ref] $myparam)
{
$myparam.Value = 33
}

clear-host
$fvar = 42
"fvar before: $fvar"
Set-fvar ([ref] $fvar) # Must add ref to call
"fvar after: $fvar"

# Read from pipeline
function Get-CoolFiles()
{
    begin {$retval = "Here are some cool files: `r`n"}
    process {
                if ($_.Name -like "*.ps1")
                    {$retval = $retval + "`t"+ $_.Name + "`r`n"}
                }
    end {return $retval}
}


clear-host
Get-ChildItem | Get-CoolFiles

# Above works but ties it to PS1


# Filters can be built to remove unwanted files
filter Show-PS1Files
{
    $filename = $_.Name
    if ($filename -like "*.ps1")
        { 
            return $_
         }
}

clear-host
Get-ChildItem | Show-PS1Files

# This Version doesn't check for ps1, it just lists what's passed in
function List-FileNames()
{
  begin {$retval = "Here are some cool files: `r`n"}
    process {
               $retval = $retval + "`t"+ $_.Name + "`r`n"
                }
    end {return $retval}
    
}

clear-host
Get-ChildItem | List-FileNames

#Now combine the two for real flexibility
Get-ChildItem | Show-PS1Files | List-FileNames

# Now to do other files, just create another filter
filter Show-textfiles
{
    $filename = $_.Name
    if ($filename -like "*.txt")
        { 
            return $_
         }
}


Get-ChildItem | Show-textFiles | List-FileNames

# Now you have two ways to use your functions
clear-host
Get-ChildItem | Show-PS1Files | List-FileNames
Get-ChildItem | Show-textFiles | List-FileNames

# Having your function output to the pipeline
clear-host
Get-ChildItem | Select-Object "Name"

function Get-ChildName()
{
    Write-output (Get-ChildItem | Select-Object "Name")
}

Get-ChildName | Where-Object {$_.Name -like "*.ps1"}

# Supporting -verbose and -debug options
# To support, first need to change the values of the special variables:
# $DebugPreference        Default is SilentlyContinue, change to Continue
# $VerbosePreference      Default is SilentlyContinue, change to Continue

function Get-ChildName()
{
    param([switch]$verbose, [switch]$debug)
    
    if ($verbose.IsPresent)
    { $VerbosePreference = "Continue"} 
    else
    {$VerbosePreference = "SilentlyContinue"}   
    if ($debug.IsPresent)
    {
        $DebugPreference = "Continue"
    }
    else
    {
        $DebugPreference = "SilentlyContinue"
    }
    
    
    write-verbose "Current working location is $(Get-Location)"
    write-output (Get-ChildItem | Select-Object "Name")
    write-debug "OK I've selected some."
}

clear-host
Get-ChildName
Get-childname -verbose
Get-childName -debug
Get-ChildName -verbose -debug


#-------------------------------------------------------
# Adding help to your functions
#-------------------------------------------------------

clear-host
get-help get-childname

#Custom tags within a comment block that Get-Help will recognize
# Note that not all of them are required
# .SYNOPSIS        - A brief description of the command
# .DESCRIPTION     - Detailed command description
# .PARAMETER name  - Include one description for each parameter
# .EXAMPLE         - Detailed examples on how to use the command
# .INPUTS          - What pipeline inputs are supported
# .OUTPUTS         - What this function outputs
# .NOTES           - Any misc notes you haven't put anywhere else
# .LINK            - A link to the URL for more help. Use one .Link tag per URL
# Use "Get-Help about_comment_based_help" for full list and details

function Get-ChildName()
{
<#
    .SYNOPSIS
    Returns a list of only the names for the child items in the current location.
    
    .DESCRIPTION
    This function is similar to Get-ChildItem, except that it returns only the name property.
    
    .INPUTS
    None.
    
    .OUTPUTS
    System.String. sends a collection of strings out of the piepeline.
        
#>

    Write-output (Get-ChildItem | Select-Object "Name")
}


clear-host
get-help get-childname


clear-host
get-help get-childname -full

#---------------------------------------------------------------
# Error handling
#---------------------------------------------------------------

function divier($enum, $denom)
{
    Write-Host "Divier begin"
    $result = $enum / $denom
    Write-host "Result: $result"
    Write-Host "Divier done."
}

clear-host
divier 33 11

divier 33 0

function divier($enum, $denom)
{
    Write-Host "Divier begin"
    $result = $enum / $denom
    Write-host "Result: $result"
    Write-Host "Divier done."
    trap
    {
        write-host "oh no! An error has occured !!"
        write-host $_.ErrorId
        write-host $_.Exception.Message
        continue # Continue will continue with the next line of code after the error
    }
}

clear-host
divier 33 0

function divier($enum, $denom)
{
    Write-Host "Divier begin"
    $result = $enum / $denom
    Write-host "Result: $result"
    Write-Host "Divier done."
    trap
    {
        write-host "oh no! An error has occured !!"
        write-host $_.ErrorId
        write-host $_.Exception.Message
        break # With break, or omitting it, error bubbles up to parent
    }
}

clear-host
divier 33 0

function divier($enum, $denom)
{
    trap [System.DivideByZeroException]
    {
        write-host "Hey, chowderhead, you can't divide by zero!"
        continue
    }
     trap
    {
        write-host "oh no! An error has occured !!"
        write-host $_.ErrorId
        write-host $_.Exception.Message
        break # With break, or omitting it, error bubbles up to parent
    }
    Write-Host "Divier begin"
    $result = $enum / $denom
    Write-host "Result: $result"
    Write-Host "Divier done."
   
}

clear-host
divier 33 0

# Two main ways to handle errors
# Option 1 - Handle error internally - see above function

# option 2 - Add trap logic in parent

# Change continue to break
function divier($enum, $denom)
{
    trap [System.DivideByZeroException]
    {
        write-host "Hey, chowderhead, you can't divide by zero!"
        break
    }
     trap
    {
        write-host "oh no! An error has occured !!"
        write-host $_.ErrorId
        write-host $_.Exception.Message
        break # With break, or omitting it, error bubbles up to parent
    }
    Write-Host "Divier begin"
    $result = $enum / $denom
    Write-host "Result: $result"
    Write-Host "Divier done."
   
}

# Now call routine in a script block or other function
& {
clear-host
divier 33 0

# Assume child has handled error, keep goin silently
trap
{ continue }

}

#-----------------------------------------------------------#
# Working with files
#-----------------------------------------------------------#
clear-host
Get-ChildItem "?.txt"

Get-Content "a.txt"
$a = Get-Content "a.txt"

clear-host
$a

# Looks are decptive, this actually an array
$a[0]
$a[1]

$a.GetType()

clear-host
for($i =0;$i -le $a.Count;$i++)
{$a[$i]}

# To combine, we can use join, passing in the seperator and the variable
$seperator = [System.Environment]::NewLine # could have done `r`n
$all = [string]::Join($seperator, $a)

$all

$all.GetType()  # string

# Supports wildcards
$courses = Get-content "?.txt"
$courses

$allcourses =[string]::Join($seperator, $courses)
$allcourses

# To write things to disk, use set-content

# Just to prove it's not there
Get-ChildItem "All Courses.txt"

set-content -value $allcourses -path "All Courses.txt"

Get-Content "All Courses.txt"

# Set-Content is destructive!!! If the file exists it's overwritten
Set-Content -Value "Powershell" -Path "All Courses.txt"
Get-Content "All Courses.txt"

# To append, use add-content
set-content -value $allcourses -path "All Courses.txt" # Recreate file
Get-Content "All Courses.txt"


Add-Content -Value "Powershell" -Path "All Courses.txt"
Get-Content "All Courses.txt" # Show it again with new course

# clean up afterward
Remove-item "All courses.txt"

# csv files
# use it to save objects

Get-process | Export-CSV "Processes.csv"

# And then read them
$header = "_NounName", "Name", "Handles", "VM", "WS", "PM", "NPM", "Path", "Company", "CPU", "FileVersion", "ProductVersion", "Product"
$processes = Import-CSV "Processes.csv" -Header $header
$processes

# XML Files
# Create an XML Template
$courseTemplate = @"
<courses version="1.0">
    <course>
        <name></name>
        <level></level>
    </course>
</courses>
"@

$courseTemplate | Out-File "C:\Users\Kpatil\documents\Powershell_Tut\somecourses.xml"

# Create a new xml variable and load it from the file
$courseXml = New-Object xml
$courseXml.Load("C:\Users\kpatil\documents\Powershell_Tut\SomeCourses.xml")

# Grab the template
$newCourse = (@($courseXml.courses.course)[0]).Clone()

#Loop over the collection from CSV and add them to the xml
$header = "Course", "Level"
$coursecsv = Import-Csv "All Courses.csv" -Header $header

for($i=0;$i -lt $coursecsv.Count;$i++)
{
    $newCourse = $newCourse.Clone() # copy the previous object, or for the first time copy the template
    $newCourse.Name = $coursecsv[$i].Course
    $newCourse.Level = $coursecsv[$i].Level
    $courseXml.Courses.AppendChild($newCourse) > $null # If you don't redirect to Null it echos each appen
}

#Remove the template since we now have data
$courseXml.Courses.Course |
    Where-Object {$_.Name -eq ""} |
    ForEach-Object {[void]$courseXml.Courses.RemoveChild($_)}

# Save to Xml file
$courseXml.Save("C:\Users\kpatil\documents\Powershell_Tut\SomeCourses.xml")

# Open it up and show as a plain text file
$textxml = Get-content "C:\Users\kpatil\documents\Powershell_Tut\SomeCourses.xml"
$textxml

# Open it up and work with it as an xml file
$mycoursesxml = get-content "C:\Users\kpatil\documents\Powershell_Tut\SomeCourses.xml"
foreach($course in $mycoursesXml.courses.course)
{
    Write-host "The course" $course.Name "is a Level" $course.Level "course."
}

3 thoughts on “Powershell – Basics 3

  1. Chin

    Hello there men, superb website, rather wealthy in material and accurately carefully thought out, personally I found right here substantially remarkable and advantageous

    Reply
  2. Malcolm Northrup

    I was just looking for this specifics for a while. Just after 6 hrs of ongoing Googleing, at last I got it in your word wide web online site. I question what is the Google’s predicament that doesn’t rank this kind of helpful web-sites closer towards the top notch. Often the highest web pages are filled with garbage.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.