Monday, April 20, 2020

Chrome: Disabling Auto Update using PowerShell

In a previous post (Chrome: Disabling Auto Update using RegEdit), it was shown how to prevent Chrome from auto updating by editing registry using RegEdit. The point of this series of posts is to automate administrative tasks. In this post it will be shown how to disable Chrome from auto updating using PowerShell to update the registry.

To recap the steps required to disable Chrome auto updating are as follows:

1) Insure the following registry key exists and if it does not exist, create it:
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google

2) Insure the following registry key exists and if it does not exist, create it:
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Update

3) Insure the AutoUpdateCheckPeriodMinutes registry value exists with a value of zero under the  previous key:
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Update

The code to perform this is as follows:

[string] $softwarePolicyPath = 'HKLM:\SOFTWARE\Policies'
[string] $googleKey = 'Google'
[string] $googleUpdateKey = 'Update'

[string] $autoUpdateCheckPeriodMinutesValueName = 
             'AutoUpdateCheckPeriodMinutes'
[int] $autoUpdateCheckPeriodMinutesValue = 0
# If you are using pre-PowerShell 6.0 use this line of code instead

# [string] $softwarePolicyGoogleUpdatePath = 
#     Join-Path `
#         -Path $softwarePolicyPath `
#         -ChildPath $googleKey
[string] $softwarePolicyGooglePath = Join-Path $softwarePolicyPath $googleKey


if (-not (Test-Path $softwarePolicyGooglePath)) {
    Write-Host "Creating: $SoftwarePolicyGooglePath"

    New-Item `
        -Path $softwarePolicyPath `
        -Name $googleKey | Out-Null
}

# If you are using pre-PowerShell 6.0 use this line of code instead
# [string] $softwarePolicyGoogleUpdatePath = 
#     Join-Path `
#         -Path $SoftwarePolicyGooglePath `
#         -ChildPath $googleUpdateKey
[string] $softwarePolicyGoogleUpdatePath = Join-Path $softwarePolicyGooglePath $googleUpdateKey

if (-not (Test-Path $softwarePolicyGoogleUpdatePath)) {
    Write-Host "Creating: $softwarePolicyGoogleUpdatePath"

    New-Item `
        -Path $softwarePolicyGooglePath `
        -Name $googleUpdateKey | Out-Null
}

# create or update
Set-ItemProperty `
    -Path $softwarePolicyGoogleUpdatePath `
    -Name $autoUpdateCheckPeriodMinutesValueName `
    -Value $autoUpdateCheckPeriodMinutesValue


The Join-Path cmdlet shown above was reviewed in the previous post, PowerShell: Join-Path Joining Multiple Children.

The following cmdlets were used to access the registry and create the appropriate entities required to disable Chrome's auto update feature:
  • Test-Path: tests is a registry key exists
  • New-Item: creates a registry key
  • Set-ItemProperty: update a registry value if the value already exists or creates a registry value of the value does not exist

Sunday, April 19, 2020

PowerShell: Join-Path Joining Multiple Children

PowerShell's Join-Path cmdlet allows file paths, registry paths, etc. to be combined. Using Join-Path does not take a PhD in quantum physics to understand but prior to PowerShell 6.0 joining multiple paths was tedious. PowerShell 6.x, 7.x and later versions support joining paths as follows (excerpt from Microsoft's documentation for Join-Path):


To understand the elegance of the documentations "Example 7" consider a registry key that needs to be created programmatically:
HKLM:\SOFTWARE\Policies\Google\Update

The following code works for PowerShell 6.0 or later and can generate the aforementioned path programmatically in the style of Example 7:

[string] $hive = 'HKLM:'
[string] $softwareKey = 'SOFTWARE'
[string] $policiesKey = 'Policies'
[string] $googleKey = 'Google'
[string] $updateKey = 'Update'


[string] $path = Join-Path `
                    $hive `
                    $softwareKey `
                    $policiesKey `
                    $googleKey `
                    $updateKey

$path

The output from the above script is as follows:


PowerShell 5.x and Earlier

The previous code will fail if run under PowerShell 5.x or earlier. These versions of PowerShell do not support the command-line option allowing the combination of an indefinite number of paths. A more verbose usage of Join-Path is required to create the equivalent path (see below):

[string] $hive = 'HKLM:'
[string] $softwareKey = 'SOFTWARE'
[string] $policiesKey = 'Policies'
[string] $googleKey = 'Google'
[string] $updateKey = 'Update'
[string] $path =
        Join-Path -Path $hive -ChildPath $softwareKey |
        Join-Path -ChildPath $policiesKey |
        Join-Path -ChildPath $googleKey |
        Join-Path -ChildPath $updateKey

$path

The previous PowerShell code make use of the -Path and -ChildPath command-line options to create the desired registry path.


Saturday, April 18, 2020

Chrome: Disabling Auto Update using RegEdit

The latest series of blog postings have been focused on automating Chrome with PowerShell and Selenium. When working with Selenium the underling libraries (DLLs) must match the version of Chrome installed. Corporate environments do not always update Chrome to the latest version. The virtual machines used to run automation tasks often restrict auto updating software applications including Chrome. As part of automating Chrome using PowerShell and Selenium it is sometimes necessary to prevent Chrome from automatically updating so that an earlier version of Chromes can be automated.

On Windows the steps to disable Chrome auto update are as follows:

In the search box on the taskbar enter RegEdit which should allow the Registry Editor app (regedit) to be invoke:


From the RegEdit application, navigate to the following key:
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Google\Update\

The path HKEY_LOCAL_MACHINE\SOFTWARE\Policies will exist but the Google and Update keys may not exist and will have to be created manually (see below):


To create the missing Google key:

Right click on the Polices folder to display the context menu and from this menu select New | Key:


When the Key menu item is invoked a new key named "New Key #1" will be created:


Rename "New Key #1" to Google:


Follow the same steps to add the Update key under the Google key. With the Update key selected:

Right click on values panel to the right and select New | DWORD (32-bit) Value:


When the DWORD (32-bit) Value menu item is invoked a new key named "New Value #1" will be created:


Rename "New Value #1" to AutoUpdateCheckPeriodMinutes and leave the value set to 0:


This disable Chrome auto updating on Windows

Wednesday, April 15, 2020

PowerShell: Chrome Automation with Selenium

Selenium is most often associated with QA and testing web sites. DevOps can also make use Selenium in order to automate health checks and a varaiety of administrative tasks. DevOps engineers have numerous logging consolidators, packages and application at their disposal: AppDynamics, SolarWinds, Splunk, etc. There are just times especially with legacy infrastructure or third party sites/applications that browser automation is helpful. A QA engineer would be concerned with Edge, Safari, Firefox, and Chrome. As a DevOps engineer, the focus of this post will be on automation using Selenium and Chrome. There is no reason to test all browser flavors when it is more practical for a DevOps team to standard on a single type of browser such as Chrome.

In a previous post, PowerShell: Install-Module and Uninstall-Module, it was shown how to install the Selenium module for PowerShell and with respect to installation using the all users scope. The Selenium module for PowerShell is an open source project hosted on Git Hub: https://github.com/adamdriscoll/selenium-powershell.

The https://github.com/adamdriscoll/selenium-powershell Git Hub home page includes a Readme.md page which contains a usage section describing how to use the PowerShell module to automate browsers with Selenium:


The URL used to demonstrate browser automation is https://www.google.com. A previous blog post showed how to inspect the element on this page in which the search term is entered, Chrome: Fundamentals of Browser Automation.

The PowerShell code to enter a search term and invoke search via the Enter key is straightforward. The term searched for will be "The Wedding Present Dalliance" which of course refers to the song "Daliance" but the band, The Wedding Present.

The browser automation code is as follows:

$driver = $null
try {
    $driver = Start-SeChrome
    Enter-SeUrl 'https://www.google.com' -Driver $driver

    # The name of the input element is q (name="q")
    # <input class="gLFyf gsfi" maxlength="2048" name="q"     

    $element = Find-SeElement -Driver $driver -Name 'q'
    Send-SeKeys -Element $element `
                -Keys "the wedding present dalliance`n"
}

catch {
    Write-Host $PSItem.Exception
}

finally {
    if ($null -ne $driver) {
        Stop-SeDriver $driver
        $driver = $null
    }
}

Chrome is launched and terminated using the Start-SeChrome and Stop-SeDriver functions which utilize PowerShells try/finally construct to insure that the Chrome is closed even if the script generates an error:

$driver = $null
try {
    $driver = Start-SeChrome
# ... additional code here ....
}
finally {
    if ($null -ne $driver) {
        Stop-SeDriver $driver
        $driver = $null
    }
}

Each browser supported by Selenium has it own start function:
  • Start-SeChrome: starts Chrome
  • Start-SeEdge: starts the version of Edge that is not implemented with Chromium
  • Start-SeNewEdge: starts the version of Edge that is implemented with Chromium
  • Start-SeFirefoxL starts Firefox
  • Start-SeInternetExplorer: starts Internet Explorer

The URL is assigned using the function, Enter-SeUrl:
    Enter-SeUrl 'https://www.google.com' -Driver $driver

The input element is selected by name using the fuction, Find-SeElement:
    # The name of the input element is q (name="q")
    # <input class="gLFyf gsfi" maxlength="2048" name="q"     
    $element = Find-SeElement -Driver $driver -Name 'q'

The text to search on and the Enter key to invoke search is invoked using function, Send-SeKeys:
    Send-SeKeys -Element $element `
                -Keys "the wedding present dalliance`n"

The result of running the script is the as anticipated search results:






Chrome: Fundamentals of Browser Automation

The page that will be automated as an example is https://www.google.com/ as it is displayed in Chrome. PowerShell and Selenium will be the technology the facilitates browser autoamtion.  Before coding the automation in PowerShell the elements on the page must be inspected so that a strategy for automation can be devised.

In Chrome,  https://www.google.com/ is displayed as follows:


Right clicking inside the search box displays a context menu and selecting the Inspect menu option allows the underlying HTML element of the search box to be inspected:


Selecting the Inspect menu item will display the Chrome Inspector with the HTML for the selected elemetnt lightlight.


Right clicking on the highlight element in Chrome Inspector allows the element to be copied:


Using Copy | Copy Element, the element associated with the search text field is:

<input class="gLFyf gsfi" maxlength="2048" name="q" type="text" jsaction="paste:puy29d" aria-autocomplete="both" aria-haspopup="false" autocapitalize="off" autocomplete="off" autocorrect="off" autofocus="" role="combobox" spellcheck="false" title="Search" value="" aria-label="Search" data-ved="0ahUKEwjVteiQn-ToAhVDEawKHcycBJoQ39UDCAY">

The Selnium API's Find-SeElement function can fine elements by name, class, name, etc. so the following are potential components by  which to automate the search text box:
  •  element type:input
  •  class: gLFyf gsfi
  • name: q
The class name has a space in it which is not supported. The page has multiple elements of type input. The unique component is the name, "q", which can be used by Find-SeElement to look up the underlying element.







Saturday, April 11, 2020

PowerShell: Install-Module and Uninstall-Module

In order to automate Chrome-based DevOps tasks, Selenium and PowerShell will be used. The site, PowerShellGallery, contains a variety of PowerShell modules that can be installed including Selenium for PowerShell, https://www.powershellgallery.com/packages/Selenium. The cmdlets used to install and uninstall PowerShell modules are Install-Module and Uninstall-Module respectively.

Clicking on the abo e link displays the following (note; the version number will change depending on the current version number where at the time of this blog entry being written is 3.0.0):


Install-Module: User Scope

The installation instructions shown on PowerShellGallary.com's Selenium page make use of Install-Module cmdlet which can be run from PowerShell:

Install-Module -Name Selenium

Another way to run the Install-Module cmdlet is from a Visual Studio Code Terminal window set to PowerShell versus BASH:


Running Install-Module defaults to user scope meaning the Selenium module for PowerShell (Selenium.psm1) will be installed at the following location:

C:\Users\<user name>\Documents\PowerShell\Modules\Selenium\3.0.0

To import this module (Selenium.psm1) into a PowerShell script, the following code could be used:

[string] $UserModules = 
             "$HOME\Documents\WindowsPowerShell\Modules"
Import-Module "$UserModules\Selenium\3.0.0\Selenium.psm1"


In the previous code, $HOME is an automatic variable in PowerShell defined on How-to: Automatic Variables as containing:


The Import-Module cmdlet imports the Selenium.psm1 module into the current session so that functions and classes exposed by the module can be used.

Install-Module: All Users

The environment where I develop automation scripts for uses multiple "Bot" accounts each corresponding to a different user on Windows. Installing a module with per-User scope (the default scope) would be problematic. To install PowerShell module (such as Selenium) for use by the all user scope, use the -Scope AllUsers parameter as follows:

Install-Module -Name Selenium -Scope AllUsers

An example of Visual Studio Code's Terminal window during the install of Selenium for all users is a follows:


When the Selenium or any module is installed at all users scope, there is no need to use the Import-Module cmdlet in order to access the installed module.

An example of using the Selenium.psm1 module is as follows and notice that the Import-Module cmdlet is not required due to Selenium being installed at under the all user scope:

$Driver = Start-SeChrome
Enter-SeUrl https://www.google.com -Driver $Driver


The previous PowerShell code launches an instance of Chrome and navigates the Chrome browser to the URL: https://www.google.com.

Uninstall-Module

Uninstalling a module is performed using the Uninstall-Module cmdlet. An example of the  Uninstall-Module cmdlet being used to uninstall the Selenium PowerShell module is follows:

Uninstall-Module -Name Selenium




Thursday, April 9, 2020

.NET Core: Determing which SDK and Runtime are Installed

1) Run Visual Studio Code:


2) From the View Menu select Terminal:



3) In the Terminal windows run the following command to see the currently installed .NET Core runtimes: dotnet --list-runtimes


4) In the Terminal windows run the following command to see the currently installed .NET Core SDKs: dotnet --list-sdks