Framework/Abstracts/CommandBase.ps1

using namespace System.Management.Automation
Set-StrictMode -Version Latest
# Base class for all classes being called from PS commands
# Provides functionality to fire important events at command call
class CommandBase: AzSdkRoot
{
    [string[]] $FilterTags = @();

    CommandBase([string] $subscriptionId, [InvocationInfo] $invocationContext):
        Base($subscriptionId)
    {
        [Helpers]::AbstractClass($this, [CommandBase]);
        if(-not $invocationContext)
        {
            throw [System.ArgumentException] ("The argument 'invocationContext' is null. Pass the `$PSCmdlet.MyInvocation from PowerShell command.");
        }

        $this.InvocationContext = $invocationContext;
    }

    [void] CommandStarted()
    {
        $this.PublishAzSdkRootEvent([AzSdkRootEvent]::CommandStarted, $this.CheckModuleVersion());
    }

    [void] CommandError([System.Management.Automation.ErrorRecord] $exception)
    {
        [AzSdkRootEventArgument] $arguments = $this.CreateRootEventArgumentObject();
        $arguments.ExceptionMessage = $exception;

        $this.PublishEvent([AzSdkRootEvent]::CommandError, $arguments);
    }

    [void] CommandCompleted([MessageData[]] $messages)
    {
        $this.PublishAzSdkRootEvent([AzSdkRootEvent]::CommandCompleted, $messages);
    }

    [string] InvokeFunction([PSMethod] $methodToCall)
    {
        return $this.InvokeFunction($methodToCall, @());
    }

    [string] InvokeFunction([PSMethod] $methodToCall, [System.Object[]] $arguments)
    {
        if(-not $methodToCall)
        {
            throw [System.ArgumentException] ("The argument 'methodToCall' is null. Pass the reference of method to call. e.g.: [YourClass]::new().YourMethod");
        }

        $this.PublishRunIdentifier($this.InvocationContext);
        $this.CommandStarted();
        $methodResult = @();
        try
        {
            $methodResult = $methodToCall.Invoke($arguments);
        }
        catch
        {
            # Unwrapping the first layer of exception which is added by Invoke function
            $this.CommandError($_.Exception.InnerException.ErrorRecord);
        }

        $this.CommandCompleted($methodResult);
        $this.PostCommandCompletedAction($methodResult);

        $folderPath = $this.GetOutputFolderPath();
        $DoNotOpenOutputFolder = $this.InvocationContext.BoundParameters["DoNotOpenOutputFolder"];

        if((-not $DoNotOpenOutputFolder) -and (-not [string]::IsNullOrEmpty($folderPath)))
        {
            try
            {
                Invoke-Item -Path $folderPath;
            }
            catch
            {
                #ignore if any exception occurs
            }
        }
        return $folderPath;
    }

    [string] GetOutputFolderPath()
    {
        return [WriteFolderPath]::GetInstance().FolderPath;
    }


    [MessageData] CheckModuleVersion()
    {
        $serverVersion = [System.Version] ([ConfigurationManager]::GetAzSdkConfigData().GetLatestAzSDKVersion($this.GetModuleName()));
        if($serverVersion -gt $this.GetCurrentModuleVersion())
        {
            return [MessageData]::new(([Constants]::VersionCheckMessage -f $serverVersion, [ConfigurationManager]::GetAzSdkConfigData().InstallationCommand), [MessageType]::Warning);
        }

        return $null;
    }

    [void] CommandProgress([int] $totalItems, [int] $currentItem)
    {
        $this.CommandProgress($totalItems, $currentItem, 1);
    }

    [void] CommandProgress([int] $totalItems, [int] $currentItem, [int] $granularity)
    {
        if($totalItems -gt 0)
        {
            # $granularity indicates the number of items after which percentage progress will be printed
            # Set the max granularity to total items
            if($granularity -gt $totalItems)
            {
                $granularity = $totalItems;
            }

            # conditions for posting progress: 0%, 100% and based on granularity
            if($currentItem -eq 0 -or $currentItem -eq $totalItems -or (($currentItem % $granularity) -eq 0))
            {
                $this.PublishCustomMessage("$([int](($currentItem / $totalItems) * 100))% Completed");
            }
        }
    }

    # Dummy function declaration to define the function signature
    [void] PostCommandCompletedAction([MessageData[]] $messages)
    { }
}