<?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>Forem: Lion The Hoon</title>
    <description>The latest articles on Forem by Lion The Hoon (@lionthehoon).</description>
    <link>https://forem.com/lionthehoon</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%2F271064%2Fdfa9b8f0-c5ad-444a-b33d-e33ab639f3fd.png</url>
      <title>Forem: Lion The Hoon</title>
      <link>https://forem.com/lionthehoon</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/lionthehoon"/>
    <language>en</language>
    <item>
      <title>Fixing WebView2 Issues in Linux Bottles: How I Got It Working</title>
      <dc:creator>Lion The Hoon</dc:creator>
      <pubDate>Sun, 21 Dec 2025 06:22:37 +0000</pubDate>
      <link>https://forem.com/lionthehoon/fixing-webview2-issues-in-linux-bottles-how-i-got-it-working-1ab6</link>
      <guid>https://forem.com/lionthehoon/fixing-webview2-issues-in-linux-bottles-how-i-got-it-working-1ab6</guid>
      <description>&lt;p&gt;Since setting up &lt;a href="https://docs.usebottles.com/" rel="noopener noreferrer"&gt;Bottles&lt;/a&gt;, I’ve been happily running my favorite Windows applications on my Linux development machine. Life was good—I was productive, comfortable, and didn’t have to dual‑boot or spin up a VM just to get work done.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem: A Windows App That Needs WebView2 on Linux
&lt;/h2&gt;

&lt;p&gt;Recently, I needed a desktop app to manage my investments. The app offers Windows, iOS, and Android versions—but unfortunately, no native Linux support. To make things more interesting, some key features are only available in the Windows version.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;No problem, I have Bottles for that!&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;I installed the Windows version using Bottles, launched it, and everything seemed fine at first. Most features worked flawlessly. However, when I opened a specific window, I was greeted with a popup:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;WebView2 is not installed. Do you want to install it?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Sure—I needed that feature, so I installed WebView2. The installation completed successfully, and the window opened… but the content was completely blank.&lt;/p&gt;

&lt;p&gt;At this point, it was clear that &lt;strong&gt;WebView2 wasn’t behaving correctly inside Bottles on Linux&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Usual Troubleshooting (and a Lucky Find)
&lt;/h2&gt;

&lt;p&gt;Like most of us would do, I asked ChatGPT for help. I tried a few suggestions, but no luck. So I went old‑school and Googled the issue.&lt;/p&gt;

&lt;p&gt;Thankfully, I stumbled upon a helpful &lt;a href="https://www.reddit.com/r/linux_gaming/comments/1ewgawa/comment/nkrhyq8/" rel="noopener noreferrer"&gt;Reddit post&lt;/a&gt; that pointed me in the right direction. And yes—it worked.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Getting WebView2 to Work in Bottles
&lt;/h2&gt;

&lt;p&gt;Here’s a quick summary of what fixed the issue for me.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Install Proton GE in Bottles
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;strong&gt;Bottles&lt;/strong&gt; and go to Preferences (&lt;em&gt;Shortcut:&lt;/em&gt; &lt;code&gt;Ctrl + ,&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Navigate to the &lt;code&gt;Runners&lt;/code&gt; tab&lt;/li&gt;
&lt;li&gt;Scroll down to &lt;code&gt;Proton GE&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Install the latest available version—at the time of writing, this was &lt;code&gt;ge-proton10-26&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 2: Switch the Bottle Runner to Proton GE
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open the specific &lt;strong&gt;Bottle&lt;/strong&gt; where your Windows app is installed&lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;Options &amp;gt; Settings &amp;gt; Components &amp;gt; Runner&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Change the runner to the &lt;code&gt;ge-proton10-26&lt;/code&gt; version you just installed&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 3: Install Required Dependencies
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;Dependencies&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Install the following packages:&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vcredist2022&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vcredist2019&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dotnet48&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Result: WebView2 Working Perfectly on Linux
&lt;/h2&gt;

&lt;p&gt;And that’s it.&lt;/p&gt;

&lt;p&gt;I relaunched the app, opened the problematic window again—and this time, the content loaded exactly as expected. No blank screen. No errors. Just a fully functional WebView2 component running inside Bottles on Linux.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;If you’re running Windows applications on Linux using Bottles and run into &lt;strong&gt;WebView2 rendering issues&lt;/strong&gt;, switching to &lt;strong&gt;Proton GE&lt;/strong&gt; and installing the right dependencies can make all the difference. Hopefully, this saves you some time—and a bit of head‑scratching.&lt;/p&gt;

&lt;p&gt;Happy hacking on Linux! &lt;/p&gt;

&lt;p&gt;The original post can be found &lt;a href="https://the-hoon-log.web.app/blogs/fix-webview2-linux-bottles-proton-ge" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;br&gt;
Note: This post was written by me and edited by AI. &lt;/p&gt;

</description>
      <category>linux</category>
      <category>linuxbottles</category>
      <category>webview2linux</category>
      <category>winappsonlinux</category>
    </item>
    <item>
      <title>How I Made My AMD RX6750XT Work for Machine Learning (Despite ROCm Limitations)</title>
      <dc:creator>Lion The Hoon</dc:creator>
      <pubDate>Thu, 01 May 2025 07:31:37 +0000</pubDate>
      <link>https://forem.com/lionthehoon/how-i-made-my-amd-rx6750xt-work-for-machine-learning-despite-rocm-limitations-553a</link>
      <guid>https://forem.com/lionthehoon/how-i-made-my-amd-rx6750xt-work-for-machine-learning-despite-rocm-limitations-553a</guid>
      <description>&lt;h2&gt;
  
  
  The GPU Regret: AMD vs Nvidia for AI Development
&lt;/h2&gt;

&lt;p&gt;The 2020–2022 crypto boom made buying GPUs a nightmare, especially Nvidia’s RTX series. Back then, &lt;strong&gt;Team Red’s RX6000 lineup felt like a steal&lt;/strong&gt;. I grabbed an &lt;strong&gt;AMD RX6750XT&lt;/strong&gt;—same chip as the RX6700XT (gfx1031)—and skipped ray tracing for affordable rasterization. "Price over pixels," right?&lt;/p&gt;

&lt;p&gt;Fast forward to 2024. Crypto’s fading, but the &lt;strong&gt;AI boom&lt;/strong&gt; exploded. As a developer itching to experiment with LLMs and PyTorch, I realized my mistake: &lt;strong&gt;Nvidia’s CUDA dominance&lt;/strong&gt; leaves AMD GPUs in the dust. ROCm—AMD’s answer to CUDA—officially supports RX6800XT (gfx1030) but snubs RX6700XT/6750XT (gfx1031). Cue the regret.&lt;/p&gt;

&lt;p&gt;If I could time-travel, I’d slap my 2022 self and yell: “Buy an RTX 3070 instead!” But since I’m stuck with my RX6750XT, here’s how I forced it to play nice with &lt;strong&gt;machine learning workloads&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hacking ROCm Support for RX6700XT/6750XT GPUs
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Tools Used:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OS:&lt;/strong&gt; Linux Mint 22.1&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GPU:&lt;/strong&gt; AMD RX6750XT (gfx1031)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 1: Install AMD Drivers &amp;amp; ROCm Runtime
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Download the AMD &lt;code&gt;amdgpu-install&lt;/code&gt; Debian Package for RX6700XT from &lt;a href="https://www.amd.com/en/support/downloads/drivers.html/graphics/radeon-rx/radeon-rx-6000-series/amd-radeon-rx-6700-xt.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Install the package (no tutorial here—trust your Googling skills).&lt;/li&gt;
&lt;li&gt;Run: &lt;code&gt;amdgpu-install --usecase=graphics,rocm&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 2: User Permissions &amp;amp; Reboot
&lt;/h3&gt;

&lt;p&gt;Add yourself to the video and render groups:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;usermod &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-G&lt;/span&gt; video &lt;span class="nv"&gt;$USER&lt;/span&gt;  
&lt;span class="nb"&gt;sudo &lt;/span&gt;usermod &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-G&lt;/span&gt; render &lt;span class="nv"&gt;$USER&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Reboot.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: The GFX1031 vs GFX1030 Spoof
&lt;/h3&gt;

&lt;p&gt;Post-reboot, run &lt;code&gt;rocminfo&lt;/code&gt;. You should be able to see your GPU here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Making Sure it Works
&lt;/h3&gt;

&lt;p&gt;Here’s my working Ollama Docker command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--restart&lt;/span&gt; always &lt;span class="se"&gt;\ &lt;/span&gt; 
  &lt;span class="nt"&gt;--device&lt;/span&gt; /dev/kfd &lt;span class="nt"&gt;--device&lt;/span&gt; /dev/dri &lt;span class="se"&gt;\ &lt;/span&gt; 
  &lt;span class="nt"&gt;-v&lt;/span&gt; ollama:/root/.ollama &lt;span class="nt"&gt;-p&lt;/span&gt; 11434:11434 &lt;span class="se"&gt;\ &lt;/span&gt; 
  &lt;span class="nt"&gt;--name&lt;/span&gt; ollama &lt;span class="se"&gt;\ &lt;/span&gt; 
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;HSA_OVERRIDE_GFX_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10.3.0 &lt;span class="se"&gt;\ &lt;/span&gt; 
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;HCC_AMDGPU_TARGET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;gfx1030 &lt;span class="se"&gt;\ &lt;/span&gt; 
  ollama/ollama:rocm  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;AMD’s improving ROCm, but driver issues and hardware restrictions linger. Hopefully the situation improves for future platforms. &lt;/p&gt;

&lt;p&gt;References:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/LocalLLaMA/comments/18ourt4/my_setup_for_using_rocm_with_rx_6700xt_gpu_on/" rel="noopener noreferrer"&gt;Reddit Guide for RX6700XT ROCm setup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://rocm.docs.amd.com/projects/install-on-linux/en/latest/reference/system-requirements.html" rel="noopener noreferrer"&gt;ROCm supported hardware&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Notes: this blog post was edited by AI.&lt;/p&gt;

</description>
      <category>amdrocm</category>
      <category>amdrx6750xt</category>
      <category>rocmsupport</category>
      <category>llm</category>
    </item>
    <item>
      <title>How to Run Windows Applications on Linux Using Bottles: A Step-by-Step Guide</title>
      <dc:creator>Lion The Hoon</dc:creator>
      <pubDate>Mon, 31 Mar 2025 10:26:38 +0000</pubDate>
      <link>https://forem.com/lionthehoon/how-to-run-windows-applications-on-linux-using-bottles-a-step-by-step-guide-l4b</link>
      <guid>https://forem.com/lionthehoon/how-to-run-windows-applications-on-linux-using-bottles-a-step-by-step-guide-l4b</guid>
      <description>&lt;p&gt;Are you transitioning from Windows to Linux but struggling to replace tools like &lt;a href="https://notepad-plus-plus.org/" rel="noopener noreferrer"&gt;Notepad++&lt;/a&gt; or &lt;a href="https://winmerge.org/" rel="noopener noreferrer"&gt;WinMerge&lt;/a&gt;? Thanks to &lt;a href="https://www.winehq.org/" rel="noopener noreferrer"&gt;Wine&lt;/a&gt; and &lt;a href="https://docs.usebottles.com/" rel="noopener noreferrer"&gt;Bottles&lt;/a&gt;, you can now run Windows-only applications natively on Linux. This guide will show you how to install Windows apps on Linux effortlessly, perfect for .NET developers or anyone needing Windows tools in a Linux environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use Bottles
&lt;/h2&gt;

&lt;p&gt;Bottles simplifies running Windows software on Linux by managing Wine configurations automatically. Unlike manual Wine setups, Bottles offers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pre-configured environments ("bottles")&lt;/li&gt;
&lt;li&gt;Easy installer integration&lt;/li&gt;
&lt;li&gt;Desktop shortcuts for Windows apps&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Install Bottles via Flatpak
&lt;/h2&gt;

&lt;p&gt;Bottles is available as a Flatpak, ensuring compatibility across Linux distributions. Run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flatpak install flathub com.usebottles.bottles 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Configure Bottles Permissions
&lt;/h2&gt;

&lt;p&gt;To enable desktop shortcuts and home directory access, run these commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Allow desktop entries  
flatpak override com.usebottles.bottles --user --filesystem=xdg-data/applications  
flatpak override com.usebottles.bottles --user --filesystem=~/.local/share/applications  

# Optional: Access home directory  
flatpak override com.usebottles.bottles --user --filesystem=home  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Install Windows Applications
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Launch Bottles and create a new "bottle".&lt;/li&gt;
&lt;li&gt;Download your Windows app’s installer (e.g., Notepad++ or WinMerge).&lt;/li&gt;
&lt;li&gt;In Bottles, click &lt;strong&gt;Run Executable…&lt;/strong&gt; and select the installer.&lt;/li&gt;
&lt;li&gt;Follow the Windows-style installation prompts.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 4: Create Desktop Shortcuts
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to the Programs list in your bottle.&lt;/li&gt;
&lt;li&gt;Click the kebab menu (⋮) next to the app.&lt;/li&gt;
&lt;li&gt;Select Add Desktop Entry to launch the app from your Linux desktop.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;With &lt;strong&gt;Bottles&lt;/strong&gt; and &lt;strong&gt;Wine&lt;/strong&gt;, running Windows applications on Linux is easier than ever. Whether you’re a .NET developer needing Notepad++ or a power user reliant on WinMerge, this setup bridges the gap between Windows and Linux workflows.&lt;/p&gt;

&lt;p&gt;Note: this post is edited by AI. The original post is available &lt;a href="https://the-hoon-log.web.app/blogs/install-windows-apps-linux-bottles-guide" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>winappsonlinux</category>
      <category>notepadpluspluslinux</category>
      <category>wine</category>
      <category>bottles</category>
    </item>
    <item>
      <title>Using the Decorator Pattern with Autofac for Selective Service Registration</title>
      <dc:creator>Lion The Hoon</dc:creator>
      <pubDate>Sat, 25 Jan 2025 14:22:23 +0000</pubDate>
      <link>https://forem.com/lionthehoon/using-the-decorator-pattern-with-autofac-for-selective-service-registration-3d0k</link>
      <guid>https://forem.com/lionthehoon/using-the-decorator-pattern-with-autofac-for-selective-service-registration-3d0k</guid>
      <description>&lt;p&gt;The other day, while working on a ticket at my job, I was tasked with adding a validation step to the checkout process for a specific platform. Initially, I thought this would be a simple change. I added the validation logic to the shared &lt;code&gt;CheckoutProcessCommandHandler&lt;/code&gt; class, which looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CheckoutProcessCommand&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ICommandHandler&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;platform&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;specific&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;platform&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;Validate&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;InvalidOperationException&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Other checkout logic...&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After creating a pull request (PR), I assumed the ticket was complete. However, a reviewer suggested using a decorator pattern and registering it in the platform's Autofac module instead. The challenge? There were multiple &lt;code&gt;ICommandHandler&lt;/code&gt; implementations registered in the Autofac module, and I needed a way to apply the decorator to a single class only.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the Decorator Pattern?
&lt;/h2&gt;

&lt;p&gt;The decorator pattern is a structural design pattern that allows you to dynamically add new functionality to an object by wrapping it in one or more decorator classes. Importantly, it does this without altering the object's original structure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Use the Decorator Pattern?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Reusability&lt;/code&gt;: You can create reusable components to extend functionality.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Maintainability&lt;/code&gt;: Keeps the original codebase clean and focused on core logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Flexibility&lt;/code&gt;: Allows dynamic composition of behaviors at runtime.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Registering a Decorator in Autofac
&lt;/h2&gt;

&lt;p&gt;Here’s a simple example of how to register a decorator in Autofac. In this example, we have two classes implementing &lt;code&gt;ICommandHandler&lt;/code&gt;: &lt;code&gt;CheckoutProcessCommand&lt;/code&gt; and &lt;code&gt;PaymentProcessCommandHandler&lt;/code&gt;. Additionally, there’s a decorator class, &lt;code&gt;CommandHandlerDecorator&lt;/code&gt;, which adds functionality by printing an additional message.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interface Definition
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;ICommandHandler.cs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;ICommandHandler&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Command Handler Implementations
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;CheckoutProcessCommand.cs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CheckoutProcessCommand&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ICommandHandler&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CheckoutProcessCommand&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;PaymentProcessCommandHandler.cs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PaymentProcessCommandHandler&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ICommandHandler&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PaymentProcessCommandHandler&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Decorator
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;CommandHandlerDecorator.cs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CommandHandlerDecorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ICommandHandler&lt;/span&gt; &lt;span class="n"&gt;innerHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ICommandHandler&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CommandHandlerDecorator&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;innerHandler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Autofac Registration
&lt;/h3&gt;

&lt;p&gt;Here’s how we register the command handlers and the decorator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ContainerBuilder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RegisterType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CheckoutProcessCommand&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="n"&gt;As&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ICommandHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RegisterType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PaymentProcessCommandHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="n"&gt;As&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ICommandHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RegisterDecorator&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CommandHandlerDecorator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ICommandHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;container&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Resolve&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ICommandHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;())&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Output
&lt;/h3&gt;

&lt;p&gt;When you run the application, the output will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CommandHandlerDecorator.Handle
CheckoutProcessCommand.Handle
CommandHandlerDecorator.Handle
PaymentProcessCommandHandler.Handle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that &lt;code&gt;CommandHandlerDecorator.Handle&lt;/code&gt; is executed before each command handler’s message. This happens because the decorator is applied to all instances implementing &lt;code&gt;ICommandHandler&lt;/code&gt;. However, this isn’t the behavior we want—we need to target a specific implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Keyed Services in Autofac
&lt;/h2&gt;

&lt;p&gt;After consulting the Autofac documentation on &lt;a href="https://autofac.readthedocs.io/en/v7.0.0/advanced/keyed-services.html" rel="noopener noreferrer"&gt;Keyed Service&lt;/a&gt;, I found a solution to apply the decorator to a specific implementation. Here’s the updated code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ContainerBuilder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RegisterType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CheckoutProcessCommand&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="n"&gt;As&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ICommandHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RegisterType&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;PaymentProcessCommandHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="n"&gt;Keyed&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ICommandHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PaymentProcessCommandHandler&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RegisterDecorator&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ICommandHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;innerInstance&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;CommandHandlerDecorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;innerInstance&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PaymentProcessCommandHandler&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;container&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Resolve&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ICommandHandler&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;())&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Updated Output
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CommandHandlerDecorator.Handle
CheckoutProcessCommand.Handle
CommandHandlerDecorator.Handle
PaymentProcessCommandHandler.Handle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The decorator is now only applied to &lt;code&gt;PaymentProcessCommandHandler&lt;/code&gt;, as desired.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Using Autofac’s keyed services allows for precise control over which classes to apply decorators to. This approach helped me implement the required functionality without affecting other parts of the system. My PR was approved, and I was finally able to close the ticket!&lt;/p&gt;

&lt;p&gt;The original post could be found &lt;a href="https://the-hoon-log.web.app/blogs/using-the-decorator-pattern-with-autofac-for-selective-service-registration" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: this blog post was edited by ChatGPT for a better reading experience.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>autofac</category>
      <category>designpatterns</category>
      <category>dependencyinversion</category>
    </item>
    <item>
      <title>Understanding Linux Shells: Interactive, Non-Interactive, and RC Files</title>
      <dc:creator>Lion The Hoon</dc:creator>
      <pubDate>Sun, 12 Jan 2025 05:47:08 +0000</pubDate>
      <link>https://forem.com/lionthehoon/understanding-linux-shells-interactive-non-interactive-and-rc-files-3eli</link>
      <guid>https://forem.com/lionthehoon/understanding-linux-shells-interactive-non-interactive-and-rc-files-3eli</guid>
      <description>&lt;p&gt;The original post could be found &lt;a href="https://the-hoon-log.web.app/blogs/understanding-linux-shells-interactive-non-interactive-and-rc-files" rel="noopener noreferrer"&gt;here&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;Recently, while compiling a .NET application that contains a build step to install &lt;code&gt;npm&lt;/code&gt; dependencies. I encountered an issue that got me diving deep into Linux shell configurations. The problem began with a seemingly simple command: &lt;code&gt;npm install&lt;/code&gt;. Instead of success, I got this error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/usr/bin/env: npm: No such file or directory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Confused, I switched to my terminal (using &lt;code&gt;zsh&lt;/code&gt;) and ran the same command. It worked perfectly! This led me to discover the differences between interactive and non-interactive shells, the role of rc files, and how environment variables are loaded.&lt;/p&gt;

&lt;p&gt;If you’ve faced similar issues, this post will guide you through the nuances of Linux shells and their configuration files.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Are Interactive and Non-Interactive Shells?
&lt;/h2&gt;

&lt;p&gt;Linux shells can operate in two main modes: &lt;strong&gt;interactive&lt;/strong&gt; and &lt;strong&gt;non-interactive&lt;/strong&gt;. Understanding their behavior is essential for debugging issues like missing environment variables.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interactive Shell
&lt;/h3&gt;

&lt;p&gt;An interactive shell is a shell session where you interact directly by typing commands. For instance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Opening a terminal and running &lt;code&gt;ls&lt;/code&gt; or &lt;code&gt;cd&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Prompts like &lt;code&gt;$&lt;/code&gt; (for regular users) or &lt;code&gt;#&lt;/code&gt; (for root) are visible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Interactive shells source specific configuration files, enabling personalized setups like custom &lt;code&gt;$PATH&lt;/code&gt; variables, aliases, and functions.&lt;/p&gt;

&lt;h4&gt;
  
  
  Examples of Interactive Shells:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Launching a terminal emulator (e.g., GNOME Terminal or iTerm2).&lt;/li&gt;
&lt;li&gt;Accessing a remote server via &lt;code&gt;ssh&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Non-Interactive Shell
&lt;/h3&gt;

&lt;p&gt;Non-interactive shells execute scripts or commands without user interaction. They are typically used by applications, scripts, or cron jobs.&lt;/p&gt;

&lt;h4&gt;
  
  
  Examples of Non-Interactive Shells:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Running a script: &lt;code&gt;bash script.sh&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Executing commands within another program: &lt;code&gt;Process.Start()&lt;/code&gt; in C#.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unlike interactive shells, non-interactive shells do not source all configuration files, which can lead to discrepancies in environment variables.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Shell Configuration Files
&lt;/h2&gt;

&lt;p&gt;Linux shell startup behavior depends on whether the shell is interactive or non-interactive, and whether it is a login or non-login shell. Here's a breakdown of the key files for Bash and Zsh.&lt;/p&gt;

&lt;h3&gt;
  
  
  Files for Bash
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Global Files:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/etc/profile&lt;/code&gt;: Sourced by login shells. Sets global environment variables.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  User-Specific Files:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;~/.bash_profile&lt;/code&gt; : Sourced by login shells. Used for user-specific login configuration.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/.bashrc&lt;/code&gt;: Sourced by interactive non-login shells. Typically includes aliases and functions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/.bash_login&lt;/code&gt;: Sourced after &lt;code&gt;~/.bash_profile&lt;/code&gt;. Typically shows welcome messages or customer commands.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/.profile&lt;/code&gt;: A fallback for &lt;code&gt;~/.bash_profile&lt;/code&gt; (used by other shells too).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/.bash_logout&lt;/code&gt;: Soured when login shell exits. Typically perform cleanup for the session.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Files for Zsh
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;~/.zshenv&lt;/code&gt;: Sourced by all Zsh shells.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/.zshrc&lt;/code&gt;: Sourced by interactive shells.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/.zprofile&lt;/code&gt;: Similar to Bash’s &lt;code&gt;~/.bash_profile&lt;/code&gt;, sourced by login shells.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/.zlogin&lt;/code&gt;: Sourced after &lt;code&gt;~/.bashrc&lt;/code&gt; during login.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/.zlogout&lt;/code&gt;: Sourced during logout.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How These Files Are Sourced
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Interactive Login Shell (e.g., SSH or TTY Login)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bash&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Bash&lt;/code&gt; startup: &lt;code&gt;/etc/profile&lt;/code&gt; &amp;gt; &lt;code&gt;~/.bash_profile&lt;/code&gt; &amp;gt; &lt;code&gt;~/.bash_login&lt;/code&gt; &amp;gt; &lt;code&gt;~/.profile&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Often, the &lt;code&gt;~/.bash_profile&lt;/code&gt; sources the &lt;code&gt;~/.bashrc&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Bash&lt;/code&gt; exit: &lt;code&gt;~/.bash_logout&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Zsh&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Zsh&lt;/code&gt; startup: &lt;code&gt;~/.zshenv&lt;/code&gt; &amp;gt; &lt;code&gt;~/.zprofile&lt;/code&gt; &amp;gt; &lt;code&gt;~/.zshrc&lt;/code&gt; &amp;gt; &lt;code&gt;~/.zlogin&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Zsh&lt;/code&gt; exit: &lt;code&gt;~/.zlogout&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Interactive Non-Login Shell (e.g., Terminal Emulator)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bash&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;~/.zshenv&lt;/code&gt; &amp;gt; &lt;code&gt;~/.bashrc&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Zsh&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;~/.zshrc&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Non-Interactive Shell (e.g., Script Execution)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bash&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Does not source interactive files like &lt;code&gt;~/.bashrc&lt;/code&gt; by default.&lt;/li&gt;
&lt;li&gt;Will locate and source &lt;code&gt;$BASH_ENV&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Zsh&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;~/.zshenv&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Troubleshooting and Best Practices
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Scenario: Missing PATH in Non-Interactive Shell
&lt;/h3&gt;

&lt;p&gt;When I debugged my application, I realized that my &lt;code&gt;npm&lt;/code&gt; binary was not in the &lt;code&gt;PATH&lt;/code&gt; because the non-interactive shell didn’t source &lt;code&gt;~/.zshrc&lt;/code&gt;, where &lt;code&gt;nvm&lt;/code&gt; adds its path. To resolve this, I added the following to &lt;code&gt;~/.zshenv&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.nvm/versions/node/v22.9.0/bin:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Understand Your Shell&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Know if your shell is Bash or Zsh and whether it’s interactive or non-interactive.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Centralize Common Configurations&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Use files like &lt;code&gt;~/.bashrc&lt;/code&gt; or &lt;code&gt;~/.zshrc&lt;/code&gt; for reusable configurations.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Export Variables Globally&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;For critical variables, export them in files sourced by all shell types (e.g., &lt;code&gt;~/.zshenv&lt;/code&gt; or &lt;code&gt;~/.profile&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Interactive and non-interactive shells serve different purposes, and understanding how they source configuration files can save hours of debugging. By organizing shell configurations effectively, you can avoid common pitfalls like missing environment variables.&lt;/p&gt;

</description>
      <category>linux</category>
      <category>bash</category>
      <category>zsh</category>
      <category>linuxshell</category>
    </item>
    <item>
      <title>Fixing SSR Rendering Issues with Angular Resolver for Async Pipe Data</title>
      <dc:creator>Lion The Hoon</dc:creator>
      <pubDate>Thu, 31 Oct 2024 12:45:58 +0000</pubDate>
      <link>https://forem.com/lionthehoon/fixing-ssr-rendering-issues-with-angular-resolver-for-async-pipe-data-5hbp</link>
      <guid>https://forem.com/lionthehoon/fixing-ssr-rendering-issues-with-angular-resolver-for-async-pipe-data-5hbp</guid>
      <description>&lt;p&gt;My &lt;a href="https://the-hoon-log.web.app/" rel="noopener noreferrer"&gt;blog site&lt;/a&gt;, still a WIP though, is an Angular build time pre-rendered static site. I chose to develop this blog as a static site as I don't foresee I need dynamic contents, helps with Search Engine Optimization (SEO), and the greatest factor, I can just host this blog site with firebase for free :D&lt;/p&gt;

&lt;h2&gt;
  
  
  Problem: Async Pipe Not Rendering on the Server Side
&lt;/h2&gt;

&lt;p&gt;During development of this blog site with Angular SSR, I ran into a situation where the HTML returned from the dev server lacked blog content. Although the site was rendering on the server side, the actual content wasn’t visible in the HTML sent from the server; it was only populated on the client side. Here's how my initial setup looked:&lt;/p&gt;

&lt;h3&gt;
  
  
  Initial Component Code
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;blog.component.ts&lt;/code&gt;:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-blog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;templateUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./blog.component.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;styleUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./blog.component.scss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BlogComponent&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OnDestroy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;blog$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BehaviorSubject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Blog&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;id$&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;subscriptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Subscription&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;blogService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BlogService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ActivatedRoute&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id$&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;mergeMap&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;blogService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBlogById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="nf"&gt;tap&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;blog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;blog$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blog&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="p"&gt;})&lt;/span&gt;
                &lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;code&gt;blog.component.html&lt;/code&gt;:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"blog-title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;{{ (blog$ | async)?.title }}&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"blog-content"&lt;/span&gt; &lt;span class="na"&gt;[innerHTML]=&lt;/span&gt;&lt;span class="s"&gt;"(blog$ | async)?.content"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Resulting Rendered HTML
&lt;/h4&gt;

&lt;p&gt;Upon viewing the rendered HTML from the server, I saw this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"blog-title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;span class="c"&gt;&amp;lt;!--ngEnt--&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"blog-content"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&lt;span class="c"&gt;&amp;lt;!--ngEnt--&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The missing content meant that &lt;strong&gt;the &lt;code&gt;async&lt;/code&gt; pipe was not rendering on the server side&lt;/strong&gt;. After investigating, I found &lt;a href="https://dev.to/jdgamble555/forcing-angular-ssr-to-wait-in-2024-4lc9"&gt;this helpful article&lt;/a&gt;, which explained that &lt;code&gt;ngOnInit&lt;/code&gt; &lt;strong&gt;is rendered synchronously&lt;/strong&gt;. The server completes rendering before the data is retrieved, causing the async pipe to return &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution: Using Angular Resolver to Fetch Data Before Rendering
&lt;/h2&gt;

&lt;p&gt;The solution to this issue is to leverage an &lt;strong&gt;Angular Resolver&lt;/strong&gt;. Resolvers fetch the necessary data before Angular activates a route, allowing SSR to render the content directly without waiting for client-side data retrieval.&lt;/p&gt;

&lt;h3&gt;
  
  
  Updated Component with Resolver
&lt;/h3&gt;

&lt;p&gt;With the resolver implemented, the updated component code looks like this:&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;blog.component.ts&lt;/code&gt;:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-blog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;templateUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./blog.component.html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;styleUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./blog.component.scss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BlogComponent&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;OnDestroy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;blog$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BehaviorSubject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BlogDto&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ActivatedRoute&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscriptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;blog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BlogDto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;blog$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blog&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Adding the Blog Resolver
&lt;/h3&gt;

&lt;p&gt;The Blog Resolver ensures that the blog content is loaded before the component is activated. Here’s the resolver code:&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;blog-resolver.service.ts&lt;/code&gt;:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BlogResolverService&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;Resolve&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BlogDto&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="na"&gt;blogService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BlogService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="na"&gt;route&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ActivatedRouteSnapshot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RouterStateSnapshot&lt;/span&gt;
  &lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;MaybeAsync&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;BlogDto&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;blogId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;blogService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBlogById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blogId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Applying the Resolver to Routes
&lt;/h3&gt;

&lt;p&gt;To apply the resolver to your routes, add it to your Angular router configuration. Here’s an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blog/:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;component&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BlogComponent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;blog&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;BlogResolverService&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;NgModule&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;RouterModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
  &lt;span class="na"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;RouterModule&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BlogRoutingModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final Thoughts on Angular Resolver for SSR
&lt;/h2&gt;

&lt;p&gt;Using Angular Resolver is an effective way to make sure that your SSR-rendered content is loaded and ready to be displayed. This not only improves the user experience but also ensures search engines can index your pre-rendered content. When implemented correctly, a resolver minimizes the need for post-rendering data fetching, making your application more efficient and SEO-friendly.&lt;/p&gt;

&lt;p&gt;For further reading, check out the official &lt;a href="https://angular.dev/guide/ngmodules/lazy-loading#resolvers" rel="noopener noreferrer"&gt;Angular documentation on resolvers&lt;/a&gt; to deepen your understanding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://the-hoon-log.web.app/blogs/fixing-ssr-rendering-issues-with-angular-resolver-for-async-pipe-data" rel="noopener noreferrer"&gt;Link to the original blog post&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>angular</category>
      <category>ssr</category>
      <category>learning</category>
      <category>frontend</category>
    </item>
    <item>
      <title>How to Set Up Microsoft Office on Linux Mint 21.3: A Comprehensive Guide</title>
      <dc:creator>Lion The Hoon</dc:creator>
      <pubDate>Sun, 21 Jul 2024 07:05:38 +0000</pubDate>
      <link>https://forem.com/lionthehoon/how-to-set-up-microsoft-office-on-linux-mint-213-a-comprehensive-guide-bco</link>
      <guid>https://forem.com/lionthehoon/how-to-set-up-microsoft-office-on-linux-mint-213-a-comprehensive-guide-bco</guid>
      <description>&lt;p&gt;Transitioning from Windows to Linux can be both exciting and challenging. While Linux Mint 21.3 offers a smooth and enjoyable experience, the absence of an official Microsoft Office version for Linux can be a significant hurdle for many users. Fortunately, there’s a way to bring Microsoft Office apps like Excel, PowerPoint, and Word to your Linux desktop. In this guide, I’ll walk you through setting up Microsoft Office on Linux Mint 21.3 using WinApps and Docker.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why No Official Microsoft Office for Linux?
&lt;/h2&gt;

&lt;p&gt;It's understandable to feel frustrated by the lack of a native Microsoft Office version for Linux. However, Microsoft’s decision to focus on Windows and macOS makes sense from a business perspective. If transitioning to Linux were as easy as switching between software, more users might leave Windows for Linux. Thankfully, there are alternative methods to access Office apps on Linux.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using WinApps to Run Microsoft Office on Linux
&lt;/h2&gt;

&lt;p&gt;While native support is missing, you can still use Microsoft Office on Linux by running it in a Windows environment using &lt;a href="https://github.com/winapps-org/winapps" rel="noopener noreferrer"&gt;WinApps&lt;/a&gt; (&lt;a href="https://github.com/winapps-org/winapps" rel="noopener noreferrer"&gt;https://github.com/winapps-org/winapps&lt;/a&gt;). WinApps renders Windows applications running on a Windows environment on your Linux desktop with the RDP protocal. I chose to run Windows environment via Docker containers. Here’s how you can set it up:&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Install Docker on Linux Mint 21.3
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Follow the Docker Installation Guide&lt;/strong&gt;: Linux Mint 21.3 is based on Ubuntu 22.04, so you’ll need to follow the Docker installation steps for Ubuntu Jammy Jellyfish. You can find the official guide &lt;a href="https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository" rel="noopener noreferrer"&gt;here&lt;/a&gt; (&lt;a href="https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository" rel="noopener noreferrer"&gt;https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Add Docker’s Official GPG Key and Repository&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you encounter errors related to the repository not found for “virginia” (Linux Mint’s code name), you may need to tweak the commands. This error occurs because Docker’s repository does not recognize the “virginia” code name directly. Try the following commands:
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add the repository to Apt sources:
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(echo "virginia") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list &amp;gt; /dev/null
sudo apt-get update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Configure Docker to Run as a Non-Root User&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Create the &lt;code&gt;docker&lt;/code&gt; group: &lt;code&gt;sudo groupadd docker&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add your user to the &lt;code&gt;docker&lt;/code&gt; group: &lt;code&gt;sudo usermod -aG docker $USER&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Log out and log back in for the changes to take effect.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 2: Install the Prerequisites
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Clone the WinApps Repository&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clone the repository from GitHub: &lt;a href="https://github.com/winapps-org/winapps" rel="noopener noreferrer"&gt;WinApps GitHub Repo&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Install FreeRDP&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Since FreeRDP 3 is not available in Linux Mint 21.3’s official repository, install it via Flatpak.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flatpak install flathub com.freerdp.FreeRDP
sudo flatpak override --filesystem=home com.freerdp.FreeRDP # To use `+home-drive`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Create a Windows Environment in Docker
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Configure Docker&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the default configurations, credentials, disk space, RAM, etc., provided in the &lt;code&gt;compose.yaml&lt;/code&gt; file or customise it to your liking. Find out more here &lt;a href="https://github.com/dockur/windows" rel="noopener noreferrer"&gt;dockur/windows repo&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Start Your Windows Environment&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open your terminal, navigate to the WinApps repo, and run: &lt;code&gt;docker compose up&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 4: Install Microsoft Office Apps
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Access the Windows Environment&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Remote into your Windows environment via &lt;code&gt;http://127.0.0.1:8006&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Install a Web Browser&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install a browser with Microsoft Store.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Install Office 365&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download and install Office 365 as you would on a regular Windows machine.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 5: Update Windows Credentials (Optional)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Change the Default Password&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;The default Windows environment credentials are &lt;code&gt;docker&lt;/code&gt; with an empty password. Update this password for added security.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 6: Use Microsoft Office Apps on Your Linux Desktop
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create a WinApps Configuration File&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Create a configuration file at ~/.config/winapps/winapps.conf containing the following:
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RDP_USER="docker"
RDP_PASS=""
#RDP_DOMAIN="MYDOMAIN"
#RDP_IP="192.168.123.111"
#WAFLAVOR="docker" # Acceptable values are 'docker', 'podman' and 'libvirt'.
#RDP_SCALE=100 # Acceptable values are 100, 140, and 180.
#RDP_FLAGS=""
#MULTIMON="true"
#DEBUG="true"
#FREERDP_COMMAND="xfreerdp"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Run the Install Script&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navigate to the WinApps repo and execute: &lt;code&gt;./setup.sh&lt;/code&gt;. Follow the prompts to add Office apps to your Linux desktop.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Additional Applications&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only apps from the official supported list will appear. For running other applications, refer to the &lt;a href="https://github.com/winapps-org/winapps?tab=readme-ov-file#running-applications-manually" rel="noopener noreferrer"&gt;WinApps readme&lt;/a&gt; (&lt;a href="https://github.com/winapps-org/winapps?tab=readme-ov-file#running-applications-manually" rel="noopener noreferrer"&gt;https://github.com/winapps-org/winapps?tab=readme-ov-file#running-applications-manually&lt;/a&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Setting up Microsoft Office on Linux Mint 21.3 might seem like a daunting task, but using WinApps and Docker makes it achievable. By following these steps, you can seamlessly integrate Microsoft Office into your Linux environment, allowing you to continue using familiar tools while exploring the benefits of Linux.&lt;/p&gt;

&lt;p&gt;Feel free to leave a comment if you have any questions or run into issues during the setup process. Happy computing!&lt;/p&gt;




</description>
      <category>microsoft365</category>
      <category>linux</category>
    </item>
    <item>
      <title>Backup and Restore Linux OS with Rsync</title>
      <dc:creator>Lion The Hoon</dc:creator>
      <pubDate>Mon, 08 Apr 2024 13:12:14 +0000</pubDate>
      <link>https://forem.com/lionthehoon/backup-and-restore-linux-os-with-rsync-bk5</link>
      <guid>https://forem.com/lionthehoon/backup-and-restore-linux-os-with-rsync-bk5</guid>
      <description>&lt;p&gt;As a Software Engineer tackling challenges in the realm of Software Engineering, I recently encountered the task of efficiently backing up and restoring an Ubuntu OS running on a Single Board Computer (SBC). This seemingly straightforward task proved to be more complex than anticipated, requiring a solution tailored to the unique constraints of SBCs.&lt;/p&gt;

&lt;p&gt;Initially, my approach involved exploring tools like Clonezilla for creating OS images. However, the nature of SBCs presented compatibility hurdles that made this traditional method less viable. Fortunately, my search led me to an invaluable resource on GitHub—specifically, the &lt;a href="https://github.com/jetsonhacks/backupjetson" rel="noopener noreferrer"&gt;BackupJetson repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Inside this repository, I discovered two shell scripts, &lt;code&gt;backup-rootfs.sh&lt;/code&gt; and &lt;code&gt;restore-rootfs.sh&lt;/code&gt;, designed to streamline the backup and restoration process using Rsync. &lt;a href="https://github.com/RsyncProject/rsync" rel="noopener noreferrer"&gt;Rsync&lt;/a&gt;, a powerful file-syncing tool, proved to be the linchpin of this solution, offering efficient snapshot creation and restoration capabilities suited for SBC environments.&lt;/p&gt;

&lt;p&gt;To put these scripts to the test, I executed &lt;code&gt;sudo bash backup-rootfs.sh -d /recovery/&lt;/code&gt; to generate a root filesystem snapshot within the designated &lt;code&gt;/recovery/&lt;/code&gt; directory. With this baseline in place, I deliberately disrupted the OS—tampering with SSH keys, uninstalling and installing packages—to simulate a compromised state.&lt;/p&gt;

&lt;p&gt;With the system in disarray, I then invoked &lt;code&gt;sudo bash restore-rootfs.sh -d /recovery/backup-rootfs-04-08-2024/&lt;/code&gt; and initiated a reboot. This step was crucial, as it allowed for the full restoration of services and configurations essential for the OS's functionality.&lt;/p&gt;

&lt;p&gt;Upon reboot, I was delighted to find the OS had reverted to its original, pristine state captured during the backup. This seamless restoration underscores the efficacy of the Rsync-based solution.&lt;/p&gt;

&lt;p&gt;In conclusion, the journey to streamline OS backup and restoration on Single Board Computers has been both enlightening and rewarding. Through tools like Rsync and the BackupJetson repository, the once-daunting task of managing OS snapshots on SBCs has become accessible and efficient—a testament to the ingenuity and collaborative spirit of the open-source community.&lt;/p&gt;




&lt;p&gt;As a Software Engineer with several years of experience, I often encounter challenges that require unique, context-specific remedies. By sharing these insights through blogging, I aim to contribute to the collective knowledge of the developer community while creating a personal repository of proven strategies.&lt;/p&gt;

&lt;p&gt;Stay tuned for more insights and solutions as I continue to explore the fascinating intersection of software engineering and embedded systems!&lt;/p&gt;

</description>
      <category>linux</category>
      <category>backup</category>
    </item>
    <item>
      <title>Using Existing Database Connection's with Entity Framework Core</title>
      <dc:creator>Lion The Hoon</dc:creator>
      <pubDate>Thu, 04 Jun 2020 13:48:44 +0000</pubDate>
      <link>https://forem.com/lionthehoon/using-existing-database-connection-s-with-entity-framework-core-5388</link>
      <guid>https://forem.com/lionthehoon/using-existing-database-connection-s-with-entity-framework-core-5388</guid>
      <description>&lt;p&gt;Entity Framework Core the default ORM that powers many many projects out there. It is great ORM and does its job great.  &lt;/p&gt;

&lt;p&gt;But some projects use more than one data access libraries. The post will be demonstrating how to use an existing &lt;code&gt;DbConnection&lt;/code&gt; with Entity Framework Core.  &lt;/p&gt;

&lt;p&gt;The following code was tested with:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dotnet Core 3.1&lt;/li&gt;
&lt;li&gt;Entity Framework Core 3.1.2
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You could do it...  &lt;/p&gt;

&lt;p&gt;At &lt;code&gt;Startup.cs&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Startup&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ConfigureServices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IServiceCollection&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyDbContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;((&lt;/span&gt;&lt;span class="n"&gt;IServiceProvider&lt;/span&gt; &lt;span class="n"&gt;serviceProvider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DbContextOptionsBuilder&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;DbConnection&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="c1"&gt;// Get your database connection here.&lt;/span&gt;
        &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseSqlServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At &lt;code&gt;OnConfiguring&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyDbContext&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;DbContext&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;DbConnection&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;MyDbContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DbContextOptions&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;DbConnection&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;OnConfiguring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DbContextOptionsBuilder&lt;/span&gt; &lt;span class="n"&gt;optionsBuilder&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseSqlServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/ef/core/saving/transactions#share-connection-and-transaction" rel="noopener noreferrer"&gt;In your code&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DbContextOptionsBuilder&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BloggingContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseSqlServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SqlConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connectionString&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Options&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;context1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;BloggingContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;transaction&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;context1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;BeginTransaction&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;context2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;BloggingContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="p"&gt;...&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you hit &lt;code&gt;System.InvalidOperationException: A transaction is already in progress; nested/concurrent transactions aren't supported.&lt;/code&gt; while calling &lt;code&gt;SaveChanges()&lt;/code&gt;, try the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseTransaction&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;DbTransaction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// transaction is returned when you called BeginTransaction()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As per stated in the &lt;a href="https://docs.microsoft.com/en-us/ef/core/saving/transactions#using-external-dbtransactions-relational-databases-only" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; this only works for relational database only.&lt;/p&gt;

</description>
      <category>efcore</category>
      <category>dotnet</category>
      <category>entityframework</category>
    </item>
  </channel>
</rss>
