Powershell coding journal


Write-Host "\nReporting on the results of the ping status"
if ($netResult.PingSucceeded -eq $true)
{
         Write-Host "Ping succeeded. Details will follow"
}
else 
{
         Write-Host "ping failed. Details will follow"
}

How to insert a new line character in a powershell string write-host

Search for: How to insert a new line character in a powershell string write-host


function startSection($line)
{
   #Start a new line
   #Uses backtick character as the escape
   #Also called grave accent
   Write-Host "`n$line"
}

Special characters are documented here

winscp module is documented here


#Find modules that are named like ftp in the galleries
find-module -name *ftp*

#Some module may not be named that way
find-module -name winscp

To search for modules in powershell gallery

line continuation in powershell

Search for: line continuation in powershell

it appears to be backtick

About throw


if(somefunc($input) - eq $false)
{
    //do something
}

#that is a problem

it should be

if((somefunc($input)) - eq $false)
{
    //do something
}

Notice extra brackets

Ideally it should be

if((somefunc -input $input) - eq $false)
{
    //do something
}

This is to do with grouping

<#
# *************************************************
#
# Read Credentials for an ftp host
#
# A formulated $credential object is returned
# Object type is:
# System.Management.Automation.PSCredential
#
# From the environment:

# the following from the environment
#
# Assuming an ftp host name is: ftphost
# ftp.ftphost.host
# ftp.ftphost.username
# ftp.ftphost.password
#
# *************************************************
#>
function isValid($somestring)
{
    if ($somestring -eq $null)
    {
        return $false
    }
    
    if ($something -eq "")
    {
        return $false`
    }
    return $true
}

function getEnvVariable($name)
{
    $valid = isValid($name)
    if ($valid -eq $false)
    {
        throw "Invalid environment variable name: null or empty"
    }
    $value = Get-ChildItem -Path "Env:$name" -ErrorAction Ignore
    $returnValue = $value.value

    if ((isValid($returnValue)) -eq $fasle)
    {
        throw "Empty environment output for variable:$name"
    }
    return $returnValue
}


function getCredentials($hostname)
{
    $env_username = "ftp." + $hostname + ".username"
    $env_password = "ftp." + $hostname + ".password"

    $username = getEnvVariable -name $env_username
    $passwordPlain = getEnvVariable -name $env_password

    $password = ConvertTo-SecureString $passwordPlain -AsPlainText -Force

    $credential = New-Object System.Management.Automation.PSCredential($username, $password)
    return $credential
}

$credentials = getCredentials -hostname "ftphost"
#Will loo

Write-Host "Username $($credentials.username)"
Write-Host "Password: $($credentials.password)"

How to invoke a REST call from powershell: microsoft docs Invoke-RESTMethod

ISO Date and time format

Search for: ISO Date and time format


//Notice the T
2019-09-01T00:00:00.000
YYYY-MM-DDTHH:MM:SS.SSS

or

//I have seen this work without the T
2019-09-01 00:00:00.000
YYYY-MM-DD HH:MM:SS.SSS

web reference for ISO date time format

is T optional in ISO date formats?

Search for: is T optional in ISO date formats?

Optional T discussion on SOF

Here is a CSV to JSON converter online

table to class json creators

Search for: table to class json creators

powershell class definitions

Search for: powershell class definitions

Powershell classes docs


class Device {
    [string]$Brand
    [string]$Model
    [string]$VendorSku
}

$device = [Device]::new()
$device.Brand = "Microsoft"
$device.Model = "Surface Pro 4"
$device.VendorSku = "5072641000"

$device

How to call a storedproc from powershell

Search for: How to call a storedproc from powershell

This is a good example

t-sql sample stored procedures

Search for: t-sql sample stored procedures

Here is the doc for System.Data.SqlClient.SqlCommand

Reading from a stored proc from Invoke-SQLCommand

Invoke-SQLCommand powershell

Search for: Invoke-SQLCommand powershell

Docs on invoke-sqlcommand

strangeness and rules of braces in powershell

Search for: strangeness and rules of braces in powershell


#problem calling a function
$csvFileList = getStagedCSVFiles()


#not a problem
$csvFileList = getStagedCSVFiles

How to read records from csv file in powershell

Search for: How to read records from csv file in powershell

Import-CSV Commandlet

PSCustom Object to a typed object in powershell

Search for: PSCustom Object to a typed object in powershell

Nice article on strong types

hashtables, dictionaries, objects

Add-Type commandlet

Search for: Add-Type commandlet


$somestring = @"
   line1
  line2
line3
This termination must be the first 2 characters
"@

Powershell datetime type

Search for: Powershell datetime type

A quick external reference for Powershell types


[string]    Fixed-length string of Unicode characters
 [char]      A Unicode 16-bit character
 [byte]      An 8-bit unsigned character

 [int]       32-bit signed integer
 [long]      64-bit signed integer
 [bool]      Boolean True/False value

 [decimal]   A 128-bit decimal value
 [single]    Single-precision 32-bit floating point number
 [double]    Double-precision 64-bit floating point number
 [DateTime]  Date and Time

 [xml]       Xml object
 [array]     An array of values
 [hashtable] Hashtable object

Tokenizing strings in powershell

Search for: Tokenizing strings in powershell


function extractPlantnameFromFilename($basefilename)
{
    [String[]]$tokens = $basefilename -split "_"
    if ($tokens.Count -lt 1)
    {
        throw "Filename does not contain plantname"
    }
    return $tokens.Item(0)
}

Get-Date Datetime in powershell

Date formats for Powershell


Get-Date -Format s
2020-02-07T18:34:48

function processStagedFiles()
{
    $csvFileList = getStagedCSVFiles
    #printSimpleTypeInfo($csvFileList)

    foreach($file in $csvFileList)
    {
        #printSimpleTypeInfo($file)
        [System.IO.FileSystemInfo]$file1 = $file
        $fullFilenamne = $file1.FullName
        $baseFilename = $file1.BaseName
        $filesize = $file1.Length
        p -message "Going to process $fullFilenamne"

        processFile -fullFilename $fullFilenamne `
            -basefilename $baseFilename `
            -filesize $filesize
    }
}

convert datetime to ISO format in powershell

Search for: convert datetime to ISO format in powershell


Get-Date -Format "dddd MM/dd/yyyy HH:mm K"

Tuesday 06/25/2019 16:17 -07:00

function testDates()
 {
     [DateTime]$datetime = Get-Date

     $ut = $datetime.ToUniversalTime()
     p -message "Universal time $ut"
     #Universal time 02/08/2020 17:13:52

     $iso = $datetime.ToString("yyyy-MM-ddTHH:MM:ss.mmm")
     p -message "iso time $iso"
     #iso time 2020-02-08T12:02:52.13
    }

In VSCdoe, use Ctrl-B to gain more space

A discussion on types and import-csv commandlet

data types for import-csv commandlet

Search for: data types for import-csv commandlet


function testImportCSV()
{
    [Object[]]$rows = Import-Csv -Path $g_testCSVFile
    $numOfRows = $rows.Count
    p -message "Number of rows read $numOfRows"
    foreach ($row in $rows)
    {

        #printSimpleTypeInfo -inputObject $row.datetime
        #This indicates it is a string

        p -message "As a string $($row.datetime)"
        #As a string 2019-10-22 08:30:00

        $datetime = Get-Date -Date $row.datetime
        p -message "As a UTC $($datetime)"
        #As a UTC 10/22/2019 08:30:00
    }

}

How to pass command line arguments to a powershell

Search for: How to pass command line arguments to a powershell

A nice alternative to calling functions with parameters


f1 -a1 10 -a2 "satya" -a3 12

Instead

$args = @{
  a1=10
  a2 = "satya"
  a3 = 12
}

f1 @arrgs

:)

How to work with command line arguments:SOF

about param powershell

Search for: about param powershell

how to test the number of arguments passed in powershell

Search for: how to test the number of arguments passed in powershell

How to call one powershell script from another powershell script

Search for: How to call one powershell script from another powershell script

what is CmdletBinding in powershell

Search for: what is CmdletBinding in powershell

what is $PSScriptRoot

Search for: what is $PSScriptRoot

Invoke-Expression Commandlet

Search for: Invoke-Expression Commandlet

how to include one .ps1 file from another

Search for: how to include one .ps1 file from another

how to include one .ps1 file from another: SOF to the resscue

The dot operator in powershell

Search for: The dot operator in powershell


$scriptDir="C:\satya\....\utils"

$psutils = "$scriptDir\psutils.ps1"
. $psutils

#All functions in psutils.ps1 is now visible

#*********************************************
#  Execute Common libraries: Include this one at the top
#********************************************
function getScriptDir() {
    $script_path    =  $myinvocation.PSCommandPath
    $script_folder  = split-path $script_path -parent
    $script_name    = split-path $script_path -leaf    
    return $script_folder
}
$libScriptDir = getScriptDir

if ($psutilsIncluded -eq $null)
{
    Write-Host "Invoking psutils.ps1 Common utilities"
    ."$libScriptDir\psutils.ps1"
}
#*********************************************
#  Execute Common libraries
#********************************************

Please note, modules may still be the way to go.

Nature of duplicate function names in powershell

Search for: Nature of duplicate function names in powershell


function f1()
{
    Write-host "first time"
}

function f1()
{
    Write-host "second time"
}

#Allowed to have duplicates
#Last one gets the preference
f1

$arsgs is an automatic variable. Here are the docs

Args is much better explained here


#In some .ps1 file you want to test args

function testargsBad()
{
    p -message "From test args"
    p -message "Number of args: $($args.Count)"
}

function testargsGood($myargs)
{
    p -message "From test args"
    p -message "Number of args: $($myargs.Count)"
}

#Try to call a function to examine args
testArgsBad
testargsGood -myargs $args

1. $args is a locally scoped variable in every function including the script itself and all its internal functions

2. that is why what is passed in, into the script file is only valid at the global scope for that script and not at the individual function level scope

3. Not directly related, but on a side note, the $args only contain unnamed variables, that is those that are not declared in params or explicitly qualified with their argument name.

1. If you pass 10 arguments, say, all unnamed

2. say the script has 4 named params as input

3. Then the args array will 6 unnamed params in it

4. The first 4, if they match the names, are assigned to named variables. If they don't match the variable is not initialized. However even then, only the last 6 are considered unnamed.

How do I redirect stdout and stderr from powershell scripts

Search for: How do I redirect stdout and stderr from powershell scripts

Redirection options in powershell are documented here

Write-Information is documented here


function Test-Info
{
    Get-Process P*
    Write-Information "Here you go"
}
Test-Info 6> Info.txt

Notice the 6

How to declare an array in powershell

Search for: How to declare an array in powershell

arrays in powershell


class ErrorArray {
    [String []]$errorArray = @()

    [void]addError($message)
    {
        $this.errorArray += ("Error:" + $message)
    }
    [bool] areThereErros()
    {
        if ($this.errorArray.Count -eq 0)
        {
            return $false
        }
        else {
            return $true
        }
    }

    [void] printErrorArray()
    {
        foreach($error in $this.errorArray)
        {
            p -message $error
        }
    }
}

function getANewErrorArray()
{
    return [ErrorArray]::new()
}

function testErrorArray() 
{
    [ErrorArray]$errorArray = getANewErrorArray
    $errorArray.addError("first one")
    $errorArray.addError("second one")
    if ($errorArray.areThereErros() -eq $true)
    {
        $errorArray.printErrorArray()
    }
}

How to check for a file existence in powershell

Search for: How to check for a file existence in powershell

Test-Path docs


[bool]$result = Test-Path -Path "C:\Documents and Settings\DavidC"

$dirDictionary = [ordered]@{
  c=33
  a=5
  b=10
}

#dirDictionary will keep the order

#But the following doesn't!!!
[System.Collections.Hashtable]$d = $dirDictionary;

Scopes can throw you off. Docs on scope

GetType is documented here


function f1($somearg){}

Then do not call that as

f1($value) 

EVER

INSTEAD

f1 -somearg $value

function countFiles($fileList)
{
    if ($fileList -eq $null)
    {
        return 0
    }
    $fullname = getTypeFullname -inputObject $fileList
    if ($fullname -eq 'System.Object[]')
    {
        [System.Object[]]$a = $fileList
        return $a.Count
    }
    if ($fullname -eq "System.IO.FileInfo")
    {
        return 1
    }
    return $null
}
function testFileList()
{
    hp -message "testing FileList object"
    gotoStageDirectory
    $csvFileList = getStagedCSVFiles

    printSimpleTypeInfo -inputObject $csvFileList

    if ($csvFileList -eq $null)
    {
        p -message "the file list is null"
        return
    }
    if ($csvFileList.isArray -eq $true)
    {
        p -message "It is an array"
    }
    else {
        p -message "it is not an array"
    }

    $numOfFiles = countFiles -fileList $csvFileList
    p -message "Number of files: $numOfFiles"

}

# **********************************************
 # It is useful to know what are the types of 
 # variables in powershell scripts
 # **********************************************
 function printTypeInformation ($inputobject)
 {
     Write-Host "printing type information for type: $($inputobject.GetType())"
     $typeDetails = $inputobject  | Get-Member
     $typeDetails
     $inputObject.GetType()
 }

 function printSimpleTypeInfo($inputObject)
 {
    if ($inputObject -eq $null)
    {
        p -message "The input object you passed is null."
        return
    }
    $typeObject = $inputObject.GetType()
    $typename = $typeObject.FullName
    $typeShortName = $typeObject.name

    p -message "Fullname of the type is: $typename"
    p -message "Short name is: $typeShortName"
    $typeObject
 }

 function getTypeFullname($inputObject)
 {
    if ($inputObject -eq $null)
    {
        p -message "The input object you passed is null."
        return $null
    }
    return $inputObject.GetType().FullName
 }

function testSimpleTypeInfo()
{
    $s = "hello"
    printSimpleTypeInfo -inputObject $s

    #Don't do this
    printSimpleTypeInfo($s)
}

Try and catch

Terminating and nonterminating exceptions

Terminating and non terminating exceptions in powershell

Search for: Terminating and non terminating exceptions in powershell


$ErrorActionPreference = "Stop".

$ErrorActionPreference powershell

Search for: $ErrorActionPreference powershell

work with json files in powershell

Search for: work with json files in powershell

statistic functions in powershell

Search for: statistic functions in powershell

Statistics module for powershell

Measure-Object Powershell

Search for: Measure-Object Powershell

Docs on Measure-object

Sorry that wasn't it. it is here


Median            : 1647.65
Variance          : 191.604814814815
StandardDeviation : 13.8421390982324
Percentile10      : 1635.2
Percentile25      : 1642.2
Percentile75      : 1710.2
Percentile90      :
TukeysRange       : 102
Confidence95      : 0
Count             : 6
Average           : 1662.96666666667
Sum               : 9977.8
Maximum           : 1710.2
Minimum           : 1627.9
Property          : tag_value

#**************************************
    # Measure Average wind direction
    #**************************************
    #Get windspeed tagsg
    $windDirectionArray = $qtrArray | Where-Object {$_.tag_name -eq "YawDirection"} 
    p -message "Number of wind direction records in Q: $($windDirectionArray.Count)"

    $sin = 0
    $cos = 0

    foreach($item in $windDirectionArray)
    {
        [double]$angle = $item.tag_value
        p -message "angle: $angle"
        $sin += [Math]::Sin($angle * 0.0174533)
        $cos += [Math]::Cos($angle * 0.0174533)
    }

    p -message "$sin : $cos"
    $avgAngle = [Math]::Atan2($sin, $cos)
    $avgAngleInDegrees = $avgAngle * 57.2958
    $angle360 = calc360 -angle $avgAngleInDegrees

    p -message "The average angle is $avgAngle : $avgAngleInDegrees : $angle360"
}

function calc360($angle)
{
    $n = 360 + $angle;
    [int]$i = $n % 360
    return $i
}

angle: 310.899993896484
angle: 307.899993896484
angle: 325.200012207031
angle: 323.100006103516
angle: 319.899993896484
angle: 203
angle: 196.100006103516
angle: 307.299987792969
angle: 316.900024414063
angle: 316.5
angle: 313.5
-55.7941435452635 : 34.1923780225009

The average angle is 
in radians: -1.0209956848016 : 
in degrees: -58.4987645572553 : 
in positive degrees: 302

class PlantDataRecord
{
    [single]$generatedCapacity
    [single]$windSpeed
    [single]$windDirection

    [string]ToString(){
        return ("Power: {0}, WindSpeed {1}, Direction {2}" -f `
            $this.generatedCapacity, `
            $this.windSpeed, `
            $this.windDirection)
    }    
}

How to automate powershell scripts through windows task scheduler

Search for: How to automate powershell scripts through windows task scheduler

Here is a good scheduler question where your tasks appear to disappear

Click on "Task Scheduler Library" and see the right hand side change

How to redirect output in task scheduler in windows

Search for: How to redirect output in task scheduler in windows


program >> somelog.txt

Doesn't look like that simple with powershell

And have all the redirections controlled by that batch file.


function importForecastDataCSV($forecastDataFullFilename, $inPlantObject)
{
    $windForecastHeaderRow = 'datetime','forecast_generation_mw',....
    $solarForecastHeaderRow = 'datetime','forecast_generation_mw', ...
    [Plant]$plantObject = $inPlantObject

    $headerRow = $null

    if ($plantObject.typeName -eq "wind")
    {
        p -message "Processing using wind forecast header row"
        $headerRow = $windForecastHeaderRow
    }
    else {
        p -message "Processing using solar forecast header row"
        $headerRow = $solarForecastHeaderRow
    }
    [Object[]]$rows = Import-Csv -Path $forecastDataFullFilename -Header $headerRow

    #First row will have the header that came with the file
    #Remove it from the array
    $rows = $rows[1..($rows.Count - 1)]
    return $rows
}

powershell regex

Search for: powershell regex


#Format: Forecaster_plant_HA_2020-02-22_10-00-00.csv
function validateHAforecastFilename($basefilename)
{
    $regex = "^[a-zA-Z0-9]+_[a-zA-Z0-9]+_HA_\d\d\d\d-\d\d-\d\d_\d\d-\d\d-\d\d.csv$"
    $result = $basefilename -match $regex
    return $result
}
function testReqex()
{
    $n1 = "ul_sidrap_HA_2020-02-28_10-05-00.csv"
    $n2 = "ul_sidrap_HA_2020-02-28_10-05-00.csvdd"
    $n3 = "ul_sidrap_HA_2020-02-28_10-05-00.json"
    $n4 = "_sidrap_HA_2020-02-28_100500.csv"
    $n5 = "ul_sidrap_HAT_2020-02-28_10-05-00.csv"
    $n6 = "ul_sidrap_DA_2020-02-28_10-05-00.csv"

    $n7 = "l_sidrap_HA_2020-02-28_10-05-00.csv"
    $n8 = "7ul_sidrap_HA_2020-02-28_10-05-00.csv"
    $n9 = "l999_sidrap_HA_2020-02-28_10-05-00.csv"

    validateHAforecastFilename -basefilename $n1 #true
    validateHAforecastFilename -basefilename $n2 #false
    validateHAforecastFilename -basefilename $n3 #false
    validateHAforecastFilename -basefilename $n4 #false
    validateHAforecastFilename -basefilename $n5 #false
    validateHAforecastFilename -basefilename $n6 #false

    validateHAforecastFilename -basefilename $n7 #true
    validateHAforecastFilename -basefilename $n8 #true
    validateHAforecastFilename -basefilename $n9 #true

}

Regex from ss64.com

online regex tester

regex cheatsheet


^[a-zA-Z0-9]+_[a-zA-Z0-9]+_HA_\d\d\d\d-\d\d-\d\d_\d\d-\d\d-\d\d.csv$

//using EXACT number of instances
^[a-zA-Z0-9]+_[a-zA-Z0-9]+_HA_\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}.csv$

[string]ToString(){
        return ("Power: {0}, WindSpeed {1}, Direction {2}" -f `
            $this.generatedCapacity, `
            $this.windSpeed, `
            $this.windDirection)
    }

"$($var1)_sometext_$($var2).csv"

why is the task scheduler trying to launch multiple instances at the same time

Search for: why is the task scheduler trying to launch multiple instances at the same time

How to start a task when another task ends in windows task scheduler

Search for: How to start a task when another task ends in windows task scheduler

windows start command

Search for: windows start command

ss64 on start

Microsoft docs on start

Nuances of running a powershell script

how do I simulate wait in a powershell script?

Search for: how do I simulate wait in a powershell script?

start-sleep docs

Get-Error commandlet

Search for: Get-Error commandlet

Docs Get-Error commandlet


function testException()
{
    try { NonsenseString }
    catch {
        pe -message "error"
        [System.Management.Automation.ErrorRecord]$er = $_
        printTypeInformation -inputobject $er
        pe -message "Script stack trace is below"
        p -message $er.ScriptStackTrace
        p -message "Error details: $er.ErrorDetails"
    }
}
testException

function getExceptionMessage($errorRecord)
{
    if ($errorRecord -eq $null)
    {
        return "Sorry Error Record itself is null."
    }

    [System.Management.Automation.ErrorRecord]$er = $errorRecord
    if ($er.ErrorDetails -ne $null)
    {
        return $er.ErrorDetails.ToString()
    }

    #errordetails is null. See for exceptions
    if ($er.Exception -eq $null)
    {
        return "Sorry Error details is null and the Exception object is null in the error record"
    }

    #Exception exists
    $baseException = $er.Exception.GetBaseException()
    if ($baseException -ne $null)
    {
        return $baseException.Message
    }

    #base exception doesn't exist
    return $er.Exception.Message
}
function printErrorRecordDetails($errorRecord)
{
    if ($errorRecord -eq $null)
    {
        pe -message "A null error record is passed in to print its details"
        return
    }

    [System.Management.Automation.ErrorRecord]$er = $errorRecord
    if ($er.ErrorDetails -eq $null)
    {
        pe -message "ErrorDetail is null"
    }
    else {
        pe -message "Error Details follow"
        pe -message $er.ErrorDetails
    }
    if ($er.Exception -eq $null)
    {
        pe -message "Exception of the error record is null"
    }
    else {
        pe -message "Exception message: $er.Exception.Message"
    }

    # possibly [System.Management.Automation.RuntimeException]
    $baseException = $er.Exception.GetBaseException()
    printSimpleTypeInfo -inputObject $baseException

    pe -message "Script Stack trace for the error is below"
    pe -message $er.ScriptStackTrace

    if ($baseException -eq $null)
    {
        pe -message "Base exception is null"
    }
    else {
        pe -message "Base Exception message is: $($baseException.Message)"
        pd -message "Base Exception is: $baseException"
    }
}

Trim for strings in powershell

Search for: Trim for strings in powershell

Trim function from SS64.com

How to figure out if a string is non empty in powershell

Search for: How to figure out if a string is non empty in powershell


function isValid($somestring)
{
    if ($somestring -eq $null)
    {
        return $false
    }
    
    if ($somestring -eq "")
    {
        return $false
    }

    $b = [String]::IsNullOrWhiteSpace($somestring)
    if ($b -eq $true)
    {
        #it is null or white space
        return $false
    }
    return $true
}

How to verify the type of the input variable is a stirng?

what is the perf impact of calling a .net string call? Not sure? I haven't analyzed

Perhaps in the next version


function getSQLStringForNonString($val)
{
    if ($val -eq $null)
    {
        return "null"
    }
    [String]$s = $val
    return $s
}
function getSQLStringForString($val)
{
    if ($val -eq $null)
    {
        return "null"
    }
    if ((isValid -somestring $val) -eq $false)
    {
        #Empty or null
        return "null"
    }
    #a valid string
    return escapeSingleQuotes -s $val
}


function test()
{

    #***********************************
    # Test for non strings
    #***********************************
    $i = 0
    $s = getSQLStringForNonString -val $i
    #0
    p -message "1$s"

    [single]$d = 3.46
    $s = getSQLStringForNonString -val $d
    #3.46
    p -message "2$s"

    $a = $null
    $s = getSQLStringForNonString -val $a
    #null
    p -message "3$s"


    #***********************************
    # Test for strings
    #***********************************
    $a = $null
    $s = getSQLStringForString -val $a
    #null
    p -message "4$s"

    $a = ""
    $s = getSQLStringForString -val $a
    #null
    p -message "5$s"

    $a = "   "
    $s = getSQLStringForString -val $a
    #null
    p -message "6$s"

    $a = " hello"
    $s = getSQLStringForString -val $a
    # hello
    p -message "7$s"

    $a = " hello'there "
    $s = getSQLStringForString -val $a
    # hello''there
    p -message "8$s"

}

function convertStringToNumber($s)
{
    if ((isValid -somestring $s) -eq $false)
    {
        #invaliad string
        return $null
    }

    #valid string
    [int]$number = [int]$s
    return $number
}

function convertStringToFloat($s)
{
    if ((isValid -somestring $s) -eq $false)
    {
        #invaliad string
        return $null
    }

    #valid string
    [single]$numberFloat = [single]$s
    return $numberFloat
}

function invokeVSCode()
 {
     $vscodeWS = "C:\satya\data\code\vs-workspaces\pyspark-vs-workspace.code-workspace"
     code $vscodeWS
 }

Here "code" is a reference to vscode executable code.exe (or a batch file, as I am not sure).


#Say there is a function

function f1() {}

You can then do

[String]$functionName = "f1"

Then you can execute that function

Invoke-Expression -Command $functionName

Or

Invoke-Express -Command "f1"

#
 # This is a better way to initialize
 # as this allows calling functions inside the initialization
 #
 # without this approach, the functions must be defined
 # prior to the initialization. 
 # That forces all dependent functions to be before as well
 #
 $script:dirDictionary = $null
 function init()
 {
    $script:dirDictionary = [ordered]@{
        vscode=createVSCodeCommand
        psutils = 'C:\satya\data\code\power-shell-scripts\individual\satya\git-util'
        home = 'c:\satya'
        pslearn = 'C:\satya\data\code\power-shell-scripts\individual\satya\learn'
        vsworkspaces = "C:\satya\data\code\vs-workspaces"
        shortcuts="C:\Users\satya\OneDrive\Desktop\shortcuts"
        test_func=createTestFunc
    }
}

My Sample code for powershell: Learn Powershell Repo on Github

Here is some sample code to automate your command line needs in windows

1. Remember directories

2. Change directories easily

3. Remember and execute commands as if the commands are directories where changing a directory is just a special function :)

is there a Pair class in powershell

Search for: is there a Pair class in powershell


function getDateForISOString($isoDateString)
{
    return [DateTime]::ParseExact($isoDateString, "yyyy-MM-dd HH:mm:ss",$null)
}

function dbuTestDates()
{
    $dateS = Get-Date -Format s
    p -message "with -Format s: $dateS"
    #"2020-03-22T20:37:35"

    $dateS = Get-Date -Format "yyyy-MM-dd"
    p -message "with format yyyy-MM-dd: $dateS"
    #"2020-03-22"

    [DateTime]$today = Get-Date 
    $trow = $today.AddDays(1)
    p -message $today
    $todayMaxString = $trow.ToString("yyyy-MM-dd")
    p -message "Today midnight: $todayMaxString"

    [DateTime]$todayMaxDateTimeObj = convertDateOnlyStringToDateTime -dateOnlyString $todayMaxString
    p -message "Today midnight: $todayMaxDateTimeObj"

    $backDateTime = $todayMaxDateTimeObj.AddDays(-30)
    p -message "30days ago midnight: $backDateTime"

}

function convertDateOnlyStringToDateTime($dateOnlyString)
{
    $datetime = [DateTime]::ParseExact($dateOnlyString, "yyyy-MM-dd",$null)
    return $datetime
}
function getDurationFor($numberOfDaysBack)
{
    [DateTime]$today = Get-Date 
    $trow = $today.AddDays(1)
    $todayMaxString = $trow.ToString("yyyy-MM-dd")

    [DateTime]$todayMaxDateTimeObj = convertDateOnlyStringToDateTime -dateOnlyString $todayMaxString
    $backDateTime = $todayMaxDateTimeObj.AddDays(-$numberOfDaysBack)

    $duration = @{}
    $duration.fromDateString = getDateStringOnly -dateTimeObj $backDateTime
    $duration.toDateString = getDateStringOnly -dateTimeObj $todayMaxDateTimeObj
    return $duration
}
function getDateStringOnly($dateTimeObj)
{
    return $dateTimeObj.ToString("yyyy-MM-dd")
}

function testDuration()
{
    $d = getDurationFor -numberOfDaysBack 30
    p -message $d.fromDateString
    p -message $d.toDateString
}

Compare-object article

intersection of datasets in powershell

Search for: intersection of datasets in powershell

Compare-Object

Search for: Compare-Object

Compare-object at SS64

Docs on compare-object


function whatChanged($since)
{
    $codeDir = "C:\satya\data\code\jakarta\general-repo"
    changeDirectory -toDir $codeDir
    $filenames = Get-ChildItem *.* -Recurse -File | `
        Where-Object {(whatchangedFileFilter -since $since -fileObj $_)}

    #$filenames | Format-Table -Property FullName

    $filenames | ForEach-Object {replaceRoot -fileObj $_ -root $codeDir} 

}

function replaceRoot($fileObj, $root)
{
    [System.IO.FileInfo]$f = $fileObj
    [String]$fullName = $f.FullName
    return $fullName.Replace($root, "")
}
function whatchangedFileFilter($fileObj, $since)
{
    [System.IO.FileInfo]$f = $fileObj
    if (($f.Extension -in ".txt", ".csv", ".json", ".bak", ".xlsx", ".xml") -eq $true)
    {
        return $false
    }
    #If the file is more recent
    $past = getDateInThePastFor($since)
    if ($f.LastWriteTime -gt $past)
    {
        return $true
    }
    return $false
}

how can I function in powershell receive a piped input

Search for: how can I function in powershell receive a piped input

Operators in powershell

Call operator in powershell

Search for: Call operator in powershell


function getStagedCSVFiles()
{
    hp("Listing staged csv files")
    $csvFileList = listHourAheadCSVFiles -directory $stagingDirectoryPath
    #printTypeInformation -inputobject $csvFileList
    return $csvFileList
}

function listHourAheadCSVFiles($directory)
{
    $fileList = Get-ChildItem -path "$directory/*_XYZ_*.csv" 
    return $fileList
}

function countFiles($fileList)
{
    if ($fileList -eq $null)
    {
        return 0
    }
    $fullname = getTypeFullname -inputObject $fileList
    if ($fullname -eq 'System.Object[]')
    {
        [System.Object[]]$a = $fileList
        return $a.Count
    }
    if ($fullname -eq "System.IO.FileInfo")
    {
        return 1
    }
    return $null
}


function getTypeFullname($inputObject)
 {
    if ($inputObject -eq $null)
    {
        p -message "The input object you passed is null."
        return $null
    }
    return $inputObject.GetType().FullName
}

$csvFileList = getStagedCSVFiles
$numOfFiles = countFiles -fileList $csvFileList

if ($numOfFiles -eq 0)
{
}

function printFileList($csvFileList)
{
    foreach($file in $csvFileList)
    {
        [System.IO.FileInfo]$file1 = $file
        p -message $file1.FullName
    }
}

Formatting numbers is documented here


class QuarterArrays
{
    [System.Collections.ArrayList]$firstQtr = [System.Collections.ArrayList]@()
    [System.Collections.ArrayList]$secondQtr = [System.Collections.ArrayList]@()
    [System.Collections.ArrayList]$thirdQtr = [System.Collections.ArrayList]@()
    [System.Collections.ArrayList]$fourthQtr = [System.Collections.ArrayList]@()

    [void]sinkRow($dataItem)
    {
        $time = $dataItem.timestamp
        $min = getMinutePortion1 -time $time
        if (($min -ge 0) -and ($min -lt 14))
        {
            $this.firstQtr.Add($dataItem)
        }
        elseif (($min -ge 15) -and ($min -lt 30)) {
            $this.secondQtr.Add($dataItem)
        }
        elseif (($min -ge 30) -and ($min -lt 45)) {
            $this.thirdQtr.Add($dataItem)
        }
        elseif (($min -ge 45) -and ($min -le 59)) {
            $this.fourthQtr.Add($dataItem)
        }
    }
    [void]reportNumbers()
    {
        hp -message "Reporting numbers from quarter arrrays"
        p -message "1stQtr: $($this.firstQtr.Count)"
        p -message "2 Qtr: $($this.secondQtr.Count)"
        p -message "3 stQtr: $($this.thirdQtr.Count)"
        p -message " 4stQtr: $($this.fourthQtr.Count)"

    }
}

param (
    #Forecaster id
    $paramForecasterId,

    $paramForecasterName,

    #Base directory for the stage and archive directories
    $paramForecasterBaseDir,

    $paramMaxFilesToProcess,

    $paramRunLocal = $true
)

#Common db utilities
."$libScriptDir\common-dbutils.ps1"

How do you filter filenames on command line in powershell

Search for: How do you filter filenames on command line in powershell


dir | where-object -property name -like "*.*"

dir | where {($_.name -like "*.*")}

#as

dir *.*

#but the approach is valuable when

#Tell me on a file object 
#is there a property like "len"

dir | get-member | where -property name -like *len*

Remove-item docs

Search for: Remove-item docs

docs for Remove-item

write-host considered harmful: article

book excerpt: understanding ps pipeline


function showAndDelete($jsonDi)
{
    [DirInfo]$di = $jsonDi
    hp -message "Showing top 10 files... "
    #This line avoids conflict between write-host and the pipeline output
    #uses write-host via function "p" below instead of printing to the pipeline that is the default
    
    $di.oldFileList | Select-Object -First 10 | ForEach-Object {p -message $_.fullname}
    
    $ans = consoleUtils.readHostWithDefault -prompt "Shall I delete...(y/n):" -default "n"
    if ($ans -eq "n")
    {
        p -message "returning."
        return
    }
    pt -message "Going to delete all the .json files now"
    $di.oldFileList | ForEach-Object {Remove-Item -path $_}
    pt -message "Done deleting .json files"
}

foreach-object docs


ForEach-Object {$_.size = [int]($_.size/1000000); $_}

Format-table docs

it has an alignment directive


$propString = @("dirName", "numOfFiles", "size", "oldFiles", "age", "oldFileSize", "netSize")

$sizeProp = @{
    name="size"
    expression={$_.size}
    alignment="right"
}

$propString2 = @("dirName", 
    "numOfFiles", 
    $sizeProp, 
    "oldFiles", 
    "age", 
    "oldFileSize", 
    "netSize")

powershell.exe -file option


powershell.exe -File ./something.ps1 -arg1 blah -arg2 abc

./a.ps1 "arg1" arg2 "arg3 is a longone"

or

./a.ps1 arg1 arg2 arg3

or

./a.ps1 -arg1 arg1 -arg2 arg2 -arg3 "arg3 is a longone"

$myHashTable = @{a="b";c="d"}

#not fruitful
$myHashTable.tostring()

#but you can do this
$myHashTable | Format-table

#or just on a line by itself
$myHashtable

#Get your type right
[System.Collections.Hashtable]$newargs = $script:myargs

#you can vscode to prompt for methods
$newArgs.add("paramRunMode", "auto")

#print it
$newargs

."$scriptDir\$realScriptName"  @myargs 6>&1 > $logfilename

function getInverterDataArray($invHt)
{
    $keys = $invHt.Keys
    [System.Collections.ArrayList]$invArrayList = [System.Collections.ArrayList]@()
        
    foreach ($invName in $keys)
    {
        $individualInvArray = $invHt[$invName]
        $m = Measure-Object -Data $individualInvArray -property tag_value
        
        [classInverterData]$inverterData = [classInverterData]::new()
        $inverterData.name = $invName
        $inverterData.numOfPoints = $m.count
        $inverterData.averageEnergy = $m.average
        $inverterData.totalEnergy = $m.sum
    #The below can create havoc as well with out $result
        $result = $invArrayList.Add($inverterData)
    }
    #The below can create havoc
    $invArrayList | Format-table
    return $invArrayList
}

How to validate function arguments for null in powershell

Search for: How to validate function arguments for null in powershell

Syntax for parameter validation is verbose for simple run of the mill functions

How to test for non nulls in powershell

Search for: How to test for non nulls in powershell


function fileUtil.getGeneralTimeStampedJustFilename($prefix, $datetimeObj, $ext)
{
    vutils.notnull $prefix $datetimeObj $ext
    vutils.notEmpty $prefix $ext
....
....
rest of the code
....

1. Define an object

2. Get an array of those objects

3. Use export-csv commandlet with the options you need to export to a csv file


function datetime.getRandom()
{
    $hour = Get-Random -Maximum 23 -Minimum 0
    $min = Get-Random -Maximum 59 -Minimum 0
    $sec = Get-Random -Maximum 59 -Minimum 0
    $date = Get-Date
    $d2 = $date.Date
    $d2 = $d2.AddHours($hour)
    $d2 = $d2.AddMinutes($min)
    $d2 = $d2.AddSeconds($sec)
    return $d2
}

function datetime.sampleQtr($datetimeObj)
{
    [DateTime]$d = $datetimeObj
    $date = $d.Date
    $hour = $d.Hour
    $min = $d.Minute
    $qtr = $null
    switch ($min) {
        {$_ -ge 0 -and $_ -lt 15} {$qtr = 0;break }
        {$_ -ge 15 -and $_ -lt 30} {$qtr = 15;break }
        {$_ -ge 30 -and $_ -lt 45} {$qtr = 30;break }
        {$_ -ge 45 -and $_ -lt 60} {$qtr = 45;break }
    }
    if ($qtr -eq $null) {throw "Invalid. quarter cannot be null"}
    $nd = $date.AddHours($hour)
    $nd = $nd.AddMinutes($qtr)
    return $nd
}

ss65: Nature of swtich

docs on switch at microsoft

how to declare function return types

Search for: how to declare function return types


function Get-Time
{
  [OutputType([DateTime])]
  Param (
    [parameter(Mandatory=$true)]
    [Datetime]$DateTime
  )

  $DateTime.ToShortTimeString()
}

Curious concept: ouput type attribute docs

A useful thing I hope to use: Get-PsCallstack


function printCallStack()
{
    hp -message "Pringing call stack"
    $a = Get-PSCallStack | ForEach-Object {$_.Command + "," + $_.Location}
    foreach($item in $a)
    {
        p -message $item
    }
}

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    PSCustomObject                           System.Object

TypeName   : Selected.System.Management.Automation.PSCustomObject
Name       : Equals
MemberType : Method
Definition : bool Equals(System.Object obj)


TypeName   : Selected.System.Management.Automation.PSCustomObject
Name       : GetHashCode
MemberType : Method
Definition : int GetHashCode()


TypeName   : Selected.System.Management.Automation.PSCustomObject
Name       : GetType
MemberType : Method
Definition : type GetType()


TypeName   : Selected.System.Management.Automation.PSCustomObject
Name       : ToString
MemberType : Method
Definition : string ToString()


TypeName   : Selected.System.Management.Automation.PSCustomObject
Name       : root
MemberType : NoteProperty
Definition : string root=Sensor-1082


TypeName   : Selected.System.Management.Automation.PSCustomObject
Name       : tag_name
MemberType : NoteProperty
Definition : string tag_name=T_MOD


TypeName   : Selected.System.Management.Automation.PSCustomObject
Name       : tag_value
MemberType : NoteProperty
Definition : string tag_value=24.42698


TypeName   : Selected.System.Management.Automation.PSCustomObject
Name       : timestamp
MemberType : NoteProperty
Definition : string timestamp=2020-05-01 20:45:00

True     False    PSCustomObject                           System.Object

Add-Member has an explanation of NoteProperties

Documentation of Export-csv

Controlling format-table. Annoying

Out-String commandlet

Search for: Out-String commandlet

Out-String useful docs


Some-list | Format-Table -Autosize | out-string -width 100

$dlist = @($d1, $d2, $d3, $d4)
$dSortedList = $dList | Sort-Object -Property start

sequence generator commandlet in powershell

Search for: sequence generator commandlet in powershell


function utils.number.getSeqGenerator($increment=1)
{
    $count=0;
    {
        $script:count += $increment
        return $count
    }.GetNewClosure()
}

$script:utils_number_SeqGenerator_next = utils.number.getSeqGenerator

function utils.number.getNextSeq()
{
    $n  = &$script:utils_number_SeqGenerator_next
    return $n
}

function testSeq()
{
    $n = utils.number.getNextSeq
    p -message $n
    $n = utils.number.getNextSeq
    p -message $n
    $n = utils.number.getNextSeq
    p -message $n
    $n = utils.number.getNextSeq
    p -message $n
}

I wonder if a class is not better instead, as that will give resets and more methods


dir | Where-Object -Property LastWriteTime -LT yyyy-mm-dd | Remove-item

inheritance in powershell

Search for: inheritance in powershell


class classDuration
{
    [DateTime]$start
    [DateTime]$end

    [string]ToString(){
        return ("start: {0}, End {1}" -f `
            $this.start, `
            $this.end)
    }   
}#end of class

class classDurationDateStrings : classDuration {
    [String]startDateString(){
        return $this.start.ToString("yyyy-MM-dd")
    }

    [String]endDateString(){
        return $this.end.ToString("yyyy-MM-dd")
    }
    [string]ToString(){
        return ("start: {0}, End {1}" -f `
            $this.startDateString(), `
            $this.endDateString())
    }   
}

class classDurationDateStrings : classDuration {

    classDurationDateStrings(){}
    classDurationDateStrings([classDuration]$d)
    {
        $this.start = $d.start
        $this.end = $d.end
    }

    [String]startDateString(){
        return $this.start.ToString("yyyy-MM-dd")
    }

    [String]endDateString(){
        return $this.end.ToString("yyyy-MM-dd")
    }
    [string]ToString(){
        return ("start: {0}, End {1}" -f `
            $this.startDateString(), `
            $this.endDateString())
    }   
}

1. provides a way to convert from base to derived

2. Also keeps the base class initialization undisturbed with an empty constructor so both initializations are valid.


function collectionUtils.printArray3($a, $message)
{
    p -message $message
    if ($a -eq $null)
    {
        "The data array is null"
        return
    }
    $c = $a.Count
    if ($c -eq 0)
    {
        "The data array is empty"
        return
    }
    $msg = $a | Format-Table | Out-String
    p -message $msg

}

System.data.DataRow

function getTimeArray($rs)
{
    #This will create a set of objects
    #where each object has one property named "f_date_time"
    #so that is an array of hashtables or objects
    $dtArray = $rs | Select-Object -Property f_date_time

    #This is a collection, on the otherhand, of date time array
    $dtArray = $rs | ForEach-Object {return $_.f_date_time}

    return $dtArray
}

function vutils.default($param, $value, $default)
{
    if ($param -eq $null)
    {
        return $default
    }
    return $value
}

function vutils.default($param, $default)
{
    if ($param -eq $null)
    {
        return $default
    }
    return $param
}

function fcDataReportFor($plant, $forecaster, $frequency, $howFarBackInDays)
{
    vutils.notnull $plant $forecaster
    $lFrequency = vutils.default -param $frequency -default 15
    $lPast = vutils.default -param $howFarBackInDays -default 30

param (
    $paramRunMode = "runReport"
)

$optionHelp = "help"
$optionRunReport = "runReport"
$optionCleanupManual = "cleanupManual"
$optionCleanupAuto = "cleanupAuto"

$optionArray = @(
    $optionHelp,
    $optionRunReport,
    $optionCleanupManual,
    $optionCleanupAuto
)

function driverMainProc()
{
    if ($paramRunMode -eq $null)
    {
        p -message "No Parameters passed"
        p -message "Running Run Report as the default"
        p -message "use string 'help' as an option if you need help"
        runReport
        return
    }
    
    if ($paramRunMode -eq $optionHelp)
    {
        promptHelp
        return
    }

    if ($paramRunMode -eq $optionRunReport)
    {
        runReport
        return
    }
    if ($paramRunMode -eq $optionCleanupManual)
    {
        runManually
        return
    }
    if ($paramRunMode -eq $optionCleanupAuto)
    {
        runAuto
        return
    }
    #none
    p -message "Unrecognized string as an option"
    promptHelp
}

driverMainProc

function promptHelp()
{
    hp -message "Here are the params"

    $optionArray
}

function driverMainProc1()
{
    init
    switch ($paramRunMode) 
    {
        $null {
            p -message "No Parameters passed"
            p -message "Running Report just for data"
            p -message "use string 'help' as an option if you need help"
            runReport
            break
        }
        $optionHelp
        {
            promptHelp
            break
        }
        $optionJustData
        {
            runReport
            break
        }
        $optionGaps
        {
            runReport
            break
        }
        default 
        {
            p -message "Unrecognized string as an option"
            promptHelp
            break
        }
    }#end of switch
}

$x = "ha"
$y = "dddd"
$tableName = switch ($y)
{
    "ha" { "a" }
    "da" { "b" }
    default {"x"}
}

p -message $tableName

function map($var, $op1, $op1Value, $op2, $op2Value, $defaultValue)
{
    $r = switch ($var)
    {
        $op1 { $op1Value }
        $op2 { $op2Value }
        default {$defaultValue}
    }
    return $r
}

$tableName = map -var $x `
    -op1 "ha" -op1Value "a" `
    -op2 "da" -op2Value "b" `
    -defaultValue "x"

p -message $tableName

vutils.notnull $plant $forecaster $duration $forecastType

    $daTableName = "t_vre_da_forecast_data"
    $haTableName = "t_vre_ha_forecast_data"

    $tableName = vutils.map -var $forecastType `
        -op1 "ha" $haTableName `
        -op2 "da" $daTableName `
        -defaultValue $null
        
    vutils.notnull $tableName

Using Regex with Powershell: Kevin

Powershellexplained.com


function getDateTimeFromFilenameUsingRegEx($filename, $expr)
{
    #returns a boolean
    $reply = $filename -match $expr

    $date = $Matches.date
    $month = $Matches.month
    $year = $Matches.year

    #Make sure the expression has correctly located year, month, and day
    vutils.notnull $date $month $year

    $datetime = [DateTime]::new($year, $month, $date)
    return $datetime
}

function test()
{
    $filename = "SomeFilePrefix12-05-2020"
    $expr = "SomeFilePrefix(?<date>\d\d)-(?<month>\d\d)-(?<year>\d\d\d\d)"    

    $dt = getDateTimeFromFilenameUsingRegEx -filename $filename -expr $expr
    $s = convertToISOTime2 -datetime $dt

    #prints 2020-05-12 00:00:00
    p -message $s
}

How can I see a list of function names in a powershell script file in vscode

Search for: How can I see a list of function names in a powershell script file in vscode

Sort-Object with comparator powershell

Search for: Sort-Object with comparator powershell

Sort-Object docs


$someFileList = Get-ChildItem

$someFileList | Sort-Object -Property @{ 
      Expression = (someFunc -arg1 $_); 
      Descending = $true }, 

     #sub expression
     @{ Expression = 'Name'; Ascending = $true }

function someFunc($arg1) {}

Precision of an NTFS is 100 nanoseconds. So be aware of storing last file times!!

Understand file times

datetime milliseconds and microseconds is explained here

DateTime class documentation

Notice the precision of milliseconds: 7fs


string dateFormat = "MM/dd/yyyy hh:mm:ss.fffffff";
DateTime date1 = new DateTime(2010, 9, 8, 16, 0, 0);

How are strings formatted in .Net: Composite formatting

Try that again

Formatting numbers


string dateFormat = "MM/dd/yyyy hh:mm:ss.fffffff";
DateTime date1 = new DateTime(2010, 9, 8, 16, 0, 0);
Console.WriteLine("Original date: {0} ({1:N0} ticks)\n",
                  date1.ToString(dateFormat), date1.Ticks);

DateTime date2 = date1.AddMilliseconds(1);
Console.WriteLine("Second date:   {0} ({1:N0} ticks)",
                  date2.ToString(dateFormat), date2.Ticks);
Console.WriteLine("Difference between dates: {0} ({1:N0} ticks)\n",
                  date2 - date1, date2.Ticks - date1.Ticks);

DateTime date3 = date1.AddMilliseconds(1.5);
Console.WriteLine("Third date:    {0} ({1:N0} ticks)",
                  date3.ToString(dateFormat), date3.Ticks);
Console.WriteLine("Difference between dates: {0} ({1:N0} ticks)",
                  date3 - date1, date3.Ticks - date1.Ticks);
// The example displays the following output:
//    Original date: 09/08/2010 04:00:00.0000000 (634,195,584,000,000,000 ticks)
//
//    Second date:   09/08/2010 04:00:00.0010000 (634,195,584,000,010,000 ticks)
//    Difference between dates: 00:00:00.0010000 (10,000 ticks)
//
//    Third date:    09/08/2010 04:00:00.0020000 (634,195,584,000,020,000 ticks)
//    Difference between dates: 00:00:00.0020000 (20,000 ticks)

import xml file in powershell

Search for: import xml file in powershell


# From CSV
Import-CSV $filename

# From json
$s = Get-Content $jsonfile | ConvertFrom-Json

There is no convert from or importing an XML file I found

I did see Select-XML however here

XPath examples from MS

Strangeness of Select-XML is very quietly documented here


"Name: {0}, `nFreq {1}, `nstart {2}"

Select-string grep like docs


function writeToCSV($dir, $taskObjList)
{
    $filepath = $dir + "\exported-tasks.csv"
    p -message "Going to write a csv file: $filepath"
    $r = $taskObjList | Export-Csv -Path $filepath -NoTypeInformation
    p -message "Finished writing a csv file: $filepath"
}

class TaskObject
{
    $name
    $start_dt
    $freq
    $script
    $status
    [string]$cmd #if needed, use type
}

#Get an array of TaskObjects
$taskObjArray = getSomeFunction()

#pick the fields you like

$newTaskObjArray = $taskObjArray | Select-Object -Property name, freq

#Write those to a csv file

#dir = "c:\some-dir"

#Call the write to csv function above
writeToCSV -dir $dir -taskObjList $na

Export CSV docs

1. Define an object

2. Get an array of those objects

3. Use export-csv commandlet with the options you need to export to a csv file

Import-csv:Search On Web

ConvertTo-Csv:Search On Web

Export-CSV:Search On Web

ConvertFrom-CSV:Search On Web

Powershell and REST


<#
#*********************************************
# A starting file for writing scripts
#********************************************
#>

param (
    $paramOutputFilename
)

#*********************************************
#  Execute Common libraries: Include this one at the top
#********************************************
function getScriptDir() {
    $script_path    =  $myinvocation.PSCommandPath
    $script_folder  = split-path $script_path -parent
    $script_name    = split-path $script_path -leaf    
    return $script_folder
}

$libScriptDir = getScriptDir

if ($psutilsIncluded -eq $null)
{
    ."$libScriptDir\psutils.ps1"
    ."$libScriptDir\common-utils.ps1"
}

#*********************************************
# End Execute Common libraries
#********************************************

$realScriptName="show-plant-data-files.ps1"

function printHelp()
{
    p -message "Specify an output filename as the first argument"
    return
}
function mainproc()
{
    mhp -message "Running report to show received plant files"
    if ((isValid -somestring $paramOutputFilename) -eq $false)
    {
        printHelp
        return
    }
    p -message "Going to write output to: $paramOutputFilename"

    p -message "Going to run script below"
    p -message "$libScriptDir\$realScriptName"

    ."$libScriptDir\$realScriptName" 6>&1 > $paramOutputFilename

    p -message "Finished running the script."
}

#run the stuff
mainproc
p -message ""

powershell mandatory params

Search for: powershell mandatory params

interfaces and inheritance in powershell

Search for: interfaces and inheritance in powershell

Multiline strings in powershell

Search for: Multiline strings in powershell


$somestring = @"
   line1
  line2
line3
This termination must be the first 2 characters
"@

function sayAbout()
{
    $aboutMessage = 
@"
A program to generate a private key
Inputs: Password, filename
Outputs: Writes the filename to the local directory
"@
    hp "About: Private Key Generator Script"
    p $aboutMessage
}

exit process in powershell

Search for: exit process in powershell