tag:blogger.com,1999:blog-76556345775631391292024-03-15T18:11:25.476-07:00Jan David Narkiewicz (Developer)Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.comBlogger258125tag:blogger.com,1999:blog-7655634577563139129.post-33152439454634746732024-02-07T03:33:00.000-08:002024-02-07T03:33:41.964-08:00Azure: Virtual Machines that support WSL<h1>Azure Nested Virtualization Capable VMs</h1><p>In order to run WSL and potentially Docker on an Azure Virtual Machine (VM) a VM's SKU Family must be hyper-threaded and be capable of running nested virtualization. The following link from Microsoft Learning, <a href="https://learn.microsoft.com/en-us/azure/virtual-machines/acu">Azure compute unit (ACU)</a>, demarcates in a table all nested virtualization capable VMs by three asterisks: </p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTbWVfNpbLOIpDUVCvudX-NH99b6KartCnzbb-WV_gRYbV4-GqtZ6TAy61m7XpV-0-8141aZcassxg2B0gw7nkjCTvtHClIUfgJqAtczYvSTJR9_JSa-MNyml1rPMuOXtZamIe48xuLu3xEq64zQrqSn5VtiiCVkUJDqPkWoKAtGDehn4iawU9BrqtgQ/s1210/acu02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="92" data-original-width="1210" height="48" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTbWVfNpbLOIpDUVCvudX-NH99b6KartCnzbb-WV_gRYbV4-GqtZ6TAy61m7XpV-0-8141aZcassxg2B0gw7nkjCTvtHClIUfgJqAtczYvSTJR9_JSa-MNyml1rPMuOXtZamIe48xuLu3xEq64zQrqSn5VtiiCVkUJDqPkWoKAtGDehn4iawU9BrqtgQ/w640-h48/acu02.png" width="640" /></a></div><p><span style="-webkit-text-stroke-width: 0px; color: black; display: inline !important; float: none; font-family: "Times New Roman"; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-decoration-thickness: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;"></span></p><h1 style="-webkit-text-stroke-width: 0px; color: black; font-family: "Times New Roman"; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; letter-spacing: normal; orphans: 2; text-align: left; text-decoration-color: initial; text-decoration-style: initial; text-decoration-thickness: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">Azure WSL Capable VM Types</h1><p>The Azure VM that are capable of supported WSL (a.k.a. capable of running nested virtualization) are as follow from Microsoft's article, <a href="https://learn.microsoft.com/en-us/azure/virtual-machines/acu">Azure compute unit (ACU)</a>, provided that the vCPU: Core column contains three asterisks:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgy1oSpMTxXitZO9YoQKSX9oIJyWLaTHlQcabGihE6mqJK2D-wW_kVwALGC50jSi07GErqHllxuircou8I_8YwLgbp72rOsjKhd36bOi1Z6D3e4Z6sDUe8hAetUPp2UR2-qQYNO5PMmmKqlTkaMXKIgsZMZUniMrJJxf6rFLYbMTErY7HSA3neG4upd5A/s1512/azure_vm_header.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="102" data-original-width="1512" height="44" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgy1oSpMTxXitZO9YoQKSX9oIJyWLaTHlQcabGihE6mqJK2D-wW_kVwALGC50jSi07GErqHllxuircou8I_8YwLgbp72rOsjKhd36bOi1Z6D3e4Z6sDUe8hAetUPp2UR2-qQYNO5PMmmKqlTkaMXKIgsZMZUniMrJJxf6rFLYbMTErY7HSA3neG4upd5A/w640-h44/azure_vm_header.png" width="640" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9oyTTupiWT6V95X7qjOzFMOI53I3qA3S7-NL-jg4_1lIERs-6KEXDqGpqZTuTejhXICc6CHXhhXt_odA_Q2LeFC6hP3jYbh7poDJcZrffkC0IJ3HJScGgj_gKuxB8Mvzym5ZKs44AN0pdaHkMT0FJ0fPJz3kYvwkXcsPsAq3yUR8SLvOP1IGFuf_0uQ/s1600/acu00.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1600" data-original-width="1490" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9oyTTupiWT6V95X7qjOzFMOI53I3qA3S7-NL-jg4_1lIERs-6KEXDqGpqZTuTejhXICc6CHXhhXt_odA_Q2LeFC6hP3jYbh7poDJcZrffkC0IJ3HJScGgj_gKuxB8Mvzym5ZKs44AN0pdaHkMT0FJ0fPJz3kYvwkXcsPsAq3yUR8SLvOP1IGFuf_0uQ/w596-h640/acu00.png" width="596" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: left;">The following include several other VM types on which WSL can be installed:</div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzJESIn7yuJRZC4qmmgCA2YkT9Qea8SmeKvtg-HSB9GX4GzjLZwKopoJaB2N2QrL8GafXxmVgepiFm22X87o4ZNErJ2ybp7PvU6r36Q-S_RkJ91zcq9Ms-_tOCERr6cTnchr0Ukjo1zzppZ6osT3uw766nzvMd86M_SwvXzEeL8gTYcqv5kCmj96gY8A/s1435/acu01.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="945" data-original-width="1435" height="422" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzJESIn7yuJRZC4qmmgCA2YkT9Qea8SmeKvtg-HSB9GX4GzjLZwKopoJaB2N2QrL8GafXxmVgepiFm22X87o4ZNErJ2ybp7PvU6r36Q-S_RkJ91zcq9Ms-_tOCERr6cTnchr0Ukjo1zzppZ6osT3uw766nzvMd86M_SwvXzEeL8gTYcqv5kCmj96gY8A/w640-h422/acu01.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><br /></div><h1 style="text-align: left;">Azure Subscription may not include WSL Capable VM Types</h1>Be aware the not ever Microsoft subscription supports such Virtual Machines. For example the subscription that comes in a Visual Studio Subscription (the $150 free monthly Azure credit) might contain no virtual machines types that are nested virtualization capable.<br /><p><br /></p>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com0tag:blogger.com,1999:blog-7655634577563139129.post-87798166624523829222024-02-03T03:49:00.000-08:002024-02-03T03:49:23.854-08:00Docker: Fails on Windows Immediately After Install<p>Recently I installed Docker on a Windows 11 Pro laptop. Immediately after install I attempted to run a Docker image containing PowerShell. This image was run by invoking the following command from a PowerShell console:</p><div style="text-align: left;"><div><span style="font-family: courier;">docker run -it mcr.microsoft.com/powershell</span></div><div><br /></div><div>The error returned by this command was:</div><div><br /></div><div><div><span style="font-family: courier;">docker: error during connect: this error may indicate that the docker daemon is not running: Post "http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.24/containers/create": open //./pipe/docker_engine: The system cannot find the file specified.</span></div><div><span style="font-family: courier;">See 'docker run --help'.</span></div></div><div><br /></div><div>The error above is clear "this error may indicate that the docker daemon is not running" which means I had forgotten to run Docker Desktop. Windows 11 Pro and Windows 10 Pro require Docket Desktop in order to run the Docker Engine.</div><div><br /></div><div>I started Docker Desktop, reran the docker run command, and received a subsequent error:</div><div><br /></div><div><div><span style="font-family: courier;">docker: request returned Internal Server Error for API route and version http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.24/containers/create, check if the server supports the requested API version.</span></div><div><span style="font-family: courier;">See 'docker run --help'.</span></div></div><div><br /></div></div><p>As engineers we all have our Home Simpson, "Duh" moments. When I actually looked at Docker Desktop, I saw the following:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIcO9AmWaB1W5RJUhyphenhyphen3TafxhpQ5BazZGgEjHu7OxWJBAeglYVE_3KyaBpM13AmKFth395yP7damhU-v0pZCHxEwO1IPfLvrZGJr1ccGMbLMMzIzah2xGZfrkrMGojUQCofRbOx9nGn6rgK9Uuqi494tZeAoZK40ohki0NvpQwJikjy-XDB-lBndAPzCg/s2185/docker_desktop_windows_accept_terms.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1500" data-original-width="2185" height="440" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIcO9AmWaB1W5RJUhyphenhyphen3TafxhpQ5BazZGgEjHu7OxWJBAeglYVE_3KyaBpM13AmKFth395yP7damhU-v0pZCHxEwO1IPfLvrZGJr1ccGMbLMMzIzah2xGZfrkrMGojUQCofRbOx9nGn6rgK9Uuqi494tZeAoZK40ohki0NvpQwJikjy-XDB-lBndAPzCg/w640-h440/docker_desktop_windows_accept_terms.png" width="640" /></a></div><br /><p>I had failed to Accept the terms of service screen so the Docker Engine was not started. The lesson learned: After installing Docker Desktop on on Windows 10 Pro or Windows 11 Pro, run Docker Desktop and click on the Accept button.</p><p>I am very explicit about using Windows 11 Pro or previously Windows 10 Pro. The reason for this is that Windows 10 and Windows 11 can run Linux containers only with Docker installed. In order to run Windows containers, Windows 10 Pro or Windows 11 Pro is required.</p><p>In a previous blog, I noted a change I'd made (indirectly) to Docker's installation instructions for Docker Desktop on Windows, <a href="https://docs.docker.com/desktop/install/windows-install/">Install Docker Desktop on Windows</a>. I created a PR in the documentation noting the importance of Windows Pro and the Docker documentation team added the following warning to their installation guide</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQK6ql3dPhEN0s59VnoOAor0UBslC4CIT0_1DkVDRdTZDCCYkWgDqD1Vwke6l4K6lUXWaZoI0z9W05zQc4GxvowU0d8e4dZtKBEZIZnAFYCXGeWQwr9Ds26sbKeWqH9ca1sckXDrxlQU7G6jdGOO0ZIYbAfc6pGeCidM2eBz7kqqLhNaoSIQgOcy4Aqw/s1980/windows_11_pro_required_to_run_docker_windows_containers.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="365" data-original-width="1980" height="118" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQK6ql3dPhEN0s59VnoOAor0UBslC4CIT0_1DkVDRdTZDCCYkWgDqD1Vwke6l4K6lUXWaZoI0z9W05zQc4GxvowU0d8e4dZtKBEZIZnAFYCXGeWQwr9Ds26sbKeWqH9ca1sckXDrxlQU7G6jdGOO0ZIYbAfc6pGeCidM2eBz7kqqLhNaoSIQgOcy4Aqw/w640-h118/windows_11_pro_required_to_run_docker_windows_containers.png" width="640" /></a></div>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com0tag:blogger.com,1999:blog-7655634577563139129.post-68289235493377391652024-01-26T12:07:00.000-08:002024-01-26T12:07:05.833-08:00Azure: Open Source Contributions to Azurite emulator for local Azure Storage<p>Microsoft has begun using AI to write its documentation. One such AI written article is <a href="https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azurite?tabs=visual-studio%2Cblob-storage">Use the Azurite emulator for local Azure Storage development</a> which contains text like the following:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsRT_a45QiI7j71n98dfo_LkdnRZP7x5SkZJCK1ovTvD2ih-Z8cCkfBurnCvCh1C4TQi2ovoY5S1x_e3XPGjqiQZAfO1R_nGt_Cl7j4JVoFC91PGFVd31effYlWwN4W-xmQ1VCPjC5S9JwLMBzMwOJ0pHX_X7lpXnXSFZZTndx9NloWKALMtwI07_pEg/s1735/install_azure_azurite.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="370" data-original-width="1735" height="136" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgsRT_a45QiI7j71n98dfo_LkdnRZP7x5SkZJCK1ovTvD2ih-Z8cCkfBurnCvCh1C4TQi2ovoY5S1x_e3XPGjqiQZAfO1R_nGt_Cl7j4JVoFC91PGFVd31effYlWwN4W-xmQ1VCPjC5S9JwLMBzMwOJ0pHX_X7lpXnXSFZZTndx9NloWKALMtwI07_pEg/w640-h136/install_azure_azurite.png" width="640" /></a></div><p>The use of the word either in text means there should be two options when the AI written text provided three options (npm, Docker Hub or GitHub).</p><p>When contributing to a documentation that requires significant rewrite I often make a small change to see if there are active reviewers who can quickly approve the changes. The paragraph above from the Azurite documentation contains my first trial change specifically the text "Node Package Manager (npm)" which as of yesterday (January 25, 2024) was simply "Node Package Manager":</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiT7X2L_v834S3FF4KCr6Y-4r1I4BxTO9xWgSMhKMU7GgGWHyhUxhtD92-UKDWz9UIgANnPDI0RiE0lC5PlZGv1Nte1RBnG2hYQSBchVLh7otCWtu0CORfjRau2TJqQa4ypHLJ6HG-_aXJ0ZIxwfhz5C2VveYeckbXKiux86UyBavAzQtt7nMHCPc7zuw/s1725/azurite_visual_studio_pre_npm.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="257" data-original-width="1725" height="96" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiT7X2L_v834S3FF4KCr6Y-4r1I4BxTO9xWgSMhKMU7GgGWHyhUxhtD92-UKDWz9UIgANnPDI0RiE0lC5PlZGv1Nte1RBnG2hYQSBchVLh7otCWtu0CORfjRau2TJqQa4ypHLJ6HG-_aXJ0ZIxwfhz5C2VveYeckbXKiux86UyBavAzQtt7nMHCPc7zuw/w640-h96/azurite_visual_studio_pre_npm.png" width="640" /></a></div><div><br /></div>This page has a very active team approving PRs because my first trivial change was committed in under a day. Here is the email notifying me that the PR for the above change was merged causing the change to appear immediately on the Azurite documentation web page:<div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNSEN6iJIuiyeho4JbCpbBHJXz_mIgUPSttKkbX5QgQmF6zBc4THB5NubnIrlRX3uiv-Q7NKhlpP1T_DFwk9pFOq_fa1uIrXYQNP2ZjvXxyGQxYiZSQanI63pZP_D8joSeOmbRrauqkhwa__xw8U2D0zkLgvPhRgFhZeBw0oMmDfEmyVsxZtRxx72f4g/s1355/Azurite_pr_merge.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="447" data-original-width="1355" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjNSEN6iJIuiyeho4JbCpbBHJXz_mIgUPSttKkbX5QgQmF6zBc4THB5NubnIrlRX3uiv-Q7NKhlpP1T_DFwk9pFOq_fa1uIrXYQNP2ZjvXxyGQxYiZSQanI63pZP_D8joSeOmbRrauqkhwa__xw8U2D0zkLgvPhRgFhZeBw0oMmDfEmyVsxZtRxx72f4g/w640-h212/Azurite_pr_merge.png" width="640" /></a></div><br /><div><br /><div><br /></div><div><br /><p><br /></p><p><br /></p><p><br /></p></div></div></div>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com0tag:blogger.com,1999:blog-7655634577563139129.post-56070258171516773122024-01-17T01:09:00.000-08:002024-01-17T06:42:02.218-08:00Azure: Naming Resources<p>Before creating an resource in Azure, a naming standard should be followed such as this one proposed by Microsoft, <a href="https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-naming">Define your naming convention</a>. An excerpt from the aforementioned article is as follows which demonstrates one of the most commonly adopted naming standards with respect to Azure resources: </p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiK4xhsB1dlNrKvAfEVuoOUkVVdl_GLJ535XFNGcVo9RENxvfTcxQPxJUEBz053dTmXDl2vQChmz59PnjPB7V_XZda0gUGQUql5qg-AwAsILgCwuyfKfJXFRPI1G9f3uB-aAoQXB68QPRnPmqicEozbWT9QpGhk18EARSLLs8Uw6dReZww1sNMbhEkRRQ/s1385/Azure_resource_naming_convention.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="587" data-original-width="1385" height="272" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiK4xhsB1dlNrKvAfEVuoOUkVVdl_GLJ535XFNGcVo9RENxvfTcxQPxJUEBz053dTmXDl2vQChmz59PnjPB7V_XZda0gUGQUql5qg-AwAsILgCwuyfKfJXFRPI1G9f3uB-aAoQXB68QPRnPmqicEozbWT9QpGhk18EARSLLs8Uw6dReZww1sNMbhEkRRQ/w640-h272/Azure_resource_naming_convention.png" width="640" /></a></div><p>The above naming strategy uses a prefix before each resource name that serves to identify the type of resource. Microsoft provides a comprehensive list of standard resource prefixes in in this document <a href="https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-abbreviations">Abbreviation examples for Azure resources</a>. The prefixes for some of the most communly used Azure resource types is as follows:</p><ul style="text-align: left;"><li>appi: Application Insights</li><li>asp: App Service Plan</li><li>cosmos: Azure Cosmos DB database (this is the name Azure uses which includes DB and database)</li><li>kv: Key Vault</li><li>logic: Logic App</li><li>sbq: Service Bus Queue</li><li>st: Storage Account</li></ul><p>From the previous document the standard prefix for an Azure Function is func. An example of an Azure Function name created using Microsoft's naming convention is func-sometestfeature-dev-southcentralus-01:</p><p></p><ul style="text-align: left;"><li>Resource Type: func (from <a href="https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-abbreviations">Abbreviation examples for Azure resources</a>)</li><li>Workload/Application: sometestfeature</li><li>Environment: dev </li><ul><li>develop naming abbreviation dev</li><li>quality assurance naming abbreviation qa</li><li>staging naming abbreviation stg</li><li>production naming abbreviation prod</li></ul><li>Azure Region: southcentralus (see <a href="https://www.softwarepronto.com/2024/01/azurepowershell-retrieving-azure.html">Azure/PowerShell: Retrieving Azure Regions using Get-AzLocation</a>)</li><li>Instance: 001</li></ul><div><br /></div><p></p>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com0tag:blogger.com,1999:blog-7655634577563139129.post-48100271886115083062024-01-16T13:17:00.000-08:002024-01-17T06:25:44.019-08:00Windows Services: Fix Online Documentation ServiceController<p>The following links related to the ServiceController class's documentation were likely written prior to 2002 (.NET 1.0 was released in January 2002) and the code samples in the documentation contain some C# examples that are functionally correct but are not written using best practices with respect to C# coding:</p><p></p><ul style="text-align: left;"><li><a href="https://learn.microsoft.com/en-us/dotnet/api/system.serviceprocess.servicecontroller.status?view=dotnet-plat-ext-7.0">ServiceController.Status Property</a></li><li><a href="https://learn.microsoft.com/en-us/dotnet/api/system.serviceprocess.servicecontroller.start?view=dotnet-plat-ext-7.0">ServiceController.Start Method</a></li><li><a href="https://learn.microsoft.com/en-us/dotnet/api/system.serviceprocess.servicecontrollerstatus?view=dotnet-plat-ext-7.0">ServiceControllerStatus</a></li></ul><p></p><p>The following code was found in the above links where the code demarcated in boldface is not written using best practices:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMsAkfBWhOSpPpbRnevXUSfS_iJOvcQO82v5gxTT0_36cSwamPE7NluYWCfhWbAQIVg5-RfztH2B2QYHdV82msbi4-d6nQdU9lpQLJdm3fY-RAA48vzEgJD6UUd_L51cj5a9k10-mr05QsBblbPZiOwoZaMXo8Upn7WdTqV5D__U0pbjLYhLKByBg/s1557/servicecontroller_00.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="840" data-original-width="1557" height="346" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMsAkfBWhOSpPpbRnevXUSfS_iJOvcQO82v5gxTT0_36cSwamPE7NluYWCfhWbAQIVg5-RfztH2B2QYHdV82msbi4-d6nQdU9lpQLJdm3fY-RAA48vzEgJD6UUd_L51cj5a9k10-mr05QsBblbPZiOwoZaMXo8Upn7WdTqV5D__U0pbjLYhLKByBg/w640-h346/servicecontroller_00.png" width="640" /></a></div>The Status property above is used in the Console.WriteLine is an enumeration, ServiceControllerStatus, and there is no need to specify ToString().<div><br /></div><div>The Equal method is used above to compare the Status property with a ServiceControllerService value. Best practice would be to use operator==.</div><div><br /><p>The same code as above is show below without the superfluous ToString and using operator== instead other Equals method:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhakZLBF4frptII4iCoTI8VyCWSYfDve3SwtHks9w5qZyazk2BhMAnrZKV42hew1_OHrfxb9EjFyD8YTHiAXc7PbW9wUyU5wj_RtvYbyXZ0RdXDY5ijj9ixIAVff2g7qQ1D4ldEVy-CC_IGl3k5Gotw5WOo99L1Rm2w1KcpR1R1Oo1sjt6yfVliAuQ/s1455/servicecontroller_01.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="807" data-original-width="1455" height="354" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhakZLBF4frptII4iCoTI8VyCWSYfDve3SwtHks9w5qZyazk2BhMAnrZKV42hew1_OHrfxb9EjFyD8YTHiAXc7PbW9wUyU5wj_RtvYbyXZ0RdXDY5ijj9ixIAVff2g7qQ1D4ldEVy-CC_IGl3k5Gotw5WOo99L1Rm2w1KcpR1R1Oo1sjt6yfVliAuQ/w640-h354/servicecontroller_01.png" width="640" /></a></div><br /><div style="text-align: left;"><br /></div><div style="text-align: left;">The above change was approved January 16, 2024 and merged into the main documentation branch:</div></div><div style="text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8qgEtIlC9reR8vhdgxzyY_wGtGpDNEAEQKVKZdCs1dAb5K52NbDQ2xefA2w1lyqXUbfjCYCnK6YtulSNJNKJRdKJnoxu8ZeDf191lst8t0cus3p1wFClV4GJ57n8JqjByevkPUJ-kc4FzeRHU8fV10FXqt8MwvaLwSUnyu3wBuiA7Og_5Qr91riAYwA/s2090/ServiceController_improved_code.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="537" data-original-width="2090" height="164" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg8qgEtIlC9reR8vhdgxzyY_wGtGpDNEAEQKVKZdCs1dAb5K52NbDQ2xefA2w1lyqXUbfjCYCnK6YtulSNJNKJRdKJnoxu8ZeDf191lst8t0cus3p1wFClV4GJ57n8JqjByevkPUJ-kc4FzeRHU8fV10FXqt8MwvaLwSUnyu3wBuiA7Og_5Qr91riAYwA/w640-h164/ServiceController_improved_code.png" width="640" /></a></div><br /><div style="text-align: left;"><br /></div><div style="text-align: left;"><br /></div>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com0tag:blogger.com,1999:blog-7655634577563139129.post-6299993468949344352024-01-16T10:39:00.000-08:002024-01-16T10:39:04.498-08:00Azure/PowerShell: Retrieving Azure Regions using Get-AzLocation<p>A standard for naming Azure resources has been proposed by Microsoft, <a href="https://learn.microsoft.com/en-us/azure/cloud-adoption-framework/ready/azure-best-practices/resource-naming">Define your naming convention</a>. The naming standard specifies that each Azure resource name contains a:</p><p></p><ul style="text-align: left;"><li>Resource type abbreviation</li><li>Workload/application</li><li>Environment (.e.g. dev, QA, stage, prod, etc.)</li><li>Azure region</li><li>Instance number</li></ul><p></p><p>A programmatic means to retrieve the Azure regions used by resource name is provided by the Get-AzLocation PowerShell cmdlet. The documentation for Get-AzLocation (<a href="https://learn.microsoft.com/en-us/powershell/module/az.resources/get-azlocation">Get-AzLocation</a>) describes the cmdlet's functionality as follows:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-0vc5Gg1lEn9OfToEbAYXSUhf5s_Y45dfTyrxbG8Q8zz_jJSyiz5_iXU79x9ppZ_ir3YHxBnmHoTecF1QuosS8MsbBuuVKBrsmcA9cXMe_O1YOW6nV86AXIrBxbjnGOpzCEYQDxJyy670cL76MMQq2ii8g61NlN3pMWIZ3owZqk_149xhCuqaN33d4A/s1350/Get_azlocation_description.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="92" data-original-width="1350" height="44" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-0vc5Gg1lEn9OfToEbAYXSUhf5s_Y45dfTyrxbG8Q8zz_jJSyiz5_iXU79x9ppZ_ir3YHxBnmHoTecF1QuosS8MsbBuuVKBrsmcA9cXMe_O1YOW6nV86AXIrBxbjnGOpzCEYQDxJyy670cL76MMQq2ii8g61NlN3pMWIZ3owZqk_149xhCuqaN33d4A/w640-h44/Get_azlocation_description.png" width="640" /></a></div><p>Get-AzLocation can be invoked as follows to return a list of Azure locations (regions) that can be used in resource names:</p><div style="text-align: left;"><div><span style="font-family: courier;">Connect-AzAccount</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;">Get-AzLocation | Select-Object -ExpandProperty Location | Sort-Object</span></div><div><br /></div></div><div style="text-align: left;">Azure regions are not static meaning regions are added and in theory could be removed. As of January 16, 2024 the Get-AzLocation script shown above returns the following list of Azure regions:</div><div style="text-align: left;"><br /></div><div><span style="font-family: courier;">asia</span></div><div><div><span style="font-family: courier;">asiapacific</span></div><div><span style="font-family: courier;">australia</span></div><div><span style="font-family: courier;">australiacentral</span></div><div><span style="font-family: courier;">australiacentral2</span></div><div><span style="font-family: courier;">australiaeast</span></div><div><span style="font-family: courier;">australiasoutheast</span></div><div><span style="font-family: courier;">brazil</span></div><div><span style="font-family: courier;">brazilsouth</span></div><div><span style="font-family: courier;">brazilsoutheast</span></div><div><span style="font-family: courier;">canada</span></div><div><span style="font-family: courier;">canadacentral</span></div><div><span style="font-family: courier;">canadaeast</span></div><div><span style="font-family: courier;">centralindia</span></div><div><span style="font-family: courier;">centralus</span></div><div><span style="font-family: courier;">centraluseuap</span></div><div><span style="font-family: courier;">eastasia</span></div><div><span style="font-family: courier;">eastus</span></div><div><span style="font-family: courier;">eastus2</span></div><div><span style="font-family: courier;">eastus2euap</span></div><div><span style="font-family: courier;">europe</span></div><div><span style="font-family: courier;">france</span></div><div><span style="font-family: courier;">francecentral</span></div><div><span style="font-family: courier;">francesouth</span></div><div><span style="font-family: courier;">germany</span></div><div><span style="font-family: courier;">germanynorth</span></div><div><span style="font-family: courier;">germanywestcentral</span></div><div><span style="font-family: courier;">global</span></div><div><span style="font-family: courier;">india</span></div><div><span style="font-family: courier;">israelcentral</span></div><div><span style="font-family: courier;">italynorth</span></div><div><span style="font-family: courier;">japan</span></div><div><span style="font-family: courier;">japaneast</span></div><div><span style="font-family: courier;">japanwest</span></div><div><span style="font-family: courier;">korea</span></div><div><span style="font-family: courier;">koreacentral</span></div><div><span style="font-family: courier;">koreasouth</span></div><div><span style="font-family: courier;">northcentralus</span></div><div><span style="font-family: courier;">northeurope</span></div><div><span style="font-family: courier;">norway</span></div><div><span style="font-family: courier;">norwayeast</span></div><div><span style="font-family: courier;">norwaywest</span></div><div><span style="font-family: courier;">polandcentral</span></div><div><span style="font-family: courier;">qatarcentral</span></div><div><span style="font-family: courier;">singapore</span></div><div><span style="font-family: courier;">southafrica</span></div><div><span style="font-family: courier;">southafricanorth</span></div><div><span style="font-family: courier;">southafricawest</span></div><div><span style="font-family: courier;">southcentralus</span></div><div><span style="font-family: courier;">southeastasia</span></div><div><span style="font-family: courier;">southindia</span></div><div><span style="font-family: courier;">sweden</span></div><div><span style="font-family: courier;">swedencentral</span></div><div><span style="font-family: courier;">switzerland</span></div><div><span style="font-family: courier;">switzerlandnorth</span></div><div><span style="font-family: courier;">switzerlandwest</span></div><div><span style="font-family: courier;">uaecentral</span></div><div><span style="font-family: courier;">uaenorth</span></div><div><span style="font-family: courier;">uksouth</span></div><div><span style="font-family: courier;">ukwest</span></div><div><span style="font-family: courier;">unitedstates</span></div><div><span style="font-family: courier;">westcentralus</span></div><div><span style="font-family: courier;">westeurope</span></div><div><span style="font-family: courier;">westindia</span></div><div><span style="font-family: courier;">westus</span></div><div><span style="font-family: courier;">westus2</span></div><div><span style="font-family: courier;">westus3</span></div></div>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com0tag:blogger.com,1999:blog-7655634577563139129.post-50422714349819907342024-01-14T08:37:00.000-08:002024-01-14T08:39:43.207-08:00Docker: Identify Linux/Windows Container Support Requirements (Open Source Contribution)<p>The Docker documentation, <a href="https://docs.docker.com/desktop/install/windows-install/">Install Docker Desktop on Windows</a>, specified at the bottom of the instructions the operating systems requirements to run Windows containers from Docker. I modified the page but at the same time the Docker documentation team split the system requirements into multiple pages (per-operating system) and made the same basic modification I had proposed to the documentation.</p><p>My PR was acknowledge as part of the changes:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjn3WFcEOv_wbTqcFK9RG7sTmqd6ztnJFrQzgioZKhndH9HOdgzmRv9SyDdkVW3rbDDUIAlj3zqYKtCsm1cOY9Bs6p3zvw8GGMRA-4ZiMO6-f3W2TGXyNgQUWxHnbjoQZLki8zZ0dMXU4LH4pzXV8v-1kT810C-uYdIvxoOhHoI_nnmXowwduJf1Zzguw/s1922/docker_open_source_contribution.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="550" data-original-width="1922" height="184" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjn3WFcEOv_wbTqcFK9RG7sTmqd6ztnJFrQzgioZKhndH9HOdgzmRv9SyDdkVW3rbDDUIAlj3zqYKtCsm1cOY9Bs6p3zvw8GGMRA-4ZiMO6-f3W2TGXyNgQUWxHnbjoQZLki8zZ0dMXU4LH4pzXV8v-1kT810C-uYdIvxoOhHoI_nnmXowwduJf1Zzguw/w640-h184/docker_open_source_contribution.png" width="640" /></a></div><p><br /></p><p>The warning entitled, Important, at the bottom of this documentation was fundamentally the change proposed in close proximity to the specific version requirements:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7cizW-qUVRsJzQYND1YlbVsyP5ySAOEseTobn4Hk4XwEmYE48XsAm_mo4tadqhcUuFU-ilqtqeIVzYQjFYoxEiPFii8Dqvnv3g1YKabUGpjP94wC8UPQwpLtYsl4hjQr337jNU3DiUtopZILtHTokaJXXK2BeoCuvoOXS8BJyt1sGY7j3cgJ_pNwomQ/s1997/docker_windows_important.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1797" data-original-width="1997" height="576" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7cizW-qUVRsJzQYND1YlbVsyP5ySAOEseTobn4Hk4XwEmYE48XsAm_mo4tadqhcUuFU-ilqtqeIVzYQjFYoxEiPFii8Dqvnv3g1YKabUGpjP94wC8UPQwpLtYsl4hjQr337jNU3DiUtopZILtHTokaJXXK2BeoCuvoOXS8BJyt1sGY7j3cgJ_pNwomQ/w640-h576/docker_windows_important.png" width="640" /></a></div><br /><p><br /></p><p><br /></p><div class="separator" style="clear: both; text-align: center;"><br /></div><br /><p><br /></p>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com0tag:blogger.com,1999:blog-7655634577563139129.post-19210571985551722982024-01-06T11:40:00.000-08:002024-01-06T11:40:44.223-08:00Git: Adding a Submodule to a Repo<h1 style="text-align: left;">Adding a Submodule</h1><p>I was tasked with adding Opkg utilties to an existing git repo so these utilities could be invoke as part of the build pipeline. The Opkg project is found at:</p><div style="text-align: left;"><a href="https://github.com/shr-project/opkg-utils"><span style="font-family: courier;">https://github.com/shr-project/opkg-utils</span></a></div><p>The logical way to add the contents of a Opkg to to an exising git repo is byusing a git submodule. A submodule can be added to a repo by navigating to the folder in which the local repo resides: </p><div style="text-align: left;"><span style="font-family: courier;">cd my-repo-folder</span></div><p><br /></p><p>From inside the local repo's folder invoke:</p><p><span style="font-family: courier;">git submodule add https://github.com/shr-project/opkg-utils</span></p><div><br /></div><div>The command above creates a clone of the repo in folder opkg-utils and creates a .gitmodules file at the local repo's root. The .gitmodules file create is as follows:</div><div><br /></div><div><div><span style="font-family: courier;">[submodule "opkg-utils"]</span></div><div><span style="font-family: courier;"> path = opkg-utils</span></div><div><span style="font-family: courier;"> url = https://github.com/shr-project/opkg-utils</span></div></div><p><br /></p><p>The following command shows the current changes related to any submodules:</p><div style="text-align: left;"><span style="font-family: courier;">git diff --cached --submodule</span></div><p><br /></p><p>The output from the above code is as follows:</p><div style="text-align: left;"><div><span style="font-family: courier;">diff --git a/.gitmodules b/.gitmodules</span></div><div><span style="font-family: courier;">new file mode 100644</span></div><div><span style="font-family: courier;">index 0000000..8205de2</span></div><div><span style="font-family: courier;">--- /dev/null</span></div><div><span style="font-family: courier;">+++ b/.gitmodules</span></div><div><span style="font-family: courier;">@@ -0,0 +1,3 @@</span></div><div><span style="font-family: courier;">+[submodule "opkg-utils"]</span></div><div><span style="font-family: courier;">+ path = opkg-utils</span></div><div><span style="font-family: courier;">+ url = https://github.com/shr-project/opkg-utils</span></div><div><span style="font-family: courier;">Submodule opkg-utils 0000000...1f5c57b (new submodule)</span></div><div><br /></div></div><div style="text-align: left;"><br /></div><div style="text-align: left;">The value 1f5c57b above corresponds to the SHA code of the latest commit the the opkg-utils repo:</div><div style="text-align: left;"><br /></div><div style="text-align: left;"><span style="font-family: courier;">1f5c57bfc8c08926a349c395e0e72058f857448e</span></div><div style="text-align: left;"><br /></div><div>To perform a git add and git commit for the local repo, the following is invoked</div><div><br /></div><div><span style="font-family: courier;">git commit -am 'Task-123: Add Opkg as submodule'</span></div><div><div><br /></div><div>The output from the above add/commit as follows:</div><div> </div><div><div><div><span style="font-family: courier;">warning: in the working copy of '.gitmodules', LF will be replaced by CRLF the next time Git touches it</span></div><div><span style="font-family: courier;">[master 91e677e] Task-123: Add Opkg as submodule</span></div><div><span style="font-family: courier;"> 2 files changed, 4 insertions(+)</span></div><div><span style="font-family: courier;"> create mode 100644 .gitmodules</span></div><div><span style="font-family: courier;"> create mode 160000 opkg-utils</span></div></div><div><br /></div></div></div><div>The mode, 160000, indicates opkg-utils is a submodule meaning in the repo, opkg-utils is a directory and not a sub directory.</div><div><br /></div><div>The submodule can be committed to origin (the remote git repo) using the following command:</div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;">git push origin master</span></div><div><br /></div><div>Note above that the branch name is master. It simply that I signed up for Azure DevOps over a decade above before there was a main branch and before it was called ADO.</div><div><br /></div><div>In Azure DevOPs the opkg-utils folder looks as follows:<br /><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1PLjgG6GLbnIJP4Lt82mG4-b-L8INGp_GdSqoYPfwI2MKt9J70j99wdfSsje1QA9rgu_W5sJr5cPcC21VAylYpCo8Mq6evchRaRv0bLjcsjbTifRFqfWc3yURrQDc3fdYHwNp5zcXwHlBxfENo63gQcPsWcCl98Y7gSj9vS8xBos4osZcQGXf4MyqTQ/s1090/main_branch.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="457" data-original-width="1090" height="168" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1PLjgG6GLbnIJP4Lt82mG4-b-L8INGp_GdSqoYPfwI2MKt9J70j99wdfSsje1QA9rgu_W5sJr5cPcC21VAylYpCo8Mq6evchRaRv0bLjcsjbTifRFqfWc3yURrQDc3fdYHwNp5zcXwHlBxfENo63gQcPsWcCl98Y7gSj9vS8xBos4osZcQGXf4MyqTQ/w400-h168/main_branch.png" width="400" /></a></div><br /><div>The SHA of the opkg-utils commit is contained in the opkg-util folder meaning the .submodules file is not where the SHA code is stored.</div><div><br /></div><div><h1>Cloning to Include the Submodule</h1></div><div>To clone a repo add the --recurse-submodules parameter tot he standard git clone for the repo:</div><div> </div><div><div><span style="font-family: courier;">git clone --recurse-submodules https://<repo url here></span></div></div><div><div><h1>Forgetting to Clone with --recurse-submodules</h1></div></div><div>If git clone is performed without --recurse-submodules then see the following to show how to add the the submodule or submodules to an already cloned git repo: <a href="https://www.softwarepronto.com/2022/09/git-get-submodules-from-already-clone.html">Git: Get Submodules from an already Cloned Repo</a>.</div><div><br /></div><div><br /></div>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com0tag:blogger.com,1999:blog-7655634577563139129.post-9950892290995834002023-12-05T18:11:00.000-08:002023-12-05T18:11:53.218-08:00WSL/Bash: Removing Zone.Identifier<p> </p><p>I copied files from an Ubuntu VM to laptop's WSL and suddenly all the files were garnished by Zone.Identifier. After some nudging, ChatGTP provided the following:</p><p><span style="font-family: courier;">find . -type f -name '*:Zone.Identifier' -exec rm '{}' \;</span></p><div><br /></div>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com0tag:blogger.com,1999:blog-7655634577563139129.post-72884056782807188142023-11-10T23:19:00.001-08:002023-11-10T23:19:14.470-08:00PowerShell: Including Line Number in Write-Host<p> I get a few comments on my blogs and today I received this comment on this post, <a href="https://www.softwarepronto.com/2020/11/powrershell-myinvocationscriptlinenumbe.html">PowerShell: $Myinvocation.ScriptLineNumber behaves incorrectly with Class Methods</a>:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjY1QhV_NUgEDeb0Ih-C2cCNJDC8_llZhZKrrpCKAwDKMHZ0ShRJ61gRtusgJvkUskVWdTbf4zuPBKZ_2bHp26adIioMzXh3XQgqeco-nY-J0vj8Xw-GaTU6fiH81wZHOFp2dT49Tn10iCJrdmzeMiOgvKRju9wDOsWRnMst-3UHd9THqqWgY0wCWlCeA/s1467/PowerShell_WriteHost_LineNumber.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="225" data-original-width="1467" height="98" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjY1QhV_NUgEDeb0Ih-C2cCNJDC8_llZhZKrrpCKAwDKMHZ0ShRJ61gRtusgJvkUskVWdTbf4zuPBKZ_2bHp26adIioMzXh3XQgqeco-nY-J0vj8Xw-GaTU6fiH81wZHOFp2dT49Tn10iCJrdmzeMiOgvKRju9wDOsWRnMst-3UHd9THqqWgY0wCWlCeA/w640-h98/PowerShell_WriteHost_LineNumber.png" width="640" /></a></div><p>Here is a function that will include the same number as the Write-Host is on:</p><div style="text-align: left;"><div><span style="font-family: courier;">function Get-LineNumber {</span></div><div><span style="font-family: courier;"> return "$($Myinvocation.ScriptLineNumber)"</span></div><div><span style="font-family: courier;">}</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;">Write-Host "$(Get-LineNumber): put your message here"</span></div><div><br /></div></div><p>To see the line number of Write-Host consider the following screenshot:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcVmuff8EykEok1bmnBuQLhpeJc7B0QjDvg9T659rOc0ycFLfppbQGutjU2d_fHIJQKXz6QRmtmxIQWNgDkfrvthqSx7oFtSNCc6jCUEd8gSW4l9MDLtteUGH8c-YJb1rkURMnssJlsE6NCI2ThQGx0RJkA4UA-dOSDsOcL86QhCnURc2Athg8gBA9Sg/s1227/PowerShell_Write_host_LineNumber_ps1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="470" data-original-width="1227" height="246" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgcVmuff8EykEok1bmnBuQLhpeJc7B0QjDvg9T659rOc0ycFLfppbQGutjU2d_fHIJQKXz6QRmtmxIQWNgDkfrvthqSx7oFtSNCc6jCUEd8gSW4l9MDLtteUGH8c-YJb1rkURMnssJlsE6NCI2ThQGx0RJkA4UA-dOSDsOcL86QhCnURc2Athg8gBA9Sg/w640-h246/PowerShell_Write_host_LineNumber_ps1.png" width="640" /></a></div><br /><p>When the above code is run (in this case Visual Studio Code using the PowerShell extension) the following is displayed showing the Write-Host is on line 5:</p><div style="text-align: left;"><div><span style="font-family: courier;">PS C:\Users\jann\Documents\PS> . 'C:\Users\jann\Documents\PS\Write-ExampleLineNumber.ps1'</span></div><div><span style="font-family: courier;">5: put your message here</span></div><div><br /></div></div><p><br /></p>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com0tag:blogger.com,1999:blog-7655634577563139129.post-85987035499340539882023-10-21T04:05:00.005-07:002023-10-21T04:05:43.783-07:00Running Windows Applications as a Different User using System Internals ShellRunas<p>Using the runas command from a Windows console windows was demonstrated in the post, <a href="https://www.softwarepronto.com/2023/10/access-sql-server-management-studio.html">Access SQL Server Management Studio using a different Active Directory Credential</a>. The concept was that a user was logged in to Windows and an application (SQL Server Management Studio e.g. ssms.exe) needed to be run as a different user (hence the use of runas).</p><p>The much vaunted Windows Sysinternals was acquired by Microsoft in 2006 and among the useful utilities produced by Sysinternals is <a href="https://learn.microsoft.com/en-us/sysinternals/downloads/shellrunas">ShellRunas</a>. As the previous documentation link shows:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5n_8PiCUKnvuzKwbpAOOleIr-qVN8X5vFM8cZJHLQPvkCkcmNkmVC3oOelsmijtwXYWhrlihQ4pvW3K5uqlZNGHldIRmUBuZQuc4pWLmzJJeFu9FJ7RkH5u3BSidgmvF-SmFmyhOz0W4m3wh1MsvmEQrm-nOo7FIBgP0TiTdjWvNfOl3eaxzHYFXfXQ/s1840/shellrunas00.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1087" data-original-width="1840" height="378" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5n_8PiCUKnvuzKwbpAOOleIr-qVN8X5vFM8cZJHLQPvkCkcmNkmVC3oOelsmijtwXYWhrlihQ4pvW3K5uqlZNGHldIRmUBuZQuc4pWLmzJJeFu9FJ7RkH5u3BSidgmvF-SmFmyhOz0W4m3wh1MsvmEQrm-nOo7FIBgP0TiTdjWvNfOl3eaxzHYFXfXQ/w640-h378/shellrunas00.png" width="640" /></a></div><br /><h2 style="text-align: left;">Install ShellRunas Shell Extension</h2><p>ShellRunas can be downloaded and zipped from <a href="https://download.sysinternals.com/files/ShellRunas.zip">Download ShellRunas</a>. The download, ShellRunas.zip contains an executable ShellRunas.exe. To install ShellRunas as as a Windows shell extension, run the following from a Windows console terminal in the folder containing ShellRunas.exe:</p><div style="text-align: left;"><span style="font-family: courier;">.\ShellRunas.exe /reg</span></div><p>Invoking ShellRunas as shown above displays a dialog indicating the shell extension has been added;</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOVZsArJ1qbOD2v3pya1bI97uHdoxjIAeCj4ypA28MLnEg-EFNii3Z8TaS2gR3tzBoPZGrgJ7r3ydI1YpmbA3xWkOc6kGVbm8z9T9nffU774w9rdvAmO4uVcSNe4r94pbrp8HrGm5GkRu3gboEwFx78XDazyzfR_T-K2Gz9orcAlbJzKusoUJewr46xA/s1645/shellrunas_reg.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="712" data-original-width="1645" height="278" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjOVZsArJ1qbOD2v3pya1bI97uHdoxjIAeCj4ypA28MLnEg-EFNii3Z8TaS2gR3tzBoPZGrgJ7r3ydI1YpmbA3xWkOc6kGVbm8z9T9nffU774w9rdvAmO4uVcSNe4r94pbrp8HrGm5GkRu3gboEwFx78XDazyzfR_T-K2Gz9orcAlbJzKusoUJewr46xA/w640-h278/shellrunas_reg.png" width="640" /></a></div><br /><h1 style="text-align: left;">Running ShellRunas from Explorer</h1><div>To demonstrated on Windows 11 how to use ShellRunas navigate in Windows Explorer to the folder of the application (such as ssms.exe): </div><div><br /></div><div style="text-align: left;"><span style="font-family: courier;">C:\Program Files (x86)\Microsoft SQL Server Management Studio 19\Common7\IDE</span></div><p>From Windows Explorer right click on the application (such as ssms.exe) which displays a context menu such as the following:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsuxhEwApc13xGf_BUR6MPTLEswa-hA1mdPCA8ba-aji9Xe_pqXDmLA9yusm08l3IyL_uqteYcBD1PsM9w2jk_6fFFpcpUXqjN0j8KPw8_9I5Lc7H3qiGitYLXX_4P-8ofuySG6q_1qlhSmo74Bi9LgMDlKcbUTqESOnjLgCwfEeXRYQHxpzq7eGSp2w/s2417/shellrunas_more_options.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1615" data-original-width="2417" height="428" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsuxhEwApc13xGf_BUR6MPTLEswa-hA1mdPCA8ba-aji9Xe_pqXDmLA9yusm08l3IyL_uqteYcBD1PsM9w2jk_6fFFpcpUXqjN0j8KPw8_9I5Lc7H3qiGitYLXX_4P-8ofuySG6q_1qlhSmo74Bi9LgMDlKcbUTqESOnjLgCwfEeXRYQHxpzq7eGSp2w/w640-h428/shellrunas_more_options.png" width="640" /></a></div><br /><p>The bottom option of the context menu is "Show more options." Select this menu item which displays the following context, sub menu:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIqPOQEp5Qj5_ysorbrLL8ccbm8YqLd4HAdRgTtUBdVSeaC3kbGR81mZ-3QIx99rbhzDy49voR8LTODWw1EqxNT85q8gxdTo-ccSm2OQrhFdPP9zzowuowgQ_ZR5vR3h4GZ-8qFxjZPXJfk-BJP0WsLkVAyUZSzq3LrBDHZ0f2wg6ZK-kVQGy2eGoeug/s1447/runasshell_run_as_different_user.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1260" data-original-width="1447" height="558" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiIqPOQEp5Qj5_ysorbrLL8ccbm8YqLd4HAdRgTtUBdVSeaC3kbGR81mZ-3QIx99rbhzDy49voR8LTODWw1EqxNT85q8gxdTo-ccSm2OQrhFdPP9zzowuowgQ_ZR5vR3h4GZ-8qFxjZPXJfk-BJP0WsLkVAyUZSzq3LrBDHZ0f2wg6ZK-kVQGy2eGoeug/w640-h558/runasshell_run_as_different_user.png" width="640" /></a></div>From the above context menu select "Run as different user" which display the following dialog courtesy of Sysinternals ShellRunas:<div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNd3DwIgWiXFVKO6_Vnf3XWRHA1qwBhbDke6wCHM7ddwKdS6meft1Wqfx-gOZmQRmqTDkjAfQQYO4rKeMRevs0zTn2g05u2bTV5UGPCIWNiv-KBxbGwc7S6-xr5KkEmSJEimGluuIK2eRgAYnE-MDmCFoOKue2UM2UAYMLWVtHaxrJfRrEs7fiZ6dVkw/s1140/ShellRUnas_different_user.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1022" data-original-width="1140" height="574" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgNd3DwIgWiXFVKO6_Vnf3XWRHA1qwBhbDke6wCHM7ddwKdS6meft1Wqfx-gOZmQRmqTDkjAfQQYO4rKeMRevs0zTn2g05u2bTV5UGPCIWNiv-KBxbGwc7S6-xr5KkEmSJEimGluuIK2eRgAYnE-MDmCFoOKue2UM2UAYMLWVtHaxrJfRrEs7fiZ6dVkw/w640-h574/ShellRUnas_different_user.png" width="640" /></a></div><br /><p>The above dialog can be used run an application as a user that differs from the currently logged in Windows user.</p><h1 style="text-align: left;">Why Such Complicated Navigation?</h1><div>ShellRunas dates back to February 26, 2008 and the era of WidnowsVista, Windows Server 2008, and President George Bush. The example shell context menu shown at the top of this post is from Microsoft's ShellRunas documentation and is as follows:</div><div><br /></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5EG580OryGQG-FkNLXJfv2SfaYSlcWT4BhifPv9zjZTlQLumhBjmLTkNVPeeszQWTpzNzAWdspmcx7bWXsQgdB5v5u1uqUoarBOX4vtzIMSUVJmbvR14_HSDUG5frP-EUrCS8BbvygWIxqvuf1Nmp_vdAPrvrQVGCP0UriSHhlA6mx18cZfsJIUjRnQ/s1072/shellrunas_context_menu.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="665" data-original-width="1072" height="398" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg5EG580OryGQG-FkNLXJfv2SfaYSlcWT4BhifPv9zjZTlQLumhBjmLTkNVPeeszQWTpzNzAWdspmcx7bWXsQgdB5v5u1uqUoarBOX4vtzIMSUVJmbvR14_HSDUG5frP-EUrCS8BbvygWIxqvuf1Nmp_vdAPrvrQVGCP0UriSHhlA6mx18cZfsJIUjRnQ/w640-h398/shellrunas_context_menu.png" width="640" /></a></div><br />The above context menu dialog box were displayed when right click on an executable that was run on Windows days of yore sometime a.k.a. some version before Windows 11.</div><div><br /></div><div>ShellRunas used to be convenient. As of modern versions of Windows, ShellRunas is a handy utility with navigation that is a bit too complex.</div><div><br /></div><h1 style="text-align: left;"> </h1><p><br /></p></div>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com0tag:blogger.com,1999:blog-7655634577563139129.post-82548450862854877212023-10-17T20:54:00.003-07:002023-10-17T21:49:16.252-07:00Access SQL Server Management Studio using a different Active Directory Credential<p>There is no way to change the "User name" in SQL Server Management Studio's "Connect to Server" dialog when using Windows Authentication. This post demonstrates how to run SQL Server Management Studio (SSMS) and authenticate a connection using a different user than the current active Windows user while authenticating with Windows Authentication. For example, a user logs in with the normal account but needs to authenticate with an administrative account to access SQL Server.</p><p>An example of SSMS's "Connect to Server" dialog authenticating a connection with Windows Authentication is as follows:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh371-sF09vUH3pFj4yAHuXjFRdcfvNaMCv_crlBz8RXhJsf7oJluIugL1CIZm4MYOP7LSzxEpgTOHOoneiO5Zlr4YVhd74dmeXfHjjXaVB-xDFOWiSlAYAbISdNCfVAj3lzpm-349Ker83UpricCskt1C3jj65IV0OKrJBHboe6F-YDGe8sLdr0rik_g/s1272/SSMS00.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="750" data-original-width="1272" height="378" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh371-sF09vUH3pFj4yAHuXjFRdcfvNaMCv_crlBz8RXhJsf7oJluIugL1CIZm4MYOP7LSzxEpgTOHOoneiO5Zlr4YVhd74dmeXfHjjXaVB-xDFOWiSlAYAbISdNCfVAj3lzpm-349Ker83UpricCskt1C3jj65IV0OKrJBHboe6F-YDGe8sLdr0rik_g/w640-h378/SSMS00.png" width="640" /></a></div><br /><p>The "User name" dropdown above is grayed out as it cannot be changed because Authentication is set to Windows Authentication. The Windows runas command-line utility (see <a href="https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/cc771525(v=ws.11)">Runas</a>) can be used to run SSMS or any application as a different user than the user currently logged into a host. For this example, considering desiring to login as:</p><p></p><ul style="text-align: left;"><li>domain: domaidAbc</li><li>user: userEfg</li></ul><p></p><p>To run SQL Server Management Studio as user domainAbc\userEfg, specify the following from a console prompt:</p><p><span style="font-family: courier;">runas /noprofile /netonly /user:domainAbc\userEfg "C:\Program Files (x86)\Microsoft SQL Server Management Studio 19\Common7\IDE\ssms.exe"</span></p><p>Once the above command is run, the user will be prompted to enter a password for account domainAbc\userEfg:</p><p><span style="font-family: courier;">Enter the password for domainAbc\userEfg:</span></p><p>There is no way to specify the password as a runas command-line option so the password must be manually entered.</p><p>The following is all the text displayed when running SSMS as a different user via the runas command:</p><div style="text-align: left;"><div><span style="font-family: courier;">C:\>runas /noprofile /netonly /user:domainAbc\userEfg "C:\Program Files (x86)\Microsoft SQL Server Management Studio 19\Common7\IDE\ssms.exe"</span></div><div><span style="font-family: courier;">Enter the password for domainAbc\userEfg:</span></div><div><span style="font-family: courier;">Attempting to start C:\Program Files (x86)\Microsoft SQL Server Management Studio 19\Common7\IDE\ssms.exe as user "domainAbc\userEfg" ...</span></div><div><br /></div><div>At this point SSMS is running as user domainAbc\userEfg. There is a bit of a twist. Here is an example of the "Connect to Server" dialog displayed when running as user domainAbc\userEfg (note the grayed out User name is different,XPS17\jann):</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9kqwIK2dNyS2OFDdq_VUjbbsSCC7BkH3JXzcsCoqBv3y3C_rVvwDDOQ2PuSiNximJH-S52P7q87OpKQ4FrBfh30MikaXat1VNZntF6YsRyG3a-xBGM3KyItdpGENF8dEjkfvO2_SX6jJi3MxlgEspHpPv0tjSH3zgYPvwhRIrO72cviwd0zgpCHM_bA/s1272/SSMS00.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="750" data-original-width="1272" height="378" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9kqwIK2dNyS2OFDdq_VUjbbsSCC7BkH3JXzcsCoqBv3y3C_rVvwDDOQ2PuSiNximJH-S52P7q87OpKQ4FrBfh30MikaXat1VNZntF6YsRyG3a-xBGM3KyItdpGENF8dEjkfvO2_SX6jJi3MxlgEspHpPv0tjSH3zgYPvwhRIrO72cviwd0zgpCHM_bA/w640-h378/SSMS00.png" width="640" /></a></div><div><br /></div><div>When the Server name is specified and the connection to SQL Server is made, the user used to authenticate is domainAbc\userEfg and not the grayed out user.</div></div>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com0tag:blogger.com,1999:blog-7655634577563139129.post-32067124856551861632023-09-17T16:18:00.002-07:002023-09-17T16:18:13.902-07:00PowerShell/Azure Graph API: Improving the Online Documentation (Open Source Contribution)<p>Microsoft provides an excellent example of how to create a report of Azure App Registrations with expiring secrets and certificates (see: <a href="https://learn.microsoft.com/en-us/azure/active-directory/manage-apps/scripts/powershell-export-apps-with-expiring-secrets">Export app registrations with expiring secrets and certificates</a>). This script uses Microsoft's Graph PowerShell SDK module which is installed as follows:</p><div style="text-align: left;"><span style="font-family: courier;">Install-Module PowerShellGet</span></div><p>In Microsoft's sample the following PowerShell snippet is included in two separate locations in the code:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXK78DtrTiOIoaa-dT2eXIF4mQKtIsxuPsQ84CWo8tWMGlm7d3aC0Vz1Lb-UDd_mK6GgjwxYFdG112GJbBQwZRiRvN2iQy1GZEqY0_qu6rE_PAL_lvM1DufHpcvum0Bx-pMKt6IYcy-UDGVbB6YfVpnTs3C8anU-6zMOEML0zvRFtFaWhr5l8rIqbJTQ/s805/azure_api_powershell_issue.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="120" data-original-width="805" height="60" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXK78DtrTiOIoaa-dT2eXIF4mQKtIsxuPsQ84CWo8tWMGlm7d3aC0Vz1Lb-UDd_mK6GgjwxYFdG112GJbBQwZRiRvN2iQy1GZEqY0_qu6rE_PAL_lvM1DufHpcvum0Bx-pMKt6IYcy-UDGVbB6YfVpnTs3C8anU-6zMOEML0zvRFtFaWhr5l8rIqbJTQ/w400-h60/azure_api_powershell_issue.png" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: justify;">Obviously, that code could be more simply written as:</div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzCybfyCKa7OAh9SuyhLXibAg8z7cm7cu_NC7R0Wi4kXS6qdMUuu8JfsvGQbRUoynDJxYN1_wh3_LfeV2HJKu33eRKSJp-xfJI3_bsAY9DZEsPyew0CvSSjIgH7-qeQOyVki4BcKh367q3wXpUo6YAHGuRs70-YwVvM16PtHtvU9xMmo_8QVCX9cCgZw/s875/Better_powerShell.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="87" data-original-width="875" height="40" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzCybfyCKa7OAh9SuyhLXibAg8z7cm7cu_NC7R0Wi4kXS6qdMUuu8JfsvGQbRUoynDJxYN1_wh3_LfeV2HJKu33eRKSJp-xfJI3_bsAY9DZEsPyew0CvSSjIgH7-qeQOyVki4BcKh367q3wXpUo6YAHGuRs70-YwVvM16PtHtvU9xMmo_8QVCX9cCgZw/w400-h40/Better_powerShell.png" width="400" /></a></div><br /><div class="separator" style="clear: both; text-align: justify;">I logged into Github.com, edited Microsoft's example, and created a pull request. Withing 24 Hours it was approved and my change as adopted meaning the online documentation was updated to include my change:</div><div class="separator" style="clear: both; text-align: justify;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoc067cbk0pAH_IfuMAlxveXQOizIKD7pUHm4PyoWHeYL7DghY3BV8UpIpxeSjOsmiu2Gcq8w70GwzzFxx2uRoBFIFlzN-4eI9u34M-A2BaxZaqIT_Jm5ypqBmvmla_2SBswK0TUoNCFKbRi5tqvRE0j2lZxvNNQWex8keDb1BPnr7hBySMcylZoI2aw/s2327/pr_graph_api.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="597" data-original-width="2327" height="165" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhoc067cbk0pAH_IfuMAlxveXQOizIKD7pUHm4PyoWHeYL7DghY3BV8UpIpxeSjOsmiu2Gcq8w70GwzzFxx2uRoBFIFlzN-4eI9u34M-A2BaxZaqIT_Jm5ypqBmvmla_2SBswK0TUoNCFKbRi5tqvRE0j2lZxvNNQWex8keDb1BPnr7hBySMcylZoI2aw/w640-h165/pr_graph_api.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: justify;"><br /></div><div class="separator" style="clear: both; text-align: justify;"><br /></div><div class="separator" style="clear: both; text-align: justify;"><br /></div><br /><p><br /></p>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com0tag:blogger.com,1999:blog-7655634577563139129.post-61444698207699477972023-08-25T22:27:00.003-07:002023-08-25T22:27:59.221-07:00Docker: Error Message "Windows Containers are not supported on your version of windows"<p>On a Windows host where Docker is configured to use Windows (versus Linux) contains the following error message, "Windows Containers are not supported on your version of windows", can be encountered. There are multiple reasons for this error message but one of the most common is that it is only possible to run Windows containers on Windows Pro or Windows Enterprise edition. Docker cannot run Windows containers on Windows Home or Windows Education edition.</p><p>Docker's setup instructions for Windows can be found at <a href="https://docs.docker.com/desktop/install/windows-install">Install Docker Desktop on Windows</a>. A the top of this web page, under System Requirements is the following (as of August 23, 2023):<br /></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieyi_ymycG8mdBfs2VvB8S95o0ODiV5ZUTtumU1mXpa82vnuh4ulnk1QG1dOdZ-BQWsbuRCnuLCGlS-UhPZL-GFMlH-YR9biqVdfbbsk-2RVJjM5Tv91vGPIeWqXaXyFUiyLnKsZOcrXlAvJ2g1W1Zb5f8jArG3_r4CyLvrKJtJ8cxoeESM8zF8k6oVA/s1910/Docker_windows_version_requirements.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="762" data-original-width="1910" height="256" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEieyi_ymycG8mdBfs2VvB8S95o0ODiV5ZUTtumU1mXpa82vnuh4ulnk1QG1dOdZ-BQWsbuRCnuLCGlS-UhPZL-GFMlH-YR9biqVdfbbsk-2RVJjM5Tv91vGPIeWqXaXyFUiyLnKsZOcrXlAvJ2g1W1Zb5f8jArG3_r4CyLvrKJtJ8cxoeESM8zF8k6oVA/w640-h256/Docker_windows_version_requirements.png" width="640" /></a></div><br /><p>There is nothing in the above documentation stating that Windows Home and Education only support Linux containers. There is nothing in the above documentation stating that in order to supports both Linux and Windows containers Windows Pro or Windows Enterprise is required.</p><p><i>Note: I have submitted a Pull Request to Docker's documentation repo (<a href="https://github.com/docker/docs">Docker docs</a>) requesting the text be changed to include the sentences "Home and Education editions support only Linux containers. Pro and Enterprise editions support Windows containers and Linux containers." alongside the Windows 11 and Windows 10 system requirements.</i></p><p>Dockers Windows install documentation (<a href="https://docs.docker.com/desktop/install/windows-install">Install Docker Desktop on Windows</a>) does include a note well below the "System requirements" tab that presents which editions of Windows are required in order to run Windows containers:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuaShZYBYqpkkNmI2T8sbMBT0A3DhxQ_KQQHLXgQK4voB2m-CypMmtSo-gaRdzvMOSUHFirZrnuvrztS7_x8neeznD6rTHC3PE5be55GOGS1prMuRQRQVKsj3r1CW3HAVv-_5E9l1TQZ4Ea5zh9_e2pPxYUy6lrpfDG2WiKY9CCjfmhIsP36070RDWjA/s1915/Docker_windows_contains_require_windows_pro_or_window_enterprise.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="330" data-original-width="1915" height="110" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhuaShZYBYqpkkNmI2T8sbMBT0A3DhxQ_KQQHLXgQK4voB2m-CypMmtSo-gaRdzvMOSUHFirZrnuvrztS7_x8neeznD6rTHC3PE5be55GOGS1prMuRQRQVKsj3r1CW3HAVv-_5E9l1TQZ4Ea5zh9_e2pPxYUy6lrpfDG2WiKY9CCjfmhIsP36070RDWjA/w640-h110/Docker_windows_contains_require_windows_pro_or_window_enterprise.png" width="640" /></a></div><br /><p><br /></p><p><br /></p>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com0tag:blogger.com,1999:blog-7655634577563139129.post-73956489199989903622023-08-14T07:12:00.001-07:002023-08-14T07:12:43.962-07:00Windows 10: Install Windows Terminal Without Windows Store<p>I was handed a laptop for a project that was Windows 10. Windows Terminal was not installed. On Windows 11 22H2, Windows Terminal is the default "command line experience" (see <a href="https://devblogs.microsoft.com/commandline/windows-terminal-is-now-the-default-in-windows-11/">Windows Terminal is now the Default in Windows 11</a>). Microsoft recommends installing Window Terminal using the Windows Store (see <a href="https://apps.microsoft.com/store/detail/windows-terminal/9N0DX20HK701">Windows Terminal</a>). The laptop I was given was a corporate laptop and Windows Store was unavailable.</p><p>It is possible to download and install Windows Terminal from <a href="https://github.com/microsoft/terminal/releases">Windows Terminal Releases</a>. Below are assets for Windows Terminal v1.17.11461.0:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjGljs3WSfclSQe_nF4oL4axUYaYHNoqpLZpkd3I6_-SIvWlhvDdf8gKDXTOV1XlpHDiwJ1buGj6JJ9VjSMDYkb7JwOYzh__W_pdhDoab2Ncg-Ghn0-EPTmmTYCnSDgOS4kIw1LpKw97xwUg2TAu54NwPC0VMcogk2P6VeXtReXv0sQ6BooQa7Avi5tw/s2250/Windows_Terminal_Assets.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="760" data-original-width="2250" height="216" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjGljs3WSfclSQe_nF4oL4axUYaYHNoqpLZpkd3I6_-SIvWlhvDdf8gKDXTOV1XlpHDiwJ1buGj6JJ9VjSMDYkb7JwOYzh__W_pdhDoab2Ncg-Ghn0-EPTmmTYCnSDgOS4kIw1LpKw97xwUg2TAu54NwPC0VMcogk2P6VeXtReXv0sQ6BooQa7Avi5tw/w640-h216/Windows_Terminal_Assets.png" width="640" /></a></div><div><br /></div>The easiest way to install is to just download and invoke the MSIX bundle.<div><br /><p><br /></p></div>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com0tag:blogger.com,1999:blog-7655634577563139129.post-74879829083478354952023-08-13T06:40:00.002-07:002023-08-13T06:49:21.370-07:00PowerShell (failure): New-TemporaryFile Cannot Create a New Filename without Creating a File<p>In PowerShell the standard way to create a temporary filename is to invoke the System.IO namespace's Path class's GetTempFileName method. To be clear, only a filename is retrieved and no actual file is created. An example of GetTempFileName being invoked by PowerShell is as follows:</p><div style="text-align: left;"><span style="font-family: courier;">[string] $tempFilenameFromCsharp = ` </span></div><div style="text-align: left;"><span style="font-family: courier;"> [System.IO.Path]::GetTempFileName() </span></div><p>The results of the code above will vary because the filename is randomly generated and the method uses a user's environment variable, $env:TEMP. An example of the value assigned to $tempFilenameFromCsharp when the code snippet above being invoked is as follows:</p><p><span style="font-family: courier;">C:\Users\jann\AppData\Local\Temp\tmpCF88.tmp</span></p><div>The New-TemporaryFile PowerShell cmdlet creatse a new temporary file and returns a corresponding instance of the System.IO.FileInfo class whihc include information such as the name of the file created.</div><div><br /></div><div><b><i>My theory that I felt had a 20% chance of working: Invoke New-TemporaryFile with the -WhatIf command-line option and instead of creating a temporary file, the comdlet will return the name of the temporary file that would have been created.</i></b></div><p>For those that need a reminder, the WhatIf command-line option is defined as follows (see: <a href="https://learn.microsoft.com/en-us/exchange/whatif-confirm-and-validateonly-switches-exchange-2013-help#whatif-switch">WhatIf Switch</a>):</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGBJ9acoUBlpN97TKkXCgRJES-ZL4FshvGSGsjUXRERr0m4VkwgfD7EUzdpraf_HfZYwWSKtmJBz0IdJgPOCZJpsVP60BgM8mIOrUq4n1M_mVYZT_cNxMIUquvPyOhn81VMzliYGTcVWy8k83OI91PGFkLXX8h82Yu9iK4qAqs2nUixP_hdbKBBs6C8A/s1815/powershell_whatif.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="320" data-original-width="1815" height="112" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGBJ9acoUBlpN97TKkXCgRJES-ZL4FshvGSGsjUXRERr0m4VkwgfD7EUzdpraf_HfZYwWSKtmJBz0IdJgPOCZJpsVP60BgM8mIOrUq4n1M_mVYZT_cNxMIUquvPyOhn81VMzliYGTcVWy8k83OI91PGFkLXX8h82Yu9iK4qAqs2nUixP_hdbKBBs6C8A/w640-h112/powershell_whatif.png" width="640" /></a></div><br /><p>My attempt to use New-TemporaryFile to create filename without creating a file was as follows:</p><div style="text-align: left;"><div><span style="font-family: courier;">[System.IO.FileInfo] $tempFilenameFromPowerShell = `</span></div><div><span style="font-family: courier;"> New-TemporaryFile -WhatIf -ErrorAction Stop</span></div></div><p>The output from invoking the above command is follows:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj44wQqBy2_8FIZZ_Ol5m23zLeRvmoM8Dta5CGh1EFg9D90iiNbyceMkocivwLdVb4iDkJmMJBPTKHqek_CzNW-RzctVRQNQL2qVwB7-M7oLsxrxTuSo5HTsM2MHpwwQAUoMuKdIkCf8Yh9epvYqFEDoL7yZvVXz7yUt4jsnEwur4Gg7GlMIYDiHdt1dg/s1817/New_TemporaryFile_Output.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="190" data-original-width="1817" height="66" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj44wQqBy2_8FIZZ_Ol5m23zLeRvmoM8Dta5CGh1EFg9D90iiNbyceMkocivwLdVb4iDkJmMJBPTKHqek_CzNW-RzctVRQNQL2qVwB7-M7oLsxrxTuSo5HTsM2MHpwwQAUoMuKdIkCf8Yh9epvYqFEDoL7yZvVXz7yUt4jsnEwur4Gg7GlMIYDiHdt1dg/w640-h66/New_TemporaryFile_Output.png" width="640" /></a></div><br /><div>The following code tests if the $tempFilenameFromPowerShell variable is assigned to $null:</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIb_08CzC4uq52HxmEEOAZaPohntxHtPBQx-25GVcpMBFnVlyVMikBezIhds2R2Ea0N4KD6gcSTZpvZp1rfgsNqyJLQutm9_a91M-c3vJxPue2pPh6N6xBkWwplE2hnAMkN_6vATRIzFne6mU-mQqQrAdtqIxrgNsVM87k-KN5W-UnRYiaH-r95O2ItA/s1632/New_TemporaryFile_Output_Null.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="107" data-original-width="1632" height="42" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhIb_08CzC4uq52HxmEEOAZaPohntxHtPBQx-25GVcpMBFnVlyVMikBezIhds2R2Ea0N4KD6gcSTZpvZp1rfgsNqyJLQutm9_a91M-c3vJxPue2pPh6N6xBkWwplE2hnAMkN_6vATRIzFne6mU-mQqQrAdtqIxrgNsVM87k-KN5W-UnRYiaH-r95O2ItA/w640-h42/New_TemporaryFile_Output_Null.png" width="640" /></a></div><br /><div>Since $tempFilenameFromPowerShell is set to $null so New-TemporaryFile combined with -WhatIf does not create a new filename. </div><p>Not every idea we try works.</p>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com0tag:blogger.com,1999:blog-7655634577563139129.post-7690813763036207102023-07-29T00:51:00.003-07:002023-07-29T00:53:37.231-07:00PowerShell: azcopy Working Around the New Version Available Information Message<p>One of the most optimal ways to upload and download blobs to/from Azure storage containers is the azcopy utility (see <a href="https://learn.microsoft.com/en-us/azure/storage/common/storage-ref-azcopy">azcopy</a>). This utility can be used from the command-line or can be included in a PowerShell script such as the following:</p><div style="text-align: left;"><div><span style="font-family: courier;">[string] $azCopyPath = 'C:\bin\azcopy.exe'</span></div><div><span style="font-family: courier;">[string] $blobSasUrl = 'put your own storage URL plus SAS token here'</span></div><div><br /></div><div><span style="font-family: courier;">& $azCopyPath list $blobSasUrl </span></div><div><br /></div><div>The above example is one of cases where azcopy is not used to upload or download files/folders/blobs. The "azcopy list" command will list the blobs for a given storage URL (see <a href="https://learn.microsoft.com/en-us/azure/storage/common/storage-ref-azcopy-list">azcopy list</a>).</div></div><p>The output from the above command is as follows:</p><div style="text-align: left;"><div><span style="font-family: courier;">INFO: azcopy.10_19_0.exe 10.19.0: A newer version 10.20.0 is available to download</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;">INFO: a.txt; Content Length: 1.20 KiB</span></div><div><span style="font-family: courier;">INFO: b.txt; Content Length: 1.20 KiB</span></div><div><span style="font-family: courier;">INFO: c.txt; Content Length: 1.20 KiB</span></div><div><span style="font-family: courier;">INFO: d.txt; Content Length: 1.20 KiB</span></div><div><br /></div><div>The desired output is as follows (sans the upgrade available message):</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgW4nT_rcBnYucbmB-VWGK5Vs4VAloweqYXARsZsTLbk7s4u7NRHS9z7mRP5kD_Nc78o3zjuE1HxIG2PQlNOFXNegN0zSTB5e23XAPMgYwZEduq8fymbIMTL2571u3gnw3Usus2iYWnDrmV5njweFbjwrR5IkqiESZJSKNwGK4ZIuvIfvlBaF-W39lggw/s740/azcopy_desired_output.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="190" data-original-width="740" height="103" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgW4nT_rcBnYucbmB-VWGK5Vs4VAloweqYXARsZsTLbk7s4u7NRHS9z7mRP5kD_Nc78o3zjuE1HxIG2PQlNOFXNegN0zSTB5e23XAPMgYwZEduq8fymbIMTL2571u3gnw3Usus2iYWnDrmV5njweFbjwrR5IkqiESZJSKNwGK4ZIuvIfvlBaF-W39lggw/w400-h103/azcopy_desired_output.png" width="400" /></a></div><div><br /></div><div><br /></div><div>The azcopy utility creates a message on the information data stream that an upgrade is available. The output from azcopy list is also provided on the information data stream. There is no way to suppress the "newer version is available to download" message.</div><div><br /></div><div>The following PowerShell code uses "Select-Object -Skip" (see <a href="https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/select-object?view=powershell-7.3">Select-Object</a>) to remove the upgrade informational message and returns only the data retrieved by azcopy list:</div><div><br /></div><div><div><span style="font-family: courier;">[string] $upgradeAvialableSuffix = 'is available to download'</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;">function Get-AzCopyList {</span></div><div><span style="font-family: courier;"> param(</span></div><div><span style="font-family: courier;"> [Parameter(Mandatory=$true)]</span></div><div><span style="font-family: courier;"> [string] $azCopyFilePath,</span></div><div><span style="font-family: courier;"> [Parameter(Mandatory=$true)]</span></div><div><span style="font-family: courier;"> [string] $blobUrlWithSasToken</span></div><div><span style="font-family: courier;"> )</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;"> [string[]] $results = & $azCopyPath list $blobSasUrl </span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;"> # always return an array</span></div><div><span style="font-family: courier;"> if (($null -eq $results) -or (0 -eq $results.Length)) {</span></div><div><span style="font-family: courier;"> return ,[string[]]::new(0)</span></div><div><span style="font-family: courier;"> }</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;"> [int] $index = 0</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;"> if ($results[0].EndsWith($upgradeAvialableSuffix)) {</span></div><div><span style="font-family: courier;"> [bool] $endMarkerFound = $false</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;"> foreach ($result in $results) {</span></div><div><span style="font-family: courier;"> $index++</span></div><div><span style="font-family: courier;"> if (0 -eq $result.Length) {</span></div><div><span style="font-family: courier;"> $endMarkerFound = $true</span></div><div><span style="font-family: courier;"> break</span></div><div><span style="font-family: courier;"> }</span></div><div><span style="font-family: courier;"> }</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;"> if ($false -eq $endMarkerFound) {</span></div><div><span style="font-family: courier;"> throw "Upgrade message not delineated from results $($result[0])"</span></div><div><span style="font-family: courier;"> }</span></div><div><span style="font-family: courier;"> }</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;"> return $results | Select-Object -Skip $index </span></div><div><span style="font-family: courier;">}</span></div><div><span style="font-family: courier;"><br /></span></div><div><div><span style="font-family: courier;">[string] $azCopyPath = 'C:\bin\azcopy.exe'</span></div><div><span style="font-family: courier;">[string] $blobSasUrl = 'put your own storage URL plus SAS token here'</span></div></div><div><span style="font-family: courier;">[string[]] $results = Get-AzCopyList $azCopyPath $blobSasUrl</span></div></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;">$results</span></div><div><br /></div><div>The output from above code is:</div><div><div><span style="font-family: courier;">INFO: a.txt; Content Length: 1.20 KiB</span></div><div><span style="font-family: courier;">INFO: b.txt; Content Length: 1.20 KiB</span></div><div><span style="font-family: courier;">INFO: c.txt; Content Length: 1.20 KiB</span></div><div><span style="font-family: courier;">INFO: d.txt; Content Length: 1.20 KiB</span></div></div><div><br /></div><div><br /></div><div><br /></div></div>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com0tag:blogger.com,1999:blog-7655634577563139129.post-89875513699671871472023-07-04T02:56:00.000-07:002023-07-04T02:56:02.202-07:00Docker/Windows: Installation Requirement "BIOS-level Hardware Virtualization"<div>Installing/running Docker on Windows requires that WSL be installed (see <a href="https://docs.docker.com/desktop/install/windows-install">Install Docker Desktop on Windows</a>). According the aforementioned write up, WSL has the following hardware requirements:</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAyd-QGGBKygGWSwJ9HFBZTy6WrEqTCacL1mY5eRF6GvWVCb5AQdYNcyo8bhwnB9L2pZDOdB9ftEsUoUtK-P8_7QTJQWBF8IeRMM9PdzpIacDXScoXDO-nYZOul60It50VKjH9u0_8-Qwq4pFZvfoEsdbmUUuRGUpGuAuXLDzd36xL1bHmH6RnWd-d6Q/s2100/wsl_hardware_requirements.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="285" data-original-width="2100" height="86" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhAyd-QGGBKygGWSwJ9HFBZTy6WrEqTCacL1mY5eRF6GvWVCb5AQdYNcyo8bhwnB9L2pZDOdB9ftEsUoUtK-P8_7QTJQWBF8IeRMM9PdzpIacDXScoXDO-nYZOul60It50VKjH9u0_8-Qwq4pFZvfoEsdbmUUuRGUpGuAuXLDzd36xL1bHmH6RnWd-d6Q/w640-h86/wsl_hardware_requirements.png" width="640" /></a></div><div><br /></div><div>While running Windows it is possible to check if hardware virtualization is enabled at the BIOS level. To check if this is enabled, launch Task Manager (Ctrl-Alt-Delete) and from Task Manager select the Performance blade:</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhy4b-4j_a3GlCcziCCXgbu5cSUMOTqj_vshLNuYKICHrvVFznGm7zL6PLfCLIYgnQEmZV5Dmxb84p3pAy0JqvcjbS97EQmV5t0Lde0N2QmtyZsuVtsQPmK0XFS5u5h2YJMPs3PqA6Tc_gOZWJid-dHnmG_j3iQXjwPk3p_B_bw8jt-FEhpA4neibJ53A/s2247/task_manager_virtualization_enabled.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1245" data-original-width="2247" height="354" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhy4b-4j_a3GlCcziCCXgbu5cSUMOTqj_vshLNuYKICHrvVFznGm7zL6PLfCLIYgnQEmZV5Dmxb84p3pAy0JqvcjbS97EQmV5t0Lde0N2QmtyZsuVtsQPmK0XFS5u5h2YJMPs3PqA6Tc_gOZWJid-dHnmG_j3iQXjwPk3p_B_bw8jt-FEhpA4neibJ53A/w640-h354/task_manager_virtualization_enabled.png" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: justify;">Notice in the lower right corner there is a box high added to the screenshot showing <b><i>Virtualization Enabled</i></b>.</div><div><br /></div>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com0tag:blogger.com,1999:blog-7655634577563139129.post-85946115417566034882023-06-07T16:10:00.000-07:002023-06-07T16:10:17.769-07:00PowerShell: Installing the latest version of Pester<p>Before installing the latest version of Pester, uninstall the legacy version of Pester (Pester 3.x) which is installed with most modern versions of Windows (see <a href="https://www.softwarepronto.com/2023/06/powershell-uninstalling-pester-30.html">PowerShell: Uninstalling Pester 3.0</a>). On a machine with PowerShell 5.0 or later install, the latest version of Pester can be installed as follows without running as administrator:</p><div style="text-align: left;"><span style="font-family: courier;">Install-Module -Name Pester</span></div><p>Once install verify that version of Pester is the most recent:</p><p><span style="background-color: white; color: #222222; font-family: courier; font-size: 13.2px;">(Get-Module -ListAvailable Pester).Version</span></p><p>An example of installing Pester is as follows (not that a user is prompted to accept the modules being installed):</p><p><span style="font-family: courier;">E:\Users\Jann\PowerShellRepos> Install-Module -Name Pester</span></p><p><span style="font-family: courier;">Untrusted repository</span></p><p><span style="font-family: courier;">You are installing the modules from an untrusted repository. If you trust this repository, change its InstallationPolicy value by running the Set-PSRepository</span></p><p><span style="font-family: courier;">cmdlet. Are you sure you want to install the modules from 'PSGallery'?</span></p><p><span style="font-family: courier;">[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): A</span></p><div><br /></div>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com0tag:blogger.com,1999:blog-7655634577563139129.post-50787221242571151432023-06-06T02:45:00.004-07:002024-02-25T16:13:30.390-08:00PowerShell: Uninstalling Pester 3.0<p>Microsoft by default installs an obsolete version of Pester on Windows (Pester 3.x). For example on one of my machines (Windows 11) the version of Pester installed is 3.4.0 (2016 Pester). In fact, Pester 3.4.0 is installed for x64 and x86 (32-bit) versions of PowerShell. To uninstall Pester 3.4.0 means that the x64 and x86 installs have to be uninstalled.</p><h2 style="text-align: left;">Detecting the Available Versions of Pester Installed</h2><p>The following PowerShell displays available versions of Pester installed:</p><div style="text-align: left;"><span style="font-family: courier;">(Get-Module -ListAvailable Pester).Version</span></div><p>The default version of Pester installed on my Windows 11 host is as follows:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-_NowtRss7-znaOeJBxZ-1ySyk9Haenbj5bwTmxJLVxfLTsB2QGJ7IU3qKB3WoPalVXDCokbL-KSRPDaxyn0tA-fWh3nPGP8gos0cn9KGyzjXS-eJz_DUs1Jwm8Sf9ShqgEObfy8-zgrUciGw0Q2-3A2N5GkvcHoeEUlaAOzOb_nLDLq6mRliHb0/s1425/Pester3_4.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="272" data-original-width="1425" height="122" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg-_NowtRss7-znaOeJBxZ-1ySyk9Haenbj5bwTmxJLVxfLTsB2QGJ7IU3qKB3WoPalVXDCokbL-KSRPDaxyn0tA-fWh3nPGP8gos0cn9KGyzjXS-eJz_DUs1Jwm8Sf9ShqgEObfy8-zgrUciGw0Q2-3A2N5GkvcHoeEUlaAOzOb_nLDLq6mRliHb0/w640-h122/Pester3_4.png" width="640" /></a></div><br /><h2>Uninstalling Pester 3.x</h2><div>The problem with Pester 3.x is that it installed as part the O.S. and it cannot be uninstalled with Uninstall-Module (this won't work: Uninstall-Module -Name Pester). The following script will understand all 3.x versions of Pester on a machine:</div><div><br /></div><div><div><span style="font-family: courier;">#Requires -RunAsAdministrator</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;">function Uninstall-PesterInstance {</span></div><div><span style="font-family: courier;"> param(</span></div><div><span style="font-family: courier;"> [Parameter(mandatory=$true)]</span></div><div><span style="font-family: courier;"> [string] $pesterFolderPath</span></div><div><span style="font-family: courier;"> ) </span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;"> takeown /F $pesterFolderPath /A /R</span></div><div><span style="font-family: courier;"> icacls $pesterFolderPath /reset</span></div><div><span style="font-family: courier;"> # Grant permissions to group, Administrators, via SID.</span></div><div><span style="font-family: courier;"> # This handles localiztion on non-U.S. Windows installations</span></div><div><span style="font-family: courier;"> icacls $pesterFolderPath /grant "*S-1-5-32-544:F" /inheritance:d /T</span></div><div><span style="font-family: courier;"> Remove-Item -Path $pesterFolderPath -Recurse -Force -Confirm:$false </span></div><div><span style="font-family: courier;">}</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;">[string] $bitness32ProgramFiles = ${env:ProgramFiles(x86)}</span></div><div><span style="font-family: courier;">[string] $bitness64ProgramFiles = $env:ProgramFiles</span></div><div><span style="font-family: courier;">[string[]] $programFilePaths = $bitness32ProgramFiles, $bitness64ProgramFiles</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;">foreach ($programFilePath in $programFilePaths) {</span></div><div><span style="font-family: courier;"> [string] $pester3xFolderPath = "$programFilePath\WindowsPowerShell\Modules\Pester"</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;"> if (Test-Path -Path $pester3xFolderPath -PathType Container) { </span></div><div><span style="font-family: courier;"> [System.IO.DirectoryInfo[]] $pesterDirectories =</span></div><div><span style="font-family: courier;"> Get-ChildItem -Path $pester3xFolderPath -Filter '3.*'</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;"> foreach ($pesterDirectory in $pesterDirectories) {</span></div><div><span style="font-family: courier;"> Uninstall-PesterInstance $pesterDirectory.FullName</span></div><div><span style="font-family: courier;"> }</span></div><div><span style="font-family: courier;"> }</span></div><div><span style="font-family: courier;">}</span></div></div><div><br /></div><div>The first line of the above script uses "#Requires -RunAsAdministrator" to mandate the script runs with administrator credentials. Pester 3.x is installed for Windows and can only be uninstalled by an administrator (see <a href="https://www.softwarepronto.com/2023/06/powershell-requiring-script-to-run-as.html">PowerShell: Requiring a Script to Run as Administrator</a>).</div><div><br /></div><div>The code above is broken into a loop the iterate through all Pester 3.x version found in program files targeting x86 and x64 bit PowerShell:</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJm-7P_gEcEXgJoa0m2hjuoSAn_uHO6gvoHa-uaxscVRGATdJScLkq2pV4jjyaPKHxGXC1sDhnO5S0Cgtk9WFgmJL1FvU0QVLUz5RCu-QtUUtSZ0lhfLmkxwUxvEFHqFBAxZJYPHxELrKDZAoCcPKbBI2i7dgHCgrdmLCq6B0wxjYa8L6WCkKE_5Q/s2155/FindAllPester3_xInstances.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="730" data-original-width="2155" height="216" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJm-7P_gEcEXgJoa0m2hjuoSAn_uHO6gvoHa-uaxscVRGATdJScLkq2pV4jjyaPKHxGXC1sDhnO5S0Cgtk9WFgmJL1FvU0QVLUz5RCu-QtUUtSZ0lhfLmkxwUxvEFHqFBAxZJYPHxELrKDZAoCcPKbBI2i7dgHCgrdmLCq6B0wxjYa8L6WCkKE_5Q/w640-h216/FindAllPester3_xInstances.png" width="640" /></a></div><br /><div><br /></div><div>For each instance of Pester 3.x install the Uninstall-PesterIntance method is invoked to physically delete the Pester 3.x folders recursively:</div><div><br /></div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEga5cIxJPPNVWK5oAEz562GqZ_kXhI8gL6Xj5zOo3zhw7qacOwJaJwgxF7sKpx6pj_RdQLv70pte1XzIwyVa5Jn9MF5uReyBjYRqm-OUXoUfFtcO-Nj40GMLk5zBpQhrKNcZi5UlJW8fgxs8HBW1b-gJvMjlmgZTUdK_Smon0dpr0BgVmq_Hmk34us/s1405/UninstallPesterInstance.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="630" data-original-width="1405" height="286" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEga5cIxJPPNVWK5oAEz562GqZ_kXhI8gL6Xj5zOo3zhw7qacOwJaJwgxF7sKpx6pj_RdQLv70pte1XzIwyVa5Jn9MF5uReyBjYRqm-OUXoUfFtcO-Nj40GMLk5zBpQhrKNcZi5UlJW8fgxs8HBW1b-gJvMjlmgZTUdK_Smon0dpr0BgVmq_Hmk34us/w640-h286/UninstallPesterInstance.png" width="640" /></a></div><br /><p><br /></p><p><br /></p>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com1tag:blogger.com,1999:blog-7655634577563139129.post-41607667977609625732023-06-05T19:37:00.001-07:002023-06-05T19:37:26.452-07:00PowerShell: Requiring a Script to Run as Administrator<p>Placing the following at the top of a PowerShell script requires that said script to run as administrator:</p><p><span style="font-family: courier;">#Requires -RunAsAdministrator</span></p><div>For example, Pester 3.x is installed with modern versions of Windows and only an administrator can uninstall this O.S. integrated version of Pester hence "#Requires -RunAsAdministrator" comes in handy.</div><div><br /></div><div>The #Requires statement is documented by Microsoft at <a href="https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_requires?view=powershell-7.3">about_Requires</a> and the comprehensive overview of #Requires provided by Microsoft's documentation is as follows:</div><div><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSC_d3sVzomnFiRA-CCIfEIKT5y_YVIGJUjwT3Gd7QNbQA-DVOafOOmxMQK-hqsYA95Cop3SwYX79hKv9OUqIOsxgIsMB2jNFTo-Rcqlhgh-nKhKeFe58fgdufRsxx47b8LqG88Q_gEoEVp1msgzXJTAE9Hd-VIWRAy2DIK9Tm9V_r0FuMf2LlHTw/s1832/requires_overview.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="795" data-original-width="1832" height="278" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSC_d3sVzomnFiRA-CCIfEIKT5y_YVIGJUjwT3Gd7QNbQA-DVOafOOmxMQK-hqsYA95Cop3SwYX79hKv9OUqIOsxgIsMB2jNFTo-Rcqlhgh-nKhKeFe58fgdufRsxx47b8LqG88Q_gEoEVp1msgzXJTAE9Hd-VIWRAy2DIK9Tm9V_r0FuMf2LlHTw/w640-h278/requires_overview.png" width="640" /></a></div><br /><div><br /></div><div><br /></div><div><br /></div><div><br /></div>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com0tag:blogger.com,1999:blog-7655634577563139129.post-67579656314205976872023-05-28T02:23:00.003-07:002023-05-28T02:23:26.195-07:00PowerShell: StringBuild AppendLine lessons from C<p>Two years ago I wrote a post, <a href="https://www.softwarepronto.com/2020/10/powershell-inadvertently-returning.html">PowerShell: Inadvertently Returning Multiple Values from a Function</a> and low and behold I found a found a common C# data type that is a common culprit of this issue, StringBuilder. I have coded C# for twenty-tree years and I did not realize the each Append* method of StringBuilder returns a reference to the StringBuilder.</p><p>To demonstrate consider this C# snippet:</p><div style="text-align: left;"><div><span style="font-family: courier;">var builder = new StringBuilder();</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;">builder.AppendLine("Environment Properties:");</span></div><div><span style="font-family: courier;">builder.AppendLine($"MachineName: {Environment.MachineName}");</span></div><div><span style="font-family: courier;">builder.AppendLine($"UserName: {Environment.UserName}");</span></div><div><span style="font-family: courier;">builder.AppendLine($"UserDomainName: {Environment.UserDomainName}");</span></div><div><span style="font-family: courier;">builder.AppendLine($"OSVersion: {Environment.OSVersion}");</span></div><div><span style="font-family: courier;">builder.AppendLine($"ProcessorCount: {Environment.ProcessorCount}");</span></div><div><span style="font-family: courier;">builder.AppendLine(</span></div><div><span style="font-family: courier;"> $"Is64BitOperatingSystem: {Environment.Is64BitOperatingSystem}");</span></div><div><span style="font-family: courier;">builder.AppendLine(</span></div><div><span style="font-family: courier;"> $"SystemDirectory: {Environment.SystemDirectory}");</span></div><div><span style="font-family: courier;">builder.AppendLine($"CurrentDirectory: {Environment.CurrentDirectory}");</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;">Console.Write(builder.ToString());</span></div><div><br /></div></div><p>In the documentation for the AppendLine method, <a href="https://learn.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.appendline?view=net-7.0#system-text-stringbuilder-appendline(system-string)">AppendLine(String)</a>, the return value of AppendLine and each Append* method of StringBuilder is defined as follows:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgY2L2CHt_4ZIAL5OPex0gZzdtudarS3AEDGAR0ZrdaW21mLc9SORJfwu7CEDMnCr-3t-MdmFrQ3LcsDFeKqAId3sUBgOfx3mEun9WACAVzrcWQ0XZfNHisLgkElcN28rQ_GIJ7P9ePQQ5xZGYV9ODwICWzjgwVjvW2mPsK_bkMfleOS6H0a9T5QK4/s1780/StringBuilderReturnValue.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="265" data-original-width="1780" height="96" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgY2L2CHt_4ZIAL5OPex0gZzdtudarS3AEDGAR0ZrdaW21mLc9SORJfwu7CEDMnCr-3t-MdmFrQ3LcsDFeKqAId3sUBgOfx3mEun9WACAVzrcWQ0XZfNHisLgkElcN28rQ_GIJ7P9ePQQ5xZGYV9ODwICWzjgwVjvW2mPsK_bkMfleOS6H0a9T5QK4/w640-h96/StringBuilderReturnValue.png" width="640" /></a></div><br /><p>A clearer way to write the above code in C# would be acknowledge the return value and to ignore it:</p><div style="text-align: left;"><div><div><span style="font-family: courier;">var builder = new StringBuilder();</span></div><div><span style="font-family: courier;"><br /></span></div><div><div><span style="font-family: courier;">_ = builder.AppendLine("Environment Properties:");</span></div><div><span style="font-family: courier;">_ = builder.AppendLine($"MachineName: {Environment.MachineName}");</span></div><div><span style="font-family: courier;">_ = builder.AppendLine($"UserName: {Environment.UserName}");</span></div><div><span style="font-family: courier;">_ = builder.AppendLine(</span></div><div><span style="font-family: courier;"> $"UserDomainName: {Environment.UserDomainName}");</span></div><div><span style="font-family: courier;">_ = builder.AppendLine($"OSVersion: {Environment.OSVersion}");</span></div><div><span style="font-family: courier;">_ = builder.AppendLine(</span></div><div><span style="font-family: courier;"> $"ProcessorCount: {Environment.ProcessorCount}");</span></div><div><span style="font-family: courier;">_ = builder.AppendLine(</span></div><div><span style="font-family: courier;"> $"Is64BitOperatingSystem: {Environment.Is64BitOperatingSystem}");</span></div><div><span style="font-family: courier;">_ = builder.AppendLine(</span></div><div><span style="font-family: courier;"> $"SystemDirectory: {Environment.SystemDirectory}");</span></div><div><span style="font-family: courier;">_ = builder.AppendLine($"CurrentDirectory: {Environment.CurrentDirectory}");</span></div></div><div><br /></div><div><span style="font-family: courier;">Console.Write(builder.ToString());</span></div><div><br /></div></div></div><p>The following code shows PowerShell invoking AppendLine multiple times:</p><div style="text-align: left;"><div><span style="font-family: courier;">function Get-EnvironmentProperties {</span></div><div><span style="font-family: courier;"> [System.Text.StringBuilder] $builder = [System.Text.StringBuilder]::new()</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;"> $builder.AppendLine("Environment Properties:")</span></div><div><span style="font-family: courier;"> $builder.AppendLine("MachineName: " + [Environment]::MachineName)</span></div><div><span style="font-family: courier;"> $builder.AppendLine("UserName: " + [Environment]::UserName)</span></div><div><span style="font-family: courier;"> $builder.AppendLine("UserDomainName: " + [Environment]::UserDomainName)</span></div><div><span style="font-family: courier;"> $builder.AppendLine("OSVersion: " + [Environment]::OSVersion)</span></div><div><span style="font-family: courier;"> $builder.AppendLine("ProcessorCount: " + [Environment]::ProcessorCount)</span></div><div><span style="font-family: courier;"> $builder.AppendLine("Is64BitOperatingSystem: " + [Environment]::Is64BitOperatingSystem)</span></div><div><span style="font-family: courier;"> $builder.AppendLine("SystemDirectory: " + [Environment]::SystemDirectory)</span></div><div><span style="font-family: courier;"> $builder.AppendLine("CurrentDirectory: " + [Environment]::CurrentDirectory)</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;"> return $builder.ToString()</span></div><div><span style="font-family: courier;">}</span></div><div><br /></div><div><span style="font-family: courier;">$result = Get-EnvironmentProperties</span></div><div><br /></div></div><p>Although it appears that the PowerShell function, Get-EnvironmentProperties, returns a string. Result (the return value from Get-EnvironmentProperties) in an array of 10 elements:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg86rsW9GmlzA2q-aTaKQapjGbGHHEKlzMVUFRImUX2fjkHn6PlVNZETjYqoF8wGC7YU-uwIxtuCywlOG06IBQq9vxMYzpCJsDFZNTghL9C7FKucPGMArs1NPyp48Q8y4D7aZ-B3cDMW3zlv8Qm0usMvilAEjh3i1tYjO4z45oPcX_Y1O3QOt7LJSM/s1295/REsultLength10.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="352" data-original-width="1295" height="174" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg86rsW9GmlzA2q-aTaKQapjGbGHHEKlzMVUFRImUX2fjkHn6PlVNZETjYqoF8wGC7YU-uwIxtuCywlOG06IBQq9vxMYzpCJsDFZNTghL9C7FKucPGMArs1NPyp48Q8y4D7aZ-B3cDMW3zlv8Qm0usMvilAEjh3i1tYjO4z45oPcX_Y1O3QOt7LJSM/w640-h174/REsultLength10.png" width="640" /></a></div><br /><p>The method AppendLine is invoked nine times so the first nine elements of the array. The tenth element of the array (index of 9) is the string return in the last line of function, Get-EnvironmentProperties.</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFHkPjmKKfMvpi8-5rhtwmuCixC3pNFT5fNE4T3uJmQRIBIPbcDzXhJWDCOQ8wncDWoHMYOhlejxutPcKvY76uUYfKZMW0Cw148IDirTRKPQs7Dt0wfkIWdmDqVmh0m_JxutC3NjiuBTT3QFl9VwzaV62W8_RjYjOC1Pmz-cCDQ5hu-Mo5LY06pao/s882/thestring.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="465" data-original-width="882" height="211" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjFHkPjmKKfMvpi8-5rhtwmuCixC3pNFT5fNE4T3uJmQRIBIPbcDzXhJWDCOQ8wncDWoHMYOhlejxutPcKvY76uUYfKZMW0Cw148IDirTRKPQs7Dt0wfkIWdmDqVmh0m_JxutC3NjiuBTT3QFl9VwzaV62W8_RjYjOC1Pmz-cCDQ5hu-Mo5LY06pao/w400-h211/thestring.png" width="400" /></a></div><br /><div style="text-align: left;">Below show a variant of the EnvironmentProperties function suppresses the return value from StringBuilder's AppendLine:</div><div style="text-align: left;"><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;">function Get-EnvironmentProperties {</span></div><div><span style="font-family: courier;"> [System.Text.StringBuilder] $builder = `</span></div><div><span style="font-family: courier;"> [System.Text.StringBuilder]::new()</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;"> $builder.AppendLine("Environment Properties:") | Out-Null</span></div><div><span style="font-family: courier;"> [void]$builder.AppendLine("MachineName: " + </span></div><div><span style="font-family: courier;"> [Environment]::MachineName)</span></div><div><span style="font-family: courier;"> $builder.AppendLine("UserName: " + </span></div><div><span style="font-family: courier;"> [Environment]::UserName) > $null</span></div><div><span style="font-family: courier;"> $null = $builder.AppendLine("UserDomainName: " + </span></div><div><span style="font-family: courier;"> [Environment]::UserDomainName)</span></div><div><span style="font-family: courier;"><br /></span></div><div><span style="font-family: courier;"> return $builder.ToString()</span></div><div><span style="font-family: courier;">}</span></div></div><p>Suppressing the StringBuilder returned by AppendLine results in the the correct behavior, the lone return value is as string as is show below:</p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZB7ihu73p8MfSVwwkky5CzAsquwVgyJP-tn7iH0ouska0zLQRB57ExxXT8V6iUBBS4GOSN8c1BgSRlfdpnjatiBYwy1w_X8WuOUCzjC0B3_Zm4636RzZBAa93optZ-7l5sibH0QDVnIMzqFPAG0WvydHl-lMVFEGgLR3eYWkWfkVnPjtIbs8mJkQ/s1295/REsultIsString.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="485" data-original-width="1295" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiZB7ihu73p8MfSVwwkky5CzAsquwVgyJP-tn7iH0ouska0zLQRB57ExxXT8V6iUBBS4GOSN8c1BgSRlfdpnjatiBYwy1w_X8WuOUCzjC0B3_Zm4636RzZBAa93optZ-7l5sibH0QDVnIMzqFPAG0WvydHl-lMVFEGgLR3eYWkWfkVnPjtIbs8mJkQ/w640-h240/REsultIsString.png" width="640" /></a></div><br /><p>A variety of mechanism were show to suppress return value of AppendLine. From the performance stand point, Out-Null is the slowest but from a readability stand point, it is the most readable for all levels of PowerShell developer.</p><p>In my code I used the following approach as I learned C as my first programming language:</p><div><span style="font-family: courier;"> [void]$builder.AppendLine("MachineName: " + </span></div><div><span style="font-family: courier;"> [Environment]::MachineName)</span></div><div><span style="font-family: courier;"><br /></span></div><p>With regard to performance and suppressing the result of a method/expression StackOverflow has an excellent post on the topic <a href="https://stackoverflow.com/questions/5260125/whats-the-better-cleaner-way-to-ignore-output-in-powershell">What's the better (cleaner) way to ignore output in PowerShell?</a> A response by JasonMArcher demonstrates and Out-Null has the worst performance.</p><p><br /></p><p><br /></p>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com0tag:blogger.com,1999:blog-7655634577563139129.post-56135913549457029062023-05-08T03:32:00.000-07:002023-05-08T03:32:32.730-07:00Visual Studio Code: Disable Format on Save per-File (including wildcards)<p>In this post, we'll explore how to disable the formatOnSave option for specific files, multiple files, using wild cards, and files with certain extensions.</p><p><br /></p><h2 style="text-align: left;">Disabling formatOnSave for a specific file</h2><p>To disable formatOnSave for a specific file, you can add the following setting to your settings.json file:</p><div style="text-align: left;"><span style="font-family: courier;">"[<b>file path/filename.ext</b>]": {<br /> "editor.formatOnSave": false<br />}</span></div><p>Replace file path/filename.ext (noted in boldface) with the path and filename of the file for which you want to disable formatOnSave.</p><p><br /></p><h2 style="text-align: left;">Disabling formatOnSave for multiple files</h2><p>To disable formatOnSave for multiple files, you can add the following setting to your settings.json file:</p><div style="text-align: left;"><span style="font-family: courier;">"editor.formatOnSave": true,<br />"[<b>file path/filename1.ext</b>]": {<br /> "editor.formatOnSave": false<br />},<br />"[<b>file path/filename2.ext</b>]": {<br /> "editor.formatOnSave": false<br />}</span></div><p>Replace file path/filename1.ext and file path/filename2.ext (noted in boldface) with the path and filenames of the files for which you want to disable formatOnSave.</p><p><br /></p><h2 style="text-align: left;">Disabling formatOnSave using wildcards</h2><p>You can also disable formatOnSave for files that match a specific pattern using wildcards. For example, to disable formatOnSave for files that have a specific prefix, you can add the following setting to your settings.json file:</p><div style="text-align: left;"><span style="font-family: courier;">"editor.formatOnSave": true,<br />"<b>[prefix]*.ext</b>": {<br /> "editor.formatOnSave": false<br />}</span></div><p>Replace prefix (noted in boldface) with the desired prefix for the files you want to exclude from formatOnSave.</p><p>Similarly, to disable formatOnSave for files that have multiple possible extensions, you can use a wildcard to match the extensions. For example:</p><div style="text-align: left;"><span style="font-family: courier;">"editor.formatOnSave": true,<br />"[<b>file path/*.ext1, *.ext2</b>]": {<br /> "editor.formatOnSave": false<br />}</span></div><p>Replace file path with the path to the directory containing the files you want to exclude from formatOnSave. Replace ext1 and ext2 with the extensions of the files you want to exclude from formatOnSave.</p><h2 style="text-align: left;">Conclusion</h2><p>And that's it! With these settings, you can easily disable the formatOnSave option for specific files, multiple files, or using wildcards.</p>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com0tag:blogger.com,1999:blog-7655634577563139129.post-19129798830404867502023-05-07T06:55:00.008-07:002023-05-07T07:26:44.000-07:00Visual Studio Code: Disable Format on Save (settings.json: formatOnSave=true) per-File-ExtensionI worked with two good engineers who loved auto format code (PowerShell) using Visual Studio Code's settings.json attribute. So I asked ChatGPT how to ignore the formatOnSave feature (trying out ChatGPT). Here is how to ignore Visual Studio Code's formatOnSave for a specific file extension. The steps to achieve presented.<div><br /></div><div><div>If you want to exclude specific file types from being formatted on save, you need to configure Visual Studio Code to ignore those file extensions.</div><div><br /></div><h2 style="text-align: left;">Step 1: Open the User Settings in VS Code</h2><div>To configure the Format on Save feature, you need to edit the user settings in VS Code. To do this, open the Command Palette by pressing Ctrl+Shift+P (Windows) or Command+Shift+P (macOS), and type "Open User Settings". You should see "Preferences: Open User Settings" in the list of suggestions. Select it, and the settings.json file will open.</div><div><br /></div><h2 style="text-align: left;">Step 2: Add the File Extensions to Ignore</h2><div>In the settings.json file, you need to add the file extensions you want to exclude from the Format on Save feature. To do this, add the following code snippet:</div><div><br /></div><div><span style="font-family: courier;">"editor.formatOnSave": true,</span></div><div><span style="font-family: courier;"><b>"[md]": {</b></span></div><div><span style="font-family: courier;"><b> "editor.formatOnSave": false</b></span></div><div><span style="font-family: courier;"><b>}</b></span></div><div><br /></div><div>The code in boldface was added to the standard settings.json to ignore Markdown files. In this example, we're telling VS Code to enable the Format on Save feature globally ("editor.formatOnSave": true) and then disabling it for Markdown files ("[md]": {"editor.formatOnSave": false}).</div><div><br /></div><h2 style="text-align: left;">Step 3: Save the User Settings</h2><div>Once you've added the code snippet to the settings.json file, save the file, and you're done. The Format on Save feature will now be disabled for the file extension specified (the markdown extension, md).</div><div><br /></div><h2 style="text-align: left;">Conclusion</h2><div>In this blog post, we've seen how to configure Visual Studio Code to ignore specific file extensions when using the Format on Save feature. This can be useful if you want to exclude certain files from being automatically formatted when you save them. With just a few simple steps, you can customize this feature to suit your coding needs. <br /></div></div><div><br /></div><div><h2 style="text-align: left;">Acknowledgments</h2></div><div>I'd like to thank my high school typing teacher, Miss Joyce. I took one year of secretarial typing (on an IBM Selectric) and I type 120 WPM. I would like to think my mother for giving me the ability to write which I inherited from her. I would like that thank ChatGPT which wrote most of this blog. This is an experiment but ChatGPT is scary useful.</div><div><br /></div>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com0tag:blogger.com,1999:blog-7655634577563139129.post-65023985478565504222023-05-07T06:04:00.003-07:002023-05-07T06:09:21.165-07:00ChatGPT (writing PowerShell example) Will Replace Most of My Searches Targeting StackOverflow.com and Microsoft.com<h2 style="text-align: left;"><span face="Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"" style="background-color: #f7f7f8; color: #374151; font-size: 16px; white-space: pre-wrap;">The Old Way of Technical Search</span></h2><div><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; background-color: #f7f7f8; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; margin: 1.25em 0px; white-space: pre-wrap;">The modus operandi I use for most of my software-development-related research is to:</p><ol style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; background-color: #f7f7f8; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: #374151; counter-reset: item 0; display: flex; flex-direction: column; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; list-style-image: initial; list-style-position: initial; margin: 1.25em 0px; padding: 0px 0px 0px 1rem; white-space: pre-wrap;"><li style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; margin: 0px; padding-left: 0.375em;"><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; margin: 0px;">Search using Google (yes, I prefer the results to Bing).</p></li><li style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; margin: 0px; padding-left: 0.375em;"><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; margin: 0px;">Search with keywords and typically target the site that will give me the best results using Google site keyword such as:</p><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; margin: 0px;">2.1 Find the man page for PowerShell's Invoke-RestMethod cmdlet: <code style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: var(--tw-prose-code); font-family: "Söhne Mono", Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-size: 0.875em; font-weight: 600;">Invoke-RestMethod site:microsoft.com</code>. Note above the <code style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: var(--tw-prose-code); font-family: "Söhne Mono", Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-size: 0.875em; font-weight: 600;">site:</code> refers to microsoft.com.</p><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; margin: 0px;">2.2 How to use PowerShell's Where-Object to select a value in an array of arrays: <code style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: var(--tw-prose-code); font-family: "Söhne Mono", Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-size: 0.875em; font-weight: 600;">filter array of string arrays PowerShell Where-Object site:stackoverflow.com</code>. Note above the <code style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: var(--tw-prose-code); font-family: "Söhne Mono", Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-size: 0.875em; font-weight: 600;">site:</code> refers to stackoverflow.com.</p></li><li style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; margin: 0px; padding-left: 0.375em;"><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; margin: 0px;">Read through and click on the results. For Stack Overflow (I have loved Stack Overflow for the last fifteen years), this is tedious because a lot of results need to be culled to find an answer to your question.</p></li></ol><h2 style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; background-color: #f7f7f8; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; margin: 1.25em 0px; text-align: left; white-space: pre-wrap;">ChatGPT: the New Way of Technical Search</h2><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; background-color: #f7f7f8; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; margin: 1.25em 0px; white-space: pre-wrap;">As an experiment, I asked ChatGPT to help me with a piece of code (yes, I could have written this code without searching) but it is complex code. Here are the instructions I gave ChatGPT:</p><ul style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; background-color: #f7f7f8; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; display: flex; flex-direction: column; list-style-image: initial; list-style-position: initial; margin: 1.25em 0px; padding: 0px 0px 0px 1rem; text-align: left;"><li><span face="Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"" style="background-color: #f7f7f8; color: #374151; font-size: 16px; white-space: pre-wrap;">I want to have a PowerShell array of type </span><code style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; background-color: #f7f7f8; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: var(--tw-prose-code); font-family: "Söhne Mono", Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-size: 0.875em; font-weight: 600; margin-top: 1.25em; white-space: pre-wrap;">[PSCustomObject[]]</code><span face="Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"" style="background-color: #f7f7f8; color: #374151; font-size: 16px; white-space: pre-wrap;"> and each element of the array is type </span><code style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; background-color: #f7f7f8; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: var(--tw-prose-code); font-family: "Söhne Mono", Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-size: 0.875em; font-weight: 600; margin-bottom: 1.25em; white-space: pre-wrap;">[PSCustomObject[]]</code><span face="Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"" style="background-color: #f7f7f8; color: #374151; font-size: 16px; white-space: pre-wrap;">. I want to select all values where index 4 equals 'monkey'.</span></li><li>I want to have a PowerShell array of type <code style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: var(--tw-prose-code); font-family: "Söhne Mono", Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-size: 0.875em; font-weight: 600; margin-top: 1.25em; white-space: pre-wrap;">[PSCustomObject[]]</code><span face="Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"" style="color: #374151; font-size: 16px; white-space: pre-wrap;"> and each element of the array is type </span><code style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: var(--tw-prose-code); font-family: "Söhne Mono", Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-size: 0.875em; font-weight: 600; margin-bottom: 1.25em; white-space: pre-wrap;">[string[]]</code><span face="Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"" style="color: #374151; font-size: 16px; white-space: pre-wrap;">. I want to select all values where index 4 equals 'monkey'.</span></li><li style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: #374151; display: block; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; margin: 0px; padding-left: 0.375em; position: relative; white-space: pre-wrap;"><code style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: var(--tw-prose-code); font-family: "Söhne Mono", Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-size: 0.875em; font-weight: 600; margin-bottom: 1.25em; margin-top: 1.25em;">[string[]] $a = 'x', 'y', 'z'; [string[]] $b = 'e', 'f', 'g'; [string[]] $c = 'q', 'r', 's'; [PSCustomObject[]] $a, $b, $c</code>. Select all values where array index 1 equals 'f'.</li><li style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: #374151; display: block; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; margin: 0px; padding-left: 0.375em; position: relative; white-space: pre-wrap;"><code style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: var(--tw-prose-code); font-family: "Söhne Mono", Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-size: 0.875em; font-weight: 600; margin-top: 1.25em;">enum SegmentIndexes { Region Subregion State }</code>. Select index <code style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: var(--tw-prose-code); font-family: "Söhne Mono", Monaco, "Andale Mono", "Ubuntu Mono", monospace; font-size: 0.875em; font-weight: 600; margin-bottom: 1.25em;">[SegmentIndexes]::Region</code> equals 'f'.</li><li style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: #374151; display: block; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; margin: 0px; padding-left: 0.375em; position: relative; white-space: pre-wrap;"><br /></li><li><span face="Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"" style="background-color: #f7f7f8; color: #374151; font-size: 16px; white-space: pre-wrap;">Use the array from the previous example. I am not interested in an array of enumerations.</span></li><li><span face="Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"" style="background-color: #f7f7f8; color: #374151; font-size: 16px; white-space: pre-wrap;">Use the array before that.</span></li><li>Rewrite the code with no comments and please put the type in front of the declared variables</li><li></li><li>I did not ask you return $filterArray so the last line is not needed</li><li></li><li>Do not use a ; when populating the hashtable</li><li></li><li>You are incorrect. The ; are still used in the hashtable</li></ul><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; background-color: #f7f7f8; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; margin: 1.25em 0px; white-space: pre-wrap;">Here is the code ChatGPT generated which is correct:</p><div style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; background-color: #f7f7f8; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; margin: 1.25em 0px; text-align: left;"><span style="color: #374151; font-family: courier;"><span style="white-space: pre-wrap;">enum SegmentIndexes {
Region
Subregion
State
}
[PSCustomObject[]]$array = @(
@{
'EmptySlot' = 'x'
'Region' = 'f'
'Division' = 'a'
}
@{
'EmptySlot' = 'y'
'Region' = 'g'
'Division' = 'b'
}
@{
'EmptySlot' = 'z'
'Region' = 'h'
'Division' = 'c'
}
)
$filteredArray = $array | Where-Object { $_[[SegmentIndexes]::Region] -eq 'f' }
</span></span></div><h2 style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; background-color: #f7f7f8; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; margin: 1.25em 0px; text-align: left; white-space: pre-wrap;">Apology</h2><p style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; background-color: #f7f7f8; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; margin: 1.25em 0px; white-space: pre-wrap;">Over the past few years, one of the best people I've worked with is Stephen Durant of Stack Overflow. He is a customer liaison to corporate users of Stack Overflow. I do not normally praise someone for doing their job, but Stephen is really elite at his work. So, Stephen, I apologize because ChatGPT has filled many more of my needs related to technical search.</p><h2 style="--tw-border-spacing-x: 0; --tw-border-spacing-y: 0; --tw-ring-color: rgba(59,130,246,0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; background-color: #f7f7f8; border: 0px solid rgb(217, 217, 227); box-sizing: border-box; color: #374151; font-family: Söhne, ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Ubuntu, Cantarell, "Noto Sans", sans-serif, "Helvetica Neue", Arial, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; font-size: 16px; margin: 1.25em 0px; white-space: pre-wrap;">Acknowledgments</h2></div><div>This blog was proofed by ChatGPT.</div><div><br /></div>Jan Narkiewiczhttp://www.blogger.com/profile/02140947228848985353noreply@blogger.com0