<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: uyriq</title>
    <description>The latest articles on DEV Community by uyriq (@uyriq).</description>
    <link>https://dev.to/uyriq</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1182693%2Fdf5461bd-926e-49c7-b600-537e4e11e719.jpeg</url>
      <title>DEV Community: uyriq</title>
      <link>https://dev.to/uyriq</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/uyriq"/>
    <language>en</language>
    <item>
      <title>A step-by-step guide to setting up SSH authentication with YubiKey 5.7 or later version and ED25519-SK keys on Windows 11.</title>
      <dc:creator>uyriq</dc:creator>
      <pubDate>Tue, 04 Mar 2025 19:58:15 +0000</pubDate>
      <link>https://dev.to/uyriq/a-step-by-step-guide-to-setting-up-ssh-authentication-with-yubikey-57-or-later-version-and-2ll9</link>
      <guid>https://dev.to/uyriq/a-step-by-step-guide-to-setting-up-ssh-authentication-with-yubikey-57-or-later-version-and-2ll9</guid>
      <description>&lt;p&gt;Here is the corrected version of your post with grammar, spelling, and clarity improvements:&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting Up YubiKey for SSH on Windows 11
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;A YubiKey 5.7 (or later) security key with a user PIN activated for FIDO2 functionality
&lt;/li&gt;
&lt;li&gt;Git installed and a GitHub repository
&lt;/li&gt;
&lt;li&gt;GitHub CLI tool (&lt;code&gt;gh&lt;/code&gt;)
&lt;/li&gt;
&lt;li&gt;Administrator rights for &lt;code&gt;ykman&lt;/code&gt; operations
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 1: Install YubiKey CLI and GUI Tools, Set PIN for FIDO
&lt;/h3&gt;

&lt;p&gt;YubiKey offers two management tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;winget&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Yubico.YubiKeyManagerCLI&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# Deprecated Windows app&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;winget&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Yubico.YubikeyManager&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c"&gt;# Modern CLI tool: ykman&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the following command in an administrative terminal to set or change your PIN:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;ykman&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fido&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;access&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;change-pin&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, you can set the PIN using the YubiKey Manager GUI.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Configure GPG Agent for SSH Support
&lt;/h3&gt;

&lt;p&gt;Locate and edit (or create if missing) the following configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;AppData&lt;/span&gt;&lt;span class="n"&gt;\Roaming\gnupg\gpg-agent.conf&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, it may be under the &lt;code&gt;.gnupg&lt;/code&gt; directory. Add or update the file with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="c"&gt;# Enable SSH support through GPG agent
&lt;/span&gt;&lt;span class="err"&gt;enable-ssh-support&lt;/span&gt;
&lt;span class="err"&gt;enable-win32-openssh-support&lt;/span&gt;
&lt;span class="err"&gt;enable-putty-support&lt;/span&gt;

&lt;span class="c"&gt;# Cache settings
&lt;/span&gt;&lt;span class="err"&gt;default-cache-ttl&lt;/span&gt; &lt;span class="err"&gt;600&lt;/span&gt;
&lt;span class="err"&gt;max-cache-ttl&lt;/span&gt; &lt;span class="err"&gt;7200&lt;/span&gt;
&lt;span class="err"&gt;default-cache-ttl-ssh&lt;/span&gt; &lt;span class="err"&gt;1800&lt;/span&gt;
&lt;span class="err"&gt;max-cache-ttl-ssh&lt;/span&gt; &lt;span class="err"&gt;7200&lt;/span&gt;

&lt;span class="c"&gt;# Use a standard socket for SSH control
&lt;/span&gt;&lt;span class="err"&gt;use-standard-socket&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Generate an ED25519-SK SSH Key
&lt;/h3&gt;

&lt;p&gt;Run the following command to generate an SSH key using the YubiKey:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;ssh-keygen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ed25519-sk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-O&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resident&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-O&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;verify-required&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-C&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Your Comment"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To generate multiple credentials on the same security key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;ssh-keygen&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ed25519-sk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-O&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;resident&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-O&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;application&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ssh:Description&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-C&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Your Comment"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;Description&lt;/code&gt; with a unique identifier, such as your email.  &lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Verify Credentials
&lt;/h3&gt;

&lt;p&gt;Run the following command in an elevated terminal to check stored credentials:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;ykman&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fido&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;credentials&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Enter your PIN:
Credential ID   RP ID   Username  Display name
50f...         ssh:    openssh   openssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensure that your SSH public key is added to your GitHub account for code signing and, optionally, for authentication.&lt;br&gt;&lt;br&gt;
&lt;a href="https://docs.github.com/en/enterprise-server@3.12/authentication/connecting-to-github-with-ssh/adding-a-new-ssh-key-to-your-github-account?tool=cli" rel="noopener noreferrer"&gt;GitHub documentation&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;gh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ssh-key&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;~/.ssh/ed25519-sk.pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--title&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Key linked to YubiKey"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;signing&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;gh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ssh-key&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;~/.ssh/ed25519-sk.pub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--title&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Key linked to YubiKey"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;authentication&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: Test SSH Authentication
&lt;/h3&gt;

&lt;p&gt;Test your SSH connection to GitHub if the key has the authentication option:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;ssh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:\Users\User\.ssh\id_ed25519_sk"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-T&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;git&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;github.com&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Confirm user presence for key ED25519-SK
SHA256:J...
User presence confirmed
Hi username! You've successfully authenticated, but GitHub does not provide shell access.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 6: Configure Git for Signed Commits
&lt;/h3&gt;

&lt;p&gt;Set up your repository for commit signing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;user.name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your_username"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;user.email&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your_username@users.noreply.github.com"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;commit.gpgsign&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;gpg.format&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ssh&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;user.signingkey&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:/Users/Username/.ssh/id_ed25519_sk"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 7: Update SSH Config File
&lt;/h3&gt;

&lt;p&gt;Edit &lt;code&gt;~/.ssh/config&lt;/code&gt; to streamline authentication. I recommend adding your key after your primary key to avoid frequent authorization prompts during &lt;code&gt;git fetch&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ini"&gt;&lt;code&gt;&lt;span class="err"&gt;Host&lt;/span&gt; &lt;span class="err"&gt;github.com&lt;/span&gt;
    &lt;span class="err"&gt;User&lt;/span&gt; &lt;span class="err"&gt;git&lt;/span&gt;
    &lt;span class="err"&gt;Port&lt;/span&gt; &lt;span class="err"&gt;22&lt;/span&gt;
    &lt;span class="err"&gt;IdentitiesOnly&lt;/span&gt; &lt;span class="err"&gt;yes&lt;/span&gt;
    &lt;span class="err"&gt;PreferredAuthentications&lt;/span&gt; &lt;span class="err"&gt;publickey&lt;/span&gt;
    &lt;span class="err"&gt;PasswordAuthentication&lt;/span&gt; &lt;span class="err"&gt;no&lt;/span&gt;
    &lt;span class="err"&gt;IdentityFile&lt;/span&gt; &lt;span class="err"&gt;~/.ssh/id_ed25519.home&lt;/span&gt; &lt;span class="c"&gt;# Primary key for Git operations
&lt;/span&gt;    &lt;span class="err"&gt;IdentityFile&lt;/span&gt; &lt;span class="err"&gt;~/.ssh/id_ed25519_sk&lt;/span&gt; &lt;span class="c"&gt;# Additional key if added to GitHub as an authentication key
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 8: Verify Git Authentication
&lt;/h3&gt;

&lt;p&gt;Try pulling from your repository:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pull&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Confirm user presence for key ED25519-SK
SHA256:...
User presence confirmed
Already up to date.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will receive the same notification when committing changes.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Yubico/developers.yubico.com/blob/9e20e3b081ed863e5373d86a98eeba2198fb80a0/content/SSH/Securing_SSH_with_FIDO2.adoc#L4" rel="noopener noreferrer"&gt;Securing SSH with FIDO2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This guide ensures secure SSH authentication using YubiKey on Windows 🚀&lt;/p&gt;

</description>
      <category>yubikey</category>
      <category>ssh</category>
      <category>security</category>
      <category>github</category>
    </item>
    <item>
      <title>Streamline Your Winget Package Updates with PowerShell</title>
      <dc:creator>uyriq</dc:creator>
      <pubDate>Sun, 01 Dec 2024 16:49:22 +0000</pubDate>
      <link>https://dev.to/uyriq/streamline-your-winget-package-updates-with-powershell-1fie</link>
      <guid>https://dev.to/uyriq/streamline-your-winget-package-updates-with-powershell-1fie</guid>
      <description>&lt;p&gt;For me, updating packages using Winget is almost a daily operation. At least once a day, I type &lt;code&gt;winget update&lt;/code&gt; in the terminal to see what’s new for the already installed software. I don’t always update, but sometimes (about every other day), I manually copy and paste package IDs one by one. That’s how &lt;code&gt;wup&lt;/code&gt; was born—a PowerShell script that automates working with Winget and made my life easier (it took just two evenings to debug it).&lt;/p&gt;

&lt;h4&gt;
  
  
  About the Problem, More Formally
&lt;/h4&gt;

&lt;p&gt;Each time I need to update a bunch of packages using Winget, I create a line in the PowerShell session similar to this, which involves a lot of copying and pasting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;winget&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;package.id1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;winget&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;package.id2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;winget&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;package.idN&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpbytkuxeq5ouizw9tytd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpbytkuxeq5ouizw9tytd.png" alt="Description of the Image" width="800" height="179"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s not only tedious but also gets complicated because sometimes &lt;code&gt;--id&lt;/code&gt; doesn’t work as expected, as mentioned &lt;a href="https://github.com/microsoft/winget-cli/issues/4751" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Due to this, I need to use &lt;code&gt;--name&lt;/code&gt; instead of &lt;code&gt;--id&lt;/code&gt; for updating some packages like &lt;code&gt;pnpm&lt;/code&gt;. Such cases are not rare, and sometimes it's the opposite—you can't update by name but can by &lt;code&gt;--id&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Solution
&lt;/h4&gt;

&lt;p&gt;To solve this problem, I wrote a PowerShell script that lists all possible updates for installed packages when called without arguments, essentially just showing the result of &lt;code&gt;winget update&lt;/code&gt;. Then, you can call the script with an argument: it accepts a list of package IDs and updates the listed packages. Note: I still copy and paste the IDs of the desired packages. The copy-paste hasn’t disappeared 😅 ("HelpWanted, need a fzv feature!")&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F17lhqhu987517nth5ev2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F17lhqhu987517nth5ev2.png" alt="Description of the Image" width="800" height="51"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here’s a brief overview of the script:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;List All Updates: If the script is called without any arguments, it lists all possible updates for the installed packages.&lt;/li&gt;
&lt;li&gt;Update Specific Packages: If package IDs are provided as arguments, it updates only those specific packages.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  How to Use the Script
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Download the Script&lt;/strong&gt;: Get the script and its README from &lt;a href="https://gist.github.com/uyriq/daef5b7b3a1f6b3e169c3298812affcc" rel="noopener noreferrer"&gt;this gist&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Place the Script Anywhere&lt;/strong&gt;: Place the script in any directory of your choice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set Alias in $PROFILE&lt;/strong&gt;: Add an alias to your &lt;code&gt;$PROFILE&lt;/code&gt; for easy access.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Set-Alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;wup&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Path\To\Script.ps1"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you can simply run &lt;code&gt;wup&lt;/code&gt; in your PowerShell session to get the list of updates or provide specific package IDs for updating.&lt;/p&gt;




&lt;h4&gt;
  
  
  Notes
&lt;/h4&gt;

&lt;p&gt;The &lt;a href="https://gist.github.com/uyriq/daef5b7b3a1f6b3e169c3298812affcc" rel="noopener noreferrer"&gt;gist with the script&lt;/a&gt; contains a &lt;code&gt;Readme.md&lt;/code&gt; with additional PowerShell thoughts.&lt;/p&gt;

&lt;p&gt;If you have any questions or improvements, feel free to contribute!&lt;/p&gt;

&lt;p&gt;All code is licensed under the MIT License. Happy updating!&lt;/p&gt;




&lt;p&gt;By the way, did you hear about the scrambled [python, not pwsh] developer who couldn’t find his packages? He said, "I guess I’m just egg-sasperated!" 🥚&lt;/p&gt;

</description>
    </item>
    <item>
      <title>PowerShell Automation: Execute Batch GitHub CLI Commands</title>
      <dc:creator>uyriq</dc:creator>
      <pubDate>Sat, 02 Nov 2024 22:08:00 +0000</pubDate>
      <link>https://dev.to/uyriq/powershell-automation-execute-batch-github-cli-commands-3ha2</link>
      <guid>https://dev.to/uyriq/powershell-automation-execute-batch-github-cli-commands-3ha2</guid>
      <description>&lt;h2&gt;
  
  
  Automating Routine Tasks with a PowerShell Script
&lt;/h2&gt;

&lt;p&gt;Working with repositories on GitHub, especially when there are many of them, can be tiresome and time-consuming. When I needed to change the visibility of multiple repositories and manage access rights, I decided to create a cross-platform PowerShell script, batchrepoaction.ps1, which automates routine tasks and saves time and effort.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Idea Behind the Script
&lt;/h2&gt;

&lt;p&gt;The idea of writing the script came from the need to perform repetitive actions for multiple repositories. For example, changing the repository's visibility from public to private and vice versa, or adding a collaborator. These operations, if done manually through the GitHub interface, require several clicks, reading banners, and scrolling through pages. When there are dozens or even hundreds of such repositories, the task becomes tedious and time-consuming.&lt;/p&gt;

&lt;p&gt;In real life, people like HR managers are always interested in our public information and check our repositories. Our team leads request to add or remove access to repositories for our future or former developer colleagues. These situations also motivated me to create this script.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Script Does
&lt;/h2&gt;

&lt;p&gt;batchrepoaction.ps1 is written in PowerShell and can work both in PowerShell 5 on Windows "out of the box" and in PowerShell Core, which is available not only on Windows but also on Linux and macOS. The main idea of the script is to get a list of repositories and process them one by one by calling the GitHub CLI utility (gh). This allows executing any GitHub CLI command in the context of working with a repository.&lt;/p&gt;

&lt;p&gt;The user must be authorized in GitHub CLI and have the gh tool installed.&lt;/p&gt;

&lt;p&gt;The most important parameter of the script is -action. Here’s what I wrote in the help section:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;PARAMETER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;The&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;regular&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`g&lt;/span&gt;&lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="se"&gt;` &lt;/span&gt;&lt;span class="nx"&gt;CLI&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;execute&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e.g.&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gh repo edit --visibility private"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gh repo delete"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So, the idea is that the command for gh is passed in action, which will be executed for each repository from the list.&lt;/p&gt;

&lt;p&gt;Some gh commands can be quite long and depend on several parameters. Such commands cannot be passed in the current version of the script, so, for example, for getting a list of collaborators and adding a collaborator, I made my own shorthands instead of writing a syntax parser:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;list-collaborators&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;add-collaborator&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;delete-collaborator&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;which can be passed in action instead of their long equivalents.&lt;/p&gt;

&lt;p&gt;The other gh commands that support one argument are passed in their syntax, so my script is still a wrapper! Moreover, if the syntax of the commands changes a bit, as promised with the upcoming release of the gh repo edit command, it will not affect the functionality of the script, just a slightly different command will be executed for the list of repositories.&lt;/p&gt;

&lt;p&gt;It looks like I need to conclude the explanation of the script by providing usage examples step by step:&lt;/p&gt;

&lt;p&gt;Changing Repository Visibility&lt;/p&gt;

&lt;p&gt;First, get a list of your repositories and save it to a text file:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;\batchrepoaction.ps1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-action&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gh repo list"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-outputfile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;repofile.txt&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can now edit repofile.txt, leaving only the repositories needed for the operation.&lt;/p&gt;

&lt;p&gt;Run the command to change the visibility of all listed repositories:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;\batchrepoaction.ps1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-repofile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;repofile.txt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-action&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gh repo edit --visibility private"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;If the number of repositories to be processed is not so large, you can use the &lt;code&gt;-repolist&lt;/code&gt; parameter, listing the required repositories in quotes, separated by commas:&lt;/p&gt;

&lt;p&gt;powershell&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;\batchrepoaction.ps1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-repolist&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user/repo1,user/repo2"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-action&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gh repo edit --visibility private"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Adding a Collaborator to Several Repositories&lt;br&gt;
To add a collaborator to all repositories, use the command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;\batchrepoaction.ps1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`-&lt;/span&gt;&lt;span class="nx"&gt;repolist&lt;/span&gt;&lt;span class="se"&gt;` &lt;/span&gt;&lt;span class="s2"&gt;"user/repo1,user/repo2"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-collab_permission&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"push"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-collaborator&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"anygithubusername"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As they say in advertisements, emphasizing the meaning of the word "can", the batchrepoaction.ps1 script can simplify the management of multiple repositories on GitHub by automating routine tasks and allowing you to focus on more important aspects of development. I hope this script will be useful, saving your time and nerves.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



</description>
      <category>pwsh</category>
      <category>powershell</category>
      <category>github</category>
      <category>cli</category>
    </item>
    <item>
      <title>Ensuring Secure Connections: How the Get-VPNConnectionInfo Function Identifies VPN Usage</title>
      <dc:creator>uyriq</dc:creator>
      <pubDate>Sat, 15 Jun 2024 17:15:16 +0000</pubDate>
      <link>https://dev.to/uyriq/ensuring-secure-connections-how-the-get-vpnconnectioninfo-function-identifies-vpn-usage-1i47</link>
      <guid>https://dev.to/uyriq/ensuring-secure-connections-how-the-get-vpnconnectioninfo-function-identifies-vpn-usage-1i47</guid>
      <description>&lt;h1&gt;
  
  
  Get-VPNConnectionInfo
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;Get-VPNConnectionInfo&lt;/code&gt; function checks if the current internet connection is made through one of the known VPN providers. It fetches the current IP information from ipapi.co and compares the organization name (org field) against a predefined list of VPN providers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;PowerShell 5.1 or higher.&lt;/li&gt;
&lt;li&gt;An Internet connection to perform queries to &lt;code&gt;ipapi.co&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;knownVPNproviders.json&lt;/code&gt; file in the same directory as the script.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The format of the &lt;code&gt;knownVPNproviders.json&lt;/code&gt; file.
&lt;/h2&gt;

&lt;p&gt;This JSON file should contain an array of strings, each representing the name of a VPN provider recognized in the &lt;code&gt;org&lt;/code&gt; field of a response from &lt;code&gt;ipapi.co&lt;/code&gt; or &lt;code&gt;ipinfo.io&lt;/code&gt; or other similar online services. The file should be structured as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"VPNProviderName1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"VPNProviderName2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"VPNProviderName3"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Replace &lt;code&gt;"VPNProviderName1"`,&lt;/code&gt;"VPNProviderName2"&lt;code&gt;, and&lt;/code&gt;&lt;code&gt;"VPNProviderName3"&lt;/code&gt; with the real names of the VPN providers you want to recognize. This can be your employer's VPN provider, a personal VPN service, or any other VPN provider you want to discover. The main thing is that this provider should provide specific information in the org field for whois services like ipapi.co/ipinfo.io. So if the org field is empty or non-unique. it can be confusing. but this doesn't happen very often.&lt;/p&gt;
&lt;h2&gt;
  
  
  Usage.
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Make sure that the &lt;code&gt;Get-VPNConnectionInfo&lt;/code&gt; function and the &lt;code&gt;knownVPNproviders.json&lt;/code&gt; file are in the same directory.&lt;/li&gt;
&lt;li&gt;Create the &lt;code&gt;Get-VPNConnectionInfo.ps1&lt;/code&gt; script file in a PowerShell session. You can do this by navigating to the script directory and running the &lt;code&gt;. .\Get-VPNConnectionInfo.ps1&lt;/code&gt; command.&lt;/li&gt;
&lt;li&gt;Call the function with &lt;code&gt;Get-VPNConnectionInfo&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Adding it to a PowerShell profile
&lt;/h2&gt;

&lt;p&gt;For convenience, you can add the function to your PowerShell profile so that it is automatically available in every session:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the PowerShell profile file for editing. If you do not know where it is located, find it by typing &lt;code&gt;$PROFILE&lt;/code&gt; in the PowerShell window.&lt;/li&gt;
&lt;li&gt;Add the following line to the profile file:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C:\path\to\to\Get-VPNConnectionInfo.ps1"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Replace "C:\path\to\to\Get-VPNConnectionInfo.ps1" with the actual path to your script. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Save the profile file and restart PowerShell. 
The &lt;code&gt;Get-VPNConnectionInfo&lt;/code&gt; function will now be available in every session.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Function Details.
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Input:&lt;/strong&gt; None.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output:&lt;/strong&gt; A custom PowerShell object with the following properties:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;connectedVPN&lt;/code&gt;: a boolean value indicating whether or not the current connection is being made through a known VPN provider.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;connect_info&lt;/code&gt;: An object containing information about the IP connection, including the name of a potentially suitable VPN provider. You can assume that if the provider name includes the word VPN, it is a suitable service.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The published code has an open license. If you have suggestions, pull requests are welcome.&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



</description>
      <category>powershell</category>
      <category>networking</category>
      <category>vpn</category>
    </item>
    <item>
      <title>Powershell to fix incorrect encoding of MP3 ID3 tags</title>
      <dc:creator>uyriq</dc:creator>
      <pubDate>Thu, 13 Jun 2024 16:52:56 +0000</pubDate>
      <link>https://dev.to/uyriq/powershell-to-fix-incorrect-encoding-of-mp3-id3-tags-5fca</link>
      <guid>https://dev.to/uyriq/powershell-to-fix-incorrect-encoding-of-mp3-id3-tags-5fca</guid>
      <description>&lt;p&gt;This PowerShell script corrects the encoding of ID3 tags in MP3 files. It is specifically designed for the case of a problem where tags encoded in WINDOWS-1251 have been saved to files as WINDOWS-1252 text, and so programs incorrectly output grainy characters (like this one"îñòðîâ") because they read the text as a Western European encoding. So the task is to save tags in modern UTF-8 encoding. TagLibSharp.dll does all the work of reading tags from the file, so to make the script work you need to place this library in the script execution directory. The main purpose of the script is to fix file encoding, but by calling it with the arguments &lt;code&gt;-AllArtists&lt;/code&gt;, &lt;code&gt;-AllAlbum&lt;/code&gt;, &lt;code&gt;-AllPicture&lt;/code&gt;, &lt;code&gt;-AllComment&lt;/code&gt;, you can also batch change related meta-properties of files. This script should not be used with diacritic languages, as it considers all these languages to be incorrect Cyrillic characters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before running this script, make sure you have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PowerShell 5.1 or higher.&lt;/li&gt;
&lt;li&gt;TagLibSharp.dll: This is required to work with MP3 tags. You can obtain `TagLibSharp.dll by either: By downloading it from &lt;a href="https://nuget.info/packages/TagLibSharp/2.3.0" rel="noopener noreferrer"&gt;NuGet&lt;/a&gt;. Or by compiling the source code available on &lt;a href="https://github.com/mono/taglib-sharp" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;in case of PowerShell 5.1 you need System.Text.Encoding.CodePages.dll (netstandard 2.0) obtain binary package from &lt;a href="https://nuget.info/packages/System.Text.Encoding.CodePages/" rel="noopener noreferrer"&gt;NuGet&lt;/a&gt; that library is defaulted to Powershell Core &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to use
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Get &lt;strong&gt;TagLibSharp.dll:&lt;/strong&gt;  and optionaly for Powershell 5.1 Get &lt;strong&gt;System.Text.Encoding.CodePages&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Locate TagLibSharp.dll/System.Text.Encoding.CodePages.dll in the same directory as the script:&lt;/strong&gt; The script expects TagLibSharp.dll to be in the same directory from which the script is run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prepare MP3 files:&lt;/strong&gt; Make sure that all MP3 files you want to fix are placed in the same directory. The script will process all .mp3 files in the directory from which it is run.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run the script:&lt;/strong&gt;.

&lt;ul&gt;
&lt;li&gt;Open PowerShell and navigate to the directory containing the script and TagLibSharp.dll.&lt;/li&gt;
&lt;li&gt;Run the script by typing .\convertIDv3tags.ps1 and pressing Enter.
The script will process each MP3 file in the catalog, correcting the ID3 tag encoding as described.&lt;/li&gt;
&lt;li&gt;You can optionally pass args as &lt;code&gt;-AllArtists&lt;/code&gt;, &lt;code&gt;-AllAlbum&lt;/code&gt;, &lt;code&gt;-AllPicture&lt;/code&gt;, &lt;code&gt;-AllComment&lt;/code&gt; to set the appropriate meta properties for a group of files&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Backup your files:&lt;/strong&gt;Before running the script, it is recommended that you back up your MP3 files to prevent unintentional data loss.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Script Restrictions:&lt;/strong&gt; The script is specifically restricted to working with MP3 files. Changing the -Filter *.mp3 parameter to work with other file formats may not produce the desired results, although in general TagLibSharp.dll supports even video.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;**NotaBene: &lt;a href="https://alexandrubucur.com/tech/2021/how-to-read-metadata-easily-in-powershell-with-taglibsharp/**" rel="noopener noreferrer"&gt;if u wish experiment more with TagLibSharp dive in with&lt;/a&gt; &lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


</description>
      <category>powershell</category>
      <category>pwsh</category>
      <category>script</category>
      <category>idv3tags</category>
    </item>
    <item>
      <title>Select best cluster of game-servers connection using PowerShell like the Wargaming launcher does. 🚀🎮</title>
      <dc:creator>uyriq</dc:creator>
      <pubDate>Fri, 07 Jun 2024 13:37:36 +0000</pubDate>
      <link>https://dev.to/uyriq/select-best-cluster-of-game-servers-connection-using-powershell-like-the-wargaming-launcher-does-n20</link>
      <guid>https://dev.to/uyriq/select-best-cluster-of-game-servers-connection-using-powershell-like-the-wargaming-launcher-does-n20</guid>
      <description>&lt;h2&gt;
  
  
  How to check connection to server clusters using powershell or how to do the same thing that the launcher does when logging into Wargaming and Lesta game account. 🚀🎮
&lt;/h2&gt;

&lt;p&gt;When throwing pebbles into the water, look at the circles formed by them; otherwise, such throwing will be an empty amusement 😉. What do I liken a good MT/WOT ping to? - To a fast projectile hitting the target.&lt;/p&gt;

&lt;p&gt;Clusters of game servers for “World of Tanks” and “World of Tanks” are distributed in different regions, and each cluster serves a certain set of servers. The game selects the server based on the lowest ping to the cluster. Probably, additional selection parameters are used, and all this happens at the moment of connection. Also, at any time in the game, you can switch to the available list of servers sorted by ping. If you want to solve the problem of choosing the optimal cluster yourself, you will need to check the ping to each server in each cluster, determine the average ping and its variance, and the less these indicators, the more suitable the cluster for the game. For this purpose, I have written a PowerShell script that performs these actions, displays the results in the console as the list is traversed, and selects the optimal cluster based on the final table. The script code is available &lt;a href="https://github.com/uyriq/wotPing" rel="noopener noreferrer"&gt;on GitHub in the public repo&lt;/a&gt;. Instructions on how to use and customize it are in the repo README.&lt;/p&gt;

&lt;p&gt;The script accepts a list of server URLs either directly through the -serverList parameter or via a JSON file specified with the -serverListFile parameter. It performs ping tests on each server, calculates the average response time and dispersion, and identifies the optimal server based on these metrics. Note that the script includes all current servers of WoT in the serverlistfile.json. Users can test and measure ping results for these servers as well as for their own list of servers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;\wotPing.ps1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-pingCount&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-serverList&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ya.ru"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"google.com"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-serverListFile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"serverList.json"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# This command pings "ya.ru", "google.com", and all servers listed in "serverList.json" five times each.&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>powershell</category>
      <category>network</category>
      <category>wargaming</category>
      <category>lesta</category>
    </item>
  </channel>
</rss>
