Page 67 - MSDN Magazine, December 15, 2017
P. 67

Figure 5 Looking for the Registry, the Web API Crashes on Startup
Figure 6 Guarding the Registry Call
Unhandled Exception: System.TypeInitializationException: The type initializer for 'Microsoft.Win32.Registry' threw an exception. ---> System. PlatformNotSupportedException: Registry is not supported on this platform.
at Microsoft.Win32.RegistryKey.OpenBaseKeyCore(RegistryHive hKey, RegistryView view)
at Microsoft.Win32.Registry..cctor()
--- End of inner exception stack trace ---
at Fabrikam.Infrastructure.Logging.Logger.GetLoggingPath()
at Microsoft.AspNetCore.Hosting.Internal.WebHost.EnsureStartup()
at Microsoft.AspNetCore.Hosting.Internal.WebHost.EnsureApplicationServices() at Microsoft.AspNetCore.Hosting.Internal.WebHost.BuildApplication()
at Microsoft.AspNetCore.Hosting.WebHostBuilder.Build()
at Fabrikam.AssetManagement.WebApi.Program.BuildWebHost(String[] args) at Fabrikam.AssetManagement.WebApi.Program.Main(String[] args))
private static string GetLoggingPath() {
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
using (var key = Registry.CurrentUser.OpenSubKey( @"Software\\Fabrikam\\AssetManagement"))
{
if (key?.GetValue("LoggingDirectoryPath") is string configuredPath)
return configuredPath; }
}
var appDataPath = Environment.GetFolderPath( Environment.SpecialFolder.LocalApplicationData);
return Path.Combine(appDataPath, "Fabrikam", "AssetManagement", "Logging"); }
the project, the code no longer compiles because it uses APIs that aren’t part of .NET Standard.
In this case, the logging component reads settings from the registry to determine where the logs should be placed:
private static string GetLoggingPath() {
using (var key = Registry.CurrentUser.OpenSubKey( @"Software\\Fabrikam\\AssetManagement"))
{
if (key?.GetValue("LoggingDirectoryPath") is string configuredPath)
return configuredPath;
can’t call a Windows-only API. This might mean using a Linux-specific API, replacing the Windows-only concept with one that’s cross- platform, or simply doing nothing. The latter can make sense if you just want to provide some extra value for customers who are running on Windows, as in this case.
Understanding Windows-Only Dependencies
Something tells me that reading the last paragraphs made you slightly uneasy. I bet you’re wondering how you can use the Com- patibility Pack safely in code you plan to migrate later or in code you know will need to run on Linux. You might even go so far as to conclude that this whole idea is diluting the promise of .NET Standard, which is about building libraries that can work on any .NET implementation and on any OS.
We don’t think it’s that dire because:
Being able to call non-portable APIs is convenient and powerful. At first, it’s tempting to think you’re better off if these APIs wouldn’t be available at all. But consider the exam- ple of Fabrikam’s shared library: It’s much easier to just call the API under a guard than it is having to split, especially if your library needs just a very few Windows-only APIs. Of course, it might still make sense to refactor your code to not depend on platform-specific APIs—it just means you have the choice not to, if only temporarily.
Non-portable APIs aren’t available by default. Having many Windows-only APIs is the primary reason why the APIs in Compatibility Pack aren’t part of .NET Standard. We want to make sure that what .NET Standard offers by default works everywhere.
}
}
var appDataPath = Environment.GetFolderPath( Environment.SpecialFolder.LocalApplicationData);
return Path.Combine(appDataPath, "Fabrikam", "AssetManagement", "Logging");
That’s because the WPF desktop application happens to store its settings in the registry. Ideally, Fabrikam would refactor the applica- tion and would no longer store settings in the registry, but it would like to do this as a separate work item and not block the migration. The easiest way to get unblocked is by adding the compatibility pack. To do this, the company installs Microsoft.Windows.Compatibility. After the package is installed, the code compiles again. Fabrikam validates that both the WPF desktop application and the Web API continue to work with the newly created .NET Standard library.
At this point, you might wonder what happens if this code runs on Linux. So, let’s do a fast-forward and see what happens when Fabrikam completes the migration of the Web API back end to .NET Core and starts to migrate from Windows to Linux. During startup, the Web API app configures, among other things, the log- ging infrastructure. As you might expect, that doesn’t work so well because it calls into the registry to
determine the path where the logs
should be placed. And, sure enough,
the Web API crashes on startup with
an exception, as shown in Figure 5.
The fix for this is simple: Fabrikam needs to guard the registry call with a platform check, as shown in Figure 6.
In this case, the fix was straight- forward as the code already handled the situation where the registry didn’t contain a configuration for the logging path. In general, you need to decide what the fallback logic is when you
msdnmagazine.com
Figure 7 API Analyzer Warns When Non-Portable APIs Are Used
Dec. 15, 2017 / Connect(); Special Issue 63



















































   65   66   67   68   69