{"id":2103,"date":"2023-06-20T21:50:57","date_gmt":"2023-06-20T13:50:57","guid":{"rendered":"http:\/\/www.jhouseconsulting.com\/?p=2103"},"modified":"2025-07-30T21:25:24","modified_gmt":"2025-07-30T13:25:24","slug":"esri-arcgis-pro-and-desktop-license-and-program-selector-user-interfaces","status":"publish","type":"post","link":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/2023\/06\/20\/esri-arcgis-pro-and-desktop-license-and-program-selector-user-interfaces-2103","title":{"rendered":"ESRI ArcGIS Pro and Desktop License Type and Program Selector User Interfaces"},"content":{"rendered":"\n<p><strong>Updated 17th July 2024<\/strong><\/p>\n\n\n\n<p>Here are two awesome User Interfaces (UI&#8217;s) I built that will compliment any ESRI ArcGIS Pro (AGP) and\/or&nbsp;ArcGIS Desktop (AGD) deployment. More specifically from my point of view, they have been developed with a Citrix Published Application, VMware Horizon, Remote Desktop, VDI and AVD deployment in mind, giving the users the ability to easily switch licensing types and launching the different programs and tools, making life much easier for them.<\/p>\n\n\n\n<p><strong>ArcGIS Pro Challenges<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Changing the licensing is not as simple as it seems, especially when launching it as a published application. This is because you have to change it from within the program once launched; and then the program needs to restart for the new licensing type to work. What that means is that the ArcGISPro.exe process will terminate and restart. Whilst that happens a published application session may log itself off, as there are no processes running to keep it open. The code in this UI will manipulate the user registry values before starting ArcGIS Pro, and therefore setting the licensing type as required. I call this Self-Service by allowing the users to switch License Levels\/Types on demand!<\/li>\n\n\n\n<li>Having a single interface allowed me to integrate other tools and processes as requested by users over time that could all be associated with ArcGIS Pro. For example, users wanted an easy way to start File Explorer in the same session. Let&#8217;s make it easy for the users to do their work! That&#8217;s my job!<\/li>\n\n\n\n<li>Update on 17th July 2024 for Python code changes I completed in back February:\n<ul class=\"wp-block-list\">\n<li>Due to some corporate licensing challenges with ArcGIS Pro, the ArcGIS Pro License Selector has been updated for the following reasons:<\/li>\n\n\n\n<li>It defaults to a Basic license, regardless of what you last used. If you need to use a Standard or Advanced license type, please select it before launching ArcGIS Pro. This behaviour can be changed back by using the\u00a0AlwaysDefaultToBasic script variable as documented below.<\/li>\n\n\n\n<li>I have added a &#8220;Reset Extensions&#8221; checkbox, that is selected by default. This will remove any Extensions you may have selected in your previous session, as the licensing for some of these Extension is also limited. You have the option here of deselecting it if you wish to continue to use previously selected Extensions in your new session.\u00a0This behaviour can be changed back by using the AlwaysResetExtensions script variable as documented below.<\/li>\n\n\n\n<li>Unfortunately, neither of these settings are managed by ESRI at an enterprise level, so I&#8217;ve enhanced this tool to assist in reducing the usage of the more advanced licensing options.<\/li>\n\n\n\n<li>I have also improved the flow of the Python code.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p><strong>ArcGIS Desktop Challenges<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>In a large enterprise deployment, setting the licensing model can be a pain. This is done via a user environment variable. So you could use Group Policy Preferences to target them based on AD Security Groups. But that adds an administrative overhead, and users must then log support tickets via the Service Desk, which creates unnecessary overhead and lost time whilst they wait for it to be actioned. That&#8217;s not agile, and doesn&#8217;t allow users to change their license type to suite their needs.\u00a0The code in this UI will manipulate the user environment variable before starting the ArcGIS Desktop program of choice, such as ArcMap or ArcCatalog, and therefore setting the licensing type as required. Again, I call this Self-Service\u00a0by allowing the users to switch License Levels\/Types on demand!<\/li>\n\n\n\n<li>There are way too many Start Menu items to publish, which is not a neat and tidy way to present it, so why not just present it via a single UI?<\/li>\n\n\n\n<li>Having a single interface allowed me to integrate all the common ArcGIS Desktop programs and other tools and processes as requested by users over time that could all be associated with ArcGIS Desktop. For example, users wanted an easy way to start File Explorer in the same session, and they wanted a way to install specific Python modules that are not part of the default Python install. Again, let&#8217;s make it easy for the users to do their work! That&#8217;s my job.<\/li>\n\n\n\n<li>ArcGIS Administrator notes:\n<ul class=\"wp-block-list\">\n<li>Since releasing this tool I&#8217;ve had a couple of people contact me and ask if this tool can overcome the Administrative requirements for running ArcGIS Administrator. The answer is simply no as this tool runs in the user context and does not elevate permissions.<\/li>\n\n\n\n<li>As documented by ESRI, to run ArcGIS Administrator users must have either local Administrator permissions, or full control of the following registry key structures:\n<ul class=\"wp-block-list\">\n<li>HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\ESRI<\/li>\n\n\n\n<li>HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Classes\\CLSID\\{E6BDAA76-4D35-11D0-98BE-00805F7CED21}<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>References:\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/support.esri.com\/en-us\/knowledge-base\/why-doesn-t-the-arcgis-desktop-administrator-allow-swit-000012731\" target=\"_blank\" rel=\"noopener\">ESRI Article ID:000012731 &#8211; Why doesn&#8217;t the ArcGIS Desktop Administrator allow switching of software types or the license manager?<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/support.esri.com\/en-us\/knowledge-base\/faq-does-the-arcgis-administrator-allow-switching-of-th-000013228\" target=\"_blank\" rel=\"noopener\">ESRI Article ID:000013228 &#8211; Does the ArcGIS Administrator allow switching of the License Manager or the software seat type?<\/a><\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>When I deploy ArcGIS Desktop, I run the following PowerShell code post-install.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: powershell; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\n$acl= get-acl -path \"HKLM:\\SOFTWARE\\Wow6432Node\\ESRI\"\n$inherit = &#x5B;system.security.accesscontrol.InheritanceFlags]\"ContainerInherit, ObjectInherit\"\n$propagation = &#x5B;system.security.accesscontrol.PropagationFlags]\"None\"\n$rule=new-object system.security.accesscontrol.registryaccessrule \"USERS\",\"FullControl\",$inherit,$propagation,\"Allow\"\n$acl.addaccessrule($rule)\n$acl|set-acl\n \n$acl= get-acl -path \"HKLM:\\SOFTWARE\\Wow6432Node\\Classes\\CLSID\\{E6BDAA76-4D35-11D0-98BE-00805F7CED21}\"\n$inherit = &#x5B;system.security.accesscontrol.InheritanceFlags]\"ContainerInherit, ObjectInherit\"\n$propagation = &#x5B;system.security.accesscontrol.PropagationFlags]\"None\"\n$rule=new-object system.security.accesscontrol.registryaccessrule \"USERS\",\"FullControl\",$inherit,$propagation,\"Allow\"\n$acl.addaccessrule($rule)\n$acl|set-acl\n<\/pre><\/div>\n\n\n<!--more-->\n\n\n\n<p><strong>About the UIs<\/strong><\/p>\n\n\n\n<p>They are both written using the Python Tkinter\u00a0library. This is the built-in de facto GUI library for Python. So nothing overly fancy, but easy to use. A very basic and poorly coded version of the ArcGIS Desktop Selector was supplied to me by an ESRI consultant. I have re-written most of it since then, adding a majority of the features you see in this release. In early 2020 the need came up to create one for ArcGIS Pro. I decided to keep them both as Python code, as I felt that the support teams that typically support GIS applications would find them easier to support themselves.<\/p>\n\n\n\n<p>These are individual scripts and UIs. However, the following screen shot shows them side-by-side for documentation purposes only. But they can certainly be deployed together on the same computer without issues.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><a href=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2023\/06\/ArcGISLicenseAndProgramSelectors-2.png\"><img fetchpriority=\"high\" decoding=\"async\" width=\"648\" height=\"608\" src=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2023\/06\/ArcGISLicenseAndProgramSelectors-2.png\" alt=\"ArcGIS License And Program Selectors\" class=\"wp-image-2968\" srcset=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2023\/06\/ArcGISLicenseAndProgramSelectors-2.png 648w, https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2023\/06\/ArcGISLicenseAndProgramSelectors-2-300x281.png 300w\" sizes=\"(max-width: 648px) 100vw, 648px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p>You&#8217;ll notice from the screen shots that both interfaces:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Tell the user which host they are running on. This is extremely helpful for support.<\/li>\n\n\n\n<li>Will automatically close themselves after 720 minutes. This is configurable by a variable called MinutesBeforeClosing as documented below. This\u00a0reduces lingering sessions running for days with pythonw.exe process running because the user hasn&#8217;t closed down the UI.<\/li>\n<\/ul>\n\n\n\n<p><strong>How we change the license types?<\/strong><\/p>\n\n\n\n<p>For ArcGIS Pro Licensing type we manipulate the following string values from under the &#8220;HKEY_CURRENT_USER\\Software\\ESRI\\ArcGISPro\\Licensing&#8221; registry key.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>ARCPRO_AUTH_TYPE<\/li>\n\n\n\n<li>SOFTWARE_CLASS<\/li>\n\n\n\n<li>SOFTWARE_CLASS_FN<\/li>\n\n\n\n<li>SingleUse_Installed<\/li>\n<\/ul>\n\n\n\n<p>I worked with ESRI Support to ensure we covered off all registry values they have used since the early days of ArcGIS Pro through to the latest version. They are either set to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Viewer for Basic licensing type<\/li>\n\n\n\n<li>Editor for Standard licensing type<\/li>\n\n\n\n<li>Professional for Advanced licensing type<\/li>\n<\/ul>\n\n\n\n<p>For ArcGIS Desktop Licensing type, we manipulate the&nbsp;&#8220;ESRI_SOFTWARE_CLASS&#8221; user environment variable. It is either set to:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Viewer for Basic licensing type (formerly ArcView)<\/li>\n\n\n\n<li>Editor for Standard licensing type\u00a0(formerly ArcEditor)<\/li>\n\n\n\n<li>Professional for Advanced licensing type\u00a0(formerly ArcInfo)<\/li>\n<\/ul>\n\n\n\n<p><strong>Deploying the ArcGIS Pro License Selector UI<\/strong><\/p>\n\n\n\n<p>It is made up of two scripts.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>ArcGIS-Pro-License-Selector.cmd<\/li>\n\n\n\n<li>ArcGIS_Pro_License_Selector.pyw<\/li>\n<\/ul>\n\n\n\n<p>Here is the full <a  data-e-Disable-Page-Transition=\"true\" class=\"download-link\" title=\"\" href=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/download\/2543\/?tmstv=1776914336\" rel=\"nofollow\" id=\"download-link-2543\" data-redirect=\"false\" >\n\tArcGIS Pro License and Program Selector\t(934 downloads\t)\n<\/a>\n&nbsp;in the in the form of a zip file.<\/p>\n\n\n\n<p>Use an installation script simply copy them to the &#8220;C:\\Program Files\\ArcGIS\\Pro&#8221; folder as per the following screen shot:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><a href=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2023\/06\/ArcGISProFolderStructure.png\"><img decoding=\"async\" width=\"611\" height=\"196\" src=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2023\/06\/ArcGISProFolderStructure.png\" alt=\"ArcGIS Pro Folder Structure\" class=\"wp-image-2497\" srcset=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2023\/06\/ArcGISProFolderStructure.png 611w, https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2023\/06\/ArcGISProFolderStructure-300x96.png 300w\" sizes=\"(max-width: 611px) 100vw, 611px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p>The ArcGIS-Pro-License-Selector.cmd batch script is simply used to launch the correct Python environment used by ArcGIS Pro. This is extremely important because if you enable the InstallPythonModules feature as documented below, the Python modules must be installed into the correct Python environment. It was also easier to use a batch script for launching as a Citrix published application.<\/p>\n\n\n\n<p>A Desktop shortcut and\/or Start Menu shortcut could also be added to launch the batch script if preferred for a Full Desktop or VDI deployment.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\n@echo off\n \nSetLocal\n \nSet ScriptLocation=%~dp0\nSet ScriptLocation=%ScriptLocation:~0,-1%\n \nCD \"%ScriptLocation%\"\nstart \"Launching...\" \"%ProgramFiles%\\ArcGIS\\Pro\\bin\\Python\\envs\\arcgispro-py3\\pythonw.exe\" \"%ScriptLocation%\\ArcGIS_Pro_License_Selector.pyw\"\n \n:Finish\nEndLocal\necho Exiting...\nExit\n<\/pre><\/div>\n\n\n<p>The&nbsp;ArcGIS_Pro_License_Selector.pyw Python script has many variables you can change to suite your needs.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>MinutesBeforeClosing : Default is 720. This is set the minutes that this window will stay open for before closing.\u00a0Set to 0 to disable the timer.<\/li>\n\n\n\n<li>AlwaysDefaultToBasic : Default is True. Set to True to default the license selection to Basic. This helps to reset the licensing after each use. Setting it to False will set it to whatever was last selected.<\/li>\n\n\n\n<li>AlwaysResetExtensions : Default is True. Set to True to enable the Reset Extensions checkbox. This will clear any Extensions that were previously selected, which helps to reset the licensing after each use.<\/li>\n\n\n\n<li>InstallPythonModules : Default is False.\u00a0Set to True to give the users the ability to install extra Python Modules from the UI. These modules are contained in the\u00a0PythonModulesToInstall variable array.<\/li>\n\n\n\n<li>PythonModulesToInstall : Defaults to &#8216;pyodbc&#8217;,&#8217;PyYAML&#8217;,&#8217;Pillow&#8217;.\u00a0This variable contains a list of extra Python modules for the user to install if the InstallPythonModules variable is set to True. You can add as many modules as needed. The UI will expand in height to allow for the list.<\/li>\n\n\n\n<li>AddFileExplorer : Default is True.\u00a0 This gives the users the ability to launch File Explorer from the UI.<\/li>\n\n\n\n<li>EnableScreenResolutionDebugging : Default is False.\u00a0Setting it to True will enable extra screen resolution (width and height) output in pixels to appear in the UI which has\u00a0assisted with the geometry of the main window.<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\n################################################################################\n# This script is an license sector listbox for ArcGIS Pro\n# \n#  Script name: ArcGIS_Pro_License_Selector.pyw\n#  Release 1.8\n#  Written by Jeremy Saunders (jeremy@jhouseconsulting.com) 17th February 2020\n#  Modified by Jeremy Saunders (jeremy@jhouseconsulting.com) 24th February 2024\n# \n################################################################################\n\n# Set these variables\n\n# Set the minutes that this window will stay open for before closing\n# Set to 0 to disable the timer\nMinutesBeforeClosing = 720\n\n# Set to True to default the license selection to Basic. This helps to reset the\n# licensing after each use. Setting it to False will set it to whatever was last\n# selected.\nAlwaysDefaultToBasic = True\n\n# Set to True to enable the Reset Extensions checkbox. This will clear any\n# Extensions that were previously selected, which helps to reset the licensing\n# after each use.\nAlwaysResetExtensions = True\n\n# Set to True to give the users the ability to install extra Python Modules\nInstallPythonModules = False\n\n# This variable contains a list of extra Python modules to install\nPythonModulesToInstall = &#x5B;'pyodbc','PyYAML','Pillow']\n\n# Set to True to give the users the ability to launch File Explorer\nAddFileExplorer = True\n\n# Set to True to enable screen resolution (width and height) output in pixels to\n# assist with the geometry of the main window.\nEnableScreenResolutionDebugging = False\n\n################################################################################\n\nimport os, sys, subprocess\nif sys.version_info&#x5B;0] == 3:\n    import winreg\n    from tkinter import *\n    from tkinter import messagebox\nelse:\n    import _winreg as winreg\n    from Tkinter import *\n    import tkMessageBox\n\n# Derive the installation location and ensure ArcGISPro.exe exists    \ntry:\n    rk = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,r&quot;SOFTWARE\\ESRI\\ArcGISPro&quot;)                        \n    tuple = winreg.QueryValueEx(rk,&quot;InstallDir&quot;)\n    Path = tuple&#x5B;0]                     \n    winreg.CloseKey(rk)\nexcept:\n    print (&quot;Registry key not accessible!&quot;)\n\ntry:\n    Path\nexcept NameError:\n    print(&quot;Could not get the ArcGIS Pro InstallDir from the registry&quot;)\n    sys.exit(0)\n\nArcGISProPath = Path + &quot;bin\\\\ArcGISPro.exe&quot;\nexists = os.path.isfile(ArcGISProPath)\nif not exists:\n    print(&quot;The folder path for ArcGIS Pro does not exist&quot;)\n    sys.exit(0)\n\n# Set registry value\ndef set_reg(path, name, value):\n    try:\n        winreg.CreateKey(winreg.HKEY_CURRENT_USER, path)\n        registry_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, path, 0, \n                                       winreg.KEY_WRITE)\n        winreg.SetValueEx(registry_key, name, 0, winreg.REG_SZ, value)\n        winreg.CloseKey(registry_key)\n        return True\n    except WindowsError:\n        return False\n\n# Get registry value\ndef get_reg(path, name):\n    try:\n        registry_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, path, 0,\n                                       winreg.KEY_READ)\n        value, regtype = winreg.QueryValueEx(registry_key, name)\n        winreg.CloseKey(registry_key)\n        return value\n    except WindowsError:\n        return None\n\n# Delete all registry values under a key\ndef delete_all_reg_values(path):\n    try:\n        registry_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, path, 0,\n                                       winreg.KEY_ALL_ACCESS)\n        while True:\n            try:\n                value_name = winreg.EnumValue(registry_key, 0)&#x5B;0]\n                winreg.DeleteValue(registry_key, value_name)\n            except OSError:\n                # When EnumValue raises an exception, it means there are no more values\n                break\n        winreg.CloseKey(registry_key)\n        return True\n    except WindowsError:\n        return False\n\npath = r&quot;Software\\ESRI\\ArcGISPro\\Licensing&quot;\n\n# Use the %USERPROFILE% as the working folder\nworkingfolder = os.getenv('USERPROFILE')\n\n# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n# To avoid the GUI from becoming unresponsive due to a &quot;thread lock&quot; issue, we can utilize the after()\n# method of the tkinter window to schedule the window to close after a specified duration without\n# blocking the main event loop. We define the close_after() function, which uses the after() method to\n# schedule the close_window() function to be called after the specified delay. This approach allows the\n# main event loop to continue running and keeps the GUI responsive. It is good practice to define these\n# outside of the mainloop to ensure it's only called once and not with each iteration of the loop.\n\ndef close_window():\n    root.destroy()\n\ndef close_after(delay):\n    root.after(delay, close_window)\n\n# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\nroot = Tk()\n# Preventing the root window to change size\nroot.resizable(0,0)\n# Allowing the root window to change size\n#root.resizable(True, True)\nroot.title(&quot;ArcGIS Pro License Selector&quot;)\nroot.iconbitmap(ArcGISProPath)\n\ncomputername = os.environ&#x5B;'COMPUTERNAME']\nl1 = Label(root, text='You are running this on ' + computername ,relief = FLAT, fg = 'gray40' , anchor = &quot;w&quot;, font = ('Arial', 8, 'bold'))\nl1.grid()\n\nl2 = Label(root, text='Choose the type of license:' ,relief = FLAT, fg = 'gray20' , anchor = &quot;w&quot;, font = ('Arial', 10, 'bold'), width = 25)\nl2.grid()\nchoices = &#x5B;&quot;Basic&quot;, &quot;Standard&quot;, &quot;Advanced&quot;]\nlist = Listbox(root, height=3, width=20, selectmode = SINGLE)\nlist.grid()\nfor item in choices:\n    list.insert(END, item)\n\nfoo = IntVar()\n\n# Create a variable to hold the checkbox state and set it to True or False by default based on the AlwaysResetExtensions variable\ncheckbox_var = BooleanVar(value=AlwaysResetExtensions)\n\n# Create a checkbox and link it to the variable\nl3 = Checkbutton(root, text=&quot;Reset Extensions&quot;, variable=checkbox_var)\nl3.grid()\n\nl4 = Label(root, text='Choose the application:' ,relief = FLAT, fg = 'gray20' , anchor = &quot;w&quot;, font = ('Arial', 10, 'bold'), width = 25)\nl4.grid()\n\nrb1 = Radiobutton(root, text = &quot;ArcGIS Pro&quot;, variable=foo, value=0, anchor = &quot;w&quot;, width = 25, padx=25)\nrb1.grid()\n\nif (InstallPythonModules and PythonModulesToInstall):\n    rb2 = Radiobutton(root, text = &quot;Install the following modules:&quot;, variable=foo, value=1, anchor = &quot;w&quot;, width = 25, padx=25)\n    rb2.grid()\n    for item in PythonModulesToInstall:\n        l4 = Label(root, text=&quot;- &quot; + item , justify=LEFT, anchor = &quot;w&quot;, padx=45)\n        l4.grid(sticky=W)\n\nif AddFileExplorer:\n    rb3 = Radiobutton(root, text = &quot;File Explorer&quot;, variable=foo, value=2, anchor = &quot;w&quot;, width = 25, padx=25)\n    rb3.grid()\n\ndef get_item_selected(slecteditem):\n    if (slecteditem == 0):\n        #print(&quot;Setting Basic (Viewer) licensing...&quot;)\n        set_reg(path, 'ARCPRO_AUTH_TYPE', &quot;Viewer&quot;)\n        set_reg(path, 'SOFTWARE_CLASS', &quot;Viewer&quot;)\n        set_reg(path, 'SOFTWARE_CLASS_FN', &quot;Viewer&quot;)\n        set_reg(path, 'SingleUse_Installed', &quot;Viewer&quot;)\n    if (slecteditem == 1):        \n        #print(&quot;Setting Standard (Editor) licensing...&quot;)\n        set_reg(path, 'ARCPRO_AUTH_TYPE', &quot;Editor&quot;)\n        set_reg(path, 'SOFTWARE_CLASS', &quot;Editor&quot;)\n        set_reg(path, 'SOFTWARE_CLASS_FN', &quot;Editor&quot;)\n        set_reg(path, 'SingleUse_Installed', &quot;Editor&quot;)\n    if (slecteditem == 2):        \n        #print(&quot;Setting Advanced (Professional) licensing...&quot;)\n        set_reg(path, 'ARCPRO_AUTH_TYPE', &quot;Professional&quot;)\n        set_reg(path, 'SOFTWARE_CLASS', &quot;Professional&quot;)\n        set_reg(path, 'SOFTWARE_CLASS_FN', &quot;Professional&quot;)\n        set_reg(path, 'SingleUse_Installed', &quot;Professional&quot;)\n\ndef view_selected():\n    flavour = str(&quot;&quot;)\n    item = int(list.curselection()&#x5B;0])\n    number = foo.get()\n    if (number == 0):\n        get_item_selected(item)\n        if checkbox_var.get():\n            delete_all_reg_values(path + r&quot;\\Extensions&quot;)\n        flavour = str(ArcGISProPath)\n    if (InstallPythonModules and PythonModulesToInstall):\n        if (number == 1):\n            for item in PythonModulesToInstall:\n                output = &quot;&quot;\n                command = &#x5B;sys.executable, '-m', 'pip', 'install', item]\n                if (sys.version_info&#x5B;0] == 2 or (sys.version_info&#x5B;0] == 3 and sys.version_info&#x5B;1] &lt; 5)):\n                    try:\n                        output = subprocess.check_output(command,universal_newlines=True)\n                    except subprocess.CalledProcessError as e:\n                        output = e.output\n                    except:\n                        output = &quot;Unexpected error&quot;\n                    #print(output)\n                if ((sys.version_info&#x5B;0] == 3 and sys.version_info&#x5B;1] &gt;= 5) or sys.version_info&#x5B;0] &gt; 3):\n                    process = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)\n                    if(len(process.stdout.strip()) &gt; 0):\n                        output = process.stdout\n                    if(len(process.stderr.strip()) &gt; 0):\n                        output = process.stderr\n                    if(len(process.stdout.strip()) == 0 and len(process.stderr.strip()) == 0):\n                        output = &quot;Unexpected error&quot;\n                    #print(output)\n    if AddFileExplorer:\n        if (number == 2):        \n            flavour = str(&quot;C:\\Windows\\explorer.exe \/n ,::{20D04FE0-3AEA-1069-A2D8-08002B30309D}&quot;)\n    if flavour.strip():\n        if os.path.exists(workingfolder):\n            # Change the current working Directory to a user specific folder before launching\n            os.chdir(workingfolder)\n            #if sys.version_info&#x5B;0] == 3:\n                # messagebox.showinfo(&quot;Working Folder&quot;, workingfolder)\n            #else:\n                # tkMessageBox.showinfo(&quot;Working Folder&quot;, workingfolder)\n        subprocess.Popen(flavour)\n\nbtn = Button(root, text = &quot;Launch Selection&quot;, command = view_selected, width = 20, font = ('Arial', 10, 'bold') )\nbtn.grid()\n\nif AlwaysDefaultToBasic:\n    list.selection_set(0,)\nelse:\n    current = (get_reg(path, 'SOFTWARE_CLASS_FN'))\n    if current:\n        if (current == &quot;Viewer&quot;):\n            list.selection_set(0,)\n        if (current == &quot;Editor&quot;):\n            list.selection_set(1,)\n        if (current == &quot;Professional&quot;):\n            list.selection_set(2,)\n        else:\n            list.selection_set(0,)\n\nif (MinutesBeforeClosing != 0):\n    MinutesBeforeClosingText = StringVar()\n    MinutesBeforeClosingText.set('after ' + str(MinutesBeforeClosing) + ' minutes.')\n    l4 = Label(root, text= 'This window will automatically close' ,relief = FLAT, fg = 'gray60' , anchor = &quot;w&quot;, font = ('Arial', 8, 'bold'))\n    l4.grid()\n    l5 = Label(root, textvariable = MinutesBeforeClosingText ,relief = FLAT, fg = 'gray60' , anchor = &quot;w&quot;, font = ('Arial', 8, 'bold'))\n    l5.grid()\n\n# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n# According to your system settings such as fonts and screen resolution, \n# you might need to adjust the root.geometry(width,height). It's typically\n# the height that becomes a problem with higher resolution (4K) screens.\n# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n# Getting screen's height in pixels\nheight = root.winfo_screenheight()\n# Getting screen's width in pixels\nwidth = root.winfo_screenwidth()\nif EnableScreenResolutionDebugging:\n    ScreenResolution = StringVar()\n    ScreenResolution.set('width x height = ' + str(width) + ' x ' + str(height) + ' (in pixels)')\n    l6 = Label(root, text='Screen Resolution:' ,relief = FLAT, fg = 'gray60' , anchor = &quot;w&quot;, font = ('Arial', 8, 'bold'))\n    l6.grid()\n    l7 = Label(root, textvariable = ScreenResolution ,relief = FLAT, fg = 'gray60' , anchor = &quot;w&quot;, font = ('Arial', 8, 'bold'))\n    l7.grid()\n\nheight = str(&quot;220&quot;)\nif AddFileExplorer:\n    height = str(int(height) + 25)\nif (InstallPythonModules and PythonModulesToInstall):\n    height = str(int(height) + ((len(PythonModulesToInstall) + 1) * 25))\nif (MinutesBeforeClosing != 0):\n    height = str(int(height) + 50)\nif EnableScreenResolutionDebugging:\n    height = str(int(height) + 50)\nroot.geometry(&quot;315x&quot; + height)\n\n# Automatically close the window after a specified time\nmytimer = int(MinutesBeforeClosing * 60 * 1000)\nif (MinutesBeforeClosing != 0):\n    close_after(mytimer)\n\nroot.mainloop()\n<\/pre><\/div>\n\n\n<p><strong>Deploying the ArcGIS Desktop License and Program Selector UI<\/strong><\/p>\n\n\n\n<p>It is made up of two scripts and an icon file:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>ArcGIS-Desktop-Selector.cmd<\/li>\n\n\n\n<li>ArcGIS_Desktop_Selector_en.pyw<\/li>\n\n\n\n<li>ArcGIS_Desktop_Product_Icon.ico<\/li>\n<\/ul>\n\n\n\n<p>Here is the full <a  data-e-Disable-Page-Transition=\"true\" class=\"download-link\" title=\"\" href=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/download\/2541\/?tmstv=1776914336\" rel=\"nofollow\" id=\"download-link-2541\" data-redirect=\"false\" >\n\tArcGIS Desktop License and Program Selector\t(1013 downloads\t)\n<\/a>\n&nbsp;in the in the form of a zip file.<\/p>\n\n\n\n<p>Use an&nbsp;installation script simply&nbsp;copy&nbsp;them to the &#8220;C:\\Program Files (x86)\\ArcGIS&#8221; folder as per the following screen shot:<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><a href=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2023\/06\/ArcGISDesktopFolderStructure.png\"><img decoding=\"async\" width=\"652\" height=\"197\" src=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2023\/06\/ArcGISDesktopFolderStructure.png\" alt=\"ArcGIS Desktop Folder Structure\" class=\"wp-image-2495\" srcset=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2023\/06\/ArcGISDesktopFolderStructure.png 652w, https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-content\/uploads\/2023\/06\/ArcGISDesktopFolderStructure-300x91.png 300w\" sizes=\"(max-width: 652px) 100vw, 652px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p>The ArcGIS-Desktop-Selector.cmd batch script is simply used to launch the correct Python environment used by ArcGIS Desktop. This is extremely important because if you enable the InstallPythonModules feature as documented below, the Python modules must be installed into the correct Python environment. It was also easier to use a batch script for launching as a Citrix published application.<\/p>\n\n\n\n<p>A Desktop shortcut and\/or Start Menu shortcut could also&nbsp;be&nbsp;added to launch the batch script if&nbsp;preferred&nbsp;for a Full Desktop or VDI deployment.<\/p>\n\n\n\n<p>A command line argument in the form of MajorVersion.MinorVersion is passed with the batch file to select the correct version of ArcGIS Desktop deployed.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>For version 10.5.x, we pass the argument\u00a010.5<\/li>\n\n\n\n<li>For version 10.7.x, we pass the argument\u00a010.7<\/li>\n\n\n\n<li>For version 10.8.x, we pass the argument\u00a010.8<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: bash; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\n@echo off\n \nSetLocal\n \n:: Set the version of ArcGIS Desktop\nSet ArcGISVersion=%1\n \nIF \/I \"%ArcGISVersion%\"==\"\" GOTO Finish\n \n:: Set the version of Python\nSet PythonVersion=27\n \nSet ScriptLocation=%~dp0\nSet ScriptLocation=%ScriptLocation:~0,-1%\n \nCD \"%ScriptLocation%\"\nstart \"Launching...\" \"%SystemDrive%\\Python%PythonVersion%\\ArcGIS%ArcGISVersion%\\pythonw.exe\" \"%ScriptLocation%\\ArcGIS_Desktop_Selector_en.pyw\" \"%ArcGISVersion%\"\n \n:Finish\nEndLocal\necho Exiting...\nExit\n<\/pre><\/div>\n\n\n<p>The ArcGIS_Desktop_Selector_en.pyw Python script has many variables you can change to suite your needs.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>VersionAsArgument : Default is True.\u00a0Pass the Version as an argument. If you set this to False, you must set a version number for the\u00a0version variable.<\/li>\n\n\n\n<li>version : Default is &#8220;10.7&#8221;. This is only used if the\u00a0VersionAsArgument variable is set to False. If you want to use it, you must set it to the\u00a0MajorVersion.MinorVersion of ArcGIS Desktop you have deployed.<\/li>\n\n\n\n<li>MinutesBeforeClosing : Default is 720. This is set the minutes that this window will stay open for before closing.\u00a0Set to 0 to disable the timer.<\/li>\n\n\n\n<li>InstallPythonModules : Default is True. This give users the ability to install extra Python Modules from the UI. These modules are contained in the\u00a0PythonModulesToInstall variable array. Setting it to False will disable this feature.<\/li>\n\n\n\n<li>PythonModulesToInstall : Defaults to \u2018pyodbc\u2019,\u2019PyYAML\u2019,\u2019Pillow\u2019.\u00a0This variable contains a list of extra Python modules for the user to install if the InstallPythonModules variable is set to True. You can add as many modules as needed. The UI will expand in height to allow for the list.<\/li>\n\n\n\n<li>AddFileExplorer : Default is True.\u00a0 This gives the users the ability to launch File Explorer from the UI.<\/li>\n\n\n\n<li>DeleteNormalmxt : Default is True.\u00a0This will\u00a0give the users the ability to delete their Normal.mxt file. It&#8217;s important to understand that this is an advanced user feature, so make sure your users understand the ramifications of deleting it. Otherwise set it to False.<\/li>\n\n\n\n<li>EnableArcMapStartupLog : Default is False.\u00a0Set to True to enable the ArcMap startup log. This will write an ArcMap.log file to the\u00a0current directory and help for debugging if needed.<\/li>\n\n\n\n<li>EnableScreenResolutionDebugging : Default is False.\u00a0Setting it to True will enable extra screen resolution (width and height) output in pixels to appear in the UI which has\u00a0assisted with the geometry of the main window.<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; auto-links: false; title: ; quick-code: false; notranslate\" title=\"\">\n################################################################################\n# This script is an license and program sector for ArcGIS Desktop\n# \n#  Script name: ArcGIS_Desktop_Selector_en.pyw\n#  Release 2.4\n#  Written by unknown 12th January 2018\n#  Modified by Jeremy Saunders (jeremy@jhouseconsulting.com) 24th February 2024\n#\n#  Enhanced to run with Python 2.7 and above and 3.6 and above.\n#\n#  Note that to run ArcGIS Administrator users must have either local Administrator permissions,\n#  or full control of the following registry key structures:\n#  - HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\ESRI\n#  - HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Classes\\CLSID\\{E6BDAA76-4D35-11D0-98BE-00805F7CED21}\n#\n# Note that on a 64-bit machine there are two Python environments installed with ArcGIS Desktop.\n# For example, for ArcGIS Desktop 10.5 the following two Python environments exist.\n# - C:\\Python27\\ArcGIS10.5\n# - C:\\Python27\\ArcGISx6410.5\n# Interestingly the Windows Shell\/Context Menu integration uses C:\\Python27\\ArcGISx6410.5.\n# However, as ArcGIS Desktop programs are 32-bit, they use C:\\Python27\\ArcGIS10.5. It can\n# be confusing. So if you are going to use this menu selector to install Python modules,\n# it must be run with the &quot;C:\\Python27\\ArcGISx6410.5\\pythonw.exe&quot; interpreter to ensure\n# that the modules are correctly installed for use with the ArcGIS Desktop programs.\n#\n################################################################################\n\n# Set these variables\n\n# Pass the Version as a argument. If you set this to False, you must set a version number\n# below\nVersionAsArgument = True\n\n# Set the Version of ArcGIS Desktop in the format of major.minor if not passing it as an\n# argument\nversion = &quot;10.8&quot;\n\n# Set the minutes that this window will stay open for before closing\n# Set to 0 to disable the timer\nMinutesBeforeClosing = 720\n\n# Set to True to give the users the ability to install extra Python Modules\nInstallPythonModules = True\n\n# This variable contains a list of extra Python modules to install\nPythonModulesToInstall = &#x5B;'pyodbc','PyYAML','Pillow']\n\n# Set to True to give the users the ability to launch File Explorer\nAddFileExplorer = True\n\n# Set to True to give the users the ability to delete the Normal.mxt file\nDeleteNormalmxt = True\n\n# Set to True to enable the ArcMap startup log. This will write an ArcMap.log file to the\n# current directory\nEnableArcMapStartupLog = False\n\n# Set to True to give the users the ability to copy existing Geodatabase Connections\nCopyGeodatabaseConnections = False\n# C:\\Users\\&lt;username&gt;\\AppData\\Roaming\\ESRI\\Desktop&lt;release#&gt;\\ArcCatalog\n# os.path.join(os.getenv(&quot;APPDATA&quot;), r&quot;ESRI\\Desktop&quot;+version+&quot;\\ArcCatalog&quot;)\n\n# Set to True to give the users the ability to copy existing Coordinate Systems and\n# projection files\nCopyCoordinateSystems = False\n# C:\\Users\\&lt;username&gt;\\AppData\\Roaming\\ESRI\\Desktop&lt;release#&gt;\\ArcMap\\Coordinate Systems\n# os.path.join(os.getenv(&quot;APPDATA&quot;), r&quot;ESRI\\Desktop&quot;+version+&quot;\\ArcMap\\Coordinate Systems&quot;)\n# Note that this includes custom projection files (.prj)\n\n# Set to True to enable screen resolution (width and height) output in pixels to\n# assist with the geometry of the main window.\nEnableScreenResolutionDebugging = False\n\n################################################################################\n\nimport os, sys, subprocess\n\nif VersionAsArgument:\n    if (len(sys.argv) == 2):\n        version = sys.argv&#x5B;1]\n    else:\n        print(&quot;Version argument missing&quot;)\n        sys.exit(0)\n\nif sys.version_info&#x5B;0] == 3:\n    import winreg\n    from tkinter import *\n    from tkinter import messagebox\nelse:\n    import _winreg as winreg\n    from Tkinter import *\n    import tkMessageBox\n\n# Derive the ArcGIS Installation directory from the registry\ntry:\n    rk = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,&quot;SOFTWARE\\\\Wow6432Node\\\\ESRI\\\\Desktop&quot; + version)\n    tuple = winreg.QueryValueEx(rk,&quot;InstallDir&quot;)\n    Path = tuple&#x5B;0]                     \n    winreg.CloseKey(rk)\nexcept:\n    print(&quot;Registry key not accessible!&quot;)\n\nArcGISDesktopPath = Path + &quot;bin\\\\&quot;\nexists = os.path.isdir(ArcGISDesktopPath)\nif not exists:\n    print(&quot;ArcGIS Desktop is not installed&quot;)\n    sys.exit(0)\n\ntry:\n    rk = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,&quot;SOFTWARE\\\\Wow6432Node\\\\ESRI\\\\ArcGIS&quot;)\n    tuple = winreg.QueryValueEx(rk,&quot;InstallDir&quot;)\n    Path = tuple&#x5B;0]                     \n    winreg.CloseKey(rk)\nexcept:\n    print(&quot;Registry key not accessible!&quot;)\n\nArcGISDesktopCommonPath = Path + &quot;bin\\\\&quot;\nexists = os.path.isdir(ArcGISDesktopCommonPath)\nif not exists:\n    print(&quot;ArcGIS Desktop is not installed&quot;)\n    sys.exit(0)\n\n# Set the name of the icon file to use. If not found it will use the default Tkinter icon.\ncurrent_directory = os.path.dirname(os.path.abspath(__file__))\niconfile = current_directory  + r&quot;\\ArcGIS_Desktop_Product_Icon.ico&quot;\nuseicon = False\nif os.path.exists(iconfile):\n    useicon = True\n\n# Derive the path to the Normal.mxt file\nnormalmxtfile = os.getenv('APPDATA') + r&quot;\\ESRI\\Desktop&quot; + version + r&quot;\\ArcMap\\Templates\\Normal.mxt&quot;\n\n# Use the %USERPROFILE% as the working folder\nworkingfolder = os.getenv('USERPROFILE')\n\n# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n# To avoid the GUI from becoming unresponsive due to a &quot;thread lock&quot; issue, we can utilize the after()\n# method of the tkinter window to schedule the window to close after a specified duration without\n# blocking the main event loop. We define the close_after() function, which uses the after() method to\n# schedule the close_window() function to be called after the specified delay. This approach allows the\n# main event loop to continue running and keeps the GUI responsive. It is good practice to define these\n# outside of the mainloop to ensure it's only called once and not with each iteration of the loop.\n\ndef close_window():\n    root.destroy()\n\ndef close_after(delay):\n    root.after(delay, close_window)\n\n# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\nroot = Tk()\n# Preventing the root window to change size\nroot.resizable(0,0)\n# Allowing the root window to change size\n#root.resizable(True, True)\nroot.title(&quot;ArcGIS Desktop &quot; + version + &quot; Selector&quot;)\nif useicon:\n    root.iconbitmap(iconfile)\n\ncomputername = os.environ&#x5B;'COMPUTERNAME']\nl1 = Label(root, text='You are running this on ' + computername ,relief = FLAT, fg = 'gray40' , anchor = &quot;w&quot;, font = ('Arial', 8, 'bold'))\nl1.grid()\n\nl2 = Label(root, text='Choose the type of license:' ,relief = FLAT, fg = 'gray20' , anchor = &quot;w&quot;, font = ('Arial', 10, 'bold'), width = 25)\nl2.grid()\nchoices = &#x5B;&quot;Basic&quot;, &quot;Standard&quot;, &quot;Advanced&quot;]\nlist = Listbox(root, height=3, width=20, selectmode = SINGLE)\nlist.grid()\nfor item in choices:\n    list.insert(END, item)\n\nfoo = IntVar()\n\nl3 = Label(root, text='Choose the application:' ,relief = FLAT, fg = 'gray20' , anchor = &quot;w&quot;, font = ('Arial', 10, 'bold'), width = 25)\nl3.grid()\n\nrb1 = Radiobutton(root, text = &quot;ArcMap&quot;, variable=foo, value=0, anchor = &quot;w&quot;, width = 25, padx=25)\nrb1.grid()\n\nrb2 = Radiobutton(root, text = &quot;ArcCatalog&quot;, variable=foo, value=1, anchor = &quot;w&quot;, width = 25, padx=25)\nrb2.grid()\n\nrb3 = Radiobutton(root, text = &quot;ArcGlobe&quot;, variable=foo, value=2, anchor = &quot;w&quot;, width = 25, padx=25)\nrb3.grid()\n\nrb4 = Radiobutton(root, text = &quot;ArcScene&quot;, variable=foo, value=3, anchor = &quot;w&quot;, width = 25, padx=25)\nrb4.grid()\n\nrb5 = Radiobutton(root, text = &quot;ArcGIS Administrator&quot;, variable=foo, value=4, anchor = &quot;w&quot;, width = 25, padx=25)\nrb5.grid()\n\nif DeleteNormalmxt:\n    rb6 = Radiobutton(root, text = &quot;Delete the Normal.mxt file&quot;, variable=foo, value=5, anchor = &quot;w&quot;, width = 25, padx=25)\n    rb6.grid()\n    if not os.path.exists(normalmxtfile):\n        rb6.configure(state = DISABLED)\n\nif (InstallPythonModules and PythonModulesToInstall):\n    rb7 = Radiobutton(root, text = &quot;Install the following modules:&quot;, variable=foo, value=6, anchor = &quot;w&quot;, width = 25, padx=25)\n    rb7.grid()\n    for item in PythonModulesToInstall:\n        l4 = Label(root, text=&quot;- &quot; + item , justify=LEFT, anchor=&quot;w&quot;, padx=45)\n        l4.grid(sticky=W)\n\nif AddFileExplorer:\n    rb8 = Radiobutton(root, text = &quot;File Explorer&quot;, variable=foo, value=7, anchor = &quot;w&quot;, width = 25, padx=25)\n    rb8.grid()\n\ndef get_item_selected(slecteditem):\n    if (slecteditem == 0):   \n        os.environ&#x5B;'ESRI_SOFTWARE_CLASS']='Viewer'\n    if (slecteditem == 1):        \n        os.environ&#x5B;'ESRI_SOFTWARE_CLASS']='Editor'\n    if (slecteditem == 2):        \n        os.environ&#x5B;'ESRI_SOFTWARE_CLASS']='Professional'\n\ndef view_selected():\n    flavour = str(&quot;&quot;)\n    item = int(list.curselection()&#x5B;0])\n    number = foo.get()\n    if (number == 0):\n        get_item_selected(item)\n        if not EnableArcMapStartupLog:\n            flavour = str(ArcGISDesktopPath + &quot;\\ArcMap.exe&quot;)\n        else:\n            flavour = str(ArcGISDesktopPath + &quot;\\ArcMap.exe&quot; + &quot; \/log&quot;)\n    if (number == 1):\n        get_item_selected(item)\n        flavour = str(ArcGISDesktopPath + &quot;\\ArcCatalog.exe&quot;)\n    if (number == 2):\n        get_item_selected(item)\n        flavour = str(ArcGISDesktopPath + &quot;\\ArcGlobe.exe&quot;)\n    if (number == 3):\n        get_item_selected(item)\n        flavour = str(ArcGISDesktopPath + &quot;\\ArcScene.exe&quot;)\n    if (number == 4):\n        get_item_selected(item)\n        flavour = str(ArcGISDesktopCommonPath + &quot;\\ArcGISAdmin.exe&quot;)\n    if DeleteNormalmxt:\n        if (number == 5):\n            if os.path.exists(normalmxtfile):\n                os.remove(normalmxtfile)\n            if not os.path.exists(normalmxtfile):\n                rb6.configure(state = DISABLED)\n    if (InstallPythonModules and PythonModulesToInstall):\n        if (number == 6):\n            for item in PythonModulesToInstall:\n                output = &quot;&quot;\n                command = &#x5B;sys.executable, '-m', 'pip', 'install', item]\n                if (sys.version_info&#x5B;0] == 2 or (sys.version_info&#x5B;0] == 3 and sys.version_info&#x5B;1] &lt; 5)):\n                    try:\n                        output = subprocess.check_output(command,universal_newlines=True)\n                    except subprocess.CalledProcessError as e:\n                        output = e.output\n                    except:\n                        output = &quot;Unexpected error&quot;\n                    #print(output)\n                if ((sys.version_info&#x5B;0] == 3 and sys.version_info&#x5B;1] &gt;= 5) or sys.version_info&#x5B;0] &gt; 3):\n                    process = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)\n                    if(len(process.stdout.strip()) &gt; 0):\n                        output = process.stdout\n                    if(len(process.stderr.strip()) &gt; 0):\n                        output = process.stderr\n                    if(len(process.stdout.strip()) == 0 and len(process.stderr.strip()) == 0):\n                        output = &quot;Unexpected error&quot;\n                    #print(output)\n    if AddFileExplorer:\n        if (number == 7):        \n            flavour = str(&quot;C:\\Windows\\explorer.exe \/n ,::{20D04FE0-3AEA-1069-A2D8-08002B30309D}&quot;)\n\n    if flavour.strip():\n        if os.path.exists(workingfolder):\n            # Change the current working Directory to a user specific folder before launching\n            os.chdir(workingfolder)\n            #if sys.version_info&#x5B;0] == 3:\n                # messagebox.showinfo(&quot;Working Folder&quot;, workingfolder)\n            #else:\n                # tkMessageBox.showinfo(&quot;Working Folder&quot;, workingfolder)\n        subprocess.Popen(flavour)\n\nbtn = Button(root, text = &quot;Launch Selection&quot;, command = view_selected, width = 20, font = ('Arial', 10, 'bold') )\nbtn.grid()\n\nlist.selection_set(0,)\n\nl5 = Label(root, text='Basic ArcGIS Desktop formerly ArcView' ,relief = FLAT, fg = 'gray60' , anchor = &quot;w&quot;, font = ('Arial', 8, 'bold'))\nl5.grid()\nl6 = Label(root, text='Standard ArcGIS Desktop formerly ArcEditor' ,relief = FLAT, fg = 'gray60' , anchor = &quot;w&quot;, font = ('Arial', 8, 'bold'))\nl6.grid()\nl7 = Label(root, text='Advanced ArcGIS Desktop formerly ArcInfo' ,relief = FLAT, fg = 'gray60' , anchor = &quot;w&quot;, font = ('Arial', 8, 'bold'))\nl7.grid()\n\nif (MinutesBeforeClosing != 0):\n    MinutesBeforeClosingText = StringVar()\n    MinutesBeforeClosingText.set('after ' + str(MinutesBeforeClosing) + ' minutes.')\n    l8 = Label(root, text= 'This window will automatically close' ,relief = FLAT, fg = 'gray60' , anchor = &quot;w&quot;, font = ('Arial', 8, 'bold'))\n    l8.grid()\n    l9 = Label(root, textvariable = MinutesBeforeClosingText ,relief = FLAT, fg = 'gray60' , anchor = &quot;w&quot;, font = ('Arial', 8, 'bold'))\n    l9.grid()\n\n# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n# According to your system settings such as fonts and screen resolution, \n# you might need to adjust the root.geometry(width,height). It's typically\n# the height that becomes a problem with higher resolution (4K) screens.\n# +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n# Getting screen's height in pixels\nheight = root.winfo_screenheight()\n# Getting screen's width in pixels\nwidth = root.winfo_screenwidth()\nif EnableScreenResolutionDebugging:\n    ScreenResolution = StringVar()\n    ScreenResolution.set('width x height = ' + str(width) + ' x ' + str(height) + ' (in pixels)')\n    l10 = Label(root, text='Screen Resolution:' ,relief = FLAT, fg = 'gray60' , anchor = &quot;w&quot;, font = ('Arial', 8, 'bold'))\n    l10.grid()\n    l11 = Label(root, textvariable = ScreenResolution ,relief = FLAT, fg = 'gray60' , anchor = &quot;w&quot;, font = ('Arial', 8, 'bold'))\n    l11.grid()\n\nheight = str(&quot;375&quot;)\nif AddFileExplorer:\n    height = str(int(height) + 25)\nif DeleteNormalmxt:\n    height = str(int(height) + 25)\nif (InstallPythonModules and PythonModulesToInstall):\n    height = str(int(height) + ((len(PythonModulesToInstall) + 1) * 25))\nif (MinutesBeforeClosing != 0):\n    height = str(int(height) + 50)\nif EnableScreenResolutionDebugging:\n    height = str(int(height) + 50)\nroot.geometry(&quot;320x&quot; + height)\n\n# Automatically close the window after a specified time\nmytimer = int(MinutesBeforeClosing * 60 * 1000)\nif (MinutesBeforeClosing != 0):\n    close_after(mytimer)\n\nroot.mainloop()\n<\/pre><\/div>\n\n\n<p>This is more of the cool stuff I build and implement to reduce operational issues and provide an improved user experience. I put a lot of personal time and research into this and feel it\u2019s important to share for the wider community to use.<\/p>\n\n\n\n<p>Enjoy!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Updated 17th July 2024 Here are two awesome User Interfaces (UI&#8217;s) I built that will compliment any ESRI ArcGIS Pro (AGP) and\/or&nbsp;ArcGIS Desktop (AGD) deployment. More specifically from my point of view, they have been developed with a Citrix Published Application, VMware Horizon, Remote Desktop, VDI and AVD deployment in mind, giving the users the &#8230; <a title=\"ESRI ArcGIS Pro and Desktop License Type and Program Selector User Interfaces\" class=\"read-more\" href=\"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/2023\/06\/20\/esri-arcgis-pro-and-desktop-license-and-program-selector-user-interfaces-2103\" aria-label=\"Read more about ESRI ArcGIS Pro and Desktop License Type and Program Selector User Interfaces\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[23,14,626,662,5,97,91,38,242],"tags":[669,621,622,665,619,620,666,674,664,667,416,586,672,663,618,678,673,624,683,625,682,267,660,623,677,675,676,668,670,299,671,587,417,433],"class_list":["post-2103","post","type-post","status-publish","format-standard","hentry","category-applications","category-citrix","category-cvad","category-python","category-scripting","category-tools","category-vdi","category-xenapp","category-xendesktop","tag-advanced","tag-agd","tag-agp","tag-arceditor","tag-arcgis-desktop","tag-arcgis-pro","tag-arcinfo","tag-arcpro_auth_type","tag-arcview","tag-basic","tag-citrix","tag-cvad","tag-editor","tag-environment-variable","tag-ersi","tag-esri","tag-esri_software_class","tag-launcher","tag-level","tag-license","tag-on-demand","tag-professional","tag-registry","tag-selector","tag-singleuse_installed","tag-software_class","tag-software_class_fn","tag-standard","tag-tkinter","tag-type","tag-viewer","tag-vmware-horizon","tag-xenapp","tag-xendesktop"],"aioseo_notices":[],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/posts\/2103","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/comments?post=2103"}],"version-history":[{"count":5,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/posts\/2103\/revisions"}],"predecessor-version":[{"id":3422,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/posts\/2103\/revisions\/3422"}],"wp:attachment":[{"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/media?parent=2103"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/categories?post=2103"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.jhouseconsulting.com\/jhouseconsulting\/wp-json\/wp\/v2\/tags?post=2103"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}