Monday, October 15, 2018

Custom private registry key

I've long been a proponent of creating a "custom" registry presence on all PC's and servers to allow the storage of critical information.  Much of what would normally be needed from systems is already accessible via existing keys, but there are always thing specific to each company that are nice to be able to keep track of.

I used to just create these manually but for domain wide deployment that's not practical.

This PowerShell script will create and/or validate that your custom private registry key exists on all systems specified whether that be a full domain or a list.

Many settings are externalized to make the script generic, however the list of key values is not.  You should edit the script to correct the list to suit your needs.

An HTML email report is generated to show the results.  The report is coded so that it's short and "relatively" clean.

Here is an example of the output email from a small test run:

As always the most current version of the script can be found at the PowerShell Gallery here:
https://www.powershellgallery.com/packages/Private-RegKey

I'll list the code below but keep in mind that this version may not be the most up to date.

Param (
  [Switch]$Debug = $false,
  [Switch]$Console = $false
)
<#======================================================================================
         File Name : Private-RegKey.ps1
   Original Author : Kenneth C. Mazie  (kcmjr AT kcmjr DOT com)
                   : 
       Description : Sets custom registry keys on all domain PCs.  This version only creates and populates with "-" as a default.
                   : If an existing value is found no changes are made.  It is expected that other processes and/or
                   : scripts will populate the keys with appropriate values.  This just makes sure the key and value
                   : structure is in place.   Creates a simplified email report with results.
                   : 
             Notes : Normal operation is with no command line options.  
                   : Optional argument: -Debug $true (defaults to false) 
                   :                    -DebugTarget name (only applies if in debug)
                   :                    -Console $true (enables local console output)
                   : 
          Warnings : None
                   :   
             Legal : Public Domain. Modify and redistribute freely. No rights reserved.
                   : SCRIPT PROVIDED "AS IS" WITHOUT WARRANTIES OR GUARANTEES OF 
                   : ANY KIND. USE AT YOUR OWN RISK. NO TECHNICAL SUPPORT PROVIDED.
                   : That being said, please report any bugs you find!!
                   :
           Credits : Code snippets and/or ideas came from many sources including but 
                   :   not limited to the following:
                   : 
    Last Update by : Kenneth C. Mazie 
   Version History : v1.00 - 12-06-13 - Original 
    Change History : v1.10 - 02-08-16 - Added "auto logon" key   
                   : v1.20 - 04-13-16 - Added authorized local admins key
                   : v2.00 - 06-27-17 - Complete rewrite using invoke-command instead of .net or WMI.
                   : v2.10 - 01-11-18 - Fixed issue with credentials.
                   : v2.20 - 10-04-18 - Added new keys.  Changed name & added values for PS Gallery.
                   : v3.00 - 10-10-18 - Added a list of keys checked to report.  Complete rewrite of
                   :                    registry pull to speed up domain wide checks.
#                  :
#=======================================================================================#>
<#PSScriptInfo
.VERSION 3.00
.GUID cc8fe6bd-2831-453e-bc16-bd5b3763471d
.AUTHOR Kenneth C. Mazie (kcmjr AT kcmjr.com)
.DESCRIPTION 
Sets custom registry keys on all domain PCs.  This version only creates and populates with "-" as a default.
If an existing value is found no changes are made.  It is expected that other processes and/or
scripts will populate the keys with appropriate values.  This just makes sure the key and value
structure is in place.  Creates a simplified email report with results.  An option to include updates
is available.
#>

clear-host
$ErrorActionPreference = "SilentlyContinue"

#--[ Functions ]-------------------------------------------------------------------------
Function LoadModules {
        Import-Module ActiveDirectory
}

Function LoadConfig { #--[ Read and load configuration file ]-----------------------------------------
    If (!(Test-Path $Script:ConfigFile)){       #--[ Error out if configuration file doesn't exist ]--
        $Script:EmailBody = "---------------------------------------------`n" 
        $Script:EmailBody += "--[ MISSING CONFIG FILE.  Script aborted. ]--`n" 
        $Script:EmailBody += "---------------------------------------------" 
      SendEmail
        Write-Host $EmailBody -ForegroundColor Red
      break
    }Else{
    [xml]$Script:Configuration = Get-Content $Script:ConfigFile 
    $Script:DebugTarget = $Script:Configuration.Settings.General.DebugTarget
        $Script:RegistryPath = $Script:Configuration.Settings.General.RegistryPath
        $Script:Domain = $Script:Configuration.Settings.General.Domain
        $Script:DebugEmail = $Script:Configuration.Settings.Email.Debug 
        $Script:CompanyName = $Script:Configuration.Settings.Email.CompanyName 
    $Script:eMailTo = $Script:Configuration.Settings.Email.To
    $Script:eMailFrom = $Script:Configuration.Settings.Email.From
    $Script:eMailHTML = $Script:Configuration.Settings.Email.HTML
    $Script:eMailSubject = $Script:Configuration.Settings.Email.Subject
    $Script:SmtpServer = $Script:Configuration.Settings.Email.SmtpServer
        $Script:UserName = $Script:Configuration.Settings.Credentials.Username
    $Script:EncryptedPW = $Script:Configuration.Settings.Credentials.Password
    $Script:Base64String = $Script:Configuration.Settings.Credentials.Key   
        $ByteArray = [System.Convert]::FromBase64String($Base64String)
        $Script:Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $UserName, ($EncryptedPW | ConvertTo-SecureString -Key $ByteArray)
        #$Script:Password = $Credential.GetNetworkCredential().Password       #--[ Warning, exposes encrypted password ]--
    }
}

Function SendEmail {
    If ($Script:Debug){ $Script:eMailTo = $Script:DebugEmail }
$msg = new-object System.Net.Mail.MailMessage
$msg.From = $Script:eMailFrom
$msg.To.Add("$Script:eMailTo")
$msg.Subject = $Script:eMailSubject
$msg.IsBodyHtml = $Script:eMailHTML
$msg.Body = $Script:EmailBody 
$ErrorActionPreference = "silentlycontinue"
$smtp = new-object System.Net.Mail.SmtpClient($Script:SmtpServer)
    $smtp.Send($msg)
    If ($Console){Write-Host "--- Email Sent ---" -ForegroundColor White } 
}

#==[ Main Body ]================================================================
$DayOfWeek = (get-date).DayOfWeek
$StartTime = [datetime]::Now
#$domain = (Get-ADDomain).DNSroot      #--[ Optional.  Pulled from config file. ]--
$Script:Message = ""
$Target = ""
$Local = $False
$ScriptName = ($MyInvocation.MyCommand.Name).split(".")[0] 
$Script:LogFile = "$PSScriptRoot\$ScriptName-{0:MM-dd-yyyy_HHmmss}.html" -f (Get-Date)  
$Script:ConfigFile = "$PSScriptRoot\$ScriptName.xml"  

LoadConfig 
LoadModules

#--[ For testing only ]------------
#$Debug = $true
#$Console = $true
#----------------------------------

If ($Script:Debug){
If ($Console){Write-Host  "===================== DEBUG MODE ENABLED =============================" -ForegroundColor Red }
#TargetList = Get-ADComputer -Filter {Server -eq $Script:DebugTarget} -Property * | select name | sort name
    $TargetList = Get-ADComputer -Properties * -Filter * | where {$_.name -like $Script:DebugTarget} 
    If ($TargetList.count -lt 1){
        $Script:EmailBody = "-- Debug Mode Enabled --<br><br>"
        $Msg = "`nThe registry key check script found NO valid systems to scan.  `nDouble check your system list specification in the config file."
        If ($Console){Write-Host $Msg -ForegroundColor Red }
        $Script:EmailBody += $Msg
        $Script:EmailBody += "<br>The current specification = "+$Script:DebugTarget
        SendEmail
        break
    }
}Else{
#$TargetList = Get-ADComputer -Filter * | ForEach-Object {$_.Name}
$TargetList = Get-ADComputer -Filter {OperatingSystem -Like "*Windows*"} -Property * | select name | sort name
}

$FontFamily = "Consolas"   #--[ Use to change the font ]--

$Script:FontDarkCyan = '<span style="display:inline;font-family:'+$FontFamily+';size:7pt;color:#008B8B;margin-top:0px;margin-bottom:0px;">'
$Script:FontBlack = '<span style="display:inline;font-family:'+$FontFamily+';size:7pt;color:#000000;margin-top:0px;margin-bottom:0px;">'
$Script:FontRed = '<span style="display:inline;font-family:'+$FontFamily+';size:7pt;color:#ff0000;margin-top:0px;margin-bottom:0px;">'
$Script:FontDarkRed = '<span style="display:inline;font-family:'+$FontFamily+';size:7pt;color:#990000;margin-top:0px;margin-bottom:0px;">'
$Script:FontGreen = '<span style="display:inline;font-family:'+$FontFamily+';size:7pt;color:#00ff00;margin-top:0px;margin-bottom:0px;">'
$Script:FontDarkGreen = '<span style="display:inline;font-family:'+$FontFamily+';size:7pt;color:#009900;margin-top:0px;margin-bottom:0px;">'
$Script:FontDimGray = '<span style="display:inline;font-family:'+$FontFamily+';size:7pt;color:#696969;margin-top:0px;margin-bottom:0px;">'
$Script:FontYellow = '<span style="display:inline;font-family:'+$FontFamily+';size:7pt;color:#ffff00;margin-top:0px;margin-bottom:0px;">'

$Script:EmailBody = $Script:FontBlack +"Below is a record of the status of the "+ $Script:CompanyName +" custom registry key.  Entries are coded to reduce report size.<br>"
$Script:EmailBody += "<br><font size=2 color=gray>Coding key:<br>"
$Script:EmailBody += "B = Base RegKey. (Red means it was created, Green means it was detected)<br>O = OK.  Value exists and there is some data in it."
$Script:EmailBody += "  No new updates found.<br>C = Created missing value with default data of ""-"".<br>U = Found an existing value and an update.  Updated with new data." 
$Script:EmailBody += "<br>See end of email for list of keys in the order that they are inspected.<br></font>"

$NewValue = ""
$ValueList = @(             #--[ Adjust this list as suits your environment ]--
    "Approved Local Admins",
    "Approved RDP Access",
"Asset Tag",
"Assigned User",
"Auto Logon",
"Backup Schedule",
    "Build Date",
    "Build Validation",
    "Clean",
"Custom 1",
"Custom 2",
    "Custom 3",    
"Group",
"IE Version",
"Java Protected",
"Location",
"Product Key",
    "Purge",
    "RSAT User",
"Security Posture",
    "Serial Number",
    "XML Parser Version",
    "Z-Notes"
)

ForEach ($Target in $TargetList){
    $Failure = $false
$Target = ($Target.name).ToUpper()

If ($Console){
Write-Host "`n`n==[ "  -ForegroundColor Cyan -NoNewline 
Write-Host "Target: $Target " -NoNewline 
Write-Host "]===============================================`n" -ForegroundColor Cyan 
}
$Script:EmailBody = $Script:EmailBody + $Script:FontDarkCyan+'<br>'+$Target+'</span>' 
    $Local = $False
    If ($Target -eq $Env:ComputerName){
        If ($Console){Write-Host "Local PC - No Ping test..." -ForegroundColor Green }
        $Script:EmailBody = $Script:EmailBody + $Script:FontDarkGreen+'<font color="black">--</font>LocalPC<font color="black">--</font></span>' 
        $Local = $true
        Try{
            $Result = Test-Path -Path $Script:RegistryPath -ErrorAction "stop"            
        }Catch{
            $ErrorMsg =$_.Exception.Message
            #$ErrorMsg       #--[ Optional ]--
        }
    }Else{
    If(Test-Connection -ComputerName $Target -count 1 -BufferSize 16 -ErrorAction SilentlyContinue ){
    If ($Console){Write-Host "Ping test OK..." -ForegroundColor Green }
    $Script:EmailBody = $Script:EmailBody + $Script:FontDarkGreen+'<font color="black">--</font>PingOK<font color="black">--</font></span>' 
            Try{
                $Result = Invoke-command -ComputerName $Target -Authentication default -Credential $Credential -ScriptBlock { 
                    test-path -Path $Using:RegistryPath -ErrorAction "stop"
                }
            }Catch{
                $ErrorMsg =$_.Exception.Message
                #$ErrorMsg       #--[ Optional ]--
            }
        }Else{
    If ($Console){Write-Host "Ping test FAILED..." -ForegroundColor Red }
            $Script:EmailBody = $Script:EmailBody +'<font color="black";font-family:Consolas;>--</font>'+$Script:FontDarkRed+'Unable to ping target.<font color="black">--</font></span>'
            $Failure = $true
        }
    }    

    If (!($Failure)){
        If ($Result){
            If ($Script:Console){Write-Host "Base Key Detected" -ForegroundColor Green }
            $Script:EmailBody += $Script:FontDarkGreen+'B</span>'
        }Else{
            If ($Script:Console){Write-Host "Creating Base Key" -ForegroundColor Red}
            $Script:EmailBody += $Script:FontDarkRed+'B</span>'
            If($Local){
                Try{
                    New-Item -Path $Script:RegistryPath -Force | Out-Null
                }Catch{
                    $Failed = $True    
                    $ErrorMsg =$_.Exception.Message
                    #$ErrorMsg       #--[ Optional ]--            
                }
            }Else{
                Try{
                    $Result = Invoke-command -ComputerName $Target -Authentication default -Credential $Credential -ScriptBlock { 
                    New-Item -Path $Using:RegistryPath -Force | Out-Null
                    }
                }Catch{
                    $Failed = $True
                    $ErrorMsg =$_.Exception.Message
                    #$ErrorMsg       #--[ Optional ]--
                }
            }
            If ($Failed){
                $Script:EmailBody = $Script:EmailBody + $Script:FontDarkRed+'<font color="black";font-family:Consolas>--</font>Base Key FAIL<font color="black">--</font></span>'
                If ($Console){Write-Host "-- Base Key Detect/Create FAILED" -ForegroundColor Red }
                $Script:EmailBody += $Script:FontDarkRed+'B</span>'
            }
        }
        $Script:EmailBody += $Script:FontBlack+'--'

        #--[ Test for values ]----------------------------------------------
        Try{
            If ($Local){
                $Result = Get-ItemProperty -Path $Script:RegistryPath -ErrorAction "stop"   
            }Else{    
                $Result = Invoke-command -ComputerName $Target -Authentication default -Credential $Credential -ScriptBlock { 
                    Get-ItemProperty -Path $Using:RegistryPath -ErrorAction "stop"
                }
            }
        }Catch{
            $ErrorMsg =$_.Exception.Message
            #$ErrorMsg       #--[ Optional ]--
        }

        If ($Console){Write-Host "Checking Sub-Keys " -ForegroundColor Yellow -NoNewline}     
    ForEach ($Value in $ValueList){
            If ([string]::IsNullOrEmpty($Result.$Value)){
                If ($Console){Write-Host "*" -NoNewline -ForegroundColor Red }                       #--[ value does not exist, creating it ]--
                $Script:EmailBody = $Script:EmailBody + $Script:FontDarkRed+'C</span>'
                $NewResult = Invoke-command -ComputerName $Target -Authentication default -Credential $Credential -ScriptBlock { 
                    New-ItemProperty -Path $Using:RegistryPath -Name $Using:Value -Value "-" -PropertyType STRING -Force | Out-Null
                }
            }Else{
                If ($Script:Update){
                    If ($Console){Write-Host "*" -NoNewline -ForegroundColor Yellow}                 #--[ value already exists but needs update ]--
                    $Script:EmailBody = $Script:EmailBody + $Script:FontDarkCyan+'U</span>'
                    $NewResult = Invoke-command -ComputerName $Target -Authentication default -Credential $Credential -ScriptBlock { 
                        New-ItemProperty -Path $Using:RegistryPath -Name $Using:ValueName -Value $Using:NewValue -PropertyType STRING -Force | Out-Null
                    }
                }Else{    
                    If ($Console){Write-Host "*" -NoNewline -ForegroundColor Green}                  #--[ value already exists ]--
                    $Script:EmailBody = $Script:EmailBody + $Script:FontDarkGreen+'O</span>'
                }
            }
        }
    }
}

If ($Console){Write-Host "`n`n--- Run Completed ---" -ForegroundColor Cyan } 
$Script:EmailBody = $Script:EmailBody + $Script:FontRed+'<br><br>---Run Completed---' 

$Script:EmailBody = $Script:EmailBody +'<br><br><font color="gray";font-family:Consolas; size=2>The following keys are being checked/written according to the codes above:'
ForEach ($Value in $ValueList){
    $Script:EmailBody = $Script:EmailBody +'<br><font color="gray";size=2;font-family:Consolas>'+$Value+'</font></span>'
}

SendEmail

<#==[ XML Configuration file example.  Must reside in same folder as the script and be named like "scriptname.xml" ]=======================

<!-- Settings & Configuration File -->
<Settings>
<General>
<ReportName>Weekly Registry Key Refresh</ReportName>
<DebugTarget>*PC85*</DebugTarget>
<RegistryPath>HKLM:\Software\MyCompany</RegistryPath>
<DnsServer>dc01</DnsServer>
<Domain>MyCompany.com</Domain>
<CompanyName>MyCompany</CompanyName>
</General>
<Email>
<From>WeeklyReports@mycompany.com</From>
<To>me@mycompany.com</To>
<Debug>me@mycomapny.com</Debug>
<Subject>Weekly Registry Key Refresh</Subject>
<HTML>$true</HTML>
<SmtpServer>100.100.50.5</SmtpServer>
</Email>
<Credentials>
<UserName>mydomain\serviceaccount</UserName>
<Password>76492d1NgA0AGEAMAAwADQAZgBiAGMAYQBhAG6AHoAIAegB2AHYgB2AHYAZQAxAGIATg11IAeAegB2AHYAZQAxAGIATgBaADcAYwBtAHAAWHwAYwAzADQABaADcAYwBtAHAAWQB6AHoAIAegB2AHYAZQQA9AIAZQQA9AIAegB2AHYAZ6AHoAIAegB2AHYAZQQA9AIAegB2AHYAZGUAZgBkAGYAZAA=</Password>
<Key>kdhe8m+EhCh7HCh7HCvLOEyj2N0IObibCh7HCvLOEyj2N0IObiie8mE=</Key>
</Credentials>
</Settings>

#>

Friday, October 5, 2018

AD DNS Valiator

In a small environment AD integrated DNS is one of those things that can slip through the cracks.  As much as we want to keep it accurate and clean as long as DHCP and dynamic addressing does it's thing it usually just runs.

To keep old stale records cleaned out DNS scavenging is supposed to deal with old stale records.  It doesn't always do that so I created a script to 1: scan the records and check for a live system, and 2: delete them after two subsequent failures.

The delete option is a recent add-on.  Again, an HTML report is emailed to a set of users for review and for a record of what was done.

The script is available on the PowerShell Gallery here:  PowerShell Gallery  and called "DNSValidator".

Example output:  (the inline report is hard to view but the attachments are much cleaner)
Note: Sensitive data blocked out...




Standardized AD computer decommissioner

We seem to have a lack of , shall we say, "process engagement" here where folks don't always do their due diligence with removing computers from the environment.  To address that I created this script to automate and standardize removing systems from AD.

The idea here is that the script will be called by SharePoint.  A minimal GUI will be created on SharePoint asking for the target system and the users AD user ID.  When they click OK, or RUN or whatever the button says, it sends the two items as input variables to the script.

The script has it's own AD credential to perform the actions.  It verifies that the user is in a group preset from the XML config file.  It then checks for an AD record for the target and if found, deletes the record.  It then checks DNS for a record and again, if found, deletes it.

The resultant data set is formatted and sent in an HTML email to the users specified.  Below is an example of the resultant email.

The script is available on the PowerShell Gallery here: 
https://www.powershellgallery.com/profiles/Kcmjr


Tuesday, September 25, 2018

Automatically load RSAT as a different user

For a while now I've wanted to load the RSAT (Windows Remote Server Administration Tools) tool I use daily via a script at logon, but as my admin user account, not my normal logon.  There are numerous posts on the web about doing that but with the later versions of PowerShell most of those don't work.  Windows 10 doesn't help.

I'm sure there are better ways of doing this but after trying the suggestions I found on the web I hit on a combination that works.  The full script and all future updates are on my PowerShell Library site here: https://www.powershellgallery.com/profiles/Kcmjr

I call the script "RSAT-As-Admin.ps1".  It includes a list of RSAT tools that you must adjust to suit your needs.  The way it's written you can add additional executables easily if desired.

Here is the code from release v1.00.  Updates will be posted at the link,above.


Param(
    [Switch]$Console = $false           #--[ Set to true to enable local console result display. Defaults to false ]--
)
<#==============================================================================
         File Name : RSAT-As-Admin.ps1
   Original Author : Kenneth C. Mazie (kcmjr AT kcmjr.com)
                   :
       Description : Automatically loads specified Windows RSAT AD Admin tools using the user ID you specify.
                   :
             Notes : Normal operation is with no command line options. The list of RSAT tools below
                   : should be commented in/out as needed.  Tested on Windows 10 1803 only.
                   :
         Arguments : Command line options for testing:
                   : - "-console $true" will enable local console echo
                   :
          Warnings : None
                   :  
             Legal : Public Domain. Modify and redistribute freely. No rights reserved.
                   : SCRIPT PROVIDED "AS IS" WITHOUT WARRANTIES OR GUARANTEES OF
                   : ANY KIND. USE AT YOUR OWN RISK. NO TECHNICAL SUPPORT PROVIDED.
                   : That being said, please let me know if you find bugs or improve the script.
                   :
           Credits : Code snippets and/or ideas came from many sources including but
                   : not limited to the following:   n/a
                   :
    Last Update by : Kenneth C. Mazie    
   Version History : v1.0 - 09-24-18 - Original
    Change History : v1.1 - 00-00-00 -
                   :
==============================================================================#>
<#PSScriptInfo
.VERSION 1.00
.GUID 75f90821-5799-44ed-af38-bc4e05f9e385
.AUTHOR Kenneth C. Mazie (kcmjr AT kcmjr.com)
.DESCRIPTION
Automatically loads specified Windows RSAT AD Admin tools using the user ID you specify. 
#>
#Requires -Version 5.1

Clear-Host
$Script:Credential = ""
$ThisDomain = (Get-ADDomain).DNSroot
$Credential = Get-Credential #-Credential "domain\username"

#------------------------------------------------------------------------------------------------------
$ToolList = @()   #--[ Array of separate items to allow easy addition or removal. Comment out lines for tools you don't want loaded  ]--
#$ToolList += "dsac.exe"             #--[ Active Directory Administrative Center         ]--
$ToolList += "dsa.msc"              #--[ Active Directory Users and Computers           ]--
#$ToolList += "domain.msc"           #--[ Active Directory Domains and Trusts            ]--
#$ToolList += "dssite.msc"           #--[ Active Directory Sites and Services            ]--
$ToolList += "gpmc.msc"             #--[ Group Policy Management                        ]--
$ToolList += "dhcpmgmt.msc"         #--[ DHCP Manager                                   ]--
$ToolList += "dnsmgmt.msc"          #--[ DNS Manager                                    ]--
$ToolList += "dfsmgmt.msc"          #--[ DFS Manager                                    ]--
#$ToolList += "vmw.exe"              #--[ Volume Activation Tools                        ]--
#$ToolList += "printmanagement.msc"  #--[ Print Management                               ]--
#$ToolList += "nlbmgr.exe"           #--[ Network Load Balancing Manager                 ]--
#$ToolList += "secpol.msc /s"        #--[ Local Security Policy                          ]--
#$ToolList += "iscsicpl.exe"         #--[ iSCSI Initiator                                ]--
#$ToolList += "fsrm.msc"             #--[ File Server Resource Manager                   ]--
#$ToolList += "Cluadmin.msc"         #--[ Failover Cluster Manager                       ]--
#$ToolList += "ClusterUpdateUI.exe"  #--[ Cluster Aware Updating                         ]--
#$ToolList += "certsrv.msc"          #--[ Certification Authority                        ]--
#$ToolList += "adsiedit.msc"         #--[ ADSI Edit                                      ]--
#--------------------------------------------------------------------------------------------------------

$ToolPath = "c:\windows\system32\"
[Environment]::CurrentDirectory = (Get-Location -PSProvider FileSystem).ProviderPath

$Result = disable-UEV
#--[ Microsoft UE-V (User Experience Virtualization) is a tool that enables users to move from one Windows  ]--
#--[ device to another and maintain the same operating system (OS) and applications settings. (i.e roaming) ]--
If ($Result -Like "*successfully*"){
    If ($Console){Write-host $Result -Foregroundcolor Green}
}Else{
    If ($Console){Write-Host "There was an error disabling UE-V" -ForegroundColor Red}
}

ForEach ($Tool in $ToolList){
    write-host "`n-------------------------------------------------------------------`n"
    If ($Tool.Split(" ").count -gt 1){    #--[ There is a space in the tool command meaning some sort of argument ]--
        $Arg = $Tool.Split(" ")[1]
        $Tool = $Tool.Split(" ")[0]
           
        If ($Tool.Split('.')[1] -eq "exe"){
            $Command = 'Start-Process "'+($ToolPath+$Tool+" "+$Arg)+'" -verb runas'
        }Else{
            $Command = 'Start-Process mmc.exe -verb runas -argument "'+($ToolPath+$Tool+" "+$Arg)+'"'
        }   
    }Else{
        If ($Tool.Split('.')[1] -eq "exe"){
            $Command = 'Start-Process '+($ToolPath+$Tool)+' -verb runas'
        }Else{
            $Command = 'Start-Process mmc.exe -verb runas -argument '+($ToolPath+$Tool)
        }   
    }

    #$Command  #--[ Un-comment to display the resultant command line ]--

    If (Test-Path -Path ($ToolPath+$Tool)) {
        Start-Process powershell.exe -Credential $Credential -NoNewWindow -ArgumentList $Command
        If ($Console){write-host "Tool $Tool is starting..." -ForegroundColor Green}
    }Else{
        If ($Console){write-host "Tool $Tool was not found..." -ForegroundColor Red}
    } 
 
}