New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Referencing Assemblies from PowerShell and Binding Redirects #342
Comments
.config is for the entry assembly. In this case, powershell.exe is the entry assembly. Here is an example where the task lib calls Add-Type to load a DLL. Here is an example where a binding redirect is applied, and removed. Tasks carry a known set of specific dependencies. If other settings need to be accommodated, it is always a known set. |
Thanks Eric. I was aware that .config affects the whole assembly, in this case PowerShell, which if modified will have influence on the whole machine. I was secretly hoping that there was a way to dynamically load a .config file so that only the current process would be affected. I will look at the resolve assembly examples. This is also what I concluded was probably the way to go. Just a stupid question: What will happen if I explicitly loaded the depending assemblies in the correct version before loading the main assembly? In my case, System.Net.Http 4.1.1.2 instead of the default System.Net.Http 4.0.0.0. Also, what do you mean by "Tasks carry a known set of specific dependencies"? Do you mean that I as the developer know exactly what the dependencies are? |
I just tried with the assembly-resolve event. I can't get it to work. The resolve handler only fires for Newtonsoft.Json and for none of the other assemblies. Are there any other resolve handlers registered by the system or TFS task system? Some diagnostics: _# Adding assembly resolver. Add-Type -Path (Join-Path $assemblyFolder "TfsVersionHistoryLib.dll") $service = New-Object TfsVersionHistoryLib.Service($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI, $env:SYSTEM_TEAMPROJECT); _# Resolving 'Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' _# Assemblies in current domain: |
Hi. This is basically what I do. Except, in the example, I don't see where the on-resolve-assembly handler is hooked. My code (see below) calls the handler, but only once and only for the Newtonsoft.Json. Not for any other assemblies. [appdomain]::currentdomain.getassemblies() | sort -property fullname | format-table fullname | Out-String|% {Write-Host $_} $currentScriptDirectory = Get-Location Write-Host "Adding assembly resolver."
} Add-Type -Path (Join-Path $assemblyFolder "MyLib.dll") $service = New-Object MyLib.Service("...", "...") [appdomain]::currentdomain.getassemblies() | sort -property fullname | format-table fullname | Out-String|% {Write-Host $_} ..# Crashes below with: [A]System.Net.Http.Headers.MediaTypeHeaderValue cannot be cast to [B]System.Net.Http.Headers.MediaTypeHeaderValue. kk e context 'Default' at location 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Net.Http\v4.0_4.0.0.0__b03f5f7f11d50a3a\System.Net.Http.dll'. Type B originates from 'System.Net.Http, Version=4.1.1.2, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' in the context 'LoadFrom' at location 'C:\TFSAgent-Default-17_work_tasks\AtlasGenerateReleaseNotes_130d1a10-3cd0-11e8-81c9-a13fe19f6bca\0.1.42\Tfs\System.Net.Http.dll'. $query = $service.Query(1234) |
@atlastodor it's handled in the same line as pointed.
All you need to do is, instead of |
I already have the System.Net.Http in my handler. Only that it is not called. Probably something with the load context for the assembly. I am investigating. I was asking where the $onAssemblyResolve variable is used. I can't see that this handler is used anywhere. |
@atlastodor the variable is not required. essentially its' EventHandler, will be invoked whenever system invokes that Assembly Load Event. |
After reading the .Net documentation, I came to the conclusion that the AssemblyResolve event is only raised when .Net cannot find the assembly in question. The problem is that .Net loads the assemblies in the appdomain's default context, and if it can find any assembly that matches the requested assembly, it will be loaded. In my case System.Net.Http, Version=4.1.1.2 is requested but for some reason the system finds System.Net.Http, Version=4.0.0.0 in the GAC and loads that assembly. The event is not raised, since the system found a match. It is only raised if it cannot find the assembly. I ended up loading an additional AppDomain that is configured to use my custom .config file. This was the simplest approach for me. |
"[System.AppDomain]::CurrentDomain.add_AssemblyResolve($OnAssemblyResolve)" |
I am writing a custom build task, where the PowerShell script will need to access additional .Net assemblies. I am having problems referencing those, especially the binding redirects that are normally given in the .config file.
What is the proper way to handle this? I've seen examples using the ResolveAssembly event, but this to me sounds as a work around. Also, there may be other settings in the .config file that may be relevant and can't be ignored.
PS: Running on TFS 2018 Update 2, on premise.
The text was updated successfully, but these errors were encountered: