Roland Weigelt

Born to Code

  • Save and Restore Webcam Properties with CamProps 1.3.0

    CamProps is a free utility for quickly adjusting and managing the properties of webcams and other video capture devices. I wrote it when I struggled with my Logitech C920 that required some manual tweaking to achieve a good picture quality. CamProps enables you to store and quickly recall settings which comes in handy if you have different lighting situations in your room – or when the webcam once again simply “forgets” its settings.

    About this version

    After the release of 1.2.1 (which moved from .NET 5 to 6), some users reported that their webcams no longer showed up in CamProps. The issue occurred only with the release version, but not the debug version of the executable.

    Version 1.3.0 adds optional logging that can be enabled via the “•••” menu in the upper-right corner of the window. Originally intended to help with analyzing the issues of 1.2.1, the changes introduced to the code (even if logging is not active) seem to have fixed the problem. Because accessing the video devices involves COM, this does not come as a complete surprise.

    Where can I get it?

    You can download CamProps at

    Which devices can I use?

    CamProps works with all webcams and video capture devices that support opening the webcam driver property dialog (either the default provided by Windows or a specific dialog by the manufacturer's driver).

    For instance, when you press the “” button for a Logitech C920 without the Logitech software installed, this will open the following dialog:

    (This dialog may look different for other devices)

  • Trying out What ChatGPT Knows About XML Doc Comments

    Back in 2003, I started a Visual Studio add-in called “GhostDoc” that used some simple heuristics to create basic XML doc comments as a starting point for writing the “real” documentation (remarks on the purpose, edge cases, special parameter values, etc. but not implementation or other internals). GhostDoc did not really understand the English language, but relied on recommended naming conventions of the .NET Framework. Later versions were also able to use documentation of base classes and interfaces.

    I worked on GhostDoc until 2009 when SubMain acquired the rights to the software. Since then, the topic of documentation continues to play an important role for me. Some of my hobby projects have a considerable amount of old code that has not been modified for years, and thus is used more like a third-party library. It is not uncommon that I come across a helpful <remark> tag that I added to the auto-generated XML doc comment for an “obvious” function  – wondering whether I would have written the remark back then if I had to write all the boiler text myself.

    Trying out ChatGPT

    When I got around to playing with ChatGPT, one thing I wondered whether it could write XML doc comments. So here is how that went:

    My question to ChatGPT:

    In the context of the .NET framework and the C# language, do you know what an XML doc comment is?

    ChatGPT’s answer:

    Yes, I'm familiar with XML doc comments in the context of .NET framework and C# language. XML doc comments are special comments that are used to document code elements such as classes, methods, properties, events, and parameters in C# code. They are written using XML syntax and provide a way to add documentation directly to the source code, which can be later extracted and used to generate documentation for the code.

    XML doc comments begin with three forward slashes (///) in C# and are placed immediately before the code element that is being documented. They can contain various XML tags such as <summary>, <param>, <returns>, <example>, etc., to provide structured documentation for the code element. For example, the <summary> tag can be used to provide a summary of what a code element does, the <param> tag can be used to document parameters of a method, and the <returns> tag can be used to document the return value of a method.

    XML doc comments are commonly used by developers to generate API documentation using tools such as Visual Studio's IntelliSense or third-party documentation generators like Sandcastle or DocFX. They can also be used to provide documentation for library users to understand how to use the code correctly and effectively.


    Could you write an XML doc comment for a function with the following signature: public string GetDetailedExceptionMessage(Exception exception)


    Sure! Here's an example of an XML doc comment for the given function signature:

    /// <summary>
    /// Gets a detailed exception message that includes the exception message,
    /// inner exception message(s), and stack trace information.
    /// </summary>
    /// <param name="exception">The exception for which to retrieve the detailed message.</param>
    /// <returns>
    /// A string containing the detailed exception message, including the exception message,
    /// inner exception message(s), and stack trace information.
    /// </returns>
    public string GetDetailedExceptionMessage(Exception exception)
    // Implementation goes here

    [… rest of answer omitted for brevity …]

    That is pretty impressive.

    And no, I do not have plans to write an XML doc generator using ChatGPT…

  • Emaroo 5.1.0 - Support for Typora (Markdown Editor)

    Emaroo is a free utility for browsing most recently used (MRU) file lists of programs like Visual Studio, VS Code, Word, Excel, PowerPoint, Photoshop, Illustrator and more. Quickly open files, jump to their folder in Windows Explorer, copy them (and their path) to the clipboard - or run your own tools on files and folders with custom actions!

    About this release

    • Added: Support for documents and directories most recently opened in Typora.

    About Typora

    Typora ( is a fantastic markdown editor available for Windows, macOS, and Linux. The first thing you will notice is that the live preview is not a side-by-side split view like in other editors. You can use Typora both like a WYSIWYG editor (with many usual hotkeys like Ctrl+B for bold, Ctrl+I for italic, Ctrl+K for links) and as a text editor that you type the raw Markdown code into.

    This is what the display looks like when the text cursor is inside the Markdown code for a link:

    As soon as you move the text cursor outside the link, the Markdown code disappears:

    Creating tables is an absolute highlight. You simply type the column headers in Markdown…

    …press Enter, and you get an interactive table editor:

    In addition to the solid core mechanics, Typora offers extensive export options (HTML, PDF, DOCX, and many more), theme support, and a constantly growing feature set while keeping the UI distraction-free.

    Typora is a commercial product at a very fair price ($14.99 plus taxes for up to three devices, 15-day trial phase). And no, I am not paid to write this, I am just a happy user.

    For more information, see the website at

  • How to (Find the Option to) Enable Separator Lines for C# in Visual Studio

    Today I learned that Visual Studio can display separator lines between methods. The lines are enabled for VB.Net by default, but not for C# (which is why I did not know this option exists in the first place).

    It turned out that knowing what to do is only half the way, though.

    How to do it

    Open the Options dialog (Tools > Options), navigate to Text Editor > C# > Advanced and tick the checkbox “Show procedure line separators”. Sounds easy enough.

    Unfortunately, the option is not visible at first:

    You have to scroll down a considerable number of lines to find the option, and it is very easy to scroll past it:

    (Hint: It’s the fifth option from the bottom)

    Use the search…

    Navigating to the option is much easier if you use the dialog’s search feature. Type “separator” into the search box and the dialog will scroll to the option, highlighting the search term:

    As a side note, when it comes to a search feature as part of the UI, there tend to be two large groups of people: Those who use the search all the time and those who for some reason did not even notice it in the first place (maybe because it did not exist when they started using the product many years ago).

    … but not all searches are equal

    In addition to the search feature of the Options dialog, Visual Studio also has a global search feature, which will find the option as well:

    A small drawback is that you do not get the highlight for the search term (but at least the option is now at the bottom of the visible area):

    A workaround is to press Ctrl+A, Ctrl+C (i.e., copy the search term to the clipboard) before hitting Enter in the global search. Then, when the Options dialog opens, you continue with Ctrl+E, Ctrl+V to paste the search term into the text box. This will make the highlight visible.

  • Convert GUIDs to a Shorter Textual Representation and Back

    The shortest textual representation of a GUID available out-of-the-box is with ToString("N"), which will create a string of 32 characters, e.g.:


    If you have several GUIDs next to each other, e.g., in columns in an Excel file, they can take up a considerable amount of space. For my use case (Excel export/import of data from/to an application), hiding the columns was not an option, as I needed to be able to take a look at the GUIDs. Not for the actual value, just to notice differences and patterns in the data.

    Behind the scenes, a GUID consists of 128 bits. Converting the bits to a (case-insensitive) hex number as done with ToString("N")  leaves some room for improvement. The usual choice for a better conversion from binary to text is base64 encoding, which is described in This encoding creates text that consists of case-sensitive letters, digits, and only a few special characters (more on that later).

    The .NET framework offers the functions Convert.ToBase64String() and Convert.FromBase64String(), so implementing the conversion is straightforward.

    Details worth noting

    • The result of Convert.ToBase64String(someGuid.ToByteArray()) is a string that always ends on two padding characters (“==”). These can be removed and added back later for a conversion into the other direction.
    • The base64 encoding uses the characters “+” and “/”. Depending on your scenario, this may cause issues, so replacing them with different characters is an option. In my case, I did not feel comfortable having arithmetic operators around in Excel, even though they do not cause trouble unless a cell value starts with “=”. This is why my code uses the characters “_” and “$” instead.

    The code

    I wrote a helper class with two functions and published it on

    The following code

    var originalGuid = Guid.NewGuid();
    Console.WriteLine($"From GUID   : {originalGuid:N}");
    var shortId=ShortGuidHelper.GetShortId(originalGuid);
    Console.WriteLine($"To short ID : {shortId}");
    var recreatedGuid=ShortGuidHelper.GetGuid(shortId);
    Console.WriteLine($"Back to GUID: {recreatedGuid:N}");

    results in output similar to this:

    From GUID   : b91d07b8826e4233ba40142603cff7ef
    To short ID : uAcduW6CM0K6QBQmA8$37w
    Back to GUID: b91d07b8826e4233ba40142603cff7ef

    Ten characters saved for one GUID may not be much, but with several GUIDs next to each other, it still adds up.

  • HTML/CSS: How to (Maybe) Prevent the Text of a Time Display from Jiggling Around, Part 2

    In my previous blog post, I described how to deal with text output of time codes (e.g., hours:minutes:seconds) in Windows Presentation Foundation (WPF) when using a font where not all digits take up the same space.

    This article is a short follow-up on how to solve this issue in HTML/CSS.

    What to do in CSS

    Here is the default behavior for the “Impact” typeface:

    After setting font-variant-numeric: tabular-nums; in CSS, the result is

    Why the “Maybe” in the title?

    Not all fonts actually support the feature; for more information, see the WPF version of the article.


  • WPF: How to (Maybe) Prevent the Text of a Time Display from Jiggling Around

    Imagine you want to develop a time display that is updated in quick succession, e.g., the timecode during media playback. One unexpected problem that you may run into, depending on the typeface you use, is that the time display shifts to the left or right after updates.

    Why you may not notice it at first

    When you create a WPF application and do not specify the FontFamily, text output uses the system font of your operating system. The default is “Segoe UI”, a typeface where all digits take up the same space:

    If you change to, e.g., the “Impact” typeface (FontFamily="Impact"), the digit “1” takes up less space than, e.g., a “0”:

    Granted, a time display usually does not jump from “00:00:00” straight to “11:11:11”. But even if just one digit changes, the different width is still noticeable:

    For “Impact”, the digits “1” and “7” take up the same space, “2” and “4” are different, and “0”, “3” as well as “5” to “9” have the same width. So from “0” to “5”, the width changes every second, creating the visual effect of the time display “jiggling” left and right.

    What to do

    The Typography class provides access to various OpenType typography properties. The property Typography.NumeralAlignment is intended to control the alignment of digits (note the choice of the word “intended”, more on that later).

    If you set Typography.NumeralAlignment="Tabular" on a TextBlock or a Run, all digits take up the same width:

    Note how the glyph of the “1” does not change, it is just laid out differently.

    In contrast, the typeface “Bahnschrift” (introduced with Windows 10 version 1704) actually changes the glyph:



    What about the “Maybe” in the title?

    Unfortunately, not all fonts support modifying the numeral alignment. Text set in “Arial”, for instance, is not affected by setting  Typography.NumeralAlignment="Tabular":

    In general, setting the numeral alignment does not hurt, but if you want to be certain, you obviously have to try it out.

    Here are the results of testing fonts that come with Windows and that have different widths for digits:

    • “Tabular” does work for:
      • Candara
      • Comic Sans MS
      • Constantia
      • Corbel
      • Impact
    • “Tabular” does not work for:
      • Arial
      • Gabriola
      • Georgia


  • Emaroo 5.0.0 - Support for Adobe CC 2023

    Emaroo is a free utility for browsing most recently used (MRU) file lists of programs like Visual Studio, VS Code, Word, Excel, PowerPoint, Photoshop, Illustrator and more. Quickly open files, jump to their folder in Windows Explorer, copy them (and their path) to the clipboard - or run your own tools on files and folders with custom actions!

    About this release

    • Added: Support for Photoshop/Illustrator/InDesign CC 2022.
    • Changed: Start menu folder renamed to just “Emaroo”.
  • A Swiss Army Knife for Developers: DevToys

    Recently, I came across a wonderful tool called DevToys. It combines many common developer tasks like converting, encoding/decoding, formatting or escaping/unescaping text in one tool. DevToys can also generate UUIDs, “Lorem ipsum” texts, checksums and hashes. And it offers so much more (e.g., regex tester, text diff, Markdown preview) – here is a complete list.

    A nice touch is that DevToys can detect and highlight tools that match the content of your clipboard (the feature can be disabled in the settings if you are not feeling comfortable with this).

    Where to get DevToys

    You can install DevToys from the Microsoft Store or download it from GitHub. Other deployment options (WinGet, Chocolatey) are also available.

    For more information, see the DevToys website:

    For source code and issue tracking, visit DevToys on GitHub

  • Anti-Patterns for Software Features: Pony, Unicorn, Baby


    A feature that someone, who is not part of the actual implementation, demands for the wrong reasons. For example, because of a desire to follow some current trend, political maneuvering, an unhealthy fascination with technology, or maybe infatuation with his/her intelligence.


    A feature with unrealistic requirements. Low-cost, high-performance, with perfect user experience, bug-free, delivered yesterday.


    A feature that a member of the project team wants to implement – or even worse – has already implemented. The emotional attachment makes it hard to abandon the “baby”, even if it would be better for the overall project.