I have a ClickOnce server set up to host Outlook plugins. It automatically serves whichever the current version is to client machines.
When the plugin version changes, it updates perfectly. But if one of the configuration files within the version changes, I regenerate the manifest, but it won't update because it sees the .vsto pointing to the same version number. It ignores the change to the digital signature DigestValue:
<dependency>
<dependentAssembly dependencyType="install" codebase="MyAddin.dll.manifest" size="12345">
<assemblyIdentity name="MyAddin.dll" version="1.0.0.25" publicKeyToken="1234567890abcdef" language="neutral" processorArchitecture="msil" type="win32" />
<hash>
<dsig:Transforms>
<dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity" />
</dsig:Transforms>
<dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256" />
<dsig:DigestValue>********************************</dsig:DigestValue>
</hash>
<dependentAssembly>
</dependency>
The only part of the sample that changes is the ********** (and obviously the .vsto signature at the bottom).
If I try to change any of the other values, it complains that the .vsto definition doesn't match the .dll.manifest definition, or the .dll.manifest definition doesn't match the target assembly. I don't want to require a new build just because a .config file changed.
How can I force Outlook to notice the manifest change so it will actually install, instead of thinking it's exactly the same with no changes?
I finally found the relevant question on Stackoverflow for someone trying to do the same thing:
How to update just one DLL in a ClickOnce installation?
All it requires is changing the version number. But it has to be changed in 3 places, or it will complain about not manifest versions not matching. This version number DOES NOT have to match any of the .dll files that are being deployed (even though it shows up under tag "assemblyIdentity", which is confusing). The version can be generated new each time any file changes to force an update (auto-increment, hashing, timestamp, random number, however you like).
I wasn't able to get it working before because I was only updating 2 of the references, not all 3.
First reference to this version number is found at the top of the application manifest:
<asmv1:assemblyIdentity name="MyAddin.dll" version="w.x.y.z" publicKeyToken="1234567890abcdef" language="neutral" processorArchitecture="msil" type="win32" />
Second place is at the top of the deploy manifest:
<asmv1:assemblyIdentity name="MyAddin.vsto" version="w.x.y.z" publicKeyToken="1234567890abcdef" language="neutral" processorArchitecture="msil" xmlns="urn:schemas-microsoft-com:asm.v1" />
And the third place is inside the deploy manifest:
<dependentAssembly dependencyType="install" codebase="MyAddin.dll.manifest" size="12345">
<assemblyIdentity name="MyAddin.dll" version="w.x.y.z" publicKeyToken="1234567890abcdef" language="neutral" processorArchitecture="msil" type="win32" />
Related
I have a vb.net solution with a separate project containing a file class to access Azure files and 2 projects. In both I call the file class which contains this code
Dim mascThis as ShareClient
... mascThis is initialized ...
If mascThis.Exists.Value then ... do something ..
In one project this works, in the other I get the message
Could not load file or assembly 'System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
I've seen this problem discussed before (assembly issues), but all projects are in the same solution in to which I added Azure.Storage.Files.Shares 12.8.0 via Nuget and only the "File class" project has a reference to it, the other projects don't.
So what am I missing here?
Please check if any of the below is your case.
Sometimes, we will have the situation where different parts(projects) of our solution depend on different versions of the same DLL i.e; assemblies with the same assembly name.
The error
Could not load file or assembly
'System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1,
Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its
dependencies. The located assembly's manifest definition does not
match the assembly reference. (Exception from HRESULT: 0x80131040)
suggests , your project is looking for assembly version 4.0.4.1
Work arounds
i. Usually Nuget Package 4.5.3 contains assembly version 4.0.4.1.
Please check if both the projects in your solution can be worked on that assembly version and add that particular version as new version(ex:4.0.4.1) through binding redirect in the project where you are getting error. And keep the old version in place of old version.
Also Right click on the package reference and set 'specific version' to false under its properties
Example:
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.6.0" newVersion="4.0.6.0" />
</dependentAssembly>
In this example ,this way of adding specifies that the runtime should use version 4.0.6.0 in the Assembly versions between olderversion range 0.0.0.0-4.0.6.0
Else If above is not the case, the solution might need different versions.
ii.
Right click in the project properties and choose the ApplicationConfiguration file and App.config
Add the following settings in the app.config file.
To configure multiple assemblies with the same name through codeBases.
Sample code for some package say “A” :
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="A " publicKeyToken="3d67ed1f87d44c89" />
<codeBase version="3.0" href="...\A.dll"/>
<codeBase version="5.0" href="...\A.dll"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
iii. See if you could solve that problem by using extern alias.
iv. Binding redirects are added if your app or its components reference more than one version of the same assembly .See Enable or disable autogenerated binding redirects | Microsoft Docs .If you do it manually ,you need to disable under project properties.
Manually you can add <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> in csproj file in property group.
Ex:
<PropertyGroup>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>
References that can be helpful.
SO reference
Referencing Multiple Versions
load same assembly of different version-SO
I'm trying to build a solution using Azure DevOps and publish the result as a nuGet package in a private repository.
A project in the solution contains a localized resource Language.resx containing the English texts.
The localized versions are:
Language.da.resx, Language.se.resx and Language.no.resx yet none of these are included in the resulting nuget package.
I tried adding /target:Resource,Compile to the MSBuild arguments property of the Build Solution task in DevOps, but it just resulted in an error saying no 'Resource' target was found.
I'm sure I'm just missing something obvious, but I just can't see it.
I must be close, the nuGet package gets published after all, and works, except for the localization resources.
I inspected the resulting nuGet Package and extracted the DLL from the project in question. Opening the DLL in .Net Reflector 10 shows me that it does indeed contain the text strings in English, but no other languages.
It appears the localized ressources were indeed built by default, though not visible in .Net Reflector 10.
The reason is that they weren't included in the nuGet package in the Packaging task.
A bit of research lead me to add a .nuspec file to the project.
In this file, I specified the relevant files etc. and they are now included in the nuGet package.
Not ideal though, since the list of files and dependencies now have to be maintained manually. But I was unable to find a way of making it dynamic.
Most of the details in the .nuspec file was possible to be made dynamic though, using variables referring to the AssemblyInfo.cs file.
I ended up with the following content in the .nuspec file (some details cleaned though, since this is displayed in public)
Note: The word Release in the src attribute of the files section is the name of my build profile. Your solution might use a different name.
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<!-- The identifier that must be unique within the hosting gallery -->
<id>$id$</id>
<!-- The package version number that is used when resolving dependencies -->
<version>$version$</version>
<!-- Authors contain text that appears directly on the gallery -->
<authors>$author$</authors>
<!--
Owners are typically nuget.org identities that allow gallery
users to easily find other packages by the same owners.
-->
<owners>$author$</owners>
<!-- License and project URLs provide links for the gallery -->
<!--<licenseUrl></licenseUrl>-->
<!--<projectUrl></projectUrl>-->
<!-- The icon is used in Visual Studio's package manager UI -->
<!--<iconUrl></iconUrl>-->
<!--
If true, this value prompts the user to accept the license when
installing the package.
-->
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<!-- Any details about this particular release -->
<!--<releaseNotes></releaseNotes>-->
<!--
The description can be used in package manager UI. Note that the
nuget.org gallery uses information you add in the portal.
Must be included, and must never be empty.
-->
<description>$description$</description>
<!-- Copyright information -->
<copyright>$copyright$</copyright>
<!-- Tags appear in the gallery and can be used for tag searches -->
<!--<tags></tags>-->
<!-- Dependencies are automatically installed when the package is installed -->
<dependencies>
<dependency id="MicrosoftOfficeCore" version="15.0.0" />
<dependency id="Microsoft.Office.Interop.Word" version="15.0.4797.1003" />
</dependencies>
</metadata>
<!-- Files to include in the package -->
<files>
<file src="bin\Release\$id$.dll" target="lib\net462\$id$.dll" />
<file src="bin\Release\da\$id$.resources.dll" target="lib\net462\da\$id$.resources.dll" />
<file src="bin\Release\no\$id$.resources.dll" target="lib\net462\no\$id$.resources.dll" />
<file src="bin\Release\sv\$id$.resources.dll" target="lib\net462\sv\$id$.resources.dll" />
</files>
</package>
I'd like to know how to change web.config when upgrading to Microsoft.WindowsAzure.StorageClient 4.3. Current web.config is like
<assemblyIdentity name="Microsoft.WindowsAzure.StorageClient" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.7.0.0" newVersion="1.7.0.0" />
You can directly delete it. This configuration is used for binding "Microsoft.WindowsAzure.StorageClient" reference which is older than 1.7.0.0 to the assembly whose version is 1.7.0.0. For example, originally the project references Microsoft.WindowsAzure.StorageClient 1.5.0.0 in compile time, after this part is added to web.config, it can leverage Microsoft.WindowsAzure.StorageClient 1.7.0.0 instead of 1.5.0.0 in run time, as long as the assembly is backward-compatible.
Because you have replaced "Microsoft.WindowsAzure.StorageClient.dll" with "Microsoft.WindowsAzure.Storage.dll" (both name and version are different), this configuration is not needed at all.
I'm having trouble setting the path to a DLL that is not in the same directory as the executable.
I have a reference to dllA.dll. At present, everything is just copied into the same directory and all is well; however, I need to move the executable to another directory while still referencing the DLL in the original directory.
So, it's setup like:
C:\Original\Dir
program.exe
dllA.dll
dllB.dll
dllC.dll
But I need to have it setup like:
C:\New\Dir
program.exe
dllB.dll
dllC.dl
Such that it is still able to reference dllA.dll in C:\Original\dir
I tried the following, but to no avail:
Set the "Copy Local" value to false for dllA.dll because I want it to be referenced in its original location.
Under "Tools > Options > Projects and Solutions > VC++ Directories" I have added the path to "C:\Original\Dir"
Added "C:\Original\Dir" to both the PATH and LIB environment variables
At runtime, it informs me that it cannot locate dllA.dll Maybe the above steps I took only matter at compile time?
I was able to find this
C# : Specifying a location for Dll reference
But I was thinking that my above method should've worked.
Any ideas?
Your compile-time settings won't affect the run-time path. Try adding C:\Original\dir
to the system-wide path, and you should see that it picks up the DLL correctly. If so, then your solutions appear to be:
1) modify the system path permanently. May or may not be feasible.
2) alter the environment path at run-time.
3) use relative paths when referring to the DLL.
4) record the path to the DLL at installation time, perhaps in the registry, so that your exe can load it explicitly.
While I may still foolishly believe this can be accomplished through specifying the proper path variables, I was able to overcome this issue by adding some entries to my app.config
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="dllA" publicKeyToken="blah" culture="neutral" />
<codeBase version="blah" href="file:///C:/Original/Dir/dllA.dll" />
</dependentAssembly>
</runtime>
Working from the above answer (Thanks Karl), it wasn't clear to me about the syntax for href, especially for relative paths:
<dependentAssembly>
<assemblyIdentity name="SVDInterface" culture="neutral" />
<codeBase version="1.0.3114.29282" href="./System/SVD/SVDInterface.dll" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Math Functions" culture="neutral" />
<codeBase version="1" href="./System/SVD/Math Functions.dll" />
</dependentAssembly>
The version number for the 1st dll I got from the references tab.
Having looked into lots of ways of specifying where a dll is, this was by far the easiest way - still took me all day to get it to work fully.
The last nugget of information is that the App.config entries above get written out to yourappname.exe.config which you must copy with your app to its final destination otherwise it will never find your dlls.
Hopefully of use to someone.
Kristian
I have a custom Task that I want to execute when building my C# projects. This task is located in MyTask.dll, which references another assembly, MyCommon.DLL.
The problem is that MyCommon.dll is located at "..\Common\MyCommon.dll" relative to MyTask.dll, which puts it outside the AppBase dir for MSBuild process. I've confirmed that this is indeed the problem by analyzing MSBuild's log and seeing Fusion's report about the binding failure.
What can I do to make Fusion find MyCommon.dll during the build process? Note that moving the assembly would break my app, which also depends on it.
UPDATE: Well, it seems I'll go with using a copy afterall. Other solutions all require system-wide modifications, which isn't really warranted here.
So copy it instead? Just a thought. Have a copy there just to support the build that you delete once you're done with it.
I see multiple solutions :
1st : Add the assembly in the GAC (your assembly must have a strong name)
gacutil /I <assembly name>
2nd : Locate the assembly through Codebases or Probing, in your machine.config file or in msbuild.exe.config .
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="MyCommon"
publicKeyToken="32ab4ba45e0a69a1"
culture="neutral" />
<codeBase version="2.0.0.0"
href="file://C:/yourpath/MyCommon.DLL"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
3rd : copy the assembly in the same directory before and delete it after, like David M said.
All of these "solutions" create more dependencies which complicate the environment. There should be an easier way to update the probing path at runtime..
Specifically MSBuild should allow you to add probing paths in your .proj file, or to specify the dependant dlls
You can define a custom UsingTask:
<UsingTask TaskName="Task" AssemblyFile="Assembly.dll" />
but you cant add dependencies? it should be included... here with something like
<UsingTask TaskName="Task" AssemblyFile="Assembly.dll">
<DependantAssembly AssemblyFile="dependant.dll"/>
</UsingTask>
But, no this isn't supported...
An option is to use ILMerge to merge the dependency into the task assembly.