0

I'm using the Microsoft.WindowsAzure.StorageClient version 1.7.1.0 available at: https://github.com/WindowsAzure/azure-sdk-for-net/tree/sdk_1.7.1. My project compiles just fine, but when I run it I get the following error:

Could not create Microsoft.WindowsAzure.Diagnostics.DiagnosticMonitorTraceListener, Microsoft.WindowsAzure.Diagnostics, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35.

with an inner exception of:

Could not load file or assembly 'Microsoft.WindowsAzure.StorageClient, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)":"Microsoft.WindowsAzure.StorageClient, Version=1.7.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35

I looks like there is a dependency in Microsoft.WindowsAzure.Diagnostics on version 1.7.0.0 of Microsoft.WindowsAzure.StorageClient. However I am using version 1.7.1.0, and as far as I know I can't have both 1.7.0 and 1.7.1 in the same project. Any ideas how to make Microsoft.WindowsAzure.Diagnostics dependent on 1.7.1 if this is indeed the problem?

Thanks, Kurt


Update


As per recommendation below I added s startup task to load the version 1.7.0 using gacutil (this was useful http://blogs.infosupport.com/adding-assemblies-to-the-gac-in-windows-azure/). I have 2 WorkerRoles and 2 WebRoles. The problem I have now is that when I compile and run, VS2012 copies the 1.7.0 into the WebRoles' respective ...\csx\Debug\roles[WebRoleName]\approot folder, despite there being no direct reference to version 1.7.0 in the project. The following compile output shows the error this introduces when Azure attempts to load verison 1.7.1 (which it now can't find):

System.TypeLoadException: Unable to load the role entry point due to the following exceptions:
-- System.IO.FileLoadException: Could not load file or assembly 'Microsoft.WindowsAzure.StorageClient, Version=1.7.1.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
File name: 'Microsoft.WindowsAzure.StorageClient, Version=1.7.1.0, Culture=neutral, PublicKeyToken=null'

=== Pre-bind state information ===
LOG: User = BERTIES_MAIN\kurt_000
LOG: DisplayName = Microsoft.WindowsAzure.StorageClient, Version=1.7.1.0, Culture=neutral, PublicKeyToken=null
 (Fully-specified)
LOG: Appbase = file:///H:/Everything/Current_Work/Web_Apps/Azure/InSysCloud/InSysCloud/InSysCloud/csx/Debug/roles/InSysWatcher/approot
LOG: Initial PrivatePath = H:\Everything\Current_Work\Web_Apps\Azure\InSysCloud\InSysCloud\InSysCloud\csx\Debug\roles\InSysWatcher\approot
Calling assembly : InSysWatcher, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: H:\Everything\Current_Work\Web_Apps\Azure\InSysCloud\InSysCloud\InSysCloud\csx\Debug\roles\InSysWatcher\approot\InSysWatcher.dll.config
LOG: Using host configuration file: 
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///H:/Everything/Current_Work/Web_Apps/Azure/InSysCloud/InSysCloud/InSysCloud/csx/Debug/roles/InSysWatcher/approot/Microsoft.WindowsAzure.StorageClient.DLL.
WRN: Comparing the assembly name resulted in the mismatch: PUBLIC KEY TOKEN
ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.

Why would VS2012 be adding the DLL for version 1.7.0, when 1.7.1 is referenced in the project itself, and version 1.7.0 is only included as content, and loaded into the GAC at app startup?

ProfNimrod
  • 4,142
  • 2
  • 35
  • 54
  • Is there something in particular you require in your version? Honestly, I would probably just go back to 1.7.0 official release for now. You will have this problem everywhere 3rd party tries to load the storage client (e.g. Diagnostics agent as well). – dunnry Oct 11 '12 at 14:28
  • I was to use the Shared Access Key functionality for Tables and Queues, which I don't think is support in 1.7.0. I'm assuming (and really hoping) this functionality in 1.7.1 will make it into the official 1.8. – ProfNimrod Oct 12 '12 at 14:15

2 Answers2

1

Well, in such cases you would use a binding redirect in the web.config/app.config. But the problem is the PublicKeyToken. The 'official' assembly 1.7.0.0 has the following PublicKeyToken: 31bf3856ad364e35.

Now, since you're building the 1.7.1.0 version yourself you'll end up with a different PublicKeyToken and in that case the binding redirect does not work.

But the GAC was built for this, to support multiple versions of an assembly. What I would suggest is the following:

  1. Include the 1.7.0.0 assembly in your package, but add it as content (not as reference).
  2. Create a startup task that deploys the assembly to the GAC (using gacutil), since the task will run before starting your role.
  3. Keep using 1.7.1.0 with a normal assembly reference.
  4. Your app should use 1.7.1.0 for your code, and the diagnostics assembly should be able to use version 1.7.0.0 from the GAC

I didn't have a chance to test this yet so I'm looking forword to your feedback.

Dene
  • 578
  • 5
  • 9
Sandrino Di Mattia
  • 24,739
  • 2
  • 60
  • 65
  • OK - this looks promising. I added the startup task with one little wrinkle - I had to change the 1.7.0 filename of the assembly, otherwise when I tried to add 1.7.1 version Visual Studio would reference 1.7.0 regardless of what version I tried to add a direct reference to. Anyway, now I have a problem whereby when I try to build my solution, for the WorkerRoles only, VS2012 puts version 1.7.0 (not 1.7.1) into the csx/Debug/roles/WorkerRoleName/approot folder despite there being no direct reference to it in my project. For the WebRoles, the correct version (1.7.1) is copied over. Any ideas? – ProfNimrod Oct 12 '12 at 15:07
  • Can I force the PublicKeyToken of my compiled 1.7.1 to be 31bf3856ad364e35? – ProfNimrod Oct 12 '12 at 15:26
  • I actually tried to change the PublicKeyToken by using ILDASM to cut and paste the relevant parts of 1.7.0 into 1.7.1, but then realized I didn't have access to Microsoft's private key :-( This meant I had to turn off strong name verification for the resulting 1.7.1, when then lead to security issues with the GetObjectData method... Something about "Inheritance security rules violated while overriding member..." – ProfNimrod Oct 12 '12 at 18:26
  • I also tried just renaming and recompiling version 1.7.1 of Microsoft.WindowsAzure.StorageClient with an assembly name of Microsoft.WindowsAzure.StorageClient2 <-- note the 2. Works just fine in development environment, and Microsoft.WindowsAzure.Diagnostics is happy too, as 1.7.0 is found and loaded. However, this doesn't work in the production environment presumably because the published package includes Microsoft.WindowsAzure.StorageClient.dll and Microsoft.WindowsAzure.StorageClient2.dll in the same folder, and their types clash. – ProfNimrod Oct 12 '12 at 19:48
  • BTW This shouldn't be marked as an answer as it didn't work for me. I don't have sufficient reputation points to vote it down. – ProfNimrod Oct 15 '12 at 19:01
0

It appears I can add the following reference into my web.config to work-around this problem:

  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.WindowsAzure.StorageClient"
                          publicKeyToken="31bf3856ad364e35"
                          culture="neutral" />
        <bindingRedirect oldVersion="1.1.0.0"
                         newVersion="1.7.0.0"/>
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.WindowsAzure.StorageClient"
                          publicKeyToken="31bf3856ad364e35"
                          culture="neutral" />
        <publisherPolicy apply="no" />
      </dependentAssembly>

    </assemblyBinding>
  </runtime>

This essentially allows the references to v1.1 of the dll to be re-mapped to 1.7.

Jaime Botero
  • 2,263
  • 2
  • 22
  • 14