Menu

Virtual Geek

Tales from real IT system administrators world and non-production environment

Powershell Trick : Execute or run any file as a script file

October 18, 2017 02:22PM

This blog post is addition to my earlier article Different ways to bypass Powershell execution policy :.ps1 cannot be loaded because running scripts is disabled. Just to recap If you have execution policy blocked in your environment and want to execute riles in PowerShell, you can compile the the file to PowerShell ScriptBlock using .net object. In the screen shot right side is my text file with sample content.

First line of the script is reading text file, using -Raw parameter, will return all data as single string. This us required in next line of code.
$AnyFile = Get-Content C:\temp\AnyFile.txt -Raw

In next I am using .net object System.Management.Automation.ScriptBlock and method create to compile text content to script block.
$ScriptBlock = [System.Management.Automation.ScriptBlock]::Create($AnyFile)

Using & I can easily execute the this compiled and formatted text file.
& $ScriptBlock

Powershell script executionpolicy execute any file as script, get-content, automation, scriptblock create .net system.management,automation.scriptblock create

Check the gettype() and its fullname results, information is perfect for execution.

PS C:\> $ScriptBlock.GetType()
IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     ScriptBlock                              System.Object

PS C:\> $ScriptBlock.GetType().Fullname
System.Management.Automation.ScriptBlock

Powershell .net object scriptblock gettype(), system.management.automation.scriptblock convert execute any file compile

Useful blogs
Different ways to bypass Powershell execution policy :.ps1 cannot be loaded because running scripts is disabled
Installing, importing and using any module in powershell

Powershell: Temporary group membership on Windows 2016 Active Directory

October 17, 2017 12:15PM

This is second part of configuring and architecting AD infrastructure new features. Microsoft has introduced new great feature with Windows Server 2016 Active directory, PAM (Privileged Access Management) Feature, Where user can be added to a group for a particular time. Once that Time to live (TTL) is expired account is automatically removed from group. This is the true automated way, and doesn't require much settings or any other third party software.

Before starting make sure you are on latest windows 2016 Domain and Forest functional level mode, Verify it using Get-Domain | select DomainMode and Get-ADForest | Select Forestmode. For another feature check Microsoft Active directory additional features - AD Recycle Bin Powershell.

Active Directory powershell domain controller Get-AdDomain, Get-Forest forestmode and DomainMode functional level

This feature information can be viewed using below command. Note down DistinguishedName, It will be required in next one-liner command for configuration. EnabledScopes is empty, means feature is not configured yet and Requiredforestmode is matching my current forest functional level.
Get-ADOptionalFeature 'Privileged Access Management Feature'

Next command enables the feature on the forest level, I have used earlier info DistinguishedName as identity. This shows warning, that Enabling 'Privileged Access Management Feature' on  'CN=Partitions,CN=Configuration,DC=vcloud-lab,DC=com' is an irreversible action and you will not be able to disable if you proceed, If you agree press Y. (Make sure you have Enterprise admins and Schema Admins rights before proceeding)
Enable-ADOptionalFeature -Identity 'CN=Privileged Access Management Feature,CN=Optional Features,CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration,DC=vcloud-lab,DC=com' -Scope ForestOrConfigurationSet -Target vcloud-lab.com

If I use see the feature information again EnabledScopes attributes is no longer empty.Powershell Active directory ad domain controller Get-AdoptionalFeature, Enable-AdoptionalFeature, Privileged access management feature, target, enabled scopes, object guid class

"The New-TimeSpan cmdlet creates a TimeSpan object that represents a time interval. You can use a TimeSpan object to add or subtract time from DateTime objects."
In next I have created small time span interval of  30 minutes, User will be part of domain for the period of time mentioned here. 
$TimeToLive = New-TimeSpan -Minutes 30

In the next I am adding user account name Demouser in Group (Identity) Enterprise Admins using given timespan interval.
Add-ADGroupMember -Identity 'Enterprise Admins' -Members DemoUser -MemberTimeToLive $TimeToLive

To identify the expiry time of user on the group use below one-liner. Check out the highlighted result It has extra property TTL and the value is in the seconds. Other permanent users don't have any TTL value. 
Get-ADGroup 'Enterprise Admins' -Properties Member -ShowMemberTimeToLive | Select-Object -ExpandProperty Member

Microsoft Powershell Active directory domain Controller, Time to live, pam priviledged access management features add-adgroupmember, get-adgroup, new-timespan.png

Keep running above command every few times and you will see the difference of decrease in TTL, time is reducing. Once the time expired user is automatically removed from group.

Powershell active directory dc, Get-Adgroup showmembertimetolive pam priviledged access management, temporary group access time based, select object ttl on group

Note: When you add a new member to a group, the change needs to replicate to other domain controllers (DCs) in the bastion forest. Replication latency can impact the ability for users to access resources.

Below are the few use case for PAM.

  • There’s no reason for all of users to have full access to every system, even if they are trusted.
  • You have situations where a user needs escalated privileges, but only temporarily
  • Your organization has strict compliance to mandates that you must follow.
  • Managing privileged access is inefficient and requires too many resources.
  • Group membership need to be rotated.

Userful Articles
Installing, importing and using any module in powershell
POWERSHELL: INSTALLING AND CONFIGURING ACTIVE DIRECTORY 

Microsoft Active directory additional features - AD Recycle Bin Powershell

October 11, 2017 01:00PM

I recently was involved and architected IT infrastructure for one of the small startup group, I deployed Windows Server 2016 server and architected Active Directory infrastructure, Startup staff's work was involved using heavy use of AD API in their own software, creation and deletion of AD accounts, I wanted all the recent new features on AD, specially recycle bin feature, Although it is introduced in Windows 2008 R2, I thought it is worth documenting the procedure here and create more awareness. Before deploying you should read the below statement if you have some other AD architecture in your mind.

"When the Recycle Bin optional feature is enabled, every DC is responsible for updating its cross-domain object references in the event that the referenced object is moved, renamed, or deleted. In this case, there are no tasks associated with the Infrastructure FSMO role, and it is not important which domain controller owns the Infrastructure Master role."

Powershell: Temporary group membership on Windows 2016 Active Directory PAM (Privileged Access Management Feature)

To get know list of all optional additional features run below cmdlet. It lists two features Recycle Bin Feature and Privileged Access Management Feature. I am going to write about second feature in my next blog. For the Recycle bin feature requires forest mode to be at atleast Windows 2008 R2 level. Same can be changed using Set-AdForestMode cmdlet. As I deployed my first DC on windows server 2016, my forest and domain functional level are already Windows 2016, Verify it running command Get-ADDomain | select Domainmode and Get-ADForest | Select Forestmode

Check on Installing, importing and using any module in powershell

Active directory Powershell, Get-ADDomain Domain mode, Get-Adforest Forestmode forest, functional level command let set-addomain and forest

Get-ADOptionalFeature -Filter * 
DistinguishedName  : CN=Recycle Bin Feature,CN=Optional Features,CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration,DC=vcloud-lab,DC=com
EnabledScopes      : {CN=Partitions,CN=Configuration,DC=vcloud-lab,DC=com, CN=NTDS Settings,CN=SERVER01,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=vcloud-lab,DC=com}
FeatureGUID        : 766ddcd8-acd0-445e-f3b9-a7f9b6744f2a
FeatureScope       : {ForestOrConfigurationSet}
IsDisableable      : False
Name               : Recycle Bin Feature
ObjectClass        : msDS-OptionalFeature
ObjectGUID         : b797addd-61c3-4f3e-8168-b2f4d0c77423
RequiredDomainMode :
RequiredForestMode : Windows2008R2Forest

DistinguishedName  : CN=Privileged Access Management Feature,CN=Optional Features,CN=Directory Service,CN=Windows NT,CN=Services,CN=Configuration,DC=vcloud-lab,DC=com
EnabledScopes      : {}
FeatureGUID        : ec43e873-cce8-4640-b4ab-07ffe4ab5bcd
FeatureScope       : {ForestOrConfigurationSet}
IsDisableable      : False
Name               : Privileged Access Management Feature
ObjectClass        : msDS-OptionalFeature
ObjectGUID         : 06037360-fbf9-4682-8fb9-07a428a21d11
RequiredDomainMode :
RequiredForestMode : Windows2016Forest

Windows Powershell Get-AdOptionalFeature option active directory option features filter, Privileged Access Management Feature

To enable the Recycle bin Feature you should know its complete identity name which you will find with above screenshot in DistinguishedName, For scope there are 2 options forest and domain. Target name is the domain name. This action is irreversible and you will not be able to disable it. this information is stored in AD configuration partition.
Enable-ADOptionalFeature -Identity 'CN=Recycle Bin Feature, CN=Optional Features, CN=Directory Service, CN=Windows NT, CN=Services, CN=Configuration, DC=vcloud-lab,DC=com' -Scope ForestOrConfigurationSet -Target vcloud-lab.com

Enable-ADOptionalFeature recycle bin feature forest or configuration set target Powershell Active Directory run as administrator

Next all my accounts are kept in a single OU, which I can list using below command. Here I am gathering information because I need GUID and verify later if restored objects have same GUID number. 

Get-ADObject -SearchBase 'OU=DeleteOu, DC=vcloud-lab, dc=com' -Filter {Name -Like 'Demo*'}
DistinguishedName                                Name         ObjectClass ObjectGUID
-----------------                                ----         ----------- ----------
CN=DemoUser,OU=DeleteOu,DC=vcloud-lab,DC=com     DemoUser     user        24632275-ea54-408c-bc07-fa23f8305da1
CN=DemoGroup,OU=DeleteOu,DC=vcloud-lab,DC=com    DemoGroup    group       7a299a0e-2e4b-4ec1-b45b-cb4727a6f0cb
CN=DemoComputer,OU=DeleteOu,DC=vcloud-lab,DC=com DemoComputer computer    f04b216e-be48-4dc5-8ada-5c843d03cfbc

Powershell Active Directory Get-AdObject -searchbase ou Filter like, Distinguishedname, objectclass, objectguid, guid, Recycle Bin

Here next I am removing (Deleting) ad accounts. They will be marked as deleted tag, and kept for next 180 days timespan. They are called tombstone objects.
Get-ADObject -SearchBase 'OU=DeleteOu, DC=vcloud-lab, dc=com' -Filter {Name -Like 'Demo*'} | Remove-ADObject -Confirm:$false

Once accounts are deleted I can verify and see there are no account objects in OU, I can confirm the same in gui dsa.msc, it is empty. 
Get-ADObject -SearchBase 'OU=DeleteOu, DC=vcloud-lab, dc=com' -Filter {Name -Like 'Demo*'}

Get-AdObject -SearchBase -Filter, Remove-Object delete user account powershell active Driectory recycle bin feature

To view deleted account objects use parameter -IncludeDeletedObjects, I can use searchbase to get strict result from specific organization unit, Note down the the attribute name deleted marked as true.
Get-ADObject -Filter {Name -Like 'Demo*' -and Deleted -eq $True} -IncludeDeletedObjects

Pipeline and use Restore-ADObject, to recover tombstone objects. This is very good option, and doesn't require any third party software to restore account (backup is always essential), Instantly you can restore account.
Get-ADObject -Filter {Name -Like 'Demo*' -and Deleted -eq $True} -IncludeDeletedObjects | Restore-ADObject

List the object information to verify GUID information, I have already information fetched earlier, whether they have same account.
Get-ADObject -Filter {Name -Like 'Demo*'}

Active directory Powershell, Get-Adobject includeDeletedObjects, deleted true, Restore-AdObject restore recover ad users computers and groups

Useful blogs
Installing, importing and using any module in powershell
POWERSHELL: INSTALLING AND CONFIGURING ACTIVE DIRECTORY 

Vembu Free Edition

October 8, 2017 10:46PM

Vembu is a leading software product development that has been focusing on Backup and Disaster Recovery software for data centers over a decade. It’s flagship offering- the BDR Suite of products consists of VM Backup for VMware vSphere and Hyper-V, Disk Image backups for Physical machines, Workstations. Backing up individual files and folders to physical servers and cloud can be performed with Vembu Network Backup and Online Backup respectively.

Moreover, it has multiple flexible deployment like on-site, off-site and to the cloud through single user interface. Another offering of the Vembu BDR Suite is to be able to configure item level backups like Microsoft Exchange Servers, SharePoint, SQL, My SQL, Office 365, G Suite etc., This latest version of Vembu BDR Suite v3.8.0 has come out with the few notable features in two major offerings- one unlimited features for three virtual machines and the second thing being able to backup unlimited virtual machines with restricted features.

This latest free edition of Vembu BDR Suite was designed understanding the setbacks by any common IT Administrator. Hence making Vembu an important name in the market for backup vendor for its enterprise level product for SMBs. This free edition is free forever and IT administrators can continue managing their backups with the trial version without any feature restriction. Let's take a plunge into the detailed features of this free edition.

Unlimited features for Limited environment (3 VMs):

Using the Vembu BDR Suite in its trial version does not require purchasing a license. This category of the Free edition offers unlimited features and few of them are listed below:

  1. Agentless VMware backups for multiple VMs: Configuring backups for protecting multiple VMs without physically installing any agent.
  2. Disk Image Backups from BDR Server: Disk Image Backups can now be configured and managed via Vembu BDR Server. Relying on proxy agents is no longer required, unless it’s a distributed deployment which require individual proxy agent installation.
  3. Full VM Backup: Will back up the entire VM including OS, applications and the data.
  4. Storage Pooling: Storage Pools are used to aggregate the space available from different volumes and utilise them as a storage for specific backups. The hybrid volume manager of Vembu BDR Server supports scalable and extendable backup storage for different storage media such as Local drives, NAS (NFS and CIFS) and SAN (iSCSI and FC). Vembu BDR provides storage pooling option for both backup level and group level.
  5. LAN free data transfer using SAN and Hot- Add modes: Vembu VM backup support Direct SAN, Hot-Add and network transport mode to back up the VM data.
  6. Auto Authorization: Enabling Auto authorization in Vembu BDR allows proxy agents to get registered to backup server using unique registration key generated by respective BDR server.
  7. Automatic Backup Scheduling: Backups can be automatically scheduled as per the user's flexibility
  8. Encryption Settings: Users can now provide additional security to their disk based backup jobs by assigning custom-password to backup server, such that all their backup data will be encrypted and can be restored/accessed only by providing the custom-password.
  9. FLR from GUI (Backup & Replication): File Level Recovery (FLR) is now available for both backup and replication jobs where user can choose specific files and folders from VMware/Hyper-V/Disk Image backups and VMware replication, to be restored in a quick fashion.

All the above major features are included in this free edition for 3 virtual machines. Let’s get to know those restricted features for unlimited virtual machines.

Restricted Features for unlimited virtual machines:

All the features mentioned above for limited business environment will be applicable for this categories with few restrictions in the features. They are:

  1. Application aware processing: Configuring them for a Hyper-V environment is restricted but that does not hold good with VMware vSphere Esxi(s).
  2. Changed Block Tracking: Only the incremental blocks which are changed since the previous backup will been tracked and  backed up in the successive backup schedule thereby reducing disk space and time
  3. Retention Policies: User can retain any number of recovery points of his own choice. They come to great use when it comes to store the backup data.
  4. Near CDP: Incremental backup can be scheduled every 15 Mins to ensure the RPO < than 15 Mins
  5. Quick VM recovery to ESXi: Incremental backup can be scheduled every 15 mins to ensure the RPO < than 15 Mins.
  6. Automated Backup verification: Verify the recoverability of the backed up images and screenshot of the booted Image backup will be mailed

Backup and recovery holds good for both physical and virtual environments and makes granular recovery possible with great ease.You will able to scale out your storage, secure your individual backup jobs with in-built deduplication, encryption and compression that makes its own file system called, the VembuHIVE.

This latest free edition thus becomes one of the most business-friendly and a complete backup solution. That being said,  It can be suitable for both testing and production environments! Their out-of-the box policy- backup for all was hailed even at the recent VMworld event, Las Vegas.

Well, there is nothing left to ponder now. It’s time to make the right decision. It could be done right away with getting started with their free edition of Vembu BDR Suite on a 30 days free trial. Click here.


I will just start from earlier blog VEMBU. Setup a backup job Go to Backup → Microsoft Hyper-V, Add Hyper-V server: If it's a fresh installation, click on 'Add Hyper-V Server' option. You can either choose the 'Standalone Hyper-V Host' or 'SMB Host' as server type. Choosing Standalone Hyper-V Host will ask user to provide login Hyper-V credentials, it also asks user to confirm if they are using SMB server as storage for VMs. 
     o If 'No' - Server addition will be completed with Saving the credentials.
     o If 'Yes' - Users will be redirected to the next page to provide SMB credentials.

vcloud-lab.com vembu screenshot 01.png

Choosing SMB Host will direct user to Apply SMB credentials page, where they will be required to provide SMB Host credential. Once done providing it, hit save to add Hyper-V server. Create Hyper-V Backup: Once done adding, go to Backup → Microsoft Hyper-V. The list of Hyper-V servers, added will be shown. 

From the list of servers added, Click Backup Now option in the Hyper-V server to be backed up. Choose Virtual Machine(s): Choose list of VMs you wish to get backed up and proceed. You can configure either host level backup job or can select any specific set of VMs to be backed up. · You can choose specific VMs/Host/Cluster easily using search feature.

vcloud-lab.com vembu screenshot 02

VM(s)/Disk(s) Exclusion: On selecting Host level backup, you might wish to exclude some specific set of VMs from getting backed up. Such VMs can be excluded using VM(s)/Disk(s) exclusion option. VM Exclusion Click 'VM(s)/Disk(s) Exclusion' option, you will get a popup as shown below. Choose 'Exclude VM(s)' tab. To exclude a virtual machine from a configured host level backup, click 'select VM' and choose the VMs to be excluded and click 'Exclude'. Once added, save the exclusion settings.You can also add/delete a VM to/from exclusion list, whenever required by editing the backup job. Note: Changes made in VM exclusion settings will be taken into effect immediately with next schedule.

Application-Aware Hyper-V Backups: Hyper-V backups utilize Microsoft VSS writers to take application-consistent backups(MS SQL, MS Exchange) and truncate exchange log files to free up the space.
Enabling application aware process - Truncate logs immediately: Enabling this option lets Vembu BDR truncate the exchange server logs before initiating
backup process. It purges and commits log files along with the .edb files and reduce storage space consumed.
Application Aware Image Process Prerequisites: · To perform application-aware image processing, the Guest Machine (running MS
Exchange server, MS SQL Server, MS SharePoint Server, MS Active Directory) should be installed with latest Hyper-V integration services.

Configure Scheduling: Users can configure their backup schedules flexibly based on their requirement. They can choose from Hourly/Daily/Weekly options for backup schedules. Advanced (GFS Retention): The Multilevel GFS retention reduces the time taken to restore backed up machines and most importantly reduce the size of image files in storage location. It also help avoid long chains of incrementals, ensuring safety of backup data and allow you to meet the requirements of your retention policy.

GFS retention merge incrementals on a daily, weekly and monthly basis: 
o Daily - Daily merge will merge hourly incrementals on the third day's first successful incremental backup.
o Weekly - Weekly merge will commence based on user scheduled day's first successful incremental backup. It will merge all daily merged incrementals into a single weekly merged file.
o Monthly - Monthly merge is much similar as weekly merge where user need to schedule particular day in a month(For example: Third Wednesday) and the merge will get initiated at first successful incremental of the day. It merges all weekly merged files as a single monthly file.

Progress Details: Thus, backup progress is witnessed and can be verified once it completes successfully.
Disaster Recovery
Go to Recovery tab. Backups configured from various client machines to the server, will be listed for recovery, along with below listed options:
o Restore
o Virtual mount
o Proceed to Persistent Instant Boot version delete
o Delete
o Replication actions
o Status
o Reports

Users can either take a copy of this mounted data or boot respective files if needed on KVM(IMG file in Linux), VMware vSphere(VMDK) or Hyper-V(VHD, VHDX).

Vembu Virtual Drive is an exclusive feature of VembuBDR server, that allows user to instant access backup data. With the help of Vembu HIVE file system, Vembu Virtual Drive virtual mount backup data and allow instant access for users. Vembu Virtual Drive will make following file format types available for any image based backups mounted in it:
· VHD
· VMDK
· VHDX
· VMDK-Flat
· RAW image files
These files can be used based on user requirements. For example, a VHD file can be mounted in Hyper-V or a VMDK file can be mounted in a ESXi server or a RAW image file can be mounted in KVM to create a virtual machine. VHD file can also be mounted in disk management to access file level backup data.

Powershell: Get registry value data

October 7, 2017 05:05PM

Finding and fetching registry value data information using PowerShell is very easy, I found in one of the organization administrators where doing unnecessary changes to the registry to specific settings, for one of the example ie: I had to get information from one of the setting under HKey_Local_Machine\System\CurrentControlSet\Services\USBSTOR\Start. If value data is set to 4, USB storage devices will disabled and would not work. But admins where changing it on the system to 3. To check the status I created script for windows 2008 and 2008 R2, This script uses traditional way to connect remote registry. Make sure Remote Registry service status is running before trying to attempt. Same can be verify using Get-Service RemoteRegistry command. 

Powershell Services.msc vcloud-lab.com  remote registry get-service remoteregistry

To verify you can open remote registry using File>>Connect Netowork Registry.

Powershell Registry Editor file, connect network registry successful

Next I need a Hive name (There are 5 root nodes ClassesRoot, CurrentUser, LocalMachine, Users, CurrentConfig) and key name is System\CurrentControlSet\Services\USBStor as highlighted. ValueName is Start

Below are the hive name mappings. 
ClassesRoot --> HKEY_CLASSES_ROOT
CurrentUser  --> HKEY_CURRENT_USER
LocalMachine --> HKEY_LOCAL_MACHINE1
Users --> HKEY_USERS
CurrentConfig   --> HKEY_CURRENT_CONFIG

Microsoft Powershell Registry Editor hklm, hkey local machine, system, currentcontrolset, services

Use below script to store in $PROFILE location. and relaunch the PowerShell. Procedure has been given on Powershell Active Directory: Show treeview of User or Group memberof hierarchy. This script created created using registry .net object [Microsoft.Win32.RegistryKey]. It will use your logged in user account to connect remote registry. If you multiple computer names provide it separating comma, or store them in text file and use cat to get the list.

Get-RegistryValueData -ComputerName Server01, Member01, test -RegistryHive LocalMachine -RegistryKeyPath SYSTEM\CurrentControlSet\Services\USBSTOR -ValueName Start

Powershell get registry value, Get-RegistryValueData, Registry hive, Registry key path, value name data

Useful Blogs
Different ways to bypass Powershell execution policy :.ps1 cannot be loaded because running scripts is disabled
Installing, importing and using any module in powershell

1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
function Get-RegistryValueData {
    [CmdletBinding(SupportsShouldProcess=$True,
        ConfirmImpact='Medium',
        HelpURI='http://vcloud-lab.com')]
    Param
    ( 
        [parameter(Position=0, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)]
        [alias('C')]
        [String[]]$ComputerName = '.',
        [Parameter(Position=1, Mandatory=$True, ValueFromPipelineByPropertyName=$True)] 
        [alias('Hive')]
        [ValidateSet('ClassesRoot', 'CurrentUser', 'LocalMachine', 'Users', 'CurrentConfig')]
        [String]$RegistryHive = 'LocalMachine',
        [Parameter(Position=2, Mandatory=$True, ValueFromPipelineByPropertyName=$True)]
        [alias('KeyPath')]
        [String]$RegistryKeyPath = 'SYSTEM\CurrentControlSet\Services\USBSTOR',
        [parameter(Position=3, Mandatory=$True, ValueFromPipelineByPropertyName=$true)]
        [alias('Value')]
        [String]$ValueName = 'Start'
    )
    Begin {
        $RegistryRoot= "[{0}]::{1}" -f 'Microsoft.Win32.RegistryHive', $RegistryHive
        try {
            $RegistryHive = Invoke-Expression $RegistryRoot -ErrorAction Stop
        }
        catch {
            Write-Host "Incorrect Registry Hive mentioned, $RegistryHive does not exist" 
        }
    }
    Process {
        Foreach ($Computer in $ComputerName) {
            if (Test-Connection $computer -Count 2 -Quiet) {
                $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($RegistryHive, $Computer)
                $key = $reg.OpenSubKey($RegistryKeyPath)
                $Data = $key.GetValue($ValueName)
                $Obj = New-Object psobject
                $Obj | Add-Member -Name Computer -MemberType NoteProperty -Value $Computer
                $Obj | Add-Member -Name RegistryValueName -MemberType NoteProperty -Value "$RegistryKeyPath\$ValueName"
                $Obj | Add-Member -Name RegistryValueData -MemberType NoteProperty -Value $Data
                $Obj
            }
            else {
                Write-Host "$Computer not reachable" -BackgroundColor DarkRed
            }
        }
    }
    End {
        #[Microsoft.Win32.RegistryHive]::ClassesRoot
        #[Microsoft.Win32.RegistryHive]::CurrentUser
        #[Microsoft.Win32.RegistryHive]::LocalMachine
        #[Microsoft.Win32.RegistryHive]::Users
        #[Microsoft.Win32.RegistryHive]::CurrentConfig
    }
}


Get-RegistryValueData -ComputerName Server01, Member01, testcomp -RegistryHive LocalMachine -RegistryKeyPath SYSTEM\CurrentControlSet\Services\USBSTOR -ValueName 'Start'

Another way I can use another process to connect registry using Invoke-Command but require special configuration POWERSHELL PS REMOTING BETWEEN STANDALONE WORKGROUP COMPUTERS, This is best option if you have configured PS remoting, and you don't have to run above script or need extra stepd. You can use default inbuilt commands Get-ItemProperty combining with Invoke-Command. Below is the example cmdlet for getting information from local computer.
Get-ItemProperty -Path 'HKLM:\SOFTWARE\VMware, Inc.\VMware Tools\' -Name InstallPath | select InstallPath

Below procedure is for remote server using Invoke-Command and enclose command within carly brackets {}.
Invoke-Command -ComputerName Member01, Server01 {Get-ItemProperty -Path 'HKLM:\SOFTWARE\VMware, Inc.\VMware Tools\' -Name InstallPath | select InstallPath}

Powershell Registry remotely Invoke-command Get-ItemProperty -path select-object

Powershell Trick: Convert text to ASCII art

October 4, 2017 01:40PM

Powershell text convert to Ascii art demo abcdefghijklmnopqrstuvwxyz0123456789 without online algorithm

As PowerShell has plain command based console if you want to show different font or different bigger font on the same console as output, you will have to use ASCII Text art, I had got a request to write a script to convert any text to ASCII art. Only weirdness in the request I found was, whatever output generated as ascii art, should not be captured to file or by coping it. Someone might argue using Write-Host cmdlet, but Here I have found perfect use case for my need of using Write-Host, I have used it with backgroundcolor parameter to show font, keeping few spaces no color.

Below is the example of one of the letter A. (There are only capital alphabets, small letters are shown as capital alphabets only), You can create your own font and it is easily replaceable, I am planning to create external file in future with different fonts. 

1
Write-Host $(" " * 6) -BackgroundColor 'Yellow' -NoNewline; Write-Host " "; Write-Host "  " -BackgroundColor 'Yellow' -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor 'Yellow'  -NoNewline; Write-Host " "; Write-Host "  " -BackgroundColor 'Yellow' -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor 'Yellow'  -NoNewline; Write-Host " "; Write-Host $(" " * 6) -BackgroundColor 'Yellow' -NoNewline; Write-Host " "; Write-Host "  " -BackgroundColor 'Yellow' -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor 'Yellow'  -NoNewline; Write-Host " "

You can save script in .\Convertto-TextASCIIArt.ps1. There is a parameter -Text where your provide your custom text message. and -FontColor has choice (Black, DarkBlue, DarkGreen, DarkCyan, DarkRed, DarkMagenta, DarkYellow, Gray, DarkGray, Blue, Green, Cyan, Red, Magenta, Yellow, White). If you need spacial character send me comment on the blog so I can add it if required. 

Difficulty running script go thru my earlier blog.
Different ways to bypass Powershell execution policy :.ps1 cannot be loaded because running scripts is disabled
Installing, importing and using any module in powershell

Powershell trick convertto-textasciiart, convert text to acsii art algorithm Font color console

If you need more font choices, you can use -Online parameter, which will use api and fetch selected text from http://artii.herokuapp.com using Invoke-WebRequest using Get method. For complete font list (figlet) browse http://artii.herokuapp.com/fonts_list or user -FontName Parameter. Font name (figlet name) is case sensitive.

Powershell convertto-textasciiart convert text to ascii art using online website api powershell figlet bit font free

This code is available on GitHub.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
#
#requires -version 4
<#
.SYNOPSIS
    Convertto-TextASCIIArt converts text string to ASCII Art.
.DESCRIPTION
    The Convertto-TextASCIIArt show normal string or text as big font nicely on console. I have created one font for use (It is not exactly font but background color and cannot be copied), alternatively if you are using online parameter it will fetch more fonts online from 'http://artii.herokuapp.com'.
.PARAMETER Text
    This is common parameter for inbuilt and online and incase not provided default value is '# This is test !', If you are using inbuilt font small letter will convert to capital letter.
.PARAMETER Online
    To use this parameter make sure you have active internet connection, as it will connect to website http://artii.herokuapp.com and and using api it will download the acsii Art
.PARAMETER FontName
    There are wide variaty of font list available on http://artii.herokuapp.com/fonts_list, when using online parameter, Value provided here is case sensetive.
.PARAMETER FontColor
    Below is the list of font color can be used to show ascii art.
    'Black', 'DarkBlue','DarkGreen','DarkCyan', 'DarkRed','DarkMagenta','DarkYellow','Gray','DarkGray','Blue','Green','Cyan','Red','Magenta','Yellow','White'
.PARAMETER FontHight
    This parameter is optional and default value is 5, this is font hight and required for the font I created. Algorithm of this script is depend on the default value.
.INPUTS
    [System.String]
.OUTPUTS
    [console]
.NOTES
    Version:        1.0
    Author:         Kunal Udapi
    Creation Date:  30 September 2017
    Purpose/Change: Personal use to show text to ascii art.
    Useful URLs: http://vcloud-lab.com, http://artii.herokuapp.com/fonts_list
.EXAMPLE
    PS C:\>.\Convertto-TextASCIIArt -Online -Text "http://vcloud-lab.com" -FontColor Gray -Fontname big
  _     _   _              ____         _                 _        _       _                         
 | |   | | | |       _    / / /        | |               | |      | |     | |                        
 | |__ | |_| |_ _ __(_)  / / /_   _____| | ___  _   _  __| |______| | __ _| |__   ___ ___  _ __ ___  
 | '_ \| __| __| '_ \   / / /\ \ / / __| |/ _ \| | | |/ _` |______| |/ _` | '_ \ / __/ _ \| '_ ` _ \ 
 | | | | |_| |_| |_) | / / /  \ V / (__| | (_) | |_| | (_| |      | | (_| | |_) | (__ (_) | | | | | |
 |_| |_|\__|\__| .__(_)_/_/    \_/ \___|_|\___/ \__,_|\__,_|      |_|\__,_|_.__(_)___\___/|_| |_| |_|
               | |                                                                                   
               |_|                                                                                   

    Shows and converts text to cool ascii art from online site http://artii.herokuapp.com using apis.
.EXAMPLE
    PS C:\>.\Convertto-TextASCIIArt -Text '# This !'

      ██  ██     ██████ ██  ██ ██   ████     ██
    ██████████     ██   ██  ██ ██ ██         ██  
      ██  ██       ██   ██████ ██   ██       ██  
    ██████████     ██   ██  ██ ██     ██    
      ██  ██       ██   ██  ██ ██ ████       ██  
    
    Shows local font on the script not internet required
#>

[CmdletBinding(SupportsShouldProcess=$True,
    ConfirmImpact='Medium',
    HelpURI='http://vcloud-lab.com',
    DefaultParameterSetName='Inbuilt')]
Param
(
    [parameter(Position=0, ParameterSetName='Inbuilt', ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true, HelpMessage='Provide valid text')]
    [parameter(Position=0, ParameterSetName='Online', ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true, HelpMessage='Provide valid text')]
    [string]$Text = '# This is test !',
    [parameter(Position=2, ParameterSetName='Inbuilt', ValueFromPipelineByPropertyName=$true, HelpMessage='Provide existing font hight')]
    [Alias('Hight')]    
    [string]$FontHight = '5',
    
    [parameter(Position=2, ParameterSetName='Online', ValueFromPipelineByPropertyName=$true, HelpMessage='Provide font name list is avaliable on http://artii.herokuapp.com/fonts_list')]
    [ValidateSet('3-d','3x5','5lineoblique','1943____','4x4_offr','64f1____','a_zooloo','advenger','aquaplan','asc_____','ascii___','assalt_m','asslt__m','atc_____','atc_gran','b_m__200','battle_s','battlesh','baz__bil','beer_pub','bubble__','bubble_b','c1______','c2______','c_ascii_','c_consen','caus_in_','char1___','char2___','char3___','char4___','charact1','charact2','charact3','charact4','charact5','charact6','characte','charset_','coil_cop','com_sen_','computer','convoy__','d_dragon','dcs_bfmo','deep_str','demo_1__','demo_2__','demo_m__','devilish','druid___','e__fist_','ebbs_1__','ebbs_2__','eca_____','etcrvs__','f15_____','faces_of','fair_mea','fairligh','fantasy_','fbr12___','fbr1____','fbr2____','fbr_stri','fbr_tilt','finalass','fireing_','flyn_sh','fp1_____','fp2_____','funky_dr','future_1','future_2','future_3','future_4','future_5','future_6','future_7','future_8','gauntlet','ghost_bo','gothic','gothic__','grand_pr','green_be','hades___','heavy_me','heroboti','high_noo','hills___','home_pak','house_of','hypa_bal','hyper___','inc_raw_','italics_','joust___','kgames_i','kik_star','krak_out','lazy_jon','letter_w','letterw3','lexible_','mad_nurs','magic_ma','master_o','mayhem_d','mcg_____','mig_ally','modern__','new_asci','nfi1____','notie_ca','npn_____','odel_lak','ok_beer_','outrun__','p_s_h_m_','p_skateb','pacos_pe','panther_','pawn_ins','phonix__','platoon2','platoon_','pod_____','r2-d2___','rad_____','rad_phan','radical_','rainbow_','rally_s2','rally_sp','rampage_','rastan__','raw_recu','rci_____','ripper!_','road_rai','rockbox_','rok_____','roman','roman___','script__','skate_ro','skateord','skateroc','sketch_s','sm______','space_op','spc_demo','star_war','stealth_','stencil1','stencil2','street_s','subteran','super_te','t__of_ap','tav1____','taxi____','tec1____','tec_7000','tecrvs__','ti_pan__','timesofl','tomahawk','top_duck','trashman','triad_st','ts1_____','tsm_____','tsn_base','twin_cob','type_set','ucf_fan_','ugalympi','unarmed_','usa_____','usa_pq__','vortron_','war_of_w','yie-ar__','yie_ar_k','z-pilot_','zig_zag_','zone7___','acrobatic','alligator','alligator2','alphabet','avatar','banner','banner3-D','banner3','banner4','barbwire','basic','5x7','5x8','6x10','6x9','brite','briteb','britebi','britei','chartr','chartri','clb6x10','clb8x10','clb8x8','cli8x8','clr4x6','clr5x10','clr5x6','clr5x8','clr6x10','clr6x6','clr6x8','clr7x10','clr7x8','clr8x10','clr8x8','cour','courb','courbi','couri','helv','helvb','helvbi','helvi','sans','sansb','sansbi','sansi','sbook','sbookb','sbookbi','sbooki','times','tty','ttyb','utopia','utopiab','utopiabi','utopiai','xbrite','xbriteb','xbritebi','xbritei','xchartr','xchartri','xcour','xcourb','xcourbi','xcouri','xhelv','xhelvb','xhelvbi','xhelvi','xsans','xsansb','xsansbi','xsansi','xsbook','xsbookb','xsbookbi','xsbooki','xtimes','xtty','xttyb','bell','big','bigchief','binary','block','broadway','bubble','bulbhead','calgphy2','caligraphy','catwalk','chunky','coinstak','colossal','contessa','contrast','cosmic','cosmike','crawford','cricket','cursive','cyberlarge','cybermedium','cybersmall','decimal','diamond','digital','doh','doom','dotmatrix','double','drpepper','dwhistled','eftichess','eftifont','eftipiti','eftirobot','eftitalic','eftiwall','eftiwater','epic','fender','fourtops','fraktur','goofy','graceful','gradient','graffiti','hex','hollywood','invita','isometric1','isometric2','isometric3','isometric4','italic','ivrit','jazmine','jerusalem','katakana','kban','l4me','larry3d','lcd','lean','letters','linux','lockergnome','madrid','marquee','maxfour','mike','mini','mirror','mnemonic','morse','moscow','mshebrew210','nancyj-fancy','nancyj-underlined','nancyj','nipples','ntgreek','nvscript','o8','octal','ogre','os2','pawp','peaks','pebbles','pepper','poison','puffy','pyramid','rectangles','relief','relief2','rev','rot13','rounded','rowancap','rozzo','runic','runyc','sblood','script','serifcap','shadow','short','slant','slide','slscript','small','smisome1','smkeyboard','smscript','smshadow','smslant','smtengwar','speed','stacey','stampatello','standard','starwars','stellar','stop','straight','tanja','tengwar','term','thick','thin','threepoint','ticks','ticksslant','tinker-toy','tombstone','trek','tsalagi','twopoint','univers','usaflag','weird','whimsy')]
    [Alias('Font')]
    [string]$FontName = 'big',

    [parameter(ParameterSetName = 'Online', Position=0, Mandatory=$false)]
    [Switch]$Online,

    [parameter(Position=1, ParameterSetName='Inbuilt', ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true, HelpMessage='Provide valid console color')]
    [parameter(ParameterSetName = 'Online', Position=1, Mandatory=$false, HelpMessage='Provide valid console color')]  
    [Alias('Color')]
    [ValidateSet('Black', 'DarkBlue','DarkGreen','DarkCyan', 'DarkRed','DarkMagenta','DarkYellow','Gray','DarkGray','Blue','Green','Cyan','Red','Magenta','Yellow','White')]
    [string]$FontColor = 'Yellow'
)
Begin {
    #$NonExistFont = $null
    if ($PsCmdlet.ParameterSetName -eq 'Inbuilt') {
        $a = {<#a 07#> Write-Host $(" " * 6) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#a#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor  -NoNewline; Write-Host " "
        <#a#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor  -NoNewline; Write-Host " "
        <#a#> Write-Host $(" " * 6) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#a#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor  -NoNewline; Write-Host " "} 
        $b = {<#b 07#> Write-Host $(" " * 4) -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 3) 
        <#b#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor   -NoNewline; Write-Host " "
        <#b#> Write-Host $(" " * 6) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#b#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor  -NoNewline; Write-Host " "
        <#b#> Write-Host $(" " * 4) -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 3) } 
        $c = {<#c 07#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#c#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 4) 
        <#c#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 4)
        <#c#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 4)
        <#c#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $d = {<#d 07#> Write-Host $(" " * 4) -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 3)
        <#d#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#d#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#d#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#d#> Write-Host $(" " * 4) -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 3)}  
        $e = {<#e 06#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#e#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 4)
        <#e#> Write-Host $(" " * 4) -BackgroundColor $FontColor -NoNewline; Write-Host "  " 
        <#e#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 4)
        <#e#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $f = {<#f 07#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#f#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 4)
        <#f#> Write-Host $(" " * 4) -BackgroundColor $FontColor -NoNewline; Write-Host "  "
        <#f#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 4)
        <#f#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 4)}
        $g = {<#g 07#> Write-Host $(" " * 6) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#g#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 5)
        <#g#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " -NoNewline; Write-Host " " -NoNewline -BackgroundColor $FontColor; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#g#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#g#> Write-Host $(" " * 6) -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $h = {<#h 07#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <#h#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <#h#> Write-Host $(" " * 6) -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <#h#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#h#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $i = {<#i 03#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <#i#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "  
        <#i#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <#i#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <#i#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $j = {<#j 07#> Write-Host "  " -NoNewline; Write-Host $(" " * 4) -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <#j#> Write-Host $(" " * 4) -NoNewline; Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host " "  
        <#j#> Write-Host $(" " * 4) -NoNewline; Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host " " 
        <#h#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#j#> Write-Host $(" " * 6) -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $k = {<#k 09#> Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 3) -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#k#> Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host " " -NoNewline; Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 3)
        <#k#> Write-Host $(" " * 3) -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 5)
        <#k#> Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host " " -NoNewline; Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 3)
        <#k#> Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 3) -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $l = {<#l 05#> Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host "  " -NoNewline; Write-Host " "
        <#l#> Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 3)
        <#l#> Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 3)
        <#l#> Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 3)
        <#l#> Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $m = {<#m 09#> Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 4) -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#m#> Write-Host $(" " * 3) -NoNewline -BackgroundColor $FontColor; Write-Host "  " -NoNewline; Write-Host $(" " * 3) -NoNewline -BackgroundColor $FontColor; Write-Host " "
        <#m#> Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host " " -NoNewline ; Write-Host "  " -NoNewline -BackgroundColor $FontColor ; Write-Host " " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#m#> Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 4) -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#m#> Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 4) -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $n = {<#n 09#> Write-Host $(" " * 3) -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 3) -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#n#> Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host " " -NoNewline; Write-Host " " -NoNewline -BackgroundColor $FontColor; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#n#> Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host "  " -NoNewline; Write-Host " " -NoNewline -BackgroundColor $FontColor ; Write-Host " " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#n#> Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 3) -NoNewline; Write-Host " " -NoNewline -BackgroundColor $FontColor; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#n#> Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 4) -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $o = {<#o 07#> Write-Host $(" " * 6) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#o#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#o#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#o#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#o#> Write-Host $(" " * 6) -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $p = {<#p 07#> Write-Host $(" " * 6) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#p#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#p#> Write-Host $(" " * 6) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#p#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 5) 
        <#p#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 5)}
        $q = {<#q 09#> Write-Host "  " -NoNewline; Write-Host $(" " * 4) -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 3)
        <#q#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 4) -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#q#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 4) -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#q#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 3)
        <#q#> Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $r = {<#r 07#> Write-Host $(" " * 6) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#r#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#r#> Write-Host $(" " * 6) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#r#> Write-Host $(" " * 4) -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 3)
        <#r#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $s = {<#s 07#> Write-Host "  " -NoNewline; Write-Host $(" " * 4) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#s#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 5)
        <#s#> Write-Host "  " -NoNewline; Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 3)
        <#s#> Write-Host $(" " * 4) -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#s#> Write-Host $(" " * 4) -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host " "}
        $t = {<#t 07#> Write-Host $(" " * 6) -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <#t#> Write-Host "  " -NoNewline; Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 3)
        <#t#> Write-Host "  " -NoNewline; Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 3)
        <#t#> Write-Host "  " -NoNewline; Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 3) 
        <#t#> Write-Host "  " -NoNewline; Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 3)}
        $u = {<#u 07#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#u#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#u#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#u#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#u#> Write-Host $(" " * 6) -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $v = {<#v 11#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 6) -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#v#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 6) -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#v#> Write-Host " " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 4) -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  "
        <#v#> Write-Host "  " -NoNewline; Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host "  " -NoNewline; Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 3)
        <#v#> Write-Host $(" " * 4) -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 5)}
        $w = {<#W 09#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host  $(" " * 4) -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#W#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host  $(" " * 4) -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#W#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " -NoNewline ; Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host " " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#W#> Write-Host $(" " * 3) -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host $(" " * 3) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#W#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host  $(" " * 4) -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $x = {<#x 09#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 4) -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#x#> Write-Host " " -NoNewline ; Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host "  " -NoNewline; Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host "  " 
        <#x#> Write-Host $(" " * 3) -NoNewline; Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 4) 
        <#x#> Write-Host " " -NoNewline ; Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host "  " -NoNewline; Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host "  " 
        <#x#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 4) -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $y = {<#y 11#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 4) -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#y#> Write-Host " " -NoNewline;  Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  "
        <#y#> Write-Host $(" " * 3) -NoNewline; Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 4) 
        <#y#> Write-Host $(" " * 3) -NoNewline; Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 4) 
        <#y#> Write-Host $(" " * 3) -NoNewline; Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 4)}
        $z = {<#z 07#> Write-Host $(" " * 6) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#z#> Write-Host $(" " * 4) -NoNewline; Write-Host "  " -NoNewline -BackgroundColor $FontColor ; Write-Host " " 
        <#z#> Write-Host "  " -NoNewline; Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 3) 
        <#z#> Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 5)
        <#z#> Write-Host $(" " * 6) -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $hyphen = {<#- 05#> Write-Host $(" " * 5)
        <#-#> Write-Host $(" " * 5)
        <#-#> Write-Host $(" " * 4) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#-#> Write-Host $(" " * 5)
        <#-#> Write-Host $(" " * 5)}
        $Hash = {<## 11#> Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host (" " * 3)
        <###> Write-Host $(" " * 10) -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <###> Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host (" " * 3)
        <###> Write-Host $(" " * 10) -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <###> Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host (" " * 3)}
        $AtRate = {<#@ 09#> Write-Host " " -NosNewline; Write-Host $(" " * 6) -BackgroundColor $FontColor -NoNewline; Write-Host "  "
        <#@#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host (" " * 4) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#@#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " -NoNewline; Write-Host " " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#@#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  " -NoNewline; Write-Host " " -BackgroundColor $FontColor -NoNewline; Write-Host " " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#@#> Write-Host " " -NoNewline; Write-Host $(" " * 4) -BackgroundColor $FontColor -NoNewline; Write-Host " " -NoNewline;  Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $Exlaim = {<#! 03#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <#!#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "  
        <#!#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <#!#> Write-Host $(" " * 3)
        <#!#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $Dot = {<#. 03#> Write-Host $(" " * 3)
        <#.#> Write-Host $(" " * 3)  
        <#.#> Write-Host $(" " * 3) 
        <#.#> Write-Host $(" " * 3)
        <#.#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $Forward = {<#. 07#> Write-Host $(" " * 4) -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#/#> Write-Host $(" " * 3) -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host "  "
        <#/#> Write-Host "  " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 3)
        <#/#> Write-Host $(" " * 1) -NoNewline ; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 4)
        <#/#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 5)}
        $Colun = {<#: 03#> Write-Host $(" " * 3)
        <#:#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <#:#> Write-Host $(" " * 3)  
        <#:#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#:#> Write-Host $(" " * 3)}
        $Space = {<#  02#> Write-Host $(" " * 2)
        <# #> Write-Host $(" " * 2)
        <# #> Write-Host $(" " * 2)
        <# #> Write-Host $(" " * 2)
        <# #> Write-Host $(" " * 2)}
        $1 = {<#1 04#> Write-Host $(" " * 3) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#1 #> Write-Host " " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#1 #> Write-Host " " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#1 #> Write-Host " " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#1 #> Write-Host " " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $2 = {<#2 06#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#2#> Write-Host $(" " * 3) -NoNewline; Write-Host "  " -NoNewline -BackgroundColor $FontColor ; Write-Host " " 
        <#z#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#z#> Write-Host "  " -NoNewline -BackgroundColor $FontColor; Write-Host $(" " * 4)
        <#z#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $3 = {<#3 06#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#3#> Write-Host $(" " * 3) -NoNewline;  Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <#3#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#3#> Write-Host $(" " * 3) -NoNewline;  Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <#3#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $4 = {<#4 06#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#4#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#4#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#4#> Write-Host $(" " * 3) -NoNewline;  Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <#4#> Write-Host $(" " * 3) -NoNewline;  Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $5 = {<#5 06#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#s#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 4)
        <#s#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#s#> Write-Host $(" " * 3) -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#s#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $6 = {<#6 06#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#6#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host $(" " * 4)
        <#6#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#6#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#6#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $7 = {<#7 06#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#7#> Write-Host $(" " * 3) -NoNewline;  Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <#7#> Write-Host $(" " * 3) -NoNewline;  Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <#7#> Write-Host $(" " * 3) -NoNewline;  Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <#7#> Write-Host $(" " * 3) -NoNewline;  Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $8 = {<#8 06#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#8#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <#8#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#8#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <#8#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $9 = {<#9 06#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#9#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <#9#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "
        <#9#> Write-Host $(" " * 3) -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <#9#> Write-Host $(" " * 5) -BackgroundColor $FontColor -NoNewline; Write-Host " "}
        $0 = {<#0 06#> Write-Host " " -NoNewline ;Write-Host $(" " * 3) -BackgroundColor $FontColor -NoNewline; Write-Host "  "
        <#0#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <#0#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <#0#> Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " -NoNewline; Write-Host "  " -BackgroundColor $FontColor -NoNewline; Write-Host " " 
        <#0#> Write-Host " " -NoNewline; Write-Host $(" " * 3) -BackgroundColor $FontColor -NoNewline; Write-Host "  "}
    }#if
}
Process {
    switch ($PsCmdlet.ParameterSetName) {
        'Inbuilt' {    
            [char[]]$AllCharacters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
            foreach ($singleChar in $AllCharacters) {
                $CharScript = Get-Variable -Name $singleChar | Select-Object -ExpandProperty Value
                $CharScript = ($CharScript -split "`r`n")
                New-Variable -Name $singleChar -Value $CharScript -Force
            }
            $hyphen = $hyphen -split "`r`n"
            $Hash = $Hash -split "`r`n"
            $AtRate = $AtRate -split "`r`n"
            $Exlaim = $Exlaim -split "`r`n"
            $Dot = $Dot -split "`r`n"
            $Forward = $Forward -split "`r`n"
            $Colun = $Colun -split "`r`n"
            $Space = $Space -split "`r`n"

            $textlength = $text.Length 
            [char[]]$TextBreakDown = $text 
  
            $wordart = @() 
            $FindWidth  = @()
            $NonExistFont = @()

            for ($ind= 0; $ind -lt $FontHight; $ind++) { 
                $Conf = 1 
                foreach ($character in $TextBreakDown) { 
                    $NoFont = $True
                    Switch -regex ($character) {
                        '-' {
                            $charname =  Get-Variable -Name hyphen
                            break
                        } #-
                        '#' {
                            $charname =  Get-Variable -Name Hash
                            break
                        } ##
                        '@' {
                            $charname =  Get-Variable -Name AtRate
                            break
                        } #-
                        '!' {
                            $charname =  Get-Variable -Name Exlaim
                            break
                        } #!
                        '\.' {
                            $charname =  Get-Variable -Name Dot
                            break
                        } #.
                        ':' {
                            $charname =  Get-Variable -Name Colun
                            break
                        } #.
                        '/' {
                            $charname =  Get-Variable -Name Forward
                            break
                        } #.
                        '\s' {
                            $charname =  Get-Variable -Name space
                            break
                        } #.
                        "[A-Za-z_0-9]" {
                            $charname = Get-Variable -Name $character
                            break
                        } 
                        default {
                            $NoFont = $false
                            break
                        } #default
                    } #switch
                
                    if ($NoFont -eq $True) {
                        if ($Conf -eq $textlength) { 
                            $info = $charname.value[$ind] 
                            $wordart += $info
                        } #if conf
                        else {
                            $info = $charname.value[$ind] 
                            $wordart += "{0} {1}" -f $info, '-NoNewLine'
                        } #else conf
                        $wordart += "`r`n"
                
                        #Get First Line to calculate width
                        if ($ind -eq 0) {
                            $FindWidth += $charname.value[$ind]
                        } #if ind
                
                        #Calculate font width
                        if ($ind -eq 0) {
                            $AllFirstLines = @()
                            $FindWidth = $FindWidth.trim() | Where-Object {$_ -ne ""}
                            $CharWidth = $FindWidth | foreach {$_.Substring(4,2)}
                            $BigFontWidth = $CharWidth | Measure-Object -Sum | Select-Object -ExpandProperty Sum
                        } #if ind

                    } #if NoFont
                    else {
                        $NonExistFont += $character
                    } #else NoFont
                    $Conf++
                } #foreach character
            } #for
            $TempFilePath = [System.IO.Path]::GetTempPath()
            $TempFileName = "{0}{1}" -f $TempFilePath, 'Show-BigFontOnConsole.ps1'
            $wordart | foreach {$_.trim()} | Out-File $TempFileName
            & $TempFileName
            if ($NonExistFont -ne $null) {
                $NonExistFont = $NonExistFont | Sort-Object | Get-Unique
                $NonResult = $NonExistFont -join " "
                Write-Host "`n`nSkipping as, No ascii fonts found for $NonResult" -BackgroundColor DarkRed
            } # if NonExistFont
        } #Inbuilt
        'Online' {
            if ($text -eq '# This is test !') {
                $text = 'http://vcloud-lab.com'
            }
            $testEncode = [uri]::EscapeDataString($Text)
            $url = "http://artii.herokuapp.com/make?text=$testEncode&font=$FontName"
            Try {
                $WebsiteApi = Invoke-WebRequest -Uri $url -ErrorAction Stop
                Write-Host $WebsiteApi.Content -ForegroundColor $FontColor
            }
            catch {
                $errMessage = "Check your internet connection, Verify below url in browser`n"
                $errMessage += $url
                Write-Host $errMessage -BackgroundColor DarkRed
            }
        } #Online
    } #switch pscmdlet
}
end {
}

Other useful blogs
POWERSHELL FUN SEND KEYS ON THE SCREEN
USE POWERSHELL ON MOBILE - SETUP AND CONFIGURE POWERSHELL WEB ACCESS (PSWA) 

VMWare Web Client: Datastore browse files upload copy failed error

September 27, 2017 09:21AM

While uploading files on vcenter esxi datastores using vSphere web client I met with below failed error. And went with the VMware KB article provided in the error box.

vmware vsphere the operation filed for an undetermined reason. certificates, datastore file copy upload errorThe operation failed for an undetermined reason. Typically this problem occurs due to certificates that the browser does not trust. If you are using self-signed or custom certificates, open the URL below in a new browser tab and accept the certificate, then retry the operation.

https://target-ip

If this does not resolve the problem, other possible solutions are shown in this KB article:
http://kb.vmware.com/kb/2147256

While troubleshooting I didn't find any web certificate issue. As per the error says I tried to open and connect esxi url in browser from my client desktop, but it was not working and site was not reachable. As per below diagram, when checked from the vCenter server it was working fine.

For further troubleshooting I tried pinging esxi server but didn't work. After some adjustment on DNS server and correcting IP of Esxi server, Everything was working fine, I was able to browse and copy upload files on vSphere web client successfully.

Same article is also applicable if you are facing issue while uploading OVF/OVA files.

Microsoft PowerShell: Check Windows license activation status

September 23, 2017 02:11PM

This is my version of fetching Microsoft windows license status, for stream lining environment and make compliant as per audit standards, This is old wine in new bottle. I have improvised it to get more information and made it dynamic to get information remotely using CIM(winrm) as well as or WMI(dcom) protocol, it will collect OS and Microsoft softwares ie: Office license activation status. Here made available optional choice to type user & password credentials, incase credentials are different for remote machine. Status is collected from SoftwareLicensingProduct class. This class exposes the product-specific properties and methods of the Software Licensing service. 

You can copy paste the script content in ps1 file to execute it or copy from Github, make sure you are executing it on at least powershell version 4. For more information check my earlier blogs for help if you are facing any issues.
Different ways to bypass Powershell execution policy :.ps1 cannot be loaded because running scripts is disabled
Installing, importing and using any module in powershell

Below are the Parameters to be used to get licensing information.
ComputerName: Multiple computernames or IPs with comma separated can be used, It can be used with protocol and credential.
TextFile: ComputerName and TextFile can not be used with each other and can be combined with optional parameters
Protocol: This is optional parameter and if didn't mentioned uses wmi (dcom) as default to connect remote server or computer. For ps remoting use wsman argument and if you have issue connecting follow article POWERSHELL PS REMOTING BETWEEN STANDALONE WORKGROUP COMPUTERS 
Credential: This is another optional parameter if you want to use different username and password to connect remote server.

In below example computer name information is gathered from text file using different username and password with PS remoting protocol.
.\Get-WindowsLicenseDetails.ps1 -TextFile C:\Temp\ComputerList.txt -Credential -Protocol Wsman

Microsoft Windows Powershell Get-Windows LicenseDetails, ps1, licenseStatus, get-ciminstance, get-wmiobject SoftwareLicensingProduct class

In this another example I am using computername parameter, and information is exported to CSV file, which can be opened using excel software.
.\Get-WindowsLicenseDetails.ps1 -ComputerName Member01,Member02 | Export-Csv info.csv

Microsoft Windows Powershell Get-Windows LicenseDetails, ps1, licenseStatus, get-ciminstance, get-wmiobject SoftwareLicensingProduct class, Export-csv, computername try

Find this code on Github.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#
#requires -version 4
<#
.SYNOPSIS
    Get windows office and OS licensing information.
.DESCRIPTION
    The Get-WindowsLicenseDetails list Windows licening activation details as well as Microsoft software such as office activation details.
.PARAMETER ComputerName
    Prompts for Computername or IP address. CN and Name can be used as an alias, If no information is provided, this will take local computer hostname as argument. 
.PARAMETER TextFile
    This syntax asks for valid text file name and it is mandatory parameter. Text file must contain computername or IP address in list.
.PARAMETER Protocol
    There are two protocols can be used while connecting to remote computer, This is optional parameter, first is DCOM which is default and need not to mention, Default will work in all scenario. Another protocol is WSman require PS remoting need to be enabled. 
.PARAMETER Credential
    This is optional parameter, Popups for active directory username password, supply domain admin user account to connect remote server.
.INPUTS
    [System.String]
.OUTPUTS
    [System.Object]
.NOTES
    Version:        1.0
    Author:         Kunal Udapi
    Creation Date:  20 September 2017
    Purpose/Change: Get windows office and OS licensing information.
    Useful URLs: http://vcloud-lab.com, https://msdn.microsoft.com/en-us/library/cc534596(v=vs.85).aspx
.EXAMPLE
    PS C:\>.\Get-WindowsLicenseDetails -ComputerName Server01,Server02,Server03 

    This list windows license details from provided computernames, and use wmi (DCom) protocol. This used currently logged in user account.
.EXAMPLE
    PS C:\>.\Get-WindowsLicenseDetails -ComputerName Server01 -Protocol Wsman -Crdential

    This list windows license details from provided computernames, and use wsman (winrm) protocol is used to connect remote computers, by providing credential parameter it will ask for username and password to connect remote computer.
.EXAMPLE
    PS C:\>.\Get-WindowsLicenseDetails -TextFile C:\Temp\list.txt

    Text file has computer name list, information is collected using wmi (DCom) protocol, this will try to connect remote computers with currently logged in user account.
.EXAMPLE
    PS C:\>.\Get-WindowsLicenseDetails -TextFile C:\Temp\list.txt -Protocol Wsman -Crdential

    Text file has computer name list, information is collected using wsman (winrm) protocol, It will pop ups for username password.

#>
[CmdletBinding(SupportsShouldProcess=$True,
    ConfirmImpact='Medium',
    HelpURI='http://vcloud-lab.com',
    DefaultParameterSetName='CN')]
Param
(
    [parameter(Position=0, Mandatory=$True, ParameterSetName='File', ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true, HelpMessage='Type valid text file pathname')]
    [ValidateScript({
        If(Test-Path $_){$true}else{throw "Invalid path given: $_"}
    })]
    [alias('File')]
    [string]$TextFile,
    
    [parameter(Position=0, Mandatory=$false, ParameterSetName='CN', ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true, HelpMessage='Type valid text file pathname')]
    [alias('CN', 'Name')]
    [String[]]$ComputerName = $env:COMPUTERNAME,

    [parameter(ParameterSetName = 'File', Position=1, Mandatory=$false, HelpMessage='Type valid text file pathname')]
    [parameter(ParameterSetName = 'CN', Position=0, Mandatory=$false)]
    [ValidateSet('Dcom','Default','Wsman')]
    [String]$Protocol = 'Dcom',

    [parameter(ParameterSetName = 'File', Position=2, Mandatory=$false)]
    [parameter(ParameterSetName = 'CN', Position=2, Mandatory=$false)]    
    [Switch]$Credential
)
Begin {
    #[String[]]$ComputerName = $env:COMPUTERNAME
    if ($Credential.IsPresent -eq $True) {
        $Cred = Get-Credential -Message 'Type domain credentials to connect remote Server' -UserName (WhoAmI)
    }
    $CimSessionOptions = New-CimSessionOption -Protocol $Protocol
    $Query = "Select * from  SoftwareLicensingProduct Where PartialProductKey LIKE '%'"
}
Process {
    switch ($PsCmdlet.ParameterSetName) {
        'CN' {
            Break
        }
        'File' {
            $ComputerName = Get-Content $TextFile
            Break
        }
    }
    foreach ($Computer in $ComputerName) {
        if (-not(Test-Connection -ComputerName $Computer -Count 2 -Quiet)) {
            Write-Host -BackgroundColor DarkYellow ([char]8734) -NoNewline
            Write-Host " $Computer is not reachable, ICMP may be disabled...."
            #Break
        }
        else {
            Write-Host -BackgroundColor DarkGreen ([char]8730) -NoNewline
            Write-Host " $Computer is reachable connecting...."
        }
        try {
            if ($Credential.IsPresent -eq $True) {
                $Cimsession = New-CimSession -Name $Computer -ComputerName $Computer -SessionOption $CimSessionOptions -Credential $Cred -ErrorAction Stop
            }
            else {
                $Cimsession = New-CimSession -Name $Computer -ComputerName $Computer -SessionOption $CimSessionOptions  -ErrorAction Stop
            }
            $LicenseInfo = Get-CimInstance -Query $Query -CimSession $Cimsession -ErrorAction Stop 
            Switch ($LicenseInfo.LicenseStatus) {
                0 {$LicenseStatus = 'Unlicensed'; Break}
                1 {$LicenseStatus = 'Licensed'; Break}
                2 {$LicenseStatus = 'OOBGrace'; Break}
                3 {$LicenseStatus = 'OOTGrace'; Break}
                4 {$LicenseStatus = 'NonGenuineGrace'; Break}
                5 {$LicenseStatus = 'Notification'; Break}
                6 {$LicenseStatus = 'ExtendedGrace'; Break}
            } 
            $LicenseInfo | Select-Object PSComputerName, Name, @{N = 'LicenseStatus'; E={$LicenseStatus}},AutomaticVMActivationLastActivationTime, Description, GenuineStatus, GracePeriodRemaining, LicenseFamily, PartialProductKey, RemainingSkuReArmCount, IsKeyManagementServiceMachine #, ApplicationID
            }
        catch {
            Write-Host -BackgroundColor DarkRed ([char]215) -NoNewline
            Write-Host " Cannot fetch information from $Computer" 
        }
    }
}

Useful Articles
Powershell Active Directory: List complete hierarchy of upstream nested groups recursively of User
POWERSHELL: USE PARAMETERS AND CONFIGURATION FROM INI FILE, USE AS SPLATTING

Powershell Active Directory: Show treeview of User or Group memberof hierarchy

September 20, 2017 09:32AM

After going through many testing and successfully streamlining most of the Users and Groups member of in active directory environment using Powershell Active Directory: List complete hierarchy of upstream nested groups recursively of User. I was still facing some of the issues, Earlier script was not smart enough to detect the loop and will keep running if same group is in members and memberof, this will keep running indefinitely. One thing to notice it does not show any report for 'Domain Users'.

Active Directory Domain controller Microsoft Windows Powershell, User or Group Properties members  and Members of.png

Another thing was my earlier script was not showing the result correctly as expected if there are multiple groups in memerof tab in upstream groups, Although it was working fine if single group is there. Also I wanted a true tree size view of the captured data. Here I have re-written this script from scratch again. To use this script check my earlier articles how to run script.
Different ways to bypass Powershell execution policy :.ps1 cannot be loaded because running scripts is disabled
POWERSHELL: INSTALLING AND CONFIGURING ACTIVE DIRECTORY
As here I am going to use this script frequently, I have added it to Powershell profiles, each time powershell is launched this script is loaded into memory automatically, If PowerShell profile file does not exists it will be created with command if (!(Resolve-Path $PROFILE -eq SilentlyContinue)) {New-Item $PROFILE},  I have copied below script in file name Get-AdGroupTreeViewmemberOf.ps1, and coping file content using cat C:\temp\Get-AdGroupTreeViewMemberOf.ps1 | Add-Content $PROFILE. I can verify the same by opening file location C:\Users\UserName\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1.

Microsoft Powershell profiles tree view, resolvepath $profile, error action, New-Item, Add-Content

Installing, importing and using any module in powershell
After launching powershell simply run function to show tree map for group use Get-AdGroupTreeViewMemberOf -GroupName 'Domain Admins' and for user Get-ADGroupTreeViewMemberOf -UserName 'Administrator'. Results are as below, Loop is shown in Red color and it is skipped.

Active Directory Powershell Get-AdGroupTreeViewmemberof username and groupname, show-treeview Groups, treesize

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#
function Get-ADGroupTreeViewMemberOf {
#requires -version 4
<#
.SYNOPSIS
    Show UpStream tree view hierarchy of memberof groups recursively of a Active Directory user and Group.
.DESCRIPTION
    The Show-ADGroupTreeViewMemberOf list all nested group list of a AD user. It requires only valid parameter AD username, 
.PARAMETER UserName
    Prompts you valid active directory User name. You can use first character as an alias, If information is not provided it provides 'Administrator' user information. 
.PARAMETER GroupName
    Prompts you valid active directory Group name. You can use first character as an alias, If information is not provided it provides 'Domain Admins' group[ information.
.INPUTS
    Microsoft.ActiveDirectory.Management.ADUser
.OUTPUTS
    Microsoft.ActiveDirectory.Management.ADGroup
.NOTES
    Version:        1.0
    Author:         Kunal Udapi
    Creation Date:  10 September 2017
    Purpose/Change: Get the exact nested group info of user
    Useful URLs: http://vcloud-lab.com
.EXAMPLE
    PS C:\>.\Get-ADGroupTreeViewMemberOf -UserName Administrator

    This list all the upstream memberof group of an user.
.EXAMPLE
    PS C:\>.\Get-ADGroupTreeViewMemberOf -GroupName DomainAdmins

    This list all the upstream memberof group of a Group.
#>

[CmdletBinding(SupportsShouldProcess=$True,
    ConfirmImpact='Medium',
    HelpURI='http://vcloud-lab.com',
    DefaultParameterSetName='User')]
Param
(
    [parameter(ParameterSetName = 'User',Position=0, ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true, HelpMessage='Type valid AD username')]
    [alias('User')]
    [String]$UserName = 'Administrator',
    [parameter(ParameterSetName = 'Group',Position=0, ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true, HelpMessage='Type valid AD Group')]
    [alias('Group')]
    [String]$GroupName = 'Domain Admins',
    [parameter(ParameterSetName = 'Group', DontShow=$True)]
    [parameter(ParameterSetName = 'User', DontShow=$True)]
    [alias('U')]
    $UpperValue = [System.Int32]::MaxValue,
    [parameter(ParameterSetName = 'Group', DontShow=$True)]
    [parameter(ParameterSetName = 'User', DontShow=$True)]
    [alias('L')]
    $LowerValue = 2
)
    begin {
        if (!(Get-Module Activedirectory)) {
            try {
                Import-Module ActiveDirectory -ErrorAction Stop 
            }
            catch {
                Write-Host -Object "ActiveDirectory Module didn't find, Please install it and try again" -BackgroundColor DarkRed
                Break
            }
        }
        switch ($PsCmdlet.ParameterSetName) {
            'Group' {
                try {
                    $Group =  Get-ADGroup $GroupName -Properties Memberof -ErrorAction Stop 
                    $MemberOf = $Group | Select-Object -ExpandProperty Memberof 
                    $rootname = $Group.Name
                }
                catch {
                    Write-Host -Object "`'$GroupName`' groupname doesn't exist in Active Directory, Please try again." -BackgroundColor DarkRed
                    $result = 'Break'
                    Break
                }
                break            
            }
            'User' {
                try {
                    $User = Get-ADUser $UserName -Properties Memberof -ErrorAction Stop
                    $MemberOf = $User | Select-Object -ExpandProperty Memberof -ErrorAction Stop
                    $rootname = $User.Name
                    
                }
                catch {
                    Write-Host -Object "`'$($User.Name)`' username doesn't exist in Active Directory, Please try again." -BackgroundColor DarkRed
                    $result = 'Break'
                    Break
                }
                Break
            }
        }
    }
    Process {
        $Minus = $LowerValue - 2
        $Spaces = " " * $Minus
        $Lines = "__"
        "{0}{1}{2}{3}" -f $Spaces, '|', $Lines, $rootname        
        $LowerValue++
        $LowerValue++
        if ($LowerValue -le $UpperValue) {
            foreach ($member in $MemberOf) {
                $UpperGroup = Get-ADGroup $member -Properties Memberof
                $LowerGroup = $UpperGroup | Get-ADGroupMember
                $LoopCheck = $UpperGroup.MemberOf | ForEach-Object {$lowerGroup.distinguishedName -contains $_}
            
                if ($LoopCheck -Contains $True) {
                    $rootname = $UpperGroup.Name
                    Write-Host "Loop found on $($UpperGroup.Name), Skipping..." -BackgroundColor DarkRed
                    Continue
                }
                #"xxx $($LowerGroup.name)"
                #$Member
                #"--- $($UpperGroup.Name) `n"
                Get-ADGroupTreeViewMemberOf -GroupName $member -LowerValue $LowerValue -UpperValue $UpperValue
            } #foreach ($member in $MemberOf) {
        }
    } #Process
}
#Get-ADGroupTreeViewMemberOf -groupname a1
#Get-ADGroupTreeViewMemberOf -UserName user2
#Get-ADGroupTreeViewMemberOf -UserName user1

Find this script on github

Powershell Active Directory: List complete hierarchy of upstream nested groups recursively of User

September 15, 2017 05:27PM

Recently I had seen big mess in one of my client's Active directory environment, AD Groups where keep nested into groups and further, Due to this clients where having hard time to get either exact effective permissions of particular users, and causing users have unnecessary authorization or getting unnecessary emails due to member of upstream groups, which he should not. Just to show demo here I have a user1, it is has memberof group1, that group1 is member of group2, again group 2 is member of group3, and so on. If I want to do troubleshooting it is very hard if someone is new to the environment to co-relate group members.

Active directory domain controller Microsoft Powershell, Get-aduser, get-adGroup, username and groups, nested membership memberof

Manual searching nested group memberof is be a big task if they are further nested into multiple level. I have written this powershell script to search the complete path how those Hierarchy, below articles shows how to us and run the script.

Different ways to bypass Powershell execution policy :.ps1 cannot be loaded because running scripts is disabled
POWERSHELL: INSTALLING AND CONFIGURING ACTIVE DIRECTORY
Installing, importing and using any module in powershell

Active Directory domain Controller powershell, user group tree view hierarchy upstream list group members

Active Directory domain Controller powershell, user group tree view hierarchy upstream list groupmembers recursive

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#requires -version 4
<#
.SYNOPSIS
    List all upstream nested memberof groups recursively of a Active Directory user.
.DESCRIPTION
    The Get-ADGroupsUpStream list all nested group list of a AD user. It requires only valid parameter AD username, 
.PARAMETER UserName
    Prompts you valid active directory User name. You can use first character as an alias, If information is not provided it provides 'Administrator' user information. 'Name' can be used as an alias
.INPUTS
    Microsoft.ActiveDirectory.Management.ADUser
.OUTPUTS
    Microsoft.ActiveDirectory.Management.ADGroup
.NOTES
    Version:        1.0
    Author:         Kunal Udapi
    Creation Date:  10 September 2017
    Purpose/Change: Get the exact nested group info of user
    Useful URLs: http://vcloud-lab.com
.EXAMPLE
    PS C:\>.\Get-ADGroupsUpStream -UserName Administrator

    This list all the upstream group an user a member of.
#>
[CmdletBinding(SupportsShouldProcess=$True,
    ConfirmImpact='Medium',
    HelpURI='http://vcloud-lab.com',
    DefaultParameterSetName='Manual')]
Param
(
    [parameter(Position=0, <#Mandatory=$True,#> ValueFromPipelineByPropertyName=$true, ValueFromPipeline=$true, HelpMessage='Type valid AD username')]
    [alias('Name')]
    [Microsoft.ActiveDirectory.Management.ADUser]$UserName = 'Administrator'
)
begin {
    if (!(Get-Module Activedirectory)) {
        try {
            Import-Module ActiveDirectory -ErrorAction Stop 
        }
        catch {
            Write-Host -Object "ActiveDirectory Module didn't find, Please install it and try again" -BackgroundColor DarkRed
            Break
        }
    }
}
process {
    #$UserName = 'User1'
    try {
        $MemberInfo = Get-ADUser $UserName Properties MemberOf -ErrorAction Stop
    }
    catch {
        Write-Host -Object "`'$username`' doesn't exist in Active Directory, try again with valid user" -BackgroundColor DarkRed
        break
    }
    $MemberOf = $MemberInfo | Select-Object -ExpandProperty MemberOf 
    foreach ($Group in $MemberOf) {
        $CompleteInfo = @()
        $GroupInfo = Get-ADGroup $Group Properties MemberOf
        $CompleteInfo += $MemberInfo.Name
        $CompleteInfo += $GroupInfo.Name
        $UpperGroup = $GroupInfo | Select-Object -ExpandProperty MemberOf
        #$GroupInfo.Name #test
        do 
        {
            foreach ($x in $UpperGroup) {
                $UpperGroupInfo = Get-AdGroup $x -Properties Memberof
                $CompleteInfo += $UpperGroupInfo.Name
                $UpperGroup =  $UpperGroupInfo | Select-Object -ExpandProperty Memberof
                #$UpperGroupInfo.Name #test
                #$UpperGroup
            }
        }
        while ($UpperGroup -ne $null)
        $CompleteInfo -Join " << "
        #[array]::Reverse($CompleteInfo)
        #$CompleteInfo -join '\'
    }
}
end {}

Must see new updated version of this script Powershell Active Directory: Show treeview of User or Group memberof hierarchy

View older posts »