Back to top

FREE eBook: The Most USEFUL PowerShell CmdLets and more…

Grab a copy!

Easy Steps For Writing PowerShell Advanced Functions

This article is a step up from our previous article about writing PowerShell Functions.

We will show you that converting your existing PowerShell Functions into Advanced PowerShell Functions is very easy and need just a few lines of code.

If you follow our step by step guidance you will see that writing Advanced PowerShell Functions is not that difficult and different from writing PowerShell regular Functions.

Without diving too much into the benefits of writing Advanced PowerShell Functions just to mention that the basic difference between PowerShell Functions and Advanced PowerShell Functions is that later allow us to use PowerShell Common Parameters and just to name a few (Debug, Verbose, ErrorAction, etc.).

If you have not been familiar with PowerShell Functions concept yet we strongly suggest you read our first article “Easy Steps For Writing PowerShell Functions” in the series of articles about PowerShell Functions and then come back to continue with this article.

Easy Steps For Writing PowerShell Functions
Easy Steps For Writing PowerShell Functions

This article is Part 2 of the PowerShell Functions and CmdLets Series:

Let us show you an easy step by step approach in writing Advanced PowerShell Functions.

How To Write Advanced PowerShell Function Step By Step

Let us first provide the steps and then the example that will follow the steps which will help you illustrate the defined steps so you can embrace the steps with ease.

Here are the steps to create Advance PowerShell Function:

  • Open Windows PowerShell ISE or Visual Studio Code.
  • In the new script file write the word function
  • Followed by the function name.
    • Take into consideration the PowerShell best practice and name the function in Approved Verb-Noun style.
    • Remember to have a unique PowerShell function name.
  • After function name open and close curly brackets {}.
  • Immediately after the open curly bracket add the CmdletBinding attribute.
    • IMPORTANT: This is the attribute that will convert our function into an advanced function.
  • Immediately after CmdletBinding attribute add param() PowerShell keyword.
    • Inside param() brackets we will define function input parameter(s)
    • Give a name to each parameter starting with the dollar sign $
    • Separate each input parameter with a comma ,
  • Optionally, if we want our Advanced PowerShell Function to accept PowerShell Pipeline values define Input Methods:
  • Write a function code that will produce the desired result of the function.
  • Save the code as a PowerShell script file (.ps1) so we can reuse the same code and call the function as needed.
  • Test your PowerShell Function.
  • Use PowerShell Debugging as needed.
  • Extra TipBenchmark your PowerShell function execution performance.
  • Optionally, write Comment-Based Help.
  • Deploy your PowerShell Function in the production environment.

Let’s follow the above steps and write our own Advanced PowerShell Function with the name Get-MDComputerInfo_Advanced.

Step 1: Open Windows PowerShell ISE or Visual Studio Code

We will use Windows PowerShell ISE for writing our script in the Script Window.

Step 2: Define Function writing the word function

function

Step 3: Give the function a name

function Get-MDComputerInfo_Advanced

We have followed all the PowerShell function naming guidance:

  • Used Approved Verb in the name Get,
  • Used Noun in the name ComputerInfo,
  • Used Initials to make the function name unique MD,
  • Used Advance just to emphasize that this is Advanced PowerShell Function.

Step 4: Open and close the curly brackets after the function definition.

function Get-MDComputerInfo_Advanced { }

Step 5: Add CmdletBinding attribute.

Add CmdletBinding attribute immediately after the open curly bracket.

function Get-MDComputerInfo_Advanced {
    [CmdletBinding()] #-- This converts function into Advanced PowerShell Function!
}

IMPORTANT: CmdletBinding Attribute will convert our regular PowerShell Function into Advanced. Practically that means our function will automatically implement PowerShell Common Parameters (Debug, Verbose, ErrorAction, etc.) so we can use them without any additional scripting.

Step 6: Define Input parameter writing param() keyword.

Immediately after CmdletBinding attribute add param() PowerShell keyword.

function Get-MDComputerInfo_Advanced {
    [CmdletBinding()] #-- This converts function into Advanced PowerShell Function!
    param(
        [string]$computername = 'localhost'
    )
}

  • Within param() PowerShell keyword we have defined function input parameter $computername:
    • started input parameter name with the dollar sign $
    • defined input parameter data type [string]
    • defined input parameter default value localhost

Step 7: Define Input Methods for PowerShell Pipeline in the function body

For the sake of simplicity, we have not used the PowerShell Pipeline feature in this example but if you want to know how to write PowerShell Pipeline Functions please follow this example.

Step 8: Write a function code 

Write a function code that will produce the desired result of the function.

function Get-MDComputerInfo_Advanced {
    [CmdletBinding()] #-- This converts function into Advanced PowerShell Function!
    param(
        [string]$computername = 'localhost'
    )

    $cpu = Get-CimInstance -ComputerName $computername -Class CIM_Processor -ErrorAction Stop

    $os = Get-CimInstance -ComputerName $computername -Class CIM_OperatingSystem -ErrorAction Stop


    $obj = New-Object -TypeName PSObject
    $obj | Add-Member -MemberType NoteProperty -Name ComputerName -Value $computername
    $obj | Add-Member -MemberType NoteProperty -Name OS -Value $os.Caption
    $obj | Add-Member -MemberType NoteProperty -Name CPU -Value $cpu.Name
    
    Write-Output $obj
}
Get-MDComputerInfo_Advanced PowerShell Pipeline Function

Function code is very simple but let me quickly explain what we have done

  • We have used CIM_Processor and CIM_OperatingSystem CIM Classes combined with a call to Get-CimInstance PowerShell CmdLet in order to get CPU and OS data for the local machine respectively.
  • We have used New-Object PowerShell CmdLet to create PowerShell Custom Object.
  • We have added three members to our PowerShell Custom Object that we want to present as result.
    • The first member (property) is the input parameter value (name of the computer),
    • The second member (property) is Operating System Name,
    • The third member (property) is CPU Name.
  • Finally, we have used Write-Output PowerShell CmdLet to send the output of our Advanced PowerShell Function to the caller.

We have already discussed creating Custom PowerShell Objects and Writing the Output from the functions in these two topics. So please read them for detailed explanations.


Step 9: Save the code as a PowerShell script file (.ps1)

Save the code as a PowerShell script file (.ps1) so we can reuse the same code and call the function as needed.

  • Save the script with the name AdvancedFunctions.ps1
PowerShell Script AdvancedFunctions.ps1

We have not implemented Error Handling so we can keep this example as simple as possible but remember that this is not the best PowerShell Practice.

Luckily for you, we have already written an article with many examples of how to error handle PowerShell scripts and even how to log errors in an external Error log file. So please read “How To Log PowerShell Errors And Much More“.

How To Log PowerShell Errors And Much More
How To Log PowerShell Errors And Much More

Step 10: Test your PowerShell Function.

Basically, we have two ways of testing our PowerShell Function.

  • First, we can use the dot source method and run the script, and test from the PowerShell Console.
    • We will cover the dot sourcing method in the topic “How To Call Advanced PowerShell Function Written In PowerShell Script” in a bit.
  • Second, since we are in the development phase and we can write function calls directly in the Windows PowerShell ISE script window and run from there.
  • When we are done with testing we will comment out each call or even better make Execution Examples Region.

We have already written the articles that cover the below topics so no need to repeat ourselves here but we strongly encourage each and every one of you to read them so you can get comprehensive knowledge about PowerShell Advanced Functions.

Step 11: Use PowerShell Debugging as needed.

Learn to Debug PowerShell code with examples, be more efficient while debugging by using the right shortcut key, and many more to cover in the article “How To Debug PowerShell Scripts“.

How To Debug PowerShell Scripts Featured
How To Debug PowerShell Scripts

Step 12: Extra TipBenchmark.

Benchmark your PowerShell function execution performance.

Sometimes PowerShell functions can be very complex and perform poorly (read, run very long time) or if we want to be really serious about writing our own PowerShell Advanced Function we will benchmark our PowerShell Function code anyway.

By benchmarking our code, we will know about how it was performing at the start of the production life, and if performance deteriorates we have some base to compare with.

We have written an article that provides several techniques on how to benchmark the code and probably one of them will suit your needs so please read the article “How To Benchmark Scripts With PowerShell“.

How To Benchmark Scripts With PowerShell

Step 13: Optionally, write Comment-Based Help.

Documenting the work is usually neglected and postponed when we have time to do it and most of the time is not the right time to do it. Writing the Comment-Based Help for the functions in PowerShell is not that difficult and makes the written code extremely user friendly and professional.

We have written an article that explains step by step how to write comment-based help for PowerShell Functions so please read it. “Step By Step Approach How To Write Comment-Based Help For PowerShell Scripts And CmdLets

How to Write PowerShell Help Step by Step Featured
Step By Step Approach How To Write Comment-Based Help For PowerShell Scripts And CmdLets

Step 14: Deploy your PowerShell Function in the production environment.

If we have calls to the PowerShell Advanced Function within our script that needs to be commented out we will use inline comment tag hash # so we avoid unnecessary calls to our functions before needed.

function Get-MDComputerInfo_Advanced {
    [CmdletBinding()] #-- This converts function into Advanced PowerShell Function!
    param(
        [string]$computername = 'localhost'
    )

    $cpu = Get-CimInstance -ComputerName $computername -Class CIM_Processor -ErrorAction Stop

    $os = Get-CimInstance -ComputerName $computername -Class CIM_OperatingSystem -ErrorAction Stop


    $obj = New-Object -TypeName PSObject
    $obj | Add-Member -MemberType NoteProperty -Name ComputerName -Value $computername
    $obj | Add-Member -MemberType NoteProperty -Name OS -Value $os.Caption
    $obj | Add-Member -MemberType NoteProperty -Name CPU -Value $cpu.Name
    
    Write-Output $obj
}
#Get-MDComputerInfo_Advanced

How To Convert PowerShell Function Into PowerShell Advanced Function

If I tell you that converting regular PowerShell Function into Advanced PowerShell Function can be as easy as writing just one line of code, would you believe me?

In my previous article “Easy Steps For Writing PowerShell Functions,” I have used as an example a basic Get-MDCPUInfo PowerShell Function that returns CPU properties for the specified computer.

So let’s use that regular PowerShell Function and convert it to Advanced PowerShell Function. Here is the code that we need to convert.

function Get-MDCPUInfo_Advanced {
    param(
        $computername = 'localhost'
    )
    Get-CimInstance -ComputerName $computername -Class CIM_Processor -ErrorAction Stop | Select-Object *
}

Are you ready for conversion?

Here is what we need to do to make this function advanced. We need to add the CmdletBinding attribute to the function. We write just this one line of code before the param PowerShell keyword.

[CmdletBinding()]

So here is our Advanced PowerShell Function converted from already written regular PowerShell Function.

function Get-MDCPUInfo_Advanced {
    [CmdletBinding()]
    param(
        $computername = 'localhost'
    )
    Get-CimInstance -ComputerName $computername -Class CIM_Processor -ErrorAction Stop | Select-Object *
}

NOTE: We have also changed the name of the function by adding Advanced at the end just to avoid the conflict of having two functions with the same name.

So it is simple as that but how we know that the previous function was regular and converted is now advanced. Let me show a quick test.

If we add a call to Get-Command PowerShell CmdLet after the closed curly bracket in the function script just for testing purposes and run the script we will get the answer. Here is the line of code that we need to add at the end of the script.

Get-Command Get-MDCPUInfo_Advanced -Syntax

If we run the script against regular PowerShell Function before conversion the outcome will be:

PowerShell Function check

That means our regular PowerShell Function has only one input parameter with the Object data type.

If we run the same call to Get-Command but this time against our Advanced PowerShell Function after the conversion the outcome is a little bit different.

Advanced Function check

In addition to the input parameter with the Object data type, our Advanced PowerShell Function can optionally use PowerShell Common Parameters (Verbose, Debug, ErrorAction, etc.).

What the benefits of having Common Parameters are we will discuss in our next subheading.

How To Call Advanced PowerShell Function Written In PowerShell Script

To call the Advanced PowerShell Function that we have saved in PowerShell Script (in our example we have saved Advance PowerShell Function in AdvancedFunctions.ps1 PowerShell Script file), we will use the same technique called “dot sourcing” as used for PowerShell regular Functions.

Dot Sourcing function call technique means we:

  • Open PowerShell Console.
  • type dot . first and make one space in the PowerShell Console.
  • then we provide either an absolute or relative path to the script that contains the function.
  • Press ENTER to run the script.
  • Now, the function has been loaded so we can call it from the PowerShell Console.
    • To check that function(s) have been loaded use dir function:
  • Call PowerShell Function and provide the names and values for all the input parameters as needed.

Here is an example that shows dot sourcing function call technique:

. .\AdvancedFunctions.ps1
Dot sourcing method

REMINDER: Since we are using a relative path to the script our PowerShell Console is at the folder where we have saved our AdvancedFunctions.ps1 PowerShell Script.

If we press enter we will run the script and PowerShell will load the function into the PowerShell Console environment from the script.

We can check that the PowerShell function from the script has been loaded using the following syntax:

dir function:

The result of the above code will list all the functions available for the current session of the PowerShell Console and among the other functions, we can see our Get-MDComputerInfo_Advanced PowerShell Advanced Function.

Advanced Function loaded in PowerShell Console

Now we can call our function and get the result in the PowerShell Console. We simply need to run the following line of code:

Get-MDComputerInfo_Advanced

Here is the result of PowerShell Function Get-MDComputerInfo_Advanced :

Get-MDComputerInfo_Advanced function result

But we have to mention that the dot sourcing method for calling functions has a big disadvantage and you probably realize or have experienced that every time you close your PowerShell Console (session) and open again.

The issue is that we need to run dot sourcing code every time we open a new PowerShell Console and that is a tedious and manual job that everyone wants to avoid.

The solution is to load the script using PowerShell Profiles and we have explained that at the end of this article.

In our previous article “Easy Steps For Writing PowerShell Functions” we have mentioned why the dot sourcing method must be used and some other methods are not possible so please read the topic “How NOT To Call And Why PowerShell Function Written In PowerShell Script“.

REMINDER: Since we are using CIM Classes in our Function example we need WinRM Windows service configured, up, and running. To configure the WinRM please run the following line of code from the PowerShell Console as Administrator:

winrm quickconfig
WinRM Service configuration

If we do not have WinRM Windows Service configured, up, and running we can be unpleasantly surprised with the error message that WinRM Service is either not running or not accepting requests.

What Are The Benefits Of PowerShell Advanced Functions Using Common PowerShell Parameters

As we probably already know and we have already mentioned that several times Advanced PowerShell Functions can use PowerShell Common Parameters such as Verbose, Debug, Warning Action, etc.

Just to illustrate one of the benefits of using PowerShell Common Parameters we will show you how to use Verbose Common Parameter combined with Write-Verbose PowerShell CmdLet written in our code.

In our example Advanced PowerShell Function Get-MDRAM_Advanced we read RAM properties on the local machine. Within the function code, we have several times used Write-Verbose PowerShell CmdLet and provide a useful message as feedback while our code executes.

function Get-MDRAM_Advanced {
    [CmdletBinding()] #-- This converts function into Advanced PowerShell Function!
    param(
        [string]$computername = 'localhost'
    )

    $params = @{ 'ComputerName'=$computername;
                 'Class'='CIM_PhysicalMemory';
                 'ErrorAction'='Stop'}

    Write-Verbose "We are reading the RAM properties for computer $computername."

    $RAMs = Get-CimInstance @params | Select-Object   Caption, 
                                        @{Name="RAM size(GB)";Expression={("{0:N2}" -f($_.Capacity/1gb))}}

    Write-Verbose "We have read the RAM properties for computer $computername."

    foreach ($RAM in $RAMs) {

        $properties = @{'Computer Name'=$computername;
                        'RAM'=$RAM.Caption;
                        'RAM size(GB)'=$RAM."RAM size(GB)"
                        }

        $obj = New-Object -TypeName PSObject -Property $properties
        
        Write-Verbose "RAM Property ($RAM) for the computer $computername."
          
        Write-Output $obj
    }
}

If we run our function without Verbose common parameter we will get the result

Get-MDRAM_Advanced 
Get-MDRAM_Advanced function result

If we run our function but this time with Verbose common parameter we will get feedback messages written in Write-Verbose PowerShell CmdLet as our code executes which can be valuable feedback about code execution workflow.

Get-MDRAM_Advanced -Verbose
Get-MDRAM_Advanced function result with Verbose parameter

How To Know That PowerShell Function Is Advanced

To check whether PowerShell Function is or is not PowerShell Advanced Function we will use Get-Command PowerShell CmdLet and Syntax parameter.

We have written PowerShell Advanced Function Get-MDRAM_Advanced and we will use it to illustrate and explain the topic.

Here is the syntax that will do the the test:

Get-Command Get-MDRAM_Advanced -Syntax

Here is the result of running the above line of code:

Advanced PowerShell Function Get-MDRAM_Advanced

We can see that this function utilizes PowerShell Common Parameters [<CommonParameters>] which is a confirmation that this is PowerShell Advanced Function.

In our article “Easy Steps For Writing PowerShell Functions” we have written many examples and one of the PowerShell Functions is Get-MDCPUInfo which we will use to check whether this function is Advanced or not

Get-Command Get-MDCPUInfo -Syntax

Here is the result of running the above line of code.

PowerShell Function Get-MDCPUInfo is not Advanced Function

This function has only one input parameter but doesn’t support PowerShell Common Parameters which is the confirmation that this is not PowerShell Advanced Function.

What Is The Difference Between PowerShell Function And Advanced PowerShell Function

The difference between regular PowerShell Function And Advanced PowerShell Function is that Advanced PowerShell Function has a number of common parameters (Verbose, Debug, Confirm, WhatIf, etc.) that are automatically added to the function.

In Part One of our PowerShell Functions Series we have written about PowerShell Functions so please read more of the article for detailed information about regular PowerShell Functions “Easy Steps For Writing PowerShell Functions“.

Easy Steps For Writing PowerShell Functions
Easy Steps For Writing PowerShell Functions

Here we compare some PowerShell functions features and which are specific for Advanced PowerShell Functions.

FeatureFunctionAdvanced Function
CmdletBindingNoYes
Common Parameters (Verbose, Debug, Confirm, WhatIf, etc.)NoYes
param()Yes, optionalMust implement but can be empty.
Input ParametersYes, optionalYes, optional
PowerShell Pipeline (Begin, Process, End)Yes, optionalYes, optional
Error handlingYes, optional Yes, optional
Comment-Based HelpYes, optionalYes, optional
Compare features of PowerShell Functions and Advanced PowerShell Functions.

REMEMBER: Our ultimate goal is to be capable to write our own PowerShell CmdLets that will have the same look and feel as native PowerShell CmdLet.

When we learn to write our own PowerShell Functions we have accomplished a big portion of our ultimate goal and write our own PowerShell CmdLet that will have the same look and feel as native PowerShell CmdLets.

To convert the PowerShell function into Advanced PowerShell Function demands just a few simple steps. That is the subject of this article and Part 2 of the PowerShell Functions Series.

Finally, from the Advanced PowerShell function, we need a few more steps to convert into PowerShell CmdLet. That is Part 3 of the PowerShell Functions Series.

You are on the right track to become a savvy PowerShell code scripter so please continue reading through PowerShell CmdLets article.

What Is The Difference Between PowerShell Advanced Function And PowerShell CmdLet

We are not quite sure that our terminology of defining our own PowerShell CmdLets is official but anyway this helps us differentiate the Advanced PowerShell Functions from what we consider PowerShell CmdLets.

Here are the features that will convert our own PowerShell Advanced Function into our own PowerShell CmdLet:

  • Save each Advanced PowerShell Function into its own PowerShell Script.
  • Organize PowerShell Scripts in PowerShell Module Folder structure.
  • Create a PowerShell Module (.psm1 file) and optionally PowerShell Module Manifest (.psd1 file) for each module.
    • In the PowerShell Module files load the PowerShell scripts that contain the code of our own Advanced PowerShell Functions and belong to that PowerShell Module.
  • Create a PowerShell Profile file:
    • Import PowerShell Modules in the PowerShell Profile file.
  • We test both loading of PowerShell Modules and the loading of PowerShell Advanced Functions for each PowerShell Module.

If you want to implement this approach please read the topic “How We Link Together PowerShell Profile, Module, And CmdLet” where we have explained step by step approach.

How To Create Custom PowerShell CmdLet
How To Create A Custom PowerShell CmdLet (Step By Step)

PowerShell Advanced Function And PowerShell Profiles

Our goal is to be able to load our PowerShell Advanced Functions written in our PowerShell Scripts each time we open either PowerShell Console or Windows PowerShell ISE. This text will provide you the steps to achieve exactly that but let’s discuss a few things first.

We have already learned how the PowerShell Advanced Function can be loaded (using dot source method) in our environment (PowerShell Console for example) first and then called and reused as needed.

But the biggest problem with that approach is that as soon as we close PowerShell Console our session has been closed and our functions are not loaded anymore so next time when open again PowerShell Console we need to implement dot sourcing method again.

You will agree that this is a tedious and boring job that no one likes to do, so can we do any better. Well, we can automate this using PowerShell Profiles.

So every time we open either PowerShell Console or Window PowerShell ISE, PowerShell Engine will look for PowerShell Profiles which are nothing but PowerShell Scripts with specific names and saved in specific locations.

PowerShell Engine will execute the code that is within these PowerShell Profile scripts and our environment and session will be with preloaded functions or some other features that we want to have when we start our work with PowerShell.

To achieve our goal we want to create a PowerShell Profile that will load our PowerShell Scripts with our PowerShell Functions.

IMPORTANT: We will create and configure PowerShell Profile file for the current user and all the hosts (PowerShell Console and ISE) for the PowerShell Version 5.1

If you want to learn about creating and configuring other PowerShell Profiles please read the article where we have explained that to the smallest details. “How To Create PowerShell Profile Step by Step with Examples

Here are the steps to follow to create and configure the PowerShell Profile file:

  • Open the Windows PowerShell Console.
  • Test if the Profile file already exists running the following line of code.
Test-Path $PROFILE.CurrentUserAllHosts
PowerShell Profile file doesn’t exist
  • If the result of the Profile File existence test is false, that means the profile file doesn’t exist so we can create it running the following command.
New-Item -Type File -Force $PROFILE.CurrentUserAllHosts
Creation of PowerShell Profile File
  • If the result of the Profile File existence test is true, that means the profile file exists and we can open it in PowerShell ISE to configure the file.
    • If we have just created the Profile file we can also open the file running the following line of code:
ise $PROFILE.CurrentUserAllHosts
Open PowerShell Profile File in Windows PowerShell ISE
  • Now the Profile File has been opened in PowerShell ISE so we can do the changes and save our configuration.
  • Add the following lines of code that will implement the well-known dot source method of running the scripts.

NOTICE: We have provided the absolute path to the location where our PowerShell script files have been saved.

. "C:\Temp\Functions\AdvancedFunctions.ps1"
PowerShell Profile configuration
  • Open the new PowerShell Console and test if the functions have been loaded after we have configured the Profile file.
dir function:
Advanced PowerShell Functions from AdvancedFunctions.ps1 loaded in PowerShell Console
  • Open the new PowerShell ISE environment and run the same command to check loaded functions.
Advanced Functions from AdvancedFunction.ps1 loaded in PowerShell ISE

So we have achieved our goal and no need to load the functions every time we open a new PowerShell session.

I have to emphasize that this is not the best approach and we have written two articles that explain how to write own PowerShell CmdLets and how to create and configure PowerShell Profile files.

Especially I would like to point to you on the topic “How We Link Together PowerShell Profile, Module, And CmdLet” where we have explained how to organize your code in PowerShell CmdLets, Modules, Profiles and achieve that your PowerShell Functions look and feel as native PowerShell CmdLets.

How To Create Custom PowerShell CmdLet
How To Create A Custom PowerShell CmdLet (Step By Step)
How To Create PowerShell Profile Step by Step with Examples
How To Create PowerShell Profile Step by Step with Examples

PowerShell Scripts for FREE

We have written many own PowerShell CmdLets and called them Efficiency Booster PowerShell Project.

There are thousands and thousands of code lines in them and we are sure that you can learn a lot so we are strongly encouraging you to download the source code and deploy the code on your own test environment before maybe implementing them in production.

These CmdLets provide many useful pieces of information about the system we are working on and just to name a few:

Source code can be downloaded from this zip file

Enjoy and have fun but remember PowerShell Every Day 🙂

About Dejan Mladenović

Post Author Dejan MladenovicHey Everyone! I hope that this article you read today has taken you from a place of frustration to a place of joy coding! Please let me know of anything you need for Windows PowerShell in the comments below that can help you achieve your goals!
I have 18+ years of experience in IT and you can check my Microsoft credentials. Transcript ID: 750479 and Access Code: DejanMladenovic
Credentials
About Me...

My Posts | Website

Dejan Mladenović

Hey Everyone! I hope that this article you read today has taken you from a place of frustration to a place of joy coding! Please let me know of anything you need for Windows PowerShell in the comments below that can help you achieve your goals! I have 18+ years of experience in IT and you can check my Microsoft credentials. Transcript ID: 750479 and Access Code: DejanMladenovic
Credentials About Me...

Recent Posts