Azure-sdk-for-net: ArgumentException on Mono

Created on 23 Jun 2017  路  8Comments  路  Source: Azure/azure-sdk-for-net

We have some components that target .NET Framework 4.6 when built, but run on Linux via Mono. In one of those components, we use the Azure KeyVault client, which uses the Microsoft.Rest.ServiceClient class from here.

We had one exception with ADAL, which we have a workaround for and they are fixing for the next version.

However we also have another exception, only when running on Linux:

Unhandled Exception:
System.ArgumentException: Value does not fall within the expected range.
  at System.Net.Http.Headers.Parser+Token.Check (System.String s) [0x00019] in <f9ac0c719f3449a0aa7ac0136a1ad250>:0
  at System.Net.Http.Headers.ProductHeaderValue..ctor (System.String name, System.String version) [0x0000a] in <f9ac0c719f3449a0aa7ac0136a1ad250>:0
  at System.Net.Http.Headers.ProductInfoHeaderValue..ctor (System.String productName, System.String productVersion) [0x00006] in <f9ac0c719f3449a0aa7ac0136a1ad250>:0
  at Microsoft.Rest.ServiceClient`1[T].get_DefaultUserAgentInfoList () [0x0003f] in <7d943830d9bc44fab4bd01d7a9130a9c>:0
  at Microsoft.Rest.ServiceClient`1[T].SetUserAgent (System.String productName, System.String version) [0x00010] in <7d943830d9bc44fab4bd01d7a9130a9c>:0
  at Microsoft.Rest.ServiceClient`1[T].InitializeHttpClient (System.Net.Http.HttpClient httpClient, System.Net.Http.HttpClientHandler httpClientHandler, System.Net.Http.DelegatingHandler[] handlers) [0x00092] in <7d943830d9bc44fab4bd01d7a9130a9c>:0
  at Microsoft.Rest.ServiceClient`1[T].InitializeHttpClient (System.Net.Http.HttpClientHandler httpClientHandler, System.Net.Http.DelegatingHandler[] handlers) [0x00000] in <7d943830d9bc44fab4bd01d7a9130a9c>:0
  at Microsoft.Rest.ServiceClient`1[T]..ctor (System.Net.Http.HttpClientHandler rootHandler, System.Net.Http.DelegatingHandler[] handlers) [0x00006] in <7d943830d9bc44fab4bd01d7a9130a9c>:0
  at Microsoft.Rest.ServiceClient`1[T]..ctor (System.Net.Http.DelegatingHandler[] handlers) [0x00006] in <7d943830d9bc44fab4bd01d7a9130a9c>:0
  at Microsoft.Azure.KeyVault.KeyVaultClient..ctor (System.Net.Http.DelegatingHandler[] handlers) [0x00000] in <b66b7a9568464c98a370d795acdef11c>:0
  at Microsoft.Azure.KeyVault.KeyVaultClient..ctor (Microsoft.Rest.ServiceClientCredentials credentials, System.Net.Http.DelegatingHandler[] handlers) [0x00000] in <b66b7a9568464c98a370d795acdef11c>:0
  at Microsoft.Azure.KeyVault.KeyVaultClient..ctor (Microsoft.Azure.KeyVault.KeyVaultClient+AuthenticationCallback authenticationCallback, System.Net.Http.DelegatingHandler[] handlers) [0x00007] in <b66b7a9568464c98a370d795acdef11c>:0
  at KeyVaultSecrets.KeyVaultHelper.RetrieveSecret (System.String secretKey) [0x00081] in <23498eee002143eda79164cb7d001b9d>:0
  at KeyVaultSecrets.Program.Main (System.String[] args) [0x0001c] in <23498eee002143eda79164cb7d001b9d>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.ArgumentException: Value does not fall within the expected range.
  at System.Net.Http.Headers.Parser+Token.Check (System.String s) [0x00019] in <f9ac0c719f3449a0aa7ac0136a1ad250>:0
  at System.Net.Http.Headers.ProductHeaderValue..ctor (System.String name, System.String version) [0x0000a] in <f9ac0c719f3449a0aa7ac0136a1ad250>:0
  at System.Net.Http.Headers.ProductInfoHeaderValue..ctor (System.String productName, System.String productVersion) [0x00006] in <f9ac0c719f3449a0aa7ac0136a1ad250>:0
  at Microsoft.Rest.ServiceClient`1[T].get_DefaultUserAgentInfoList () [0x0003f] in <7d943830d9bc44fab4bd01d7a9130a9c>:0
  at Microsoft.Rest.ServiceClient`1[T].SetUserAgent (System.String productName, System.String version) [0x00010] in <7d943830d9bc44fab4bd01d7a9130a9c>:0
  at Microsoft.Rest.ServiceClient`1[T].InitializeHttpClient (System.Net.Http.HttpClient httpClient, System.Net.Http.HttpClientHandler httpClientHandler, System.Net.Http.DelegatingHandler[] handlers) [0x00092] in <7d943830d9bc44fab4bd01d7a9130a9c>:0
  at Microsoft.Rest.ServiceClient`1[T].InitializeHttpClient (System.Net.Http.HttpClientHandler httpClientHandler, System.Net.Http.DelegatingHandler[] handlers) [0x00000] in <7d943830d9bc44fab4bd01d7a9130a9c>:0
  at Microsoft.Rest.ServiceClient`1[T]..ctor (System.Net.Http.HttpClientHandler rootHandler, System.Net.Http.DelegatingHandler[] handlers) [0x00006] in <7d943830d9bc44fab4bd01d7a9130a9c>:0
  at Microsoft.Rest.ServiceClient`1[T]..ctor (System.Net.Http.DelegatingHandler[] handlers) [0x00006] in <7d943830d9bc44fab4bd01d7a9130a9c>:0
  at Microsoft.Azure.KeyVault.KeyVaultClient..ctor (System.Net.Http.DelegatingHandler[] handlers) [0x00000] in <b66b7a9568464c98a370d795acdef11c>:0
  at Microsoft.Azure.KeyVault.KeyVaultClient..ctor (Microsoft.Rest.ServiceClientCredentials credentials, System.Net.Http.DelegatingHandler[] handlers) [0x00000] in <b66b7a9568464c98a370d795acdef11c>:0
  at Microsoft.Azure.KeyVault.KeyVaultClient..ctor (Microsoft.Azure.KeyVault.KeyVaultClient+AuthenticationCallback authenticationCallback, System.Net.Http.DelegatingHandler[] handlers) [0x00007] in <b66b7a9568464c98a370d795acdef11c>:0

I've traced the problem to this code, which assumes that its safe to get the OS Name and Version from the registry if compiled with FullNetFx. However, that directive only tells you that the compilation target was the full framework. It doesn't tell you that the runtime environment is Windows. It's not safe to call Win32 functions from there, which the OsName and OsVersion properties do here.

I've got a temporary workaround, which is to create fake entries in Mono's emulated registry that return something for these values, but the real fix would be to not rely on registry at all, but rather use the information in System.Environment.OSVersion for the full framework, or from System.Runtime.InteropServices.RuntimeInformation if you were to target .NET Standard.

Most helpful comment

Never mind, I figured it out! If anyone else is having this problem, you can add the fake registry keys by doing something along these lines:

Microsoft.Win32.Registry.LocalMachine.CreateSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion").SetValue("ProductName", "Windows 8.1 Pro")

All 8 comments

@mj1856 thank you for reporting this.
We will have this in our plans for our next release, but seems you have a workaround that unblocks you by generating required reg entries in your virtual hive

Yes, thanks. 馃憤

@mj1856 I'm experiencing this exact issue, but on macOS Sierra.

Do you happen to know how to create entries in the Mono virtual registry on macOS? The path seems to be /Library/Frameworks/Mono.framework/Versions/Current/etc/mono/registry, but that directory only contains an empty LocalMachine directory on my machine.

How exactly do you create the entries to get around this issue? Do you need to do it programmatically or can you simply create files in this location? What's the format?

Never mind, I figured it out! If anyone else is having this problem, you can add the fake registry keys by doing something along these lines:

Microsoft.Win32.Registry.LocalMachine.CreateSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion").SetValue("ProductName", "Windows 8.1 Pro")

@mj1856, I have the same issue while trying to use Azure Service Bus library on Mono on Linux.
How did you do the workaround?
How to add the fake entries in Mono's emulated registry?

@jake22599 - see the comment above yours for how to create them programatically. Or, if desired, you can create the files manually. They sit in /etc/mono/registry. I don't want to write a tutorial here, but I'm sure you can find some examples on the web.

I also stumbled on this problem when creating a ServiceBusManagementClient instance (from the Microsoft.Azure.Management.ServiceBus package).

Here is what I did to workaround the problem on macOS.

  1. Create the fake registry directory structure:
$ cd /Library/Frameworks/Mono.framework/Versions/Current/etc/mono/registry/LocalMachine
$ sudo mkdir -p "SOFTWARE/Microsoft/Windows NT/CurrentVersion"
$ cd "SOFTWARE/Microsoft/Windows NT/CurrentVersion"
  1. Check my actual system values:
$ cat /System/Library/CoreServices/SystemVersion.plist 

```xml




ProductBuildVersion
16G1314
ProductCopyright
1983-2018 Apple Inc.
ProductName
Mac OS X
ProductUserVisibleVersion
10.12.6
ProductVersion
10.12.6

Create a `values.xml` file in the previously created directory structure, i.e.`/Library/Frameworks/Mono.framework/Versions/Current/etc/mono/registry/LocalMachine/SOFTWARE/Microsoft/Windows NT/CurrentVersion`:
```xml
<values>
<value name="ProductName" type="string">Mac OS X</value>
<value name="CurrentVersion" type="string">10.12.6</value>
<value name="CurrentBuild" type="string">16G1314</value>
</values>

After saving this file, I was able to successfully create a ServiceBusManagementClient.

This is no longer a problem in the new Azure.Core that replaces this library. All libraries will be moving to be based on Azure.Core over time. Hopefully this year for many of the management libraries. Until then, we recommend using the workaround.

Was this page helpful?
0 / 5 - 0 ratings