How to get VMWare Remote Console to install on Kubuntu 19.04 – Probably works on other Ubuntu Versions also

When trying to set up my new Kubuntu install I went to install the VMWare Remote Console, and to my annoyance the installer would fail without any feedback on what was going wrong. Here’s what I needed to do to fix it. To start with , some details of my machines and setup:

Date: 2019-05-24
Machine details from inxi:
/m/u/h/j/S/notes> inxi
 CPU: Dual Core Intel Core i5-6200U (-MT MCP-) speed/min/max: 1468/400/2800 MHz Kernel: 5.0.0-15-generic x86_64 Up: 1h 49m 
 Mem: 4538.0/7719.6 MiB (58.8%) Storage: 238.47 GiB (54.3% used) Procs: 271 Shell: fish 3.0.2 inxi: 3.0.33

VMWare Remote Console Version: 10.0.4
VMware-Remote-Console-10.0.4-11818843.x86_64.bundle

To start with, running the installer from the command like I was getting this error:

~/d> sudo ./VMware-Remote-Console-10.0.4-11818843.x86_64.bundle --console
Extracting VMware Installer...done.
User interface initialization failed.  Exiting.  Check the log for details.

It wasn’t even clear what log file it meant, but after doing some searching on duckduckgo I discoversed the log file for the console installer is /var/log/vmware-installer. Therefore, to get an idea of the issues, I would tail that log like this:

root@jtuckey-x1-ubu:/var/log# tail -f /var/log/vmware-installer

Tailing that log showed me that there were some issues with libraries being used. To get the installer to run through I needed to install the packages:

  • libncursesw5 – for the console interface
  • desktop-file-utils – error caused when trying to run update-desktop-database command from this package

After this I was able to get the installed to run through completely. Hope this helps someone.

How to Clean up VMware Horizon View pools without vCenter online and remove missing desktop pool from Global Entitlement using ADSI Edit

Recently I had to do a cleanup of a VMware Horizon 7 connection server, which involved removing all the existing desktop pools and recreating them. The trouble was, the old vCenter server had been removed, so when I tried to delete the pools using the Horizon Administrator Console, I got the error:

Server Error
Unable to connect to the vCenter Server

To fix this, I did the following:

Get the list of VM’s you want to remove

Using PowerCLI I was able to get a list of machines in the pool I wanted to remove. Install PowerCLI from the documentation here: https://docs.vmware.com/en/VMware-Horizon-7/7.6/horizon-integration/GUID-7C7C5239-6990-47E0-B9FB-29EC0EB0F5AC.html

Make sure to also install the VMware.Hv.Helper module from here https://github.com/vmware/PowerCLI-Example-Scripts by copying in to the C:\Program Files\WindowsPowerShell\Modules folder.

Then, after connecting to the Horizon View server, get a list of VM’s:

# Get all HV Machines
$ms = Get-HVMachine

# Show the HV Machine Names
$ms[0..2] | select -ExpandProperty Base | select Name

# Select just the machines you want
$to_remove = $ms | ?{$_.Base.Name -match '17a6-clst-p...'}

# To view a list of the machine names:
$to_remove | Select -ExpandProperty Base | Select name

# And export the list to a csv
$to_remove | Select -ExpandProperty Base | Select name | Export-Csv -NoTypeInformation ~\Downloads\to_remove.csv

Use SviConfig to delete machine records from the Horizon View Composer

This is from the documentation here: https://docs.vmware.com/en/VMware-Horizon-7/7.6/horizon-virtual-desktops/GUID-F0D595CB-4E7B-4DAE-B80B-DCDCE85E8DF2.html

Once you have copied the CSV to the composer server, you have to use the list to delete all the composer records for the machines.

# Run in an admin Powershell from path C:\Program Files (x86)\VMware\VMware View Composer
# Import the CSV
$to_delete = Import-Csv ~\Downloads\to_remove.csv

# Delete each item in the list
$to_delete | %{.\SviConfig.exe -operation=removesviclone -vmname="$($_.Name)" -AdminUser=<put admin account here> -AdminPassword="<put admin password here>"}

Remove the pool from any Global Entitlements

Important — This has to be done before removing the pool using ADSI Edit, in the next step. However, if you mess this up, as I did, I have a workaround as the last step.

To do this, just go into the global entitlements and remove the pool you are cleaning up from any of the global entitlements. If you don’t do this, you will see the global entitlement saying there are 2 pools in it, for example, but when you open the global entitlement to delete the pool you can’t see the local pool to remove.

Delete the pool using ADSI edit

To delete the actual pool and machine entries, follow the guide here: https://kb.vmware.com/s/article/2015112

The simple version is, you open ADSI edit to connect to server localhost and Distinguished Name/Naming Context dc=vdi,dc=vmware,dc=int.

You then create a query with the root of the search being OU=Servers,DC=vdi,DC=vmware,DC=int and the query string being (&(objectClass=pae-VM)(pae-displayname=17a6-clst-p*))

You can then check through the item the Applications and Server Groups OU’s to find the pool and delete it. However, make sure you have removed the pool from any global entitlements first.

Workaround – Delete Global Entitlement Local Pool member using ADSI edit

To do this, open ADSI edit on the connection server, and choose “Connect to”. Use localhost:22389 as the server, and DC=vdiglobal,DC=vmware,DC=int as the Distinguished Name/Naming Context.

Create a new query, as you did with deleting the pool using ADSI edit. This query should be in the new connection, and have the settings:

Name: Find global entitlement \
Root of search: OU=Entitlements,DC=vdiglobal,DC=vmware,DC=int \
Query String: (&(objectClass=pae-GlobalAssignment)(pae-LocalEntitlement=*17a6-clst-p*))

Note that the name of the local pool you haven’t removed from the global entitlement is in the query between the * characters.

This should give you one item, of type pae-GlobalAssignment. Open it up, and make sure the pae-LocalEntitlement attribute matches what you want to delete. If so, delete it.

You now shouldn’t have the incorrect number of local pools in your global entitlement.

Fix for Windows Server 2016 Stuck at “Downloading 0%” from WSUS server – UpdateServiceUrlAlternate Registry Key

I ran into an issue recently with our Windows Server 2016 servers not installing their updates. Instead, all our 2016 servers would get stuck with the message “Updates are available. Downloading updates 0%” however they would never actually download the updates. These servers were configured to our WSUS server, which was also a Server 2016 machine.

The first thing I investigated was to look at the logs on the client server. I tried using the Get-WindowsUpdateLog cmdlet in Powershell, however, the log that was generated was useless because every line had no date and no format information (what the hell, Microsoft!). The logs look like this:

1601/01/01 09:30:00.0000000 872   1104                  Unknown( 39): GUID=50a5ef43-b2b6-3c52-145b-a386d8769665 (No Format Information found).
1601/01/01 09:30:00.0000000 872   1104                  Unknown( 38): GUID=50a5ef43-b2b6-3c52-145b-a386d8769665 (No Format Information found).
1601/01/01 09:30:00.0000000 872   1104                  Unknown( 34): GUID=7b9bf239-47b9-3688-3a9e-14f09f262608 (No Format Information found).
1601/01/01 09:30:00.0000000 872   1104                  Unknown( 39): GUID=50a5ef43-b2b6-3c52-145b-a386d8769665 (No Format Information found).
1601/01/01 09:30:00.0000000 872   1104                  Unknown( 38): GUID=50a5ef43-b2b6-3c52-145b-a386d8769665 (No Format Information found).
1601/01/01 09:30:00.0000000 872   1104                  Unknown( 34): GUID=7b9bf239-47b9-3688-3a9e-14f09f262608 (No Format Information found).
1601/01/01 09:30:00.0000000 872   1104                  Unknown( 39): GUID=50a5ef43-b2b6-3c52-145b-a386d8769665 (No Format Information found).

However, after investigating the registry keys on one of our servers, I saw a new registry key that I didn’t recognise, UpdateServiceUrlAlternate. See this dump from Powershell:

PS C:\Users\me\Desktop> ls HKLM:\SOFTWARE\Policies\Microsoft\Windows\


    Hive: HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows


Name                           Property
----                           --------
Appx
BITS                           EnableBitsMaxBandwidth     : 0
                               MaxBandwidthValidFrom      : 9
                               MaxBandwidthValidTo        : 17
                               MaxTransferRateOnSchedule  : 1000
                               MaxTransferRateOffSchedule : 9999
CurrentVersion
DataCollection
EnhancedStorageDevices         TCGSecurityActivationDisabled : 0
IPSec
Network Connections            NC_PersonalFirewallConfig : 0
NetworkConnectivityStatusIndic (default) :
ator
NetworkProvider
safer
SettingSync                    EnableBackupForWin8Apps : 1
System
WcmSvc
WindowsUpdate                  UpdateServiceUrlAlternate                    : http://localhost:8005
                               WUServer                                     : http://wsusserver.domainname.au:8530
                               WUStatusServer                               : http://wsus.domainname.au:8530
                               ElevateNonAdmins                             : 0
                               DoNotConnectToWindowsUpdateInternetLocations : 1
                               TargetGroupEnabled                           : 1
                               TargetGroup                                  : Auto Patch2
WorkplaceJoin                  (default) :
WSDAPI

After investigating this for a while, I found that the UpdateServiceUrlAlternate is a new setting introduced in the 2017 January update for Windows 10 1607 (and Server 2016, it would seem). For more details, see the Microsoft Documentation for UpdateServiceUrlAlternate.

We discovered that we had not been setting this with our current Group Policy, because we were using ADMX templates that were released before this was added. After updating our ADMX templates and setting that value to nothing, the updates download and install correctly again.

VMware User Environment Manager (UEM) Profile for Autodesk AutoCAD 2017 in VDI

In our Horizon View VDI environment we use UEM to manage some application’s user data. I used the Application Profiler included with UEM to create this profile for AutoCAD. One issue that we we have with AutoCAD is that it will reconfigure when launched by a new user. We tried to capture a default profile but the registry entries captured include lots of references to the specific user profile path for that user, which caused issues on launch. I have attached the INI file and icons to this post.

To prevent AutoCAD from crashing on launch, make sure to capture <LocalAppData>\Autodesk, which isn’t included by default when using the Application Profiler.

Application: Autodesk AutoCAD 2017

OS: Windows 7

INI Details:

# Flex config file generated with VMware User Environment Manager Application Profiler version 9.1

[IncludeRegistryTrees]
HKCU\Software\Autodesk
HKCU\SOFTWARE\FLEXlm License Manager

[IncludeFolderTrees]
<AppData>\Autodesk
# Added to prevent crash on launch
<LocalAppData>\Autodesk

[Metadata]
ProcessIfExists=
DirectFlexEnabled
DirectFlexPath=%ProgramFiles%\Autodesk\AutoCAD 2017\acad.exe
ProcessCriteria=
ProfilerChild=c:\program files\autodesk\autocad 2017\acwebbrowser\acwebbrowser.exe
ProfilerChild=c:\program files\autodesk\autocad 2017\admigrator.exe
ProfilerChild=c:\windows\microsoft.net\framework64\v4.0.30319\csc.exe
ProfilerChild=c:\windows\microsoft.net\framework64\v4.0.30319\cvtres.exe
ProfilerChild=c:\program files\autodesk\autocad 2017\dadispatcherservice.exe


[Immidio Flex]
This file was created using VMware UEM Management Console version 9.1.0.175.
Use only with VMware UEM.

Zipped INI File and Icon: Autodesk_AutoCAD_2017

Please feel free to comment with any issues or suggestions you had using AutoCAD with UEM in your environment.

How to Opt-In and Detect to Microsoft Update for other Microsoft products using Powershell

Update 2018-03-25: Updated the script to make it more easily runnable from the command line (thanks Grant for the suggestion). I’ve also made the script available from on my Gitlab repo. To run the script from the command line, download it from the Gitlab repo, and then execute like this:

# CMD Prompt
powershell.exe -ExecutionPolicy Bypass -File C:\Configure-UpdateMSProducts.ps1 -RunType InstallService
# PowerShell Prompt
C:\Configure-UpdateMSProducts.ps1 -RunType InstallService

Update 2017-04-05: Thanks to some help from rog in the comments, I discovered there is a way to do this using group policy! 😀 To set this using group policy, go to Computer Configuration\Administrative Templates\Windows Components\Windows Update\ and configure the Configure Automatic Updates setting. In this setting there is a checkbox to set the Install updates for other Microsoft products setting. I will note, however, that this setting is not available in the local group policy editor for Windows 7, so I’m not sure if this setting would correctly apply to a Windows 7 machine. It’s definitely available on a Windows 10 1607 machine, though. Thanks for the help on this one, rog!

With Windows 10 out, we have been investigating how we can better deploy and manage Windows computers. Previously have deployed our images using an SCCM server, and then managed updates using WSUS integrated with SCCM, but Windows 10 brings a new update method, Windows Update for Business.

However, have you ever seen a checkbox with this label in your updates settings: Give me updates for other Microsoft products when I update Windows. How do you set this?

My first thought was to set this from group policy. Since this is how you set the Windows Update for Business settings, this would be the correct way to set the update method for other Microsoft products, right? So I have a look through the Windows Update, but can’t find the setting. I also do a little searching online, but all I can find is This Question on Microsoft’s forum. Here, JuliusPIV is asking the exact question I have.

So what’s the solution JuliusPIV found? This Microsoft page, Opt-In to Microsoft Update where Microsoft describes how to set enable it. Fixed, right?

There are two issues with this solution:

  1. It uses VBScript. I hate VB
  2. It doesn’t have any way to turn the setting back off again, or detect whether it is on or off

So I worked out how to do it in Powershell, and added a few extra options.

Solution:

Here’s how to turn it on

$ServiceManager = New-Object -ComObject "Microsoft.Update.ServiceManager"
$ServiceManager.ClientApplicationID = "My App"
$NewService = $ServiceManager.AddService2("7971f918-a847-4430-9279-4a52d1efe18d",7,"")

Here’s how to turn it off

$ServiceManager = New-Object -ComObject "Microsoft.Update.ServiceManager"
$ServiceManager.RemoveService("7971f918-a847-4430-9279-4a52d1efe18d")

Here’s a snippet of Powershell that will do whatever you want:

param(
    [String][ValidateSet('Detect','InstallService','RemoveService')]$RunType = "InstallService"
)

# Prepare a Windows Update service manager
$ServiceManager = New-Object -ComObject "Microsoft.Update.ServiceManager"

$ServiceID = "7971f918-a847-4430-9279-4a52d1efe18d"

# 
switch ($RunType)
{
    "Detect"
    {
        $found = $false
        foreach($service in $ServiceManager.Services)
        {
            if($service.ServiceID -eq $ServiceID)
            {
                $found = $true
            }
        }

        if($found)
        {
            "Found Service"
        }
    }
    "InstallService"
    {
        $ServiceManager.ClientApplicationID = "My App"
        try
        {
            $NewService = $ServiceManager.AddService2($ServiceID,7,"")
        }
        catch
        {
            Write-Warning "Failed to register service"
            Write-Warning $_.Exception.Message
            Exit 1
        }
        if($NewService.IsPendingRegistrationWithAU)
        {
            Write-Verbose "Needs to reboot"
            Exit 3010
        }
        else
        {
            Exit 0
        }
    }
    "RemoveService"
    {
        try
        {
            $ServiceManager.RemoveService($ServiceID)
        }
        catch
        {
            if($_.Exception.ErrorCode -eq -2145091564)
            {
                Write-Verbose "The service doesn't exist, so exit successfully"
                Exit 0
            }
            else
            {
                Write-Warning "Failed to remove service"
                Write-Warning $_.Exception.Message
                Exit 1
            }
        }
    }
    default
    {
        Write-Warning "No RunType set. Exiting"
        Exit 1
    }
}