Skip to content

Commit 5de3ea1

Browse files
committed
Implemented optional trace logging for the built-in update checker (and possibly more in the future).
1 parent ba59131 commit 5de3ea1

File tree

4 files changed

+139
-37
lines changed

4 files changed

+139
-37
lines changed

README.md

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,24 @@ The [.NET Framework 4.7.2](https://dotnet.microsoft.com/en-us/download/dotnet-fr
3232

3333
It is already included in Windows 10 v1803 (April 2018 Update) or later, and *all* versions of Windows 11.
3434

35-
# Program settings
35+
## Configuration
3636

37-
The initial program settings can be adjusted in the **`CertViewer.exe.config`** configuration file.
37+
The program settings can be adjusted in the **`CertViewer.exe.config`** configuration file:
3838

39-
All settings are specified in the **`/configuration/appSettings`** section:
39+
```xml
40+
<configuration>
41+
42+
<appSettings>
43+
<add key="SettingName1" value="SettingValue1" />
44+
<add key="SettingName2" value="SettingValue2" />
45+
46+
</appSettings>
47+
</configuration>
48+
```
49+
50+
### Settings
51+
52+
The following program settings are currently supported:
4053

4154
* **`DigestAlgorithm`**
4255
The digest algorithm to be used for "fingerprint" computation. Default value: `SHA256`.
@@ -57,7 +70,24 @@ All settings are specified in the **`/configuration/appSettings`** section:
5770
Keep the CertViewer window on top of all other windows. Default value: `True`.
5871

5972
* **`EnableUpdateCheck`**
60-
Automatically check for new program versions at startup. Default value: `True`.
73+
Automatically check for new program versions at application startup. Default value: `True`.
74+
75+
## Logging
76+
77+
Optional [tracing](https://en.wikipedia.org/wiki/Tracing_(software)) can be enabled in the **`CertViewer.exe.config`** configuration file:
78+
79+
```xml
80+
<configuration>
81+
82+
<system.diagnostics>
83+
<switches>
84+
<add name="Tracing" value="True" />
85+
</switches>
86+
</system.diagnostics>
87+
</configuration>
88+
```
89+
90+
You can use a program like Sysinternals [**`DebugView`**](https://learn.microsoft.com/en-us/sysinternals/downloads/debugview) to display the tracing messages generated by CertViewer.
6191

6292
## Website
6393

src/App.config

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
<?xml version="1.0" encoding="utf-8" ?>
22
<configuration>
3-
<startup>
3+
<startup>
44
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
55
</startup>
66
<appSettings>
7-
<!-- <add key="DigestAlgorithm" value="SHA1"/> -->
8-
<!-- <add key="MaximumInputLength" value="67108864"/> -->
9-
<!-- <add key="MonitorClipboard" value="False"/> -->
10-
<!-- <add key="ReverseNameOrder" value="False"/> -->
11-
<!-- <add key="Topmost" value="False"/> -->
12-
<!-- <add key="EnableUpdateCheck" value="False"/> -->
7+
<!-- <add key="DigestAlgorithm" value="SHA1" /> -->
8+
<!-- <add key="MaximumInputLength" value="67108864" /> -->
9+
<!-- <add key="MonitorClipboard" value="False" /> -->
10+
<!-- <add key="ReverseNameOrder" value="False" /> -->
11+
<!-- <add key="Topmost" value="False" /> -->
12+
<!-- <add key="EnableUpdateCheck" value="False" /> -->
1313
</appSettings>
14+
<system.diagnostics>
15+
<switches>
16+
<!-- <add name="Tracing" value="True" /> -->
17+
</switches>
18+
</system.diagnostics>
1419
</configuration>

src/Dialogs/MainWindow.xaml.cs

Lines changed: 54 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,13 @@
5656

5757
using CertViewer.Utilities;
5858

59+
using static CertViewer.Utilities.HttpNetClient;
5960
using static CertViewer.Utilities.NativeMethods;
6061
using static CertViewer.Utilities.Utilities;
61-
using static CertViewer.Utilities.HttpNetClient;
62+
63+
#if DEBUG
64+
#pragma warning disable CS0162
65+
#endif
6266

6367
namespace CertViewer.Dialogs
6468
{
@@ -103,9 +107,9 @@ public partial class MainWindow : WindowEx
103107
private readonly AtomicSwitch m_isPopupDialogShowing;
104108

105109
#if DEBUG
106-
private static readonly bool IS_DEBUG = true;
110+
private const bool IS_DEBUG = true;
107111
#else
108-
private static readonly bool IS_DEBUG = false;
112+
private const bool IS_DEBUG = false;
109113
#endif
110114

111115
// ==================================================================
@@ -123,10 +127,6 @@ public MainWindow()
123127
m_clipbrdTimer.Tick += OnClipboardChanged;
124128
ShowPlaceholder(true);
125129
LoadConfigurationSettings();
126-
if (IS_DEBUG)
127-
{
128-
Title += " [DEBUG]";
129-
}
130130
}
131131

132132
// ==================================================================
@@ -2158,25 +2158,46 @@ private static async void CheckForUpdates()
21582158
try
21592159
{
21602160
Tuple<Version, Version, DateTime> versionLocal = GetVersionAndBuildDate();
2161+
TraceLogger logger = new TraceLogger("CheckForUpdate");
21612162
HashCode hashCode = HashCode.Compute($"{versionLocal.Item1}\\{versionLocal.Item2}\\{GetUnixTimeSeconds() / 3593}");
21622163
ulong? lastUpdateCheck = ReadRegValue(REGISTRY_VALUE_NAME);
21632164
if ((!lastUpdateCheck.HasValue) || (lastUpdateCheck.Value != hashCode.Value))
21642165
{
2166+
logger.WriteLine($"Update check is starting...");
21652167
Version versionRemote = await Task.Run(() => CheckForUpdatesTask(VERSION_URL, SIGNKEY_PUB));
21662168
if (IsNotNull(versionRemote))
21672169
{
2168-
if (versionRemote.CompareTo(versionLocal.Item1) > 0)
2170+
try
21692171
{
2170-
const string message = "A new program version is available!\n\nInstalled version: {0}\nLatest available version: {1}\n\nIt is recommended that you upgrade to the new version. Do you want to download the new version now?";
2171-
if (MessageBox.Show(string.Format(message, versionLocal.Item1, versionRemote), "Update Notification", MessageBoxButton.YesNo, MessageBoxImage.Information) == MessageBoxResult.Yes)
2172+
if (versionRemote.CompareTo(versionLocal.Item1) > 0)
21722173
{
2173-
Process.Start(new ProcessStartInfo { FileName = WEBSITE_URL, UseShellExecute = true });
2174-
Application.Current.Shutdown();
2174+
const string message = "A new program version is available!\n\nInstalled version: {0}\nLatest available version: {1}\n\nIt is recommended that you upgrade to the new version. Do you want to download the new version now?";
2175+
logger.WriteLine($"New program version is available: {versionLocal.Item1} -> {versionRemote}");
2176+
if (MessageBox.Show(string.Format(message, versionLocal.Item1, versionRemote), "Update Notification", MessageBoxButton.YesNo, MessageBoxImage.Information) == MessageBoxResult.Yes)
2177+
{
2178+
Process.Start(new ProcessStartInfo { FileName = WEBSITE_URL, UseShellExecute = true });
2179+
Application.Current.Shutdown();
2180+
}
2181+
}
2182+
else
2183+
{
2184+
logger.WriteLine($"The installed program version is still up to date.");
21752185
}
21762186
}
2177-
WriteRegValue(REGISTRY_VALUE_NAME, hashCode.Value);
2187+
finally
2188+
{
2189+
WriteRegValue(REGISTRY_VALUE_NAME, hashCode.Value);
2190+
}
2191+
}
2192+
else
2193+
{
2194+
logger.WriteLine($"Failed to download new update information !!!");
21782195
}
21792196
}
2197+
else
2198+
{
2199+
logger.WriteLine($"Skipping update check this time.");
2200+
}
21802201
}
21812202
catch
21822203
{
@@ -2186,21 +2207,39 @@ private static async void CheckForUpdates()
21862207

21872208
private static Version CheckForUpdatesTask(string versionUrl, string verificationKey)
21882209
{
2210+
TraceLogger logger = new TraceLogger("ChckUpdateTask");
2211+
const int MAX_TRIES = 5;
21892212
Tuple<string, string> updateInfo;
2190-
for (int retry = 0; retry < 5; ++retry)
2213+
Version version;
2214+
for (int retry = 0; retry < MAX_TRIES; ++retry)
21912215
{
2216+
logger.WriteLine($"Downloading update information (attempt {retry+1}/{MAX_TRIES})");
21922217
try
21932218
{
21942219
if (IsNotNull(updateInfo = DownloadFileContents(versionUrl)))
21952220
{
2221+
logger.WriteLine( $"Update information: info=\"{updateInfo.Item1}\", signature=\"{updateInfo.Item2}\"");
21962222
if (VerifySignature(updateInfo.Item1, updateInfo.Item2, verificationKey))
21972223
{
2198-
Version version;
2224+
logger.WriteLine($"Signature is valid.");
21992225
if (Version.TryParse(updateInfo.Item1, out version))
22002226
{
2227+
logger.WriteLine($"Latest available program version is: {version}");
22012228
return version;
22022229
}
2230+
else
2231+
{
2232+
logger.WriteLine($"Failed to parse version string!");
2233+
}
22032234
}
2235+
else
2236+
{
2237+
logger.WriteLine($"Signature verification has failed -> discarding update information!");
2238+
}
2239+
}
2240+
else
2241+
{
2242+
logger.WriteLine($"Failed to download update information!");
22042243
}
22052244
}
22062245
catch

src/Utilities/Utilities.cs

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,30 @@ public static bool WriteRegValue(string valueName, ulong newValue)
564564
private static void DoEventsHelper() { }
565565
}
566566

567+
// ==================================================================
568+
// Trace Log
569+
// ==================================================================
570+
571+
public class TraceLogger
572+
{
573+
private readonly string m_loggerName;
574+
private static readonly Lazy<BooleanSwitch> TRACING = new Lazy<BooleanSwitch>(() => new BooleanSwitch("Tracing", "Enable optional trace outputs", "False"));
575+
576+
public TraceLogger(string name)
577+
{
578+
m_loggerName = string.IsNullOrWhiteSpace(name) ? string.Empty : name;
579+
}
580+
581+
public void WriteLine(FormattableString message)
582+
{
583+
try
584+
{
585+
Trace.WriteLineIf(TRACING.Value.Enabled, (FormattableString)$"[{m_loggerName}] {message}");
586+
}
587+
catch { }
588+
}
589+
}
590+
567591
// ==================================================================
568592
// Network Helper
569593
// ==================================================================
@@ -575,7 +599,8 @@ public static class SecurityProtocolTypeExt
575599

576600
public static class HttpNetClient
577601
{
578-
private const string USER_AGENT_STRING = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:141.0) Gecko/20100101 Firefox/141.0";
602+
private static readonly TraceLogger logger = new TraceLogger("HttpWebRequest");
603+
private const string USER_AGENT_STRING = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0";
579604

580605
static HttpNetClient()
581606
{
@@ -584,20 +609,17 @@ static HttpNetClient()
584609
// There exist some registry hacks to change the TLS versions that are enabled by default, but we do *not* want to rely on that method.
585610
try
586611
{
587-
try
588-
{
589-
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolTypeExt.Tls13;
590-
}
591-
catch
592-
{
593-
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
594-
}
612+
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolTypeExt.Tls13;
613+
}
614+
catch
615+
{
616+
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
595617
}
596-
catch { }
597618
}
598619

599620
public static Tuple<string, string> DownloadFileContents(string url)
600621
{
622+
logger.WriteLine($"Request URL: {url}");
601623
try
602624
{
603625
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
@@ -608,6 +630,7 @@ public static Tuple<string, string> DownloadFileContents(string url)
608630
request.ReadWriteTimeout = 8000;
609631
using (HttpWebResponse response = GetResponseNoThrow(request))
610632
{
633+
logger.WriteLine($"Response status: {response.StatusCode} ({(int)response.StatusCode})");
611634
if (IsSuccess(response.StatusCode))
612635
{
613636
using (Stream responseStream = response.GetResponseStream())
@@ -623,16 +646,21 @@ public static Tuple<string, string> DownloadFileContents(string url)
623646
lines.Add(line);
624647
if (lines.Count >= 2)
625648
{
649+
logger.WriteLine($"Response data received successfully.");
626650
return Tuple.Create(lines[0], lines[1]);
627651
}
628652
}
629653
}
630654
}
631655
}
656+
logger.WriteLine($"Response is empty or incomplete.");
632657
}
633658
}
634659
}
635-
catch { }
660+
catch (Exception exception)
661+
{
662+
logger.WriteLine($"Exception: {exception}");
663+
}
636664
return null;
637665
}
638666

0 commit comments

Comments
 (0)