<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Notepad.ONGHU</title>
    <description>Knowledge without memory is useless</description>
    <link>https://notepad.onghu.com/</link>
    <atom:link href="https://notepad.onghu.com/feed.xml" rel="self" type="application/rss+xml" />
    <pubDate>Sat, 28 Mar 2026 14:44:37 +0800</pubDate>
    <lastBuildDate>Sat, 28 Mar 2026 14:44:37 +0800</lastBuildDate>
    <generator>Jekyll v4.2.0</generator>
    
      <item>
        <title>Windows: Retrospecting my setup - 0 clicks, 1 click, and more</title>
        <description>&lt;p&gt;There has been a lot of discussion around Windows 11, the start menu, taskbar, etc. and I felt that some changes annoyed me more than others. In thinking why, I ended up realising how I have set up Windows when it comes to starting applications. This post documents that thought process.&lt;/p&gt;
&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;
&lt;p&gt;I have used Windows 95+ since 1996 even though from 1996 &amp;#8211; 2000, OS/2 Warp 4 was my daily driver. I got my first laptop (&lt;span class=&quot;caps&quot;&gt;IBM&lt;/span&gt; Thinkpad) in 2000 and it came pre-installed with Windows 98 Second Edition and that became my main OS for a number of years &amp;#8211; moving thereafter to Windows XP, Windows Vista, Windows 7 and Windows 10. I&amp;#8217;m not on Windows 10 on one machine and reluctantly moving to Windows 11 on the other. I fully expect to use Windows 11 most of the time later this year.&lt;/p&gt;
&lt;p&gt;Windows 98 was also where I started customising how things worked for me and that trend continued through. I remember changing my startup screen and the shut down image for a while but the biggest change was in using the Start Menu and the Quick Launch (on the taskbar) &amp;#8211; ideas that have served me now for more than 20 years.&lt;/p&gt;
&lt;h2 id=&quot;start-menu-0-clicks&quot;&gt;Start Menu: Zero Clicks&lt;/h2&gt;
&lt;p&gt;I still use the &amp;#8220;classic&amp;#8221; start menu (I have used Classic Shell / &lt;a href=&quot;https://github.com/Open-Shell/Open-Shell-Menu&quot;&gt;OpenShell&lt;/a&gt; for many years) and I organise it as shown in the picture below. Note that OpenShell lets you press [Shift] + Windows to launch the new start menu, so that&amp;#8217;s always available if I need it (which I use sparingly).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/windows/retrospect-setup/start-menu-01.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The main addition that I have done are the folders of shortcuts that you see. These are:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;major-proj&lt;/strong&gt; : one of my major projects that has material in different parts of my PC but linked from here&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Goto&lt;/strong&gt; : short cuts to drives and major folders&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Other Machines&lt;/strong&gt; : not used much any more, but shortcuts to &lt;span class=&quot;caps&quot;&gt;RDP&lt;/span&gt; files, VMs, and even command files to launch PuTTY to get into some remote machines&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Q&lt;/strong&gt; : Quick Access (for applications)&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;W&lt;/strong&gt; : Whatever Else (a second list of applications)&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;X Org&lt;/strong&gt; : Extreme Organisation (just so it starts with &amp;#8220;X&amp;#8221;) &amp;#8211; links to organisation tools such as Project, To-do, Raindrop, etc.&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;Z&lt;/strong&gt; : Zatabase (instead of Database, but so it starts with &amp;#8220;Z&amp;#8221;) &amp;#8211; links to DB tools (not used much any more)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The key idea here was that all these folders started with unique letters so that if I pressed the Windows key and that letter (M, G, O, Q, W, X, Y, Z) it matched nothing else on the menu and would take me to that folder and expand it. Let&amp;#8217;s look at the &amp;#8220;Q&amp;#8221; menu expanded&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/windows/retrospect-setup/start-menu-02.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;As you see now, it has a list of appplications that each starts with a different letter again so that typing that letter uniquely picks that application, example:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;C&lt;/strong&gt; &amp;#8211; Calculator&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;D&lt;/strong&gt; &amp;#8211; &lt;span class=&quot;caps&quot;&gt;DOS&lt;/span&gt; (windows command)&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;J&lt;/strong&gt; &amp;#8211; JukeAMP (renamed WinAMP)&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;O&lt;/strong&gt; &amp;#8211; OneNote&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;P&lt;/strong&gt; &amp;#8211; Powerpoint&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;W&lt;/strong&gt; &amp;#8211; Word&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;X&lt;/strong&gt; &amp;#8211; Xcel (renamed Excel)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I used to have other ones earlier which have dropped in how they are launched or are not relevant any more (e.g., A &amp;#8211; Acrobat, C &amp;#8211; C++ Builder, E &amp;#8211; Evernote, G &amp;#8211; Google Chrome, V &amp;#8211; Visual Studio, etc.) or are not installed on this computer. In a similar way, I have shortcuts in the other menus (W, X, Z) though over the years, I use fewer tools and some of these could be collapsed together now.&lt;/p&gt;
&lt;p&gt;I want to also show the &amp;#8220;Goto&amp;#8221; menu quickly and you&amp;#8217;ll see that again, the idea is that the list is unique:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;strong&gt;E&lt;/strong&gt; &amp;#8211; E-books folder&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;C and D&lt;/strong&gt; &amp;#8211; for the drives&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;1&lt;/strong&gt; &amp;#8211; OneDrive Personal&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;O&lt;/strong&gt; &amp;#8211; One Drive Work&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;B&lt;/strong&gt; &amp;#8211; for BoxDrop, meaning DropBox (since &amp;#8220;D&amp;#8221; is used for &amp;#8220;D Drive&amp;#8221;)&lt;/li&gt;
	&lt;li&gt;&lt;strong&gt;J&lt;/strong&gt; &amp;#8211; Jekyll blog (my blog folder)&lt;/li&gt;
	&lt;li&gt;Some other work related folders&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/windows/retrospect-setup/start-menu-03.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What&amp;#8217;s the advantage?&lt;/strong&gt; The main advantage of this approach is that I can access all of these using &lt;strong&gt;zero clicks&lt;/strong&gt; &amp;#8211; I rely on muscle memory most of the time. In the middle of something, I need a calculator: I just do &lt;strong&gt;[Windows] + Q + C&lt;/strong&gt;, need to open Excel to calculate something: &lt;strong&gt;[Windows] + Q + P&lt;/strong&gt;, want to go to Microsoft Paint: &lt;strong&gt;[Windows] + W + P&lt;/strong&gt;, need D Drive: &lt;strong&gt;[Windows] + G + D&lt;/strong&gt; and so on. This zero-click approach makes it really easy to start something that I might need to get access to quickly without interrupting my flow. Of course, I can click through and select these, but this makes this kind of a start menu &lt;strong&gt;really useful for me&lt;/strong&gt; &amp;#8211; I&amp;#8217;m not advocating that you need to use it, but I like that I am able to use it this way without creating Windows system-level short cuts, so to speak.&lt;/p&gt;
&lt;p&gt;Windows 11 still lets you install OpenShell which gives me this menu ability &amp;#8211; and I&amp;#8217;m happy to have it work this way. Move Start button to left from the taskbar settings and use OpenShell to have this menu, and fall back to [Shift] + [Windows] for the Windows Start Menu for the few cases where I might need it.&lt;/p&gt;
&lt;h2 id=&quot;quick-launch-1-click&quot;&gt;Quick Launch: From Zero Clicks to One&lt;/h2&gt;
&lt;p&gt;The next set of applications is launched from the Quick Launch bar, and this is most strongly disrupted in Windows 11 for me. Take a look at my Quick Launch bar in Windows 10. I have here a list of applications that I use regularly but don&amp;#8217;t really expect to launch directly via shortcuts &amp;#8211; I just normally click on the icon here to launch the application.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/windows/retrospect-setup/start-menu-04.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;When I set it up, I did not think why I put these applications here, but in retrospect, I realise that most of the time, these are applications that:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Take longer to launch: example are VS Code, C++ Builder, PodMan, Virtual Box, etc.&lt;/li&gt;
	&lt;li&gt;Are launched once but live long: examples are Outlook, Thunderbird, Edge, Firefox, etc.&lt;/li&gt;
	&lt;li&gt;Are not usually launched &amp;#8220;in the flow&amp;#8221;: examples are most of the above and other apps like Typora, GitAhead, etc.&lt;/li&gt;
	&lt;li&gt;Are special: actually, the main example is the Windows console that has 2 entries: one as regular user and one shortcut that launches it as an Administrator&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I also think that I occasionally think of these applications as launched a bit more lazily and often with a mouse and not the keyboard &amp;#8211; I can&amp;#8217;t explain why but this is how my brain has adapted to it. Of course, I could put these into start somewhere and then click and launch, but that would be multiple clicks and somehow, it feels not ideal.&lt;/p&gt;
&lt;p&gt;Importantly, in my setup:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;The Quick Launch bar is &lt;strong&gt;double height&lt;/strong&gt; to accommodate more icons&lt;/li&gt;
	&lt;li&gt;It uses &lt;strong&gt;Small Icons&lt;/strong&gt; to accommodate more icons &amp;#8211; I click with the mouse, so I don&amp;#8217;t need &amp;#8220;touch targets&amp;#8221;&lt;/li&gt;
	&lt;li&gt;Each shortcut is actually &lt;strong&gt;numbered&lt;/strong&gt; &amp;#8211; e.g., &amp;#8220;07 &amp;#8211; GitHub Desktop&amp;#8221;, &amp;#8220;08 &amp;#8211; VS Code&amp;#8221; and so on, so that each icon appears at exactly the same place on restart&lt;/li&gt;
	&lt;li&gt;The Quick Launch bar is &lt;strong&gt;resized to fit exactly 2 equal width rows&lt;/strong&gt; of an equal number of icons&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Again, it might just be me, but this setup is something that I have used for many, many years &amp;#8211; and it affects me when it becomes unavailable in Windows. I don&amp;#8217;t mind the work that Microsoft does in modernising the system but I feel seasoned users have their own workflows and these get disrupted when the entire feature becomes unavailable altogether.&lt;/p&gt;
&lt;p&gt;Windows 11 kneecaps this in a couple of ways:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Quick Launch of this kind is removed&lt;/li&gt;
	&lt;li&gt;Double height and small icons don&amp;#8217;t work on the Taskbar&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;What&amp;#8217;s wrong with pinning to task bar?&lt;/strong&gt; That&amp;#8217;s a reasonable question and I think the main annoyance I have with it is that it opens the Window at the place where you click the icon. So, you have: &lt;code&gt;[Explorer Icon] [Edge Icon] [Firefox Icon]&lt;/code&gt; and then you open Explorer, now you get: &lt;code&gt;[Explorer Window] [Edge Icon] ...&lt;/code&gt; and your icons are shifted, so you have to scan and find the Edge icon again because it&amp;#8217;s no longer at the same place. It&amp;#8217;s an annoyance that kills muscle memory &amp;#8211; I just wish it wasn&amp;#8217;t required.&lt;/p&gt;
&lt;p&gt;While on &lt;strong&gt;One Click&lt;/strong&gt;, I think the notification area is also an area that I use to launch some applications &amp;#8211; Dropbox and OneDrive are obvious ones, but also things like Teams, Changing my performance level on the laptop, and so on. It would really help if Windows 11 allowed double height with small icons for this also.&lt;/p&gt;
&lt;h2 id=&quot;more-clicks&quot;&gt;More Clicks&lt;/h2&gt;
&lt;p&gt;For things that I use rarely (e.g., launching Acrobat instead of clicking on a &lt;span class=&quot;caps&quot;&gt;PDF&lt;/span&gt; file, or Wacom Table tools, and so on), I&amp;#8217;m happy to navigate the menus. I still prefer the older &amp;#8220;Programs&amp;#8221; and &amp;#8220;Apps&amp;#8221; menus that OpenShell give me but these require more attention and I&amp;#8217;m fine following whichever method as long as I can get to what I want. But if you look at 7-Zip, in the new menu, it shows only &amp;#8220;7-Zip Help&amp;#8221; under the folder while the classic menu, under Programs, shows Help and the &amp;#8220;7-Zip File Manager&amp;#8221; (which is arguably more useful). Of course, I don&amp;#8217;t know if this is an application developr&amp;#8217;s fault or a Windows thing, but it adds to the frustration and the feeling that the new menu is too smart for its own good.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/windows/retrospect-setup/start-menu-10.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;When I think back at how I have been using Windows around these features, a new menu like this really breaks the flow and is very disorienting, to say the least.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/windows/retrospect-setup/windows11-start.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;If you have some comments, I&amp;#8217;d love to hear from you. Feel free to connect or share the post (you can tag &lt;a href=&quot;https://x.com/onghu&quot;&gt;me as @onghu on X&lt;/a&gt; or on &lt;a href=&quot;https://ruby.social/@onghu&quot;&gt;Mastodon as @onghu@ruby.social&lt;/a&gt; or &lt;a href=&quot;https://bsky.app/profile/onghu.com&quot;&gt;@onghu.com on Bluesky&lt;/a&gt; to discuss more).&lt;/p&gt;</description>
        <pubDate>Sat, 28 Mar 2026 10:00:00 +0800</pubDate>
        <link>https://notepad.onghu.com/2026/retrospecting-how-windows-is-setup-clicks/</link>
        <guid isPermaLink="true">https://notepad.onghu.com/2026/retrospecting-how-windows-is-setup-clicks/</guid>
        
        <category>Windows</category>
        
        <category>Windows 10</category>
        
        <category>Windows 11</category>
        
        <category>Productivity</category>
        
        
        <category>Windows</category>
        
        <category>Customisation</category>
        
        <category>Productivity</category>
        
      </item>
    
      <item>
        <title>Using Portable PostgreSQL as a Service on Windows and Sending Logs to File</title>
        <description>&lt;p&gt;In previous posts, we have looked at how to &lt;a href=&quot;/2025/portable-postgresql-on-windows-without-installation-pg18/&quot;&gt;use portable PostgreSQL on Windows without installing&lt;/a&gt; it. However, one of the advantages of the installation is that it sets up additional things like Windows service. In this post, we show how to register and run the portable installation as a Windows service.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Why would you want to do this?&lt;/strong&gt; Using different portable installations is a great way to try PostgreSQL and to use it occasionally rather than all the time. However, every now and then, you might want to get into focussed activity and stopping and starting the database might get in the way. Occasionally setting it up as a service might remove some of the friction. I tend to do this occasionally and leave it there for a few days so that the database is always available&amp;#8230; and then, when I&amp;#8217;m done, I unregister it from being a service, so it&amp;#8217;s not running any more.&lt;/p&gt;
&lt;p&gt;To register and remove the service, the main command we use is still &lt;code&gt;bin/pg_ctl.exe&lt;/code&gt; from the version that you want to use. Note that this command needs to be run as an Administrator. For all the steps below, start Command Shell as an Administrator and execute the commands below.&lt;/p&gt;
&lt;p&gt;This post assumes that your portable setup on Windows was done using the &lt;a href=&quot;/2025/portable-postgresql-on-windows-without-installation-pg18/&quot;&gt;earlier post on this site for setting up PostgreSQL 18 without installation&lt;/a&gt;. Please read that first to understand how things are set up.&lt;/p&gt;
&lt;h2&gt;Registering and Using the Service&lt;/h2&gt;
&lt;p&gt;We use &lt;code&gt;pg_ctl.exe&lt;/code&gt; to register the PostgreSQL server as a Windows service. The simplest way is to do this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ pg-18.3\bin\pg_ctl.exe register -N &quot;PostgreSQL 18.3&quot; -D pg-18.3\data&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The command will install the PostgreSQL server as a Windows service named &lt;strong&gt;PostgreSQL 18.3&lt;/strong&gt; &amp;#8211; start up the Services Manager (&lt;code&gt;$ services.msc&lt;/code&gt;) and you&amp;#8217;ll see the service listed there. You&amp;#8217;ll notice that the startup type is &lt;strong&gt;Automatic&lt;/strong&gt; which means that it will automatically start when the computer restarts but it&amp;#8217;s not running yet.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/pg_win/service/pg183-service.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;You can click on the service and right click &lt;strong&gt;Start&lt;/strong&gt; and then you&amp;#8217;ll see it listed in the Task Manager.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/pg_win/service/pg183-tasks.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Unregistering and Removing the Service&lt;/h2&gt;
&lt;p&gt;To remove the service, stop it from the Windows Services Manager, and then execute this on a command line (with Administrator permissions):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ pg-18.3\bin\pg_ctl.exe unregister -N &quot;PostgreSQL 18.3&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that the text after the &lt;code&gt;-N&lt;/code&gt; needs to exactly match the service name you provided when you registered it.&lt;/p&gt;
&lt;h2&gt;Configuring the Service/ Server Port&lt;/h2&gt;
&lt;p&gt;When we ran the server directly from our portable setup, we set up a few variables. These were set up in the environment when we run. We don&amp;#8217;t need to worry about the &lt;code&gt;PATH&lt;/code&gt; and &lt;code&gt;PGDIR&lt;/code&gt; since we are pointing to the correct &lt;code&gt;pg_ctl.exe&lt;/code&gt; and we also passed the &lt;code&gt;PGDATA&lt;/code&gt; path when we set it up. We did not, however, pass the &lt;code&gt;PGPORT&lt;/code&gt;, so we can do that by including &lt;code&gt;-o &quot;-p %PGPORT%&quot;&lt;/code&gt; when we register the service:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ pg-18.3\bin\pg_ctl.exe register -N &quot;PostgreSQL 18.3&quot; -D &quot;%PGDATA%&quot; -o &quot;-p %PGPORT%&quot;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Handling Logs&lt;/h2&gt;
&lt;p&gt;We previously set the logs to be sent to a specific log file. However, the service automatically sends logs to Windows and these can be viewed using the Windows Event Viewer. This may be a better option for centralising logs and using it in that kind of setup. However, if you want to still send logs to a logfile, the easiest way is to have a configuration file that specifies this.&lt;/p&gt;
&lt;p&gt;In the setup you have done, you will find &lt;code&gt;postgresql.conf&lt;/code&gt; in the &lt;code&gt;data&lt;/code&gt; folder. Stop the service first, then let&amp;#8217;s open it and edit it. Search for &lt;strong&gt;logging&lt;/strong&gt; to jump to the correct section.&lt;/p&gt;
&lt;p&gt;These are the settings we want to edit:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#log_destination = 'stderr'		# Valid values are combinations of
					# stderr, csvlog, jsonlog, syslog, and
					# eventlog, depending on platform.
					# csvlog and jsonlog require
					# logging_collector to be on.

# This is used when logging to stderr:
#logging_collector = off		# Enable capturing of stderr, jsonlog,
					# and csvlog into log files. Required
					# to be on for csvlogs and jsonlogs.
					# (change requires restart)

# These are only used if logging_collector is on:
#log_directory = 'log'			# directory where log files are written,
					# can be absolute or relative to PGDATA
#log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'	# log file name pattern,
							# can include strftime() escapes
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&amp;#8217;s change these to:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;log_destination = 'stderr'
logging_collector = on
log_directory = 'd:/stack/logs/pg-18.3'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that we chose their recommended name for the logfile that is a bit more dynamic than just &lt;code&gt;logfile&lt;/code&gt; alone. Now, if you start the service again, logs will go to the logfile instead of Event Viewer. Also, if you start the server locally using the &lt;code&gt;pg18-start.cmd&lt;/code&gt; that we previously added, the Environment Variable is used in the command to start the server:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&quot;%PGDIR%\bin\pg_ctl&quot; -D &quot;%PGDATA%&quot; -l &quot;%PGLOGS%&quot; start&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This takes precedence over the setting in the configuration file &amp;#8211; you can remove this (from &lt;code&gt;pg18-start.cmd&lt;/code&gt; and &lt;code&gt;pg18-stop.cmd&lt;/code&gt;) if you prefer to follow the new approach for the logs.&lt;/p&gt;
&lt;h2&gt;Adding Command Files for the Service Register/ Unregister&lt;/h2&gt;
&lt;p&gt;If you want, you can add command files for this (I do it only because I forget the command).&lt;/p&gt;
&lt;p&gt;We add PG_SERVICE_NAME to the list of var.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@SET PATH=%~dp0pg-18\bin;%PATH%
@SET PGDIR=%~dp0\pg-18
@SET PGDATA=%PGDIR%\data
@SET PGLOCALEDIR=%PGDIR%\share\locale
@SET PGPORT=5418
@SET PGDATABASE=postgres
@SET PGUSER=postgres
@SET PGLOGS=%~dp0\logs\pg-18\logfile
@SET PG_SERVICE_NAME=PostgreSQL 18.3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We then create a new file for &lt;code&gt;pg18-register.cmd&lt;/code&gt; with this in it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@ECHO ON

:: Save the directory where we are
pushd %CD%

:: Shift directories to the correct path
%~d0
cd %~dp0

:: Set the variable using the common file
call pg18-vars.cmd

:: The actual command that needs to do something
&quot;%PGDIR%\bin\pg_ctl&quot; register -N &quot;%PG_SERVICE_NAME%&quot; -D &quot;%PGDATA%&quot; -o &quot;-p %PGPORT%&quot;

:: Restore the directory where we started from
popd
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We also create a new file for &lt;code&gt;pg18-unregister.cmd&lt;/code&gt; with this in it:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;@ECHO ON

:: Save the directory where we are
pushd %CD%

:: Shift directories to the correct path
%~d0
cd %~dp0

:: Set the variable using the common file
call pg18-vars.cmd

:: The actual command that needs to do something
&quot;%PGDIR%\bin\pg_ctl&quot; unregister -N &quot;%PG_SERVICE_NAME%&quot;

:: Restore the directory where we started from
popd
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Further Reading&lt;/h2&gt;
&lt;p&gt;These pages are helpful:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;The description of &lt;code&gt;pg_ctl&lt;/code&gt; is at the &lt;a href=&quot;https://www.postgresql.org/docs/18/app-pg-ctl.html&quot;&gt;PostgreSQL docs site&lt;/a&gt; &amp;#8211; it includes all the stuff that you can do with it and also has the explanations for the main parameters that we set.&lt;/li&gt;
	&lt;li&gt;There&amp;#8217;s a lot more on PostgreSQL logs at: &lt;a href=&quot;https://last9.io/blog/postgres-logs-101/&quot;&gt;https://last9.io/blog/postgres-logs-101/&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Logging to file from the service is discussed on &lt;a href=&quot;https://dba.stackexchange.com/questions/29386/logging-to-a-file-in-postgresql-windows-service&quot;&gt;StackExchange&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;As always, we save the current directory from where our scripts are called as explained in &lt;a href=&quot;/2020/navigate-to-cmd-file-directory/&quot;&gt;more about pushd / popd here&lt;/a&gt;)&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;/2025/portable-postgresql-on-windows-without-installation-pg18/&quot;&gt;Instructions to set up PostgreSQL 18 without installation&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;/2024/portable-postgresql-on-windows-without-installation-pg16/&quot;&gt;Instructions to set up PostgreSQL 16 without installation&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href=&quot;/2021/portable-postgresql-on-windows-without-installation/&quot;&gt;Instructions to set up PostgreSQL 12 without installation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As always, this is for me to be able to remember how to do it but if it helps someone, that&amp;#8217;s great! Also, if you have some comments, I&amp;#8217;d love to hear from you. Feel free to connect or share the post (you can tag &lt;a href=&quot;https://x.com/onghu&quot;&gt;me as @onghu on X&lt;/a&gt; or on &lt;a href=&quot;https://ruby.social/@onghu&quot;&gt;Mastodon as @onghu@ruby.social&lt;/a&gt; or &lt;a href=&quot;https://bsky.app/profile/onghu.com&quot;&gt;@onghu.com on Bluesky&lt;/a&gt; to discuss more).&lt;/p&gt;</description>
        <pubDate>Fri, 20 Mar 2026 12:35:00 +0800</pubDate>
        <link>https://notepad.onghu.com/2026/portable-postgresql-on-windows-service-pg18/</link>
        <guid isPermaLink="true">https://notepad.onghu.com/2026/portable-postgresql-on-windows-service-pg18/</guid>
        
        <category>PostgreSQL</category>
        
        <category>Programming</category>
        
        <category>Windows 10</category>
        
        <category>Remember</category>
        
        <category>Windows 11</category>
        
        
        <category>PostgreSQL</category>
        
        <category>Programming</category>
        
        <category>Windows 10</category>
        
        <category>Windows 11</category>
        
      </item>
    
      <item>
        <title>Outlook Calendar: Sharing in your Organisation</title>
        <description>&lt;p&gt;I got into a &lt;a href=&quot;https://bsky.app/profile/greyson.bsky.social/post/3mfaaocga5c2v&quot;&gt;discussion thread on Bluesky&lt;/a&gt; where the use of Teams/ Outlook/ Sharepoint and Calendar was being discussed. One of the questions that got asked was about sharing and delegating calendars in Outlook. I was going to reply directly when I realised that it might be easier to write up a short post and share the link rather than post all the screenshots into the chat thread.&lt;/p&gt;
&lt;p&gt;Outlook lets you share any calendar to others in your organisation and set what they can do with it. I normally use the online interface for the calendar, so the screenshots below are from there rather than the Windows desktop client.&lt;/p&gt;
&lt;p&gt;Head on over to the online portal at: &lt;a href=&quot;https://outlook.office.com/calendar/view/workweek&quot;&gt;https://outlook.office.com/calendar/view/workweek&lt;/a&gt; and it will ask you to log in and take you to the working week view of your calendar. On the left, half way down, you&amp;#8217;ll see the list of calendars. You can easily share any calendar listed under &lt;strong&gt;My calendars&lt;/strong&gt; there by right clicking on the 3 dots menu (&amp;#8230;) that shows up when you hover the mouse around the calendar you want to share, and selecting &lt;strong&gt;&amp;#8220;Sharing and permissions&amp;#8221;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/office/calendar/sharing/calendars-share-00.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This brings up the current sharing setup and allows you to see who has access, and of what kind. At a minimum, you probably want to have a basic setting to let everyone in your organisation see when you&amp;#8217;re busy (so that they know if you&amp;#8217;re not available at a time when they want to meet you).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/office/calendar/sharing/calendars-share-01.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;You can enter an email address and it will ask you what permissions you want to allow them.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/office/calendar/sharing/calendars-share-02.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Most of the options are obvious enough:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Can view when I&amp;#8217;m busy: this shows them no details, just that you have something in your calendar at that time.&lt;/li&gt;
	&lt;li&gt;Can view titles and locations&lt;/li&gt;
	&lt;li&gt;Can view all details&lt;/li&gt;
	&lt;li&gt;Can edit: this lets them make changes&lt;/li&gt;
	&lt;li&gt;Delegate: this is a special setting, described below&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With these, you have some flexibility in how your calendar is visible to and handled by others. The special setup is &lt;strong&gt;Delegate&lt;/strong&gt; which allows them to act on your behalf. The description is as below.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/office/calendar/sharing/calendars-share-03.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;When assigning delegates, you can allow all calendar invitations to be sent to them also in addition to you &amp;#8211; this helps them manage your calendar better. Also, you can let them see the details of private events if they are also helping you with personal stuff, e.g., making sure that your kid&amp;#8217;s recital is in the calendar.&lt;/p&gt;
&lt;p&gt;Hope this helps! I&amp;#8217;d suggest that if these look like they work for you, find someone you trust in the organisation and try the settings together with them to make sure that you understand these before you start using them en masse.&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;ve seen earlier posts, you&amp;#8217;ll know that I am quite excited by using calendars, etc. for managing time and travel better. Earlier posts are here:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Part 1: &lt;a href=&quot;/2017/travel_calendars_timezones/&quot;&gt;Tips for travel, calendars and time zones&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Part 2: &lt;a href=&quot;/2023/travel_calendars_timezones_part_2/&quot;&gt;You&amp;#8217;re not using your calendar enough&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Feel free to connect or share the post (you can tag &lt;a href=&quot;https://x.com/onghu&quot;&gt;me as @onghu on X&lt;/a&gt; or on &lt;a href=&quot;https://ruby.social/@onghu&quot;&gt;Mastodon as @onghu@ruby.social&lt;/a&gt; or &lt;a href=&quot;https://bsky.app/profile/onghu.com&quot;&gt;@onghu.com on Bluesky&lt;/a&gt; to discuss more).&lt;/p&gt;</description>
        <pubDate>Sat, 21 Feb 2026 17:20:00 +0800</pubDate>
        <link>https://notepad.onghu.com/2026/outlook-calendars-sharing-howto/</link>
        <guid isPermaLink="true">https://notepad.onghu.com/2026/outlook-calendars-sharing-howto/</guid>
        
        <category>Productivity</category>
        
        <category>Outlook</category>
        
        <category>Calendar</category>
        
        <category>Corporate</category>
        
        
        <category>Productivity</category>
        
        <category>Outlook</category>
        
        <category>Calendar</category>
        
      </item>
    
      <item>
        <title>Ruby Tips 15 - Don't let UTC trip you up</title>
        <description>&lt;p&gt;If you&amp;#8217;re using Ruby and working with timestamps, there is a chance that every now and then, you need a timestamp converted to &lt;span class=&quot;caps&quot;&gt;UTC&lt;/span&gt; or back to some other time zone. In such, you probably expect to do &lt;code&gt;timestamp.utc&lt;/code&gt; and Ruby doesn&amp;#8217;t disappoint. You get the &lt;span class=&quot;caps&quot;&gt;UTC&lt;/span&gt; timestamp and you probably continue with something like &lt;code&gt;timestamp.utc.strftime (...)&lt;/code&gt; and it seems perfect.&lt;/p&gt;
&lt;p&gt;This is till you need to use the timestamp in the local time zone&amp;#8230; and you do:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;ruby&quot;&gt;# timestamp is in local time
puts timestamp.utc.strftime('%Y-%m-%d %H:%M') # output the UTC time
puts &quot;Local time: #{timestamp}&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You do this, and for some reason, it does not print it in the local time &amp;#8211; it shows it in &lt;span class=&quot;caps&quot;&gt;UTC&lt;/span&gt;. This tripped me up for a moment because I thought &lt;code&gt;timestamp&lt;/code&gt; should have stayed in local time.&lt;/p&gt;
&lt;p&gt;However, you need to know that &lt;code&gt;.utc&lt;/code&gt; changes the object itself into the &lt;span class=&quot;caps&quot;&gt;UTC&lt;/span&gt; timezone. It does not return a new object that is in &lt;span class=&quot;caps&quot;&gt;UTC&lt;/span&gt;, leaving the original intact. It&amp;#8217;s almost as if they should have called it &lt;code&gt;utc!&lt;/code&gt; because it changes original object. Someone &lt;a href=&quot;https://ruby.social/@aa/115903340079875839&quot;&gt;pointed out&lt;/a&gt;, though, that it&amp;#8217;s expected that it&amp;#8217;s not &lt;code&gt;utc!&lt;/code&gt; since that&amp;#8217;s usually only when there are two versions of a method and one is dangerous while the other one is not.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://docs.ruby-lang.org/en/master/Time.html#method-i-utc&quot;&gt;documentation on &lt;code&gt;utc&lt;/code&gt;&lt;/a&gt; if you read it simply says: &lt;code&gt;utc -&amp;gt; self: returns self, converted to the UTC timezone&lt;/code&gt; and the code sample shows that it&amp;#8217;s &lt;span class=&quot;caps&quot;&gt;UTC&lt;/span&gt; now. It&amp;#8217;s easy to miss &amp;#8211; especially since the method appears to do exactly what you want, so you don&amp;#8217;t read the documentation closely enough.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/ruby/ruby-tips-15-utc-01.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;So, what should you use instead?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you don&amp;#8217;t want the object to get changed and want another object that is in &lt;span class=&quot;caps&quot;&gt;UTC&lt;/span&gt;, use &lt;a href=&quot;https://docs.ruby-lang.org/en/master/Time.html#method-i-getutc&quot;&gt;&lt;code&gt;getutc&lt;/code&gt;&lt;/a&gt; (or its alias &lt;code&gt;getgm&lt;/code&gt;) &amp;#8211; it &lt;code&gt;Returns a new Time object representing time in UTC.&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The new documentation is a bit clearer on this!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/ruby/ruby-tips-15-utc-02.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Take care, and pick wisely!&lt;/p&gt;
&lt;p&gt;Feel free to connect or share the post (you can tag &lt;a href=&quot;https://x.com/onghu&quot;&gt;me as @onghu on X&lt;/a&gt; or on &lt;a href=&quot;https://ruby.social/@onghu&quot;&gt;Mastodon as @onghu@ruby.social&lt;/a&gt; or &lt;a href=&quot;https://bsky.app/profile/onghu.com&quot;&gt;@onghu.com on Bluesky&lt;/a&gt; to discuss more).&lt;/p&gt;</description>
        <pubDate>Fri, 23 Jan 2026 23:45:00 +0800</pubDate>
        <link>https://notepad.onghu.com/2026/ruby-tips-015-dont-let-utc-trip-you/</link>
        <guid isPermaLink="true">https://notepad.onghu.com/2026/ruby-tips-015-dont-let-utc-trip-you/</guid>
        
        <category>Ruby</category>
        
        <category>Programming</category>
        
        <category>Remember</category>
        
        <category>Tips</category>
        
        
        <category>Ruby</category>
        
        <category>Programming</category>
        
        <category>Tips</category>
        
      </item>
    
      <item>
        <title>Short: Add an OpenStreetMap (OSM) Layer in QGIS</title>
        <description>&lt;p&gt;It&amp;#8217;s easy to add an OpenStreetMap layer in &lt;a href=&quot;https://qgis.org/&quot;&gt;&lt;span class=&quot;caps&quot;&gt;QGIS&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;These are the steps:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Open the Layers menu&lt;/li&gt;
	&lt;li&gt;Select &lt;strong&gt;Add Layer&lt;/strong&gt; &amp;gt; &lt;strong&gt;Add &lt;span class=&quot;caps&quot;&gt;XYZ&lt;/span&gt; Layer&lt;/strong&gt;&lt;/li&gt;
	&lt;li&gt;In the menu that comes up, select &lt;strong&gt;OpenStreetMap&lt;/strong&gt;&lt;/li&gt;
	&lt;li&gt;At the bottom click &lt;strong&gt;Add&lt;/strong&gt; and &lt;strong&gt;Close&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/qgis/qgis-osm-01.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/qgis/qgis-osm-02.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Feel free to connect or share the post (you can tag &lt;a href=&quot;https://x.com/onghu&quot;&gt;me as @onghu on X&lt;/a&gt; or on &lt;a href=&quot;https://ruby.social/@onghu&quot;&gt;Mastodon as @onghu@ruby.social&lt;/a&gt; or &lt;a href=&quot;https://bsky.app/profile/onghu.com&quot;&gt;@onghu.com on Bluesky&lt;/a&gt; to discuss more).&lt;/p&gt;</description>
        <pubDate>Tue, 20 Jan 2026 23:30:00 +0800</pubDate>
        <link>https://notepad.onghu.com/2026/short-openstreetmap-in-qgis/</link>
        <guid isPermaLink="true">https://notepad.onghu.com/2026/short-openstreetmap-in-qgis/</guid>
        
        <category>Web Maps</category>
        
        <category>OpenStreetMap</category>
        
        <category>GIS</category>
        
        <category>QGIS</category>
        
        
        <category>OpenStreetMap</category>
        
        <category>Web Maps</category>
        
        <category>GIS</category>
        
        <category>QGIS</category>
        
      </item>
    
      <item>
        <title>Opinion: The Upcoming AI Coding Syndrome</title>
        <description>&lt;p&gt;Generative AI, LLMs, AI-assisted coding and such remind me of something I heard when I was learning Japanese almost 20 years ago &amp;#8211; the &amp;#8220;word processor syndrome&amp;#8221; or &amp;#8220;word processor language disorder&amp;#8221;.&lt;/p&gt;
&lt;p&gt;When I was learning the Japanese language, I remember being told about a concept called &amp;#8220;word processor syndrome&amp;#8221; or &amp;#8220;word processor language disorder&amp;#8221;. The premise was that the rise of electronic devices and word processors would lead to people becoming less proficient at writing Kanji (the Japanese pictographic script) though they would still be able to recognise and read Kanji well. They would just rely on computers (word processors, computers, mobile phones, etc.) to do the conversion while entering text and would only be skilled enough to pick the correct one from a set of options. The anxiety was that this woud impact traditional literacy and writing skills.&lt;/p&gt;
&lt;p&gt;I see parallels to AI-based code generation here &amp;#8211; there are many who seem to worry that relying on AI coding tools will impact our &amp;#8220;traditional literacy and skills&amp;#8221; to write code. There are others who are flag-bearers of new technology and are calling out the luddites for being stuck in the older ways. I think we probably still want to continue to learn how to program and design systems, but we will start to suffer from an &amp;#8220;AI Coding Syndrome&amp;#8221;. We will be able to prompt for some code to be generated and we will be able to read it and verify that it seems to be correct, but we might over time, lose the ability to write it easily and effectively ourselves. I see this at least for some of the simpler things already, e.g., create a rake task that does this and defaults to using these values, write code that exports the data to a database, create a parser that can handle this kind of text, and so on. It will increasingly be more productive to produce the code using a tool where less thinking is needed.&lt;/p&gt;
&lt;p&gt;I do, however, agree with some who are concerned that a lot depends on what the models are trained on, and we will run out of quality code to train models on for newer things. We will have to wait and see how this evolves, but I expect that programming will continue to exist and people will still need to learn programming (and they should) to do a good job &amp;#8211; just that the bar may be raised and it&amp;#8217;ll be expected that people can achieve more in the working day.&lt;/p&gt;
&lt;p&gt;For now, I feel that if I sign off some code or documentation, it is my responsiblity to assure people that it is of a certain quality &amp;#8211; so, the ability to review code and ensure that it is fit for purpose still rests with me. Over time, it&amp;#8217;s likely that the LLMs &amp;#8220;writing&amp;#8221; code will be able to provide that assurance and we will be able to trust the final output more &amp;#8211; much as how almost no one checks if a C++ compiler produced the exact assembly correctly.&lt;/p&gt;
&lt;p&gt;What do you think? If you have some comments, I&amp;#8217;d love to hear from you. Feel free to connect or share the post (you can tag &lt;a href=&quot;https://x.com/onghu&quot;&gt;me as @onghu on X&lt;/a&gt; or on &lt;a href=&quot;https://ruby.social/@onghu&quot;&gt;Mastodon as @onghu@ruby.social&lt;/a&gt; or &lt;a href=&quot;https://bsky.app/profile/onghu.com&quot;&gt;@onghu.com on Bluesky&lt;/a&gt; to discuss more).&lt;/p&gt;</description>
        <pubDate>Tue, 13 Jan 2026 23:20:00 +0800</pubDate>
        <link>https://notepad.onghu.com/2026/opinion-the-upcoming-ai-coding-syndrome/</link>
        <guid isPermaLink="true">https://notepad.onghu.com/2026/opinion-the-upcoming-ai-coding-syndrome/</guid>
        
        <category>Productivity</category>
        
        <category>Programming</category>
        
        <category>AI</category>
        
        
        <category>Programming</category>
        
        <category>Productivity</category>
        
        <category>AI</category>
        
      </item>
    
      <item>
        <title>RAISE: Evaluating if AI is helping me code</title>
        <description>&lt;p&gt;In 2026, as I hope to use AI coding tools, I am keen to follow a more disciplined approach to collect some data that I may be able to look back on after a few weeks or months to establish what value, if any, it brings me. Here&amp;#8217;s how I am planning to do that.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve been a programmer for many years now, and over the years, have moved from using C as my main programming language (when I was actually programming for most of the hours of my working day) to now using Ruby most of the time because I still enjoy programming and Ruby gives me probably the best overall outcome for the precious little time that I now get to program things.&lt;/p&gt;
&lt;p&gt;This has also meant that I more often build smaller tools and utilities rather than full-fledged prouction systems. The advent and proliferation of generative AI for assistance in coding and programming tasks has been met with a wide range of reactions, ranging from doom predictions to derision to optimism. I find it necessary to tune out the noise and reflect on where AI has been helpful in what I do, and more importantly, if it&amp;#8217;s actually saving me time in what I&amp;#8217;m doing.&lt;/p&gt;
&lt;h2&gt;Background: where I am today&lt;/h2&gt;
&lt;p&gt;For now, I use Kiro most frequently, and a bit of Microsoft Copilot, but usually not for coding tasks. I&amp;#8217;ve also used ChatGPT and Gemini a bit. For now, usage has been on small multi-hour activities rather than longer multi-week activities.&lt;/p&gt;
&lt;p&gt;Anecdotally, I have observed that AI tools have helped me with these tasks while programming:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Snippets, e.g., a method that parses text with a regular expresion and extracts some parts of it. This gets all the more powerful when you can show it a sample of the text to parse and let it figure the rest out, and then point it to edge cases to tune the code/ expression&lt;/li&gt;
	&lt;li&gt;Adding a &lt;span class=&quot;caps&quot;&gt;README&lt;/span&gt; based on the code&lt;/li&gt;
	&lt;li&gt;Explaining parts of the code and creating diagrams&lt;/li&gt;
	&lt;li&gt;Adding documentation to methods and files&lt;/li&gt;
	&lt;li&gt;Adding relatively standard features, e.g., export to database, create a rake task, parse some data, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&amp;#8217;ve seen less than optimal results also:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;When some code did not run as expected: on one occasion, I realised that the schema for the database was wrong, and was preventing the code from &amp;#8220;passing&amp;#8221; &amp;#8211; the tool kept wanting to try completely different things to get it to work somehow. I had to prompt it to &amp;#8220;stop&amp;#8221; and fix the code.&lt;/li&gt;
	&lt;li&gt;Trying to repeat the same activity: I observed this while using Copilot to parse chat logs and airline itineraries. It worked fine once and for one input, and with exactly the same prompt, it gave me completely different outputs the next time it was used.&lt;/li&gt;
	&lt;li&gt;While programming, I observed that the Ruby &lt;code&gt;Gemfile&lt;/code&gt; it created had really old versions of the gems in it. Of course, it&amp;#8217;s likely based on what it was trained on, but that doesn&amp;#8217;t stop me being surprised.&lt;/li&gt;
	&lt;li&gt;Interpreting the requirements is always tricky: in one case, it re-architected the system to meet a requirement that could have been done much more simply.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However, I must say that it appears that there are some benefits to using AI while programming, and there often are time savings. So, I do intend to continue to use AI more in 2026, but want to get more structured in evaluating if it helps and where it helps.&lt;/p&gt;
&lt;h2&gt;&lt;span class=&quot;caps&quot;&gt;RAISE&lt;/span&gt;: Reasonable AI Savings Estimate&lt;/h2&gt;
&lt;p&gt;There are two questions that come up in doing an estimate on the effort/ time savings because of using AI:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Estimates are just that &amp;#8211; estimates. I don&amp;#8217;t always have an estimate for how long the activity will take, especially if I started the work via exploration.&lt;/li&gt;
	&lt;li&gt;Numerous people talk about Generative AI over-engineering the solution. I am not yet ready to pass judgment on that observation, but I did find that it often did more than was strictly necessary, e.g., I wanted to do something in batches of 1000 elements but the code was designed to have a parameter that defaulted to 1000 but could be passed even from the command line. If I implemented those features, it would take me longer to finish, so that savings were larger than if I had only implemented what was strictly necessary for the task. So, which savings are correct?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For this reason, I am trying to follow what I call &lt;strong&gt;&lt;span class=&quot;caps&quot;&gt;RAISE&lt;/span&gt;: Reasonable AI Savings Estimate&lt;/strong&gt; and this is how it works. After the work is done, I look at the output and determine:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;How long did it take to get to exactly what has been done? This is basically how long I spent on it for prompting, evaluating the output, re-prompting, letting it run, changing some of the code, committing it to the repos, etc. If I did something else, then I try to reasonably remove that time.&lt;/li&gt;
	&lt;li&gt;Looking at the working solution now, I can see what meets my needs and what exceeds it, if anything. How &lt;em&gt;much longer&lt;/em&gt; would it have taken me to implement the version without all the extra bits, e.g., hard-coding some values that I don&amp;#8217;t expect will change, etc. I call this &lt;strong&gt;&lt;span class=&quot;caps&quot;&gt;RAISE&lt;/span&gt;-1&lt;/strong&gt;.&lt;/li&gt;
	&lt;li&gt;To get to exactly what has been done, now that I can see what was done and how, how &lt;em&gt;much longer&lt;/em&gt; would it have taken me compared to the time I spent? This is a gut-feeling estimate on everything that was implemented, including things that I may not have implemented if I was doing the full implementation. I call this &lt;strong&gt;&lt;span class=&quot;caps&quot;&gt;RAISE&lt;/span&gt;-2&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/ai/raise1-raise2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;With these three numbers, I now get, as an example:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Actual time spent: 3hr&lt;/li&gt;
	&lt;li&gt;Implementing only what I wanted (actual + &lt;span class=&quot;caps&quot;&gt;RAISE&lt;/span&gt;-1): 8hr&lt;/li&gt;
	&lt;li&gt;Implementing what was actually done (actual + &lt;span class=&quot;caps&quot;&gt;RAISE&lt;/span&gt;-2): 20hr&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, I can say:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Savings of 5hr ~ 17hr for this activity&lt;/li&gt;
	&lt;li&gt;Minimally, it should be taken as 5hr savings&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I would summarise it as: &lt;code&gt;3hr/8hr/20hr&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s say that one activity resulted in: &lt;code&gt;6hr/14hr/14hr&lt;/code&gt; &amp;#8211; it would mean that everything that was done is what I would have eventually done. Sometimes, it may be more than what I thought I originally needed, but getting to the end, it feels like I would have eventually implemented it.&lt;/p&gt;
&lt;p&gt;On something else, I might get it as: &lt;code&gt;3hr/1hr/2hr&lt;/code&gt; which would mean:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;It took 3hr including AI prompting&lt;/li&gt;
	&lt;li&gt;Actually, I could have got to what I wanted in 1hr if I did it (so, I lost 2hr)&lt;/li&gt;
	&lt;li&gt;What was finally implemented would have taken me 2hr (so, even with that, I lost 1hr)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I use and often log time in Redmine on the different activities that I do. At the end of the comment for time logged, I intend to add text like this: &lt;code&gt;~^RAISE:+2.5/+3.5/T^~&lt;/code&gt; to indicate that it saved me 2.5hr on what I needed to get done and a total of 3.5hr (including the extra items) and that it&amp;#8217;s a &lt;code&gt;T&lt;/code&gt; activity (T: Technical, N: Non-technical). This should be easy to extract and summarise in the future.&lt;/p&gt;
&lt;p&gt;A sample collection of logs for a task is as below.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/ai/raise-for-a-task.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Note that these are all estimates and that&amp;#8217;s the &amp;#8220;R&amp;#8221; and &amp;#8220;E&amp;#8221; refer to &amp;#8220;Reasonable&amp;#8221; and &amp;#8220;Estimates&amp;#8221; respectively. It depends on me looking back at the work and judging how much help it was. It&amp;#8217;s not perfect and it&amp;#8217;s not an exact science but it feels like a reasonable way to evaluate if the net impact is positive, and &amp;#8220;worth it&amp;#8221;.&lt;/p&gt;
&lt;p&gt;There is probably an argument to be made that in reality, the version with more features might require more actual time (to implement, verify, document, etc.) and it&amp;#8217;s not fair to keep the same &amp;#8220;actual time&amp;#8221; value for all cases. At this point, I am biased towards making progress in collecting this data, and letting that nuance pass. It might make sense in the future to see if a refinement is feasible and relevant.&lt;/p&gt;
&lt;h2&gt;The Good, Bad and Ugly Log&lt;/h2&gt;
&lt;p&gt;The other thing that I want to do is try to maintain a log of things that, in my experience with the tools I used, were done well, badly, and terribly. I hope that this will eventually give me a clearer idea of which things are best to automate with AI and which were quite bad at the time when I tried them. I don&amp;#8217;t have a formal way or format for this, but right now, it&amp;#8217;s just expected to be rows in a spreadsheet.&lt;/p&gt;
&lt;p&gt;What do you think? Are you using something? If you have some comments, I&amp;#8217;d love to hear from you. Feel free to connect or share the post (you can tag &lt;a href=&quot;https://x.com/onghu&quot;&gt;me as @onghu on X&lt;/a&gt; or on &lt;a href=&quot;https://ruby.social/@onghu&quot;&gt;Mastodon as @onghu@ruby.social&lt;/a&gt; or &lt;a href=&quot;https://bsky.app/profile/onghu.com&quot;&gt;@onghu.com on Bluesky&lt;/a&gt; to discuss more).&lt;/p&gt;</description>
        <pubDate>Thu, 08 Jan 2026 17:20:00 +0800</pubDate>
        <link>https://notepad.onghu.com/2026/raise-ai-benefits-estimation/</link>
        <guid isPermaLink="true">https://notepad.onghu.com/2026/raise-ai-benefits-estimation/</guid>
        
        <category>Productivity</category>
        
        <category>Programming</category>
        
        <category>AI</category>
        
        
        <category>Programming</category>
        
        <category>Productivity</category>
        
        <category>AI</category>
        
      </item>
    
      <item>
        <title>DuckDB - Autoincrement Primary Key</title>
        <description>&lt;p&gt;In previous posts, we went through &lt;a href=&quot;/2025/duck-db-windows-ruby/&quot;&gt;setting up DuckDB on Windows&lt;/a&gt;, &lt;a href=&quot;/2025/exploring-duckdb-part1/&quot; title=&quot;Part 1&quot;&gt;exploring DuckDB for common tasks&lt;/a&gt; involving importing data, aggregate queries and type casting and &lt;a href=&quot;/2025/exploring-duckdb-part2/&quot;&gt;Part 2&lt;/a&gt; around date and time functions. Now, we look at how we get an &lt;code&gt;AUTOINCREMENT&lt;/code&gt; field (usually as a default value for a primary key).&lt;/p&gt;
&lt;h2 id=&quot;background-sqlite3&quot;&gt;Background&lt;/h2&gt;
&lt;p&gt;If you&amp;#8217;ve used SQLite3 before, you know it&amp;#8217;s common syntax to create a table with &lt;code&gt;INTEGER PRIMARY KEY AUTOINCREMENT&lt;/code&gt; and then you can insert values without providing that field.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;sql&quot;&gt;-- Create the table
CREATE TABLE data (id INTEGER PRIMARY KEY AUTOINCREMENT, raw_data TEXT);

-- Insert data
INSERT INTO data (raw_data) VALUES ('hello'), ('world');
INSERT INTO data (raw_data) VALUES ('he'), ('wo'), ('we'), ('xv'), ('po');

-- See what we have
select * from data;
1|hello
2|world
3|he
4|wo
5|we
6|xv
7|po
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you take a look at the schema, you will see that SQLite3 automatically creates a table to store a sequence value for this auto-increment field.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;sql&quot;&gt;.tables
data
sqlite&amp;gt; .schema
CREATE TABLE data (id INTEGER PRIMARY KEY AUTOINCREMENT, raw_data TEXT);
CREATE TABLE sqlite_sequence(name,seq);

sqlite&amp;gt; select * from sqlite_sequence;
data|7
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But, not so in DuckDB.&lt;/p&gt;
&lt;h2 id=&quot;in-duckdb&quot;&gt;In DuckDB&lt;/h2&gt;
&lt;p&gt;DuckDB behaves slightly differently and will throw an error (at least as of now) if you try to do the same.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;sql&quot;&gt;$ duckdb tduck.db
DuckDB v1.4.3 (Andium) d1dc88f950
Enter &quot;.help&quot; for usage hints.
D CREATE TABLE data (id INTEGER PRIMARY KEY AUTOINCREMENT, raw_data TEXT);
Parser Error:
syntax error at or near &quot;AUTOINCREMENT&quot;

LINE 1: CREATE TABLE data (id INTEGER PRIMARY KEY AUTOINCREMENT, raw_data TEXT);
                                                  ^
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The solution is similar to what SQLite3 does automatically under the hood &amp;#8211; we need to create a sequence and replace &lt;code&gt;AUTOINCREMENT&lt;/code&gt; with a &lt;code&gt;DEFAULT&lt;/code&gt; that reads from the sequence. The way we do it is as below.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;sql&quot;&gt;D CREATE SEQUENCE seq_data_id START 1;
D .tables
D .schema

D CREATE TABLE data (id INTEGER PRIMARY KEY DEFAULT (nextval('seq_data_id')), raw_data VARCHAR);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, we create a sequence with a name (any name) and define its start value as 1 (that&amp;#8217;s optional, but might as well). After that, we define the &lt;code&gt;INTEGER PRIMARY KEY&lt;/code&gt; with a &lt;code&gt;DEFAULT (nextval ('seq_data_id'))&lt;/code&gt; which tells it to use the next value for the sequence that we defined. After this, it behaves as normal.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;sql&quot;&gt;D  insert into data (raw_data) VALUES ('hello'), ('world');
D insert into data (raw_data) VALUES ('he'), ('wo'), ('we'), ('xv'), ('po');
D select * from data;
┌───────┬──────────┐
│  id   │ raw_data │
│ int32 │ varchar  │
├───────┼──────────┤
│     1 │ hello    │
│     2 │ world    │
│     3 │ he       │
│     4 │ wo       │
│     5 │ we       │
│     6 │ xv       │
│     7 │ po       │
└───────┴──────────┘

D .tables
data
D .schema
CREATE TABLE IF NOT EXISTS &quot;data&quot;(id INTEGER DEFAULT(nextval('seq_data_id')) PRIMARY KEY, raw_data VARCHAR);
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;command-line-options&quot;&gt;Other Notes&lt;/h2&gt;
&lt;p&gt;A couple of other notes that don&amp;#8217;t need a separate post by themselves.&lt;/p&gt;
&lt;p&gt;(1) DuckDB can read SQLite3 database files just fine. So, you can open a SQLite3 database file and process it with DuckDB also. Since it&amp;#8217;s working with the table definition of SQLite3, you don&amp;#8217;t need to do anything special to manage &lt;span class=&quot;caps&quot;&gt;AUTOINCREMENT&lt;/span&gt; primary keys. It will just use SQLite3 as normal.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ duckdb test.db
DuckDB v1.4.3 (Andium) d1dc88f950
Enter &quot;.help&quot; for usage hints.
D select * from data;
┌───────┬──────────┐
│  id   │ raw_data │
│ int64 │ varchar  │
├───────┼──────────┤
│     1 │ hello    │
│     2 │ world    │
│     3 │ he       │
│     4 │ wo       │
│     5 │ we       │
│     6 │ xv       │
│     7 │ po       │
└───────┴──────────┘
D insert into data (raw_data) VALUES ('duck'), ('inserted');
D select * from data;
┌───────┬──────────┐
│  id   │ raw_data │
│ int64 │ varchar  │
├───────┼──────────┤
│     1 │ hello    │
│     2 │ world    │
│     3 │ he       │
│     4 │ wo       │
│     5 │ we       │
│     6 │ xv       │
│     7 │ po       │
│     8 │ duck     │
│     9 │ inserted │
└───────┴──────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(2) Of course, you can provide default values for other fields. For example, a &lt;code&gt;created_at&lt;/code&gt; field might be defined using &lt;code&gt;TIMESTAMP DEFAULT (CURRENT_TIMESTAMP)&lt;/code&gt; to use the current time as the default value on insertion, if it&amp;#8217;s not provided as in the sample below:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;sql&quot;&gt;CREATE TABLE data(
  id INTEGER DEFAULT(nextval('seq_fmbc_logid')) PRIMARY KEY,
  &quot;timestamp&quot;, raw_data VARCHAR NOT NULL,
  created_at TIMESTAMP DEFAULT(CURRENT_TIMESTAMP)
);
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;links-and-references&quot;&gt;Links and References&lt;/h2&gt;
&lt;p&gt;For DuckDB, all the relevant details are in the &lt;a href=&quot;https://duckdb.org/docs/stable/sql/statements/create_sequence&quot;&gt;official documentation about sequences&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you have some comments, I&amp;#8217;d love to hear from you. Feel free to connect or share the post (you can tag &lt;a href=&quot;https://x.com/onghu&quot;&gt;me as @onghu on X&lt;/a&gt; or on &lt;a href=&quot;https://ruby.social/@onghu&quot;&gt;Mastodon as @onghu@ruby.social&lt;/a&gt; or &lt;a href=&quot;https://bsky.app/profile/onghu.com&quot;&gt;@onghu.com on Bluesky&lt;/a&gt; to discuss more).&lt;/p&gt;</description>
        <pubDate>Tue, 30 Dec 2025 18:00:00 +0800</pubDate>
        <link>https://notepad.onghu.com/2025/exploring-duckdb-part3/</link>
        <guid isPermaLink="true">https://notepad.onghu.com/2025/exploring-duckdb-part3/</guid>
        
        <category>Programming</category>
        
        <category>DuckDB</category>
        
        <category>Database</category>
        
        <category>Analytics</category>
        
        
        <category>Programming</category>
        
        <category>Database</category>
        
        <category>DuckDB</category>
        
      </item>
    
      <item>
        <title>Ruby 4.0 on Windows: Day 0 - install and Hello World</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.ruby-lang.org/en/&quot;&gt;Ruby&lt;/a&gt; is a dynamic, open source programming language with a focus on simplicity and productivity. It has an elegant syntax that is natural to read and easy to write (from the Ruby web site). On Christmas Day 2025, as is tradition now, the core team released &lt;a href=&quot;https://www.ruby-lang.org/en/news/2025/12/25/ruby-4-0-0-released/&quot;&gt;version 4.0 &amp;#8211; the next major version with &lt;span class=&quot;caps&quot;&gt;ZJIT&lt;/span&gt; (not available on Windows yet) and experimental support for Ruby Box alongside other improvements and features&lt;/a&gt; &amp;#8211; that has been in development for some time and replace the working version &amp;#8220;Ruby 3.5&amp;#8221;. The Windows RubyInstaller site has just added Ruby 4.0 to its &lt;a href=&quot;https://rubyinstaller.org/downloads/&quot;&gt;downloads page&lt;/a&gt;, so let&amp;#8217;s get it up and running.&lt;/p&gt;
&lt;p&gt;This post will help you get started with Ruby 4.0 on Windows, and covers the basics of installation. This post is along the same lines of the post to &lt;a href=&quot;/2024/ruby3.4-windows-day0-install-hello_world/&quot;&gt;install Ruby 3.4.x&lt;/a&gt; or to install even older versions such as &lt;a href=&quot;/2023/ruby3.3-windows-day0-install-hello_world/&quot;&gt;Ruby 3.3.x&lt;/a&gt; / &lt;a href=&quot;/2023/ruby3.2-windows-day0-install-hello_world/&quot;&gt;Ruby 3.2.x&lt;/a&gt; | &lt;a href=&quot;/2022/ruby3.1-windows-day0-install-hello_world/&quot;&gt;Ruby 3.1.x&lt;/a&gt; | &lt;a href=&quot;/2021/ruby3-windows-day0-install-hello_world/&quot;&gt;Ruby 3.0.x&lt;/a&gt; and so on. There is one difference, though, this year &amp;#8211; I am writing this on a Windows 11 computer, so there might be some subtle Windows differences!&lt;/p&gt;
&lt;p&gt;Do note that &lt;a href=&quot;https://endoflife.date/ruby&quot;&gt;support has ended&lt;/a&gt; for Ruby versions up to and including Ruby 3.1 and support for Ruby 3.2 will end in March 2026. So, it&amp;#8217;s a good idea to move to a newer Ruby sooner rather than later!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This post was written for Ruby 4.0 but should work for other versions also, especially minor versions.&lt;/p&gt;
&lt;p&gt;As you know, there are a &lt;a href=&quot;/2025/windows-virtualisation-and-running-linux/&quot;&gt;few ways to run Linux or similar (containers, Windows Subsystem for Linux, or Virtual Machines) on Windows&lt;/a&gt; and of course, each of those has its own way to support Ruby &amp;#8220;under Windows&amp;#8221;. However, we want to focus more on the most direct and native way to run Ruby on Windows, so we will use the RubyInstaller.&lt;/p&gt;
&lt;p&gt;Ok, so it&amp;#8217;s Day 0 &amp;#8211; the day we set up Ruby on Windows and run a simple script. We will do the following:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Download and install Ruby 4.0 on Windows&lt;/li&gt;
	&lt;li&gt;Run a Ruby script&lt;/li&gt;
	&lt;li&gt;Install a gem&lt;/li&gt;
	&lt;li&gt;Set up pik for multiple Ruby versions&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Before we get started&lt;/h2&gt;
&lt;p&gt;A full Ruby installation, as we intend to do, will take upwards of approximately 900MB of disk space. I recommend that you set the folder to be compressed automatically by Windows so that it saves you space. This becomes important especially on SSDs where the space might be limited to start with anyway (and with the current increase in prices, all the more!)&lt;/p&gt;
&lt;div style=&quot;background-color: #e8f2fb; padding: 0.5em&quot;&gt;
&lt;p&gt;&lt;strong&gt;A quick note on the path:&lt;/strong&gt; I would strongly recommend that you install Ruby to a directory that has &lt;strong&gt;no spaces&lt;/strong&gt; in the path. Some of the tools have problems compiling extensions when there are spaces in the path. So, it&amp;#8217;s much better to install to &lt;code&gt;C:\Ruby40-x64&lt;/code&gt;  or &lt;code&gt;C:\Users\JSmith\Ruby40-x64&lt;/code&gt; rather than &lt;code&gt;C:\Users\John Smith\Ruby40-x64&lt;/code&gt;.&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;You can do this step after you finish the installation but it takes much longer than doing it now when the folder is empty so that Windows will automatically compress the files on the fly as they get written to the directory as part of the installation.&lt;/p&gt;
&lt;p&gt;So, this is what you need to do. In my case, I will use the directory path &lt;code&gt;d:\stack\ruby\Ruby40-x64&lt;/code&gt; and all screenshots will show that. Adjust accordingly if you use something like &lt;code&gt;C:\Ruby40-x64&lt;/code&gt; for your installation.&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;First, I create the folder &lt;code&gt;Ruby40-x64&lt;/code&gt; under the &lt;code&gt;d:\stack\ruby&lt;/code&gt; path &amp;#8211; this is where I will install Ruby 4.0&lt;/li&gt;
	&lt;li&gt;In Explorer then, right click on the new folder and click Properties which brings up a menu like the one you see below.&lt;br /&gt;
&lt;img src=&quot;/images/posts/ruby4win/d0/0_folder1.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
	&lt;li&gt;Click on Advanced&amp;#8230; which brings up the &amp;#8216;Advanced Attributes&amp;#8217; menu.&lt;br /&gt;
&lt;img src=&quot;/images/posts/ruby4win/d0/0_folder2.png&quot; alt=&quot;&quot; /&gt;&lt;/li&gt;
	&lt;li&gt;Check the setting for &amp;#8216;Compress contents to save disk space&amp;#8217; &amp;#8211; this will ensure that the file in this folder are compressed on the disk and will save you a lot of space on the installation. At the end of the installation, we will see how much!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Uninstalling an Older Version (optional)&lt;/h2&gt;
&lt;p&gt;Do you want to uninstall an older Ruby version? There are &lt;a href=&quot;/2022/uninstalling-ruby-on-windows/&quot;&gt;instructions on this page&lt;/a&gt; should you want to. If you need to run multiple versions of Ruby on the same PC, it&amp;#8217;s not a problem if you &lt;a href=&quot;/2021/ruby3-windows-pik-multiple-installations/&quot;&gt;use something like pik&lt;/a&gt; that we also discuss below.&lt;/p&gt;
&lt;h2&gt;Download and install Ruby on Windows&lt;/h2&gt;
&lt;p&gt;Head on over to the &lt;a href=&quot;https://rubyinstaller.org/downloads/&quot;&gt;RubyInstaller Downloads site&lt;/a&gt; and grab the package for &lt;code&gt;rubyinstaller-devkit-3.4.1-1-x64&lt;/code&gt; (it&amp;#8217;s approximately 138MB). Previously, there used to be 32-bit versions, but now, you&amp;#8217;ll see that there are only &lt;span class=&quot;caps&quot;&gt;ARM&lt;/span&gt; or x64 versions. I am on a 64-bit Windows PC, so I am going to get the x64 package. I don&amp;#8217;t have experience with Windows on &lt;span class=&quot;caps&quot;&gt;ARM&lt;/span&gt; yet (I don&amp;#8217;t have any such machine) but it probably works the same way. For widest compatibility with all types of gems including C native extensions, you should get the &amp;#8216;Ruby+Devkit&amp;#8217; package though if you only want the Ruby runtime, the package without Devkit (listed further down) would also work. I would recommend getting the package with Devkit. The screenshot below shows the different items listed on the page.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/ruby4win/d0/00_ri-site.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Run the dowloaded file. It may ask if you intend to install for all users or only for yourself. In my case, I just install for all users. You may then be presented with a screen asking if you intend to install this software. Expand the details and agree to proceed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The certificate used to sign the installer should show Lars Kanis. If it does, it is fine. Currently, it costs much more to get a different certificate that would result in this screen not being shown. Alternatives are being explored but you can trust this.&lt;/p&gt;
&lt;p&gt;Read and accept the license and click Next.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/ruby4win/d0/04_installer-04.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This takes us to the next page and asks us for the path, whether it should add Ruby to our system path and if it should associate Ruby files with this installation. I personally prefer to uncheck the second option so that I have more choice in which Ruby version runs the script. Ensure that the path shown matches the folder that we had set to be compressed. Adding it to the system path has the effect that when you open a new command window, it will directly use the newer version. If you don&amp;#8217;t really care which Ruby version you are using, then it may be better to let the installer add it to your path so that by default, you continue to use the latest version.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/ruby4win/d0/05_installer-05.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Since we created the folder before the installation (to set the attribute for compressing it), the Ruby installer will warn you that the folder already exists and will ask to confirm that it is OK to proceed. Our folder is empty and it is OK to go ahead! Click Yes.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/ruby4win/d0/06_installer-06.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;In general, it is a good idea to install all these components since it makes the documentation available to you offline, and also prepares the MSYS2 development toolchain which is needed for compiling native gems. Select everything and click Next.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/ruby4win/d0/06_installer-07.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;You will next see a lot of files being installed &amp;#8211; just let that go ahead. Depending on your computer, this will take up to a few minutes.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/ruby4win/d0/06_installer-08.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This finally comes to the screen that tells you that the main installation is done and the next step is to move on to the MSYS2 Setup. Check the option to &amp;#8216;Run ridk install&amp;#8217; so that it can proceed and click &amp;#8216;Finish&amp;#8217;. Note also the important links that are shown here.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/ruby4win/d0/06_installer-09.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;This then brings us the Command Line based installation for the MSYS2 toolchain. I would recommend that you either choose 1,2,3 or just use the default 1,3 at this stage.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/ruby4win/d0/07_ridk-1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Eventually, it comes to the prompt below and just press &lt;span class=&quot;caps&quot;&gt;ENTER&lt;/span&gt; at this stage again.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/ruby4win/d0/08_ridk-2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The installer will exit now and we are good to get started.&lt;/p&gt;
&lt;h2&gt;Is it all there?&lt;/h2&gt;
&lt;p&gt;Since the installation is all done, you should be able to open a new Command Line Prompt and type &lt;code&gt;ruby -v&lt;/code&gt; to see it run. This will just work if you added it to your &lt;span class=&quot;caps&quot;&gt;PATH&lt;/span&gt; in the earlier option. If you did not, you will need to add it to your &lt;span class=&quot;caps&quot;&gt;PATH&lt;/span&gt; by doing &lt;code&gt;PATH=D:\stack\ruby\Ruby40-x64\bin;%PATH%&lt;/code&gt; (use the correct path to where you installed it, by adding &lt;code&gt;\bin&lt;/code&gt; to the end).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/ruby4win/d0/09-its-up.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;So, yes, we have Ruby 4.0.0 on our computer now. We also installed everything to &lt;code&gt;D:\stack\ruby\Ruby40-x64&lt;/code&gt; and can go and take a look at the files and folders there. Talking about that folder, you can now right click on that folder and check properties again. The exact numbers might be different, but you will likely see something like this. On my computer, the actual file sizes are approximately 1.19GB but on disk, it&amp;#8217;s only taking 635MB &amp;#8211; so, I saved more than 550MB by setting the folder to be compressed. Also, since this is applied to all the files and folders, as you install more gems, those will also be automatically compressed and will continue to take up lesser disk space.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/ruby4win/d0/10_space.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h2&gt;Hello, World!&lt;/h2&gt;
&lt;p&gt;Let&amp;#8217;s write the simplest Hello World program and save it to a file called &lt;code&gt;hello.rb&lt;/code&gt;.&lt;/p&gt;
&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;table class=&quot;rouge-table&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td class=&quot;gutter gl&quot;&gt;&lt;pre class=&quot;lineno&quot;&gt;1
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nb&quot;&gt;puts&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Hello from Ruby &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;RUBY_VERSION&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;&lt;p&gt;Then, you can run this by doing:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ ruby hello.rb&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Using Interactive Ruby&lt;/h2&gt;
&lt;p&gt;Next, you can start up Interactive Ruby and try something in it to see it work.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ irb
irb(main):001&amp;gt;
irb(main):002&amp;gt; puts RUBY_VERSION
4.0.0
=&amp;gt; nil
irb(main):003&amp;gt; 3.times {puts &quot;Welcome.&quot;}
Welcome.
Welcome.
Welcome.
=&amp;gt; 3
irb(main):004&amp;gt; puts &quot;Rocking it on #{RUBY_VERSION}&quot;
Rocking it on 4.0.0
=&amp;gt; nil
irb(main):005&amp;gt; exit
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Working with gems&lt;/h2&gt;
&lt;p&gt;All Ruby programmers will install and use gems. In Ruby, we use &lt;code&gt;gem install [gem_name]&lt;/code&gt; which is shortcut for running the system command &lt;code&gt;gem&lt;/code&gt; (which could be done as &lt;code&gt;ruby -S gem install [gem_name]&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;You can check the version of &lt;code&gt;gem&lt;/code&gt; as below.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ gem -v
4.0.3
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Gems already installed&lt;/h3&gt;
&lt;p&gt;A lot of gems are installed as part of the Ruby installation. Do the following to see the list. It should show you something like the list below.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ gem list

*** LOCAL GEMS ***

abbrev (0.1.2)
base64 (0.3.0)
benchmark (0.5.0)
bigdecimal (4.0.1)
bundler (default: 4.0.3)
csv (3.3.5)
...
weakref (default: 0.1.4)
win32-registry (default: 0.1.2)
win32ole (1.9.2)
yaml (default: 0.4.0)
zlib (default: 3.2.2)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You will note that importantly bundler is installed and you will often use that when you start working seriously with Ruby.&lt;/p&gt;
&lt;h3&gt;Installing a gem&lt;/h3&gt;
&lt;p&gt;Let&amp;#8217;s install a gem into our new Ruby 4.0 install. You can skip this is you are not keen. For simplicity, we will install &lt;code&gt;sinatra&lt;/code&gt; which is a web development framework.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ gem install sinatra
Fetching tilt-2.6.1.gem
Using rubygems directory: C:/Users/Mohit/.local/share/gem/ruby/4.0.0
Successfully installed tilt-2.6.1
Fetching rack-3.2.4.gem
Successfully installed rack-3.2.4
Fetching base64-0.3.0.gem
Successfully installed base64-0.3.0
Fetching rack-session-2.1.1.gem
Successfully installed rack-session-2.1.1
Fetching logger-1.7.0.gem
Successfully installed logger-1.7.0
Fetching rack-protection-4.2.1.gem
Successfully installed rack-protection-4.2.1
Fetching ruby2_keywords-0.0.5.gem
Successfully installed ruby2_keywords-0.0.5
Fetching mustermann-3.0.4.gem
Successfully installed mustermann-3.0.4
Fetching sinatra-4.2.1.gem
Successfully installed sinatra-4.2.1
Parsing documentation for tilt-2.6.1
Installing ri documentation for tilt-2.6.1
Parsing documentation for rack-3.2.4
Installing ri documentation for rack-3.2.4
Parsing documentation for base64-0.3.0
Installing ri documentation for base64-0.3.0
Parsing documentation for rack-session-2.1.1
Installing ri documentation for rack-session-2.1.1
Parsing documentation for logger-1.7.0
Installing ri documentation for logger-1.7.0
Parsing documentation for rack-protection-4.2.1
Installing ri documentation for rack-protection-4.2.1
Parsing documentation for ruby2_keywords-0.0.5
Installing ri documentation for ruby2_keywords-0.0.5
Parsing documentation for mustermann-3.0.4
Installing ri documentation for mustermann-3.0.4
Parsing documentation for sinatra-4.2.1
Installing ri documentation for sinatra-4.2.1
Done installing documentation for tilt, rack, base64, rack-session, logger, rack-protection, ruby2_keywords, mustermann, sinatra after 9 seconds
9 gems installed
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, we know how to install gems now. Let&amp;#8217;s install a gem that is very helpful on Windows.&lt;/p&gt;
&lt;h2&gt;Installing pik when using multiple Ruby Installations&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/vertiginous/pik&quot;&gt;pik&lt;/a&gt; is a gem that allows you to switch between different Ruby installations on a Windows computer. Although it is no longer maintained according to the github page, I found that it still works fine for me. It also works with JRuby (not just Ruby) by updating the &lt;span class=&quot;caps&quot;&gt;PATH&lt;/span&gt; and other variables.&lt;/p&gt;
&lt;p&gt;Open a command prompt that has Ruby 4.0 on the path and do &lt;code&gt;gem install pik&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ gem install pik
Fetching pik-0.2.8.gem
Using rubygems directory: C:/Users/Mohit/.local/share/gem/ruby/4.0.0

----------------------------------------------------------------------------

*  If you're upgrading from a version &amp;lt;= 0.1.1, you'll want to delete the pik.bat file
   from all of your ruby versions. Gem uninstall should do the trick.

*  Install pik to a location that's in your path, but someplace other than your ruby\bin dir
   If you're upgrading from a more recent version, pik_install will overwrite the older files as needed.

    &amp;gt;path
      PATH=C:\tools\;C:\ruby\186-p368-mingw32\bin;C:\WINDOWS\system32;C:\WINDOWS

    &amp;gt;pik_install C:\tools

*  If this is a first-time install, add all the versions of ruby that you want to use with pik

    &amp;gt;pik add
    Adding:  186: ruby 1.8.6 (2009-03-31 patchlevel 368) [i386-mingw32]
     Located at:  c:/ruby/186-p368-mingw32/bin

    &amp;gt;pik add C:\ruby\IronRuby-091\bin
    Adding:  091: IronRuby 0.9.1.0 on .NET 2.0.0.0
     Located at:  C:/ruby/IronRuby-091/bin

    &amp;gt;pik add C:\ruby\jruby-1.4.0RC1\bin
    Adding:  140: jruby 1.4.0RC1 (ruby 1.8.7 patchlevel 174) (2009-09-30 80c263b) (Java HotSpot(TM) Client VM 1.6.0_14) [x86-java]
     Located at:  C:/ruby/jruby-1.4.0RC1/bin


----------------------------------------------------------------------------

Successfully installed pik-0.2.8
Parsing documentation for pik-0.2.8
Installing ri documentation for pik-0.2.8
Done installing documentation for pik after 1 seconds
1 gem installed
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first time you ever use pik on a computer, you will need to install it to a folder that is on your &lt;span class=&quot;caps&quot;&gt;PATH&lt;/span&gt; other than the bin folder of any Ruby installation. Two common options are to install it to &lt;code&gt;c:\windows\System32&lt;/code&gt; (you will need to use an adminstrator command prompt for that) or to create a folder such as &lt;code&gt;d:\tools&lt;/code&gt; for dropping executables of this kind and adding that folder to your system path. If you need help with any of these steps, just ask below and I will add the information here. Whichever folder you choose, do as shown below (but replace &lt;code&gt;D:\tools&lt;/code&gt; with the actual directory)&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;pik_install D:\tools&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next, you add the current Ruby that is on the path by doing &lt;code&gt;pik add&lt;/code&gt; as below.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ pik add
** Adding:  400: ruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [x64-mingw-ucrt]
 Located at:  D:\stack\ruby\ruby40-x64\bin
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Alternatively, you can add by using the full path to the Ruby installation &lt;code&gt;bin&lt;/code&gt; folder as shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ pik add D:\Ruby40-x64\bin&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, to see all the Ruby installations that you have, just do &lt;code&gt;pik list&lt;/code&gt; and you should get a list of Ruby versions that you have added. My list is shown below.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ pik list
  100: jruby 10.0.0.0 (3.4.2) 2025-04-13 6ed59bc847 OpenJDK 64-Bit Server VM 21.0.5+11-LTS on 21.0.5+11-LTS +indy +jit [x86_64-mswin32]
  187: ruby 1.8.7 (2013-06-27 patchlevel 374) [i386-mingw32]
  193: ruby 1.9.3p551 (2014-11-13) [i386-mingw32]
  224: ruby 2.2.4p230 (2015-12-16 revision 53155) [x64-mingw32]
  266: ruby 2.6.8p205 (2021-07-07 revision 67951) [x64-mingw32]
  274: ruby 2.7.4p191 (2021-07-07 revision a21a3b7d23) [x64-mingw32]
  300: ruby 3.0.3p157 (2021-11-24 revision 3fb7d2cadc) [x64-mingw32]
  311: ruby 3.1.1p18 (2022-02-18 revision 53f5fc4236) [x64-mingw-ucrt]
  320: ruby 3.2.0 (2022-12-25 revision a528908271) [x64-mingw-ucrt]
  330: ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x64-mingw-ucrt]
  341: ruby 3.4.1 (2024-12-25 revision 48d4efcb85) +PRISM [x64-mingw-ucrt]
* 400: ruby 4.0.0 (2025-12-25 revision 553f1675f3) +PRISM [x64-mingw-ucrt]
  921: jruby 9.2.13.0 (2.5.7) 2020-08-03 9a89c94bcc OpenJDK 64-Bit Server VM 25.265-b01 on 1.8.0_265-b01 +jit [mswin32-x86_64]
  928: jruby 9.2.18.0 (2.5.8) 2021-06-08 d67cb7d6e0 OpenJDK 64-Bit Server VM 25.265-b01 on 1.8.0_265-b01 +jit [mswin32-x86_64]
  932: jruby 9.3.2.0 (2.6.8) 2021-12-01 0b8223f905 OpenJDK 64-Bit Server VM 25.265-b01 on 1.8.0_265-b01 +jit [mswin32-x86_64]
  946: jruby 9.4.6.0 (3.1.4) 2024-02-20 576fab2c51 OpenJDK 64-Bit Server VM 25.265-b01 on 1.8.0_265-b01 +jit [x86_64-mswin32]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I seem to have quite a few! You can switch between versions by doing something like &lt;code&gt;pik 330&lt;/code&gt; or &lt;code&gt;pik 400&lt;/code&gt; and so on &amp;#8211; basically use the 3 digit code that it shows on the line at the start.&lt;/p&gt;
&lt;h2&gt;What&amp;#8217;s next?&lt;/h2&gt;
&lt;p&gt;You&amp;#8217;re ready to use Ruby 4.0 on Windows &amp;#8211; enjoy!&lt;/p&gt;
&lt;h2&gt;Links and References&lt;/h2&gt;
&lt;p&gt;Here are the main links:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Ruby website: &lt;a href=&quot;https://www.ruby-lang.org/en/&quot;&gt;https://www.ruby-lang.org/en/&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;RubyInstaller Website: &lt;a href=&quot;https://rubyinstaller.org/&quot;&gt;https://rubyinstaller.org/&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Download RubyInstaller for Windows: &lt;a href=&quot;https://rubyinstaller.org/downloads/&quot;&gt;https://rubyinstaller.org/downloads/&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;RubyInstaller Google Group: &lt;a href=&quot;https://groups.google.com/g/rubyinstaller?pli=1&quot;&gt;https://groups.google.com/g/rubyinstaller?pli=1&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Wiki: &lt;a href=&quot;https://github.com/oneclick/rubyinstaller2/wiki&quot;&gt;https://github.com/oneclick/rubyinstaller2/wiki&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;OK, so we have done enough for Day 0 &amp;#8211; we know how to install Ruby, run a script, install gems directly and switch between different Ruby installations. We are ready for more! If you found this post useful or would like to add more thoughts, feel free to share the post (you can tag &lt;a href=&quot;https://x.com/onghu&quot;&gt;me as @onghu on X&lt;/a&gt; or on &lt;a href=&quot;https://ruby.social/@onghu&quot;&gt;Mastodon as @onghu@ruby.social&lt;/a&gt; or &lt;a href=&quot;https://bsky.app/profile/onghu.com&quot;&gt;@onghu.com on Bluesky&lt;/a&gt; to discuss).&lt;/p&gt;</description>
        <pubDate>Sat, 27 Dec 2025 23:15:00 +0800</pubDate>
        <link>https://notepad.onghu.com/2025/ruby4.0-windows-day0-install-hello_world/</link>
        <guid isPermaLink="true">https://notepad.onghu.com/2025/ruby4.0-windows-day0-install-hello_world/</guid>
        
        <category>Ruby</category>
        
        <category>Programming</category>
        
        <category>RubyOnWindows</category>
        
        <category>Day0</category>
        
        
        <category>Ruby</category>
        
        <category>Programming</category>
        
        <category>RubyOnWindows</category>
        
      </item>
    
      <item>
        <title>Windows: Changing Icons for Office Files</title>
        <description>&lt;p&gt;I use small icons in Windows and the new Office icons are just not very good in a small size. In this post, we look at how to change the icons for the main Office document files (&lt;span class=&quot;caps&quot;&gt;XLSX&lt;/span&gt;, &lt;span class=&quot;caps&quot;&gt;DOCX&lt;/span&gt;, etc.) so that they are more visible at smaller icon sizes.&lt;/p&gt;
&lt;h2 id=&quot;background&quot;&gt;Background&lt;/h2&gt;
&lt;p&gt;The way to update the icons is to update the registry entries for the &lt;code&gt;Default Icon&lt;/code&gt; entry for the specific document types. There are a number of ways to get alternative icons (you can search online, download from a specific repository, etc.) but you need to make sure that these are either embedded in a &lt;span class=&quot;caps&quot;&gt;DLL&lt;/span&gt; or &lt;span class=&quot;caps&quot;&gt;EXE&lt;/span&gt; file or need to be converted into &lt;code&gt;.ICO&lt;/code&gt; files.&lt;/p&gt;
&lt;p&gt;My &lt;a href=&quot;/2025/windows-how-see-icons-in-exe-or-dll/&quot;&gt;previous post show how to inspect the icons that are embedded in a &lt;span class=&quot;caps&quot;&gt;DLL&lt;/span&gt; or &lt;span class=&quot;caps&quot;&gt;EXE&lt;/span&gt; file&lt;/a&gt; and how to count the icon number if there are multiple icons embedded in it. You can download &lt;span class=&quot;caps&quot;&gt;ICO&lt;/span&gt; files from online searches, but if you find a &lt;span class=&quot;caps&quot;&gt;PNG&lt;/span&gt; file that you want to use, you can use a website such as https://convertico.com/ to convert the file to an &lt;span class=&quot;caps&quot;&gt;ICO&lt;/span&gt; file.&lt;/p&gt;
&lt;p&gt;Once you have identified the icons you want to use, you are ready to get started.&lt;/p&gt;
&lt;p&gt;For this post, I will use alternative icons that are already &lt;a href=&quot;/2025/windows-how-see-icons-in-exe-or-dll/#icons-for-office-apps&quot;&gt;embedded in the Office icon collections&lt;/a&gt; for the different applications. I still think the older icons look better at smaller icon sizes but for now, these are better than the new ones.&lt;/p&gt;
&lt;h2 id=&quot;background&quot;&gt;Update the registry&lt;/h2&gt;
&lt;p&gt;You need to update the registry to make these changes. If you are not familiar with changing the registry, I recommend getting helpf from someone who is, because the registry is fragile and incorrect changes can make easily break things!&lt;/p&gt;
&lt;p&gt;If you are ready, here is the list of entries to update. You will see that all my paths were updated to &lt;code&gt;C:\Program Files\Microsoft Office\Root\VFS\Windows\Installer\{90160000-000F-0000-1000-0000000FF1CE}\__icon_file.dll__,__icon_number__&lt;/code&gt; since the Office icons are at this location now. The way to read the text below is:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;First, we have the registry folder, e.g., &lt;code&gt;[HKEY_CLASSES_ROOT\Word.Document.12\DefaultIcon]&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;Next, you have to update the only entry in that folder and point it to your new icon&lt;/li&gt;
	&lt;li&gt;I show what was originally there after that and finally, what it was changed to&lt;/li&gt;
	&lt;li&gt;Since I stayed within the Office icon DLLs, only the icon number changed. If you have a completely different path, you would need to change the full path to point to the new icon.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;*For Microsoft Word*
[HKEY_CLASSES_ROOT\Word.Document.12\DefaultIcon]
Original:
C:\Program Files\Microsoft Office\Root\VFS\Windows\Installer\{90160000-000F-0000-1000-0000000FF1CE}\wordicon.exe,13
New:
C:\Program Files\Microsoft Office\Root\VFS\Windows\Installer\{90160000-000F-0000-1000-0000000FF1CE}\wordicon.exe,4

[HKEY_CLASSES_ROOT\Word.Document.8\DefaultIcon]
Original:
C:\Program Files\Microsoft Office\Root\VFS\Windows\Installer\{90160000-000F-0000-1000-0000000FF1CE}\wordicon.exe,1
New:
C:\Program Files\Microsoft Office\Root\VFS\Windows\Installer\{90160000-000F-0000-1000-0000000FF1CE}\wordicon.exe,4

[HKEY_CLASSES_ROOT\Word.DocumentMacroEnabled.12\DefaultIcon]
Note: I did not change it yet.

[HKEY_CLASSES_ROOT\Word.Template.8\DefaultIcon]
Note: I did not change it yet.

[HKEY_CLASSES_ROOT\Word.Template.12\DefaultIcon]
Note: I did not change it yet.

*For Microsoft PowerPoint*
[HKEY_CLASSES_ROOT\PowerPoint.Show.12\DefaultIcon]
Original:
C:\Program Files\Microsoft Office\Root\VFS\Windows\Installer\{90160000-000F-0000-1000-0000000FF1CE}\pptico.exe,10
New:
C:\Program Files\Microsoft Office\Root\VFS\Windows\Installer\{90160000-000F-0000-1000-0000000FF1CE}\pptico.exe,8

[HKEY_CLASSES_ROOT\PowerPoint.Show.8\DefaultIcon]
Original:
C:\Program Files\Microsoft Office\Root\VFS\Windows\Installer\{90160000-000F-0000-1000-0000000FF1CE}\pptico.exe,17
C:\Program Files\Microsoft Office\Root\VFS\Windows\Installer\{90160000-000F-0000-1000-0000000FF1CE}\pptico.exe,8

[HKEY_CLASSES_ROOT\PowerPoint.SlideShow.8\DefaultIcon]
Note: I did not change it yet.

* For Microsoft Excel*
[HKEY_CLASSES_ROOT\Excel.Sheet.12\DefaultIcon]
Original:
C:\Program Files\Microsoft Office\Root\VFS\Windows\Installer\{90160000-000F-0000-1000-0000000FF1CE}\xlicons.exe,1
New:
C:\Program Files\Microsoft Office\Root\VFS\Windows\Installer\{90160000-000F-0000-1000-0000000FF1CE}\xlicons.exe,5

[HKEY_CLASSES_ROOT\Excel.Sheet.8\DefaultIcon]
Original:
C:\Program Files\Microsoft Office\Root\VFS\Windows\Installer\{90160000-000F-0000-1000-0000000FF1CE}\xlicons.exe,28
New:
C:\Program Files\Microsoft Office\Root\VFS\Windows\Installer\{90160000-000F-0000-1000-0000000FF1CE}\xlicons.exe,5

[HKEY_CLASSES_ROOT\Excel.CSV\DefaultIcon]
Original:
C:\Program Files\Microsoft Office\Root\VFS\Windows\Installer\{90160000-000F-0000-1000-0000000FF1CE}\xlicons.exe,28
New:
C:\Program Files\Microsoft Office\Root\VFS\Windows\Installer\{90160000-000F-0000-1000-0000000FF1CE}\xlicons.exe,3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By reading the name of the field you change, you will have some idea of what you&amp;#8217;re changing &amp;#8211; there are different registry folders for things like Templates, Macro-enabled documents, etc. and you can change the icons for each of these if you really want.&lt;/p&gt;
&lt;h2 id=&quot;refresh-icons&quot;&gt;Refresh the icons&lt;/h2&gt;
&lt;p&gt;It may be enough to just restart &lt;code&gt;explorer.exe&lt;/code&gt; after this is done. If that does not work, you might need to &lt;a href=&quot;/2025/windows-fix-corrupted-icons-display/&quot;&gt;remove the Icon Cache as discussed in my other post&lt;/a&gt; on this site.&lt;/p&gt;
&lt;h2 id=&quot;the-change&quot;&gt;What changed?&lt;/h2&gt;
&lt;p&gt;The screenshots below show how the icons looked before and after the change on a dark and light background. The old display is on the left and the new ones are on the right. I still think that the &amp;#8220;P&amp;#8221; or &amp;#8220;W&amp;#8221; in the icons is a bit small, but it is easier to identify.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/windows/office-icons/dark-icons.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/windows/office-icons/light-icons.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;h2 id=&quot;whats-next&quot;&gt;What&amp;#8217;s next?&lt;/h2&gt;
&lt;p&gt;First, we changed the default icon for only a few file types &amp;#8211; there are many more. See the screenshot below to get an idea of the ones for Excel alone. If you&amp;#8217;re dedicated enough, you could work through all of these. I only changed a few for the main file types I use.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/posts/windows/office-icons/many-default-icons.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Second, I think some of the older icons were even nicer &amp;#8211; see this one below, for example from &lt;a href=&quot;https://res-1.cdn.office.net/files/fabric/assets/item-types/48/docx.png&quot;&gt;https://res-1.cdn.office.net/files/fabric/assets/item-types/48/docx.png&lt;/a&gt; for Word documents:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://res-1.cdn.office.net/files/fabric/assets/item-types/48/docx.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt;There are a few places that you can look for these icons:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;This &lt;a href=&quot;https://github.com/loryanstrant/MicrosoftCloudLogos&quot;&gt;GitHub repository&lt;/a&gt; has a huge collection&lt;/li&gt;
	&lt;li&gt;There is some information on the &lt;a href=&quot;https://developer.microsoft.com/en-us/fluentui#/styles/web/file-type-icons&quot;&gt;FluentUI site&lt;/a&gt;&lt;/li&gt;
	&lt;li&gt;Also, there are third-party icon sites like &lt;a href=&quot;https://www.flaticon.com/free-icons/microsoft&quot;&gt;Flaticon&lt;/a&gt; that have other options for you to consider.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Please definitely check what license is used and how that applies to you before you use these repositories. I could not find a simple nice &lt;span class=&quot;caps&quot;&gt;ZIP&lt;/span&gt; file with older product icons that I am allowed to use.&lt;/p&gt;
&lt;p&gt;If you have some comments, I&amp;#8217;d love to hear from you. Feel free to connect or share the post (you can tag &lt;a href=&quot;https://x.com/onghu&quot;&gt;me as @onghu on X&lt;/a&gt; or on &lt;a href=&quot;https://ruby.social/@onghu&quot;&gt;Mastodon as @onghu@ruby.social&lt;/a&gt; or &lt;a href=&quot;https://bsky.app/profile/onghu.com&quot;&gt;@onghu.com on Bluesky&lt;/a&gt; to discuss more).&lt;/p&gt;</description>
        <pubDate>Mon, 22 Dec 2025 21:00:00 +0800</pubDate>
        <link>https://notepad.onghu.com/2025/windows-update-office-document-icons/</link>
        <guid isPermaLink="true">https://notepad.onghu.com/2025/windows-update-office-document-icons/</guid>
        
        <category>Windows</category>
        
        <category>Windows 10</category>
        
        <category>Windows 11</category>
        
        <category>Customisation</category>
        
        
        <category>Windows</category>
        
        <category>Customisation</category>
        
        <category>Office</category>
        
      </item>
    
  </channel>
</rss>
