9

How to write a function to avoid Repeated code for my powershell script, which basically display list of application installed on my machine from Add and Remove window present in control panel.

Below is the powershell script

Stack.ps1

Clear-Host

#$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
$scriptPath = $PSScriptRoot
$logFilePath= Join-path $scriptPath "TestResults.log"

#If log file exists, then clear its contents 
if (Test-Path $logFilePath)
{
    clear-content -Path $logFilePath
} 


$log = "Date Of Testing: {0} " -f (Get-Date)
$logString = "Process Started." 
add-content -Path $logFilePath -Value $log -Force 
add-content -Path $logFilePath -Value $logString -Force 
add-content -Path $logFilePath -Value "`n" -Force


#Validate ADD/Remove Program list

add-content -Path $logFilePath -Value "`n" -Force
add-content -Path $logFilePath -Value "Add/Remove Programs :" -Force
add-content -Path $logFilePath -Value "`n" -Force

  $InstalledPrograms = Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*

add-content -Path $logFilePath -Value "`n" -Force
foreach ($InstalledProgram in $InstalledPrograms )
{
   if(($InstalledProgram.DisplayName -ne $Null) -and ($InstalledProgram.DisplayName.Contains("Operational Control")))
    {
        $InstalledProgram |  Select-Object DisplayName, DisplayVersion, Publisher, InstallDate | 
        Format-Table –AutoSize

        $logString = $InstalledProgram.DisplayName 
        $logp = $InstalledProgram.Publisher
        $logv = $InstalledProgram.DisplayVersion
        $logd= $InstalledProgram.InstallDate

        add-content -Path $logFilePath -Value "Product Name: $logString" -Force   
        add-content -Path $logFilePath -Value "Publisher: $logp" -Force  
        add-content -Path $logFilePath -Value "Version: $logv" -Force  
        add-content -Path $logFilePath -Value "InstallDate: $logd" -Force  
        add-content -Path $logFilePath -Value "`n" -Force****

    }

if(($InstalledProgram.DisplayName -ne $Null) -and ($InstalledProgram.DisplayName.Contains("Management Studio")))
    {
        $InstalledProgram |  Select-Object DisplayName, DisplayVersion, Publisher, InstallDate | 
        Format-Table –AutoSize

        $logString = $InstalledProgram.DisplayName 
        $logp = $InstalledProgram.Publisher
        $logv = $InstalledProgram.DisplayVersion
        $logd= $InstalledProgram.InstallDate

        add-content -Path $logFilePath -Value "Product Name: $logString" -Force   
        add-content -Path $logFilePath -Value "Publisher: $logp" -Force  
        add-content -Path $logFilePath -Value "Version: $logv" -Force  
        add-content -Path $logFilePath -Value "InstallDate: $logd" -Force  
        add-content -Path $logFilePath -Value "`n" -Force

    }

    if(($InstalledProgram.DisplayName -ne $Null) -and ($InstalledProgram.DisplayName.Contains("System Analyzer")))
    {
        $InstalledProgram |  Select-Object DisplayName, DisplayVersion, Publisher, InstallDate | 
        Format-Table –AutoSize

        $logString = $InstalledProgram.DisplayName 
        $logp = $InstalledProgram.Publisher
        $logv = $InstalledProgram.DisplayVersion
        $logd= $InstalledProgram.InstallDate

        add-content -Path $logFilePath -Value "Product Name: $logString" -Force   
        add-content -Path $logFilePath -Value "Publisher: $logp" -Force  
        add-content -Path $logFilePath -Value "Version: $logv" -Force  
        add-content -Path $logFilePath -Value "InstallDate: $logd" -Force  
        add-content -Path $logFilePath -Value "`n" -Force

    }

      if(($InstalledProgram.DisplayName -ne $Null) -and ($InstalledProgram.DisplayName.Contains("STeP")))
    {
        $InstalledProgram |  Select-Object DisplayName, DisplayVersion, Publisher, InstallDate | 
        Format-Table –AutoSize

        $logString = $InstalledProgram.DisplayName 
        $logv = $InstalledProgram.DisplayVersion
        $logd= $InstalledProgram.InstallDate

        add-content -Path $logFilePath -Value "Product Name: $logString" -Force   
        add-content -Path $logFilePath -Value "Version: $logv" -Force  
        add-content -Path $logFilePath -Value "InstallDate: $logd" -Force  
        add-content -Path $logFilePath -Value "`n" -Force

    }   
}

I am talking about the code present under each if Statements that is used to copy the Output to log file. Can i replace that code with function and call the function in each if statement.

4
  • Do you check PS documentation? - learn.microsoft.com/en-us/powershell/module/… Commented Sep 28, 2017 at 7:42
  • No, I am new to powershell like i have never created a function in powershell so i will go through the link.But in case if you can help me in creating a function for this script it would be good. Commented Sep 28, 2017 at 7:53
  • Create a function at the beginning of your script. Example of a function: Funtion FunctionName{Param($SomeParametert) #here code } You can call a function with the function name Commented Sep 28, 2017 at 8:39
  • Entering the terms "powershell" and "function" in Google returns a ton of results. Please do your own research first. Commented Sep 28, 2017 at 8:49

1 Answer 1

22

OK, lets do this. Functions are about avoiding duplicate code which can be done on several levels here. Functions in PowerShell need to be declared before they are executed, so I tend to cluster all functions at the beginning of the script, like this:

# *** FUNCTION DEFINITIONS

function Log-InstalledProgram($InstalledProgram, $LogFilePath)
{
    $InstalledProgram |  Select-Object DisplayName, DisplayVersion, Publisher, InstallDate | 
    Format-Table –AutoSize

    $logString = $InstalledProgram.DisplayName 
    $logp = $InstalledProgram.Publisher
    $logv = $InstalledProgram.DisplayVersion
    $logd= $InstalledProgram.InstallDate

    add-content -Path $LogFilePath -Value "Product Name: $logString" -Force   
    add-content -Path $LogFilePath -Value "Publisher: $logp" -Force  
    add-content -Path $LogFilePath -Value "Version: $logv" -Force  
    add-content -Path $LogFilePath -Value "InstallDate: $logd" -Force  
    add-content -Path $LogFilePath -Value "`n" -Force
}

# *** BEGIN MAIN SCRIPT

Clear-Host

#$scriptPath = split-path -parent $MyInvocation.MyCommand.Definition
$scriptPath = $PSScriptRoot
$logFilePath= Join-path $scriptPath "TestResults.log"

#If log file exists, then clear its contents 
if (Test-Path $logFilePath)
{
    clear-content -Path $logFilePath
} 


$log = "Date Of Testing: {0} " -f (Get-Date)
$logString = "Process Started." 
add-content -Path $logFilePath -Value $log -Force 
add-content -Path $logFilePath -Value $logString -Force 
add-content -Path $logFilePath -Value "`n" -Force


#Validate ADD/Remove Program list

add-content -Path $logFilePath -Value "`n" -Force
add-content -Path $logFilePath -Value "Add/Remove Programs :" -Force
add-content -Path $logFilePath -Value "`n" -Force

  $InstalledPrograms = Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*

add-content -Path $logFilePath -Value "`n" -Force

foreach ($InstalledProgram in $InstalledPrograms )
{
   if(($InstalledProgram.DisplayName -ne $Null) -and ($InstalledProgram.DisplayName.Contains("Operational Control")))
    {
        Log-InstalledProgram $InstalledProgram $logFilePath
    }

    if(($InstalledProgram.DisplayName -ne $Null) -and ($InstalledProgram.DisplayName.Contains("Management Studio")))
    {
        Log-InstalledProgram $InstalledProgram $logFilePath
    }

    if(($InstalledProgram.DisplayName -ne $Null) -and ($InstalledProgram.DisplayName.Contains("System Analyzer")))
    {
        Log-InstalledProgram $InstalledProgram $logFilePath
    }

    if(($InstalledProgram.DisplayName -ne $Null) -and ($InstalledProgram.DisplayName.Contains("STeP")))
    {
        Log-InstalledProgram $InstalledProgram $logFilePath
    }   
}

You can reduce the code further with adding an inner loop for the wanted programs:

foreach ($InstalledProgram in $InstalledPrograms )
{
    foreach ($displayName in "Operational Control","Management Studio", "System Analyzer", "STeP")
    {
        if(($InstalledProgram.DisplayName -ne $Null) -and ($InstalledProgram.DisplayName.Contains($displayName)))
        {
            Log-InstalledProgram $InstalledProgram $logFilePath
        }
    }
}

There are other optimizations, for example you could avoid the repeated calls to Add-Content because the -Value parameter also takes an array as parameter, you could use a hashtable to capture the object properties you want to extract with their display names in the log file and so on.

Sign up to request clarification or add additional context in comments.

3 Comments

Hey @TToni thank you for your help.This is exactly what i wanted and i will also work on your suggestion to avoid repeated calls to Add-Content.
@SurajPardeshi: In that case would you mind marking this answer as "accepted" and maybe give it an upvote, too?
Ya sure Done :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.