IMPORTANT MESSAGE: We are still experiencing some difficulties that will affect your ability work with the RWS AppStore. Our IT team is working to resolve this but for now you may not be able to download or upload apps through the RWS AppStore. We apologise for the inconvenience and will update the community when we have a resolution in place. In the meantime you can take advantage of the Private AppStore if you are using Trados Studio 2021 or 2022.

"Multiple ambiguous overloads" error when registering BatchExported event handler for TMX export

As mentioned recently elsewhere, I'm getting weird errors in my STraSAK when registering TMX export (and also import) event handler.
The same code runs just fine without errors with Studio 2014 and 2015, and I'm pretty sure it worked fine in earlier Studio 2017 versions (pre-SR1, like Studio 2017 CU5).

The code is PowerShell, but I'm pretty sure you get the idea since PS code looks very similar to C#...

This is the event handler (as PowerShell scriptblock). No rocket science, it just writes the number of processed and exported TUs to console:

# Event handler scriptblock
$OnBatchExported = {
    param([System.Object]$sender, [Sdl.LanguagePlatform.TranslationMemoryApi.BatchExportedEventArgs]$e)
    $TotalProcessed = $e.TotalProcessed
    $TotalExported = $e.TotalExported
    Write-Host "TUs processed: $TotalProcessed, exported: $TotalExported`r" -NoNewLine
}

And this is the relevant piece of the code - it's actually trivial, it gets a standard Studio TM object, creates TM exporter object, registers the event handler, runes the actual export and then unregisters the event handler. Again, no rocket science...

$TM = Get-FilebasedTM $SDLTM.FullName
$Exporter = New-Object Sdl.LanguagePlatform.TranslationMemoryApi.TranslationMemoryExporter ($TM.LanguageDirection)
$Exporter.Add_BatchExported($OnBatchExported)
$Exporter.Export("$TMXPath\$TMXName", ($Force.IsPresent))
$Exporter.Remove_BatchExported($OnBatchExported)

This code runs perfectly with Studio 2015, but fails with Studio 2017 (and also 2019) - see the video below.

The error 'Multiple ambiguous overloads found for "Add_BatchExported" and the argument count: "1"' would suggest that there is some difference in the API in Studio 2017/2019... yet, there is nothing mentioned in the relevant API documentation: producthelp.sdl.com/.../d829a063-705f-e34b-f504-a882125aed13.htm

BTW, the way the event handler is registered/unregistered is correct, see wensveen.wordpress.com/.../

EDIT:
Even the PrimalSense context help (which reads parameters directly from the DLLs) is not helpful since the event handler overloads are simply identical... That's really sick :(
How is one supposed to differentiate between these two?!?!


Parents
  • I guess this might need some insight from SDL people like  or ...

    Meanwhile I did some more research and it looks like there is indeed something weird in the API - comparing to previous versions, there is a new Sdl.Core.TM.ImportExport DLL in Studio 2017 (and 2019) and this DLL contains duplicates of the export/import routines... which causes the ambiguities.

    This DLL exists only since Studio 2017 CU13 released in October 2018, which perfectly confirms my previous suspicion that my code worked fine in earlier Studio 2017 versions!

    PS C:\Users\EvzenP> $Exporter.GetType().getmethods() | ? name -eq add_BatchExported | % {write-host "***`n" ; $_}
    ***

    Name                       : add_BatchExported
    DeclaringType              : Sdl.LanguagePlatform.TranslationMemoryApi.TranslationMemoryExporter
    ReflectedType              : Sdl.LanguagePlatform.TranslationMemoryApi.TranslationMemoryExporter
    MemberType                 : Method
    MetadataToken              : 100664463
    Module                     : Sdl.LanguagePlatform.TranslationMemoryApi.dll
    IsSecurityCritical         : True
    IsSecuritySafeCritical     : False
    IsSecurityTransparent      : False
    MethodHandle               : System.RuntimeMethodHandle
    Attributes                 : PrivateScope, Public, HideBySig, SpecialName
    CallingConvention          : Standard, HasThis
    ReturnType                 : System.Void
    ReturnTypeCustomAttributes : Void
    ReturnParameter            : Void
    IsGenericMethod            : False
    IsGenericMethodDefinition  : False
    ContainsGenericParameters  : False
    MethodImplementationFlags  : Managed
    IsPublic                   : True
    IsPrivate                  : False
    IsFamily                   : False
    IsAssembly                 : False
    IsFamilyAndAssembly        : False
    IsFamilyOrAssembly         : False
    IsStatic                   : False
    IsFinal                    : False
    IsVirtual                  : False
    IsHideBySig                : True
    IsAbstract                 : False
    IsSpecialName              : True
    IsConstructor              : False
    CustomAttributes           : {[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]}

    ***

    Name                       : add_BatchExported
    DeclaringType              : Sdl.Core.TM.ImportExport.Exporter
    ReflectedType              : Sdl.LanguagePlatform.TranslationMemoryApi.TranslationMemoryExporter
    MemberType                 : Method
    MetadataToken              : 100663311
    Module                     : Sdl.Core.TM.ImportExport.dll
    IsSecurityCritical         : True
    IsSecuritySafeCritical     : False
    IsSecurityTransparent      : False
    MethodHandle               : System.RuntimeMethodHandle
    Attributes                 : PrivateScope, Public, HideBySig, SpecialName
    CallingConvention          : Standard, HasThis
    ReturnType                 : System.Void
    ReturnTypeCustomAttributes : Void
    ReturnParameter            : Void
    IsGenericMethod            : False
    IsGenericMethodDefinition  : False
    ContainsGenericParameters  : False
    MethodImplementationFlags  : Managed
    IsPublic                   : True
    IsPrivate                  : False
    IsFamily                   : False
    IsAssembly                 : False
    IsFamilyAndAssembly        : False
    IsFamilyOrAssembly         : False
    IsStatic                   : False
    IsFinal                    : False
    IsVirtual                  : False
    IsHideBySig                : True
    IsAbstract                 : False
    IsSpecialName              : True
    IsConstructor              : False
    CustomAttributes           : {[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]}

    So I would like to get some feedback from SDL... most probably a confirmation of the issue and also a suggestion for a temporary workaround, plus ideally some word about planned fix.

Reply
  • I guess this might need some insight from SDL people like  or ...

    Meanwhile I did some more research and it looks like there is indeed something weird in the API - comparing to previous versions, there is a new Sdl.Core.TM.ImportExport DLL in Studio 2017 (and 2019) and this DLL contains duplicates of the export/import routines... which causes the ambiguities.

    This DLL exists only since Studio 2017 CU13 released in October 2018, which perfectly confirms my previous suspicion that my code worked fine in earlier Studio 2017 versions!

    PS C:\Users\EvzenP> $Exporter.GetType().getmethods() | ? name -eq add_BatchExported | % {write-host "***`n" ; $_}
    ***

    Name                       : add_BatchExported
    DeclaringType              : Sdl.LanguagePlatform.TranslationMemoryApi.TranslationMemoryExporter
    ReflectedType              : Sdl.LanguagePlatform.TranslationMemoryApi.TranslationMemoryExporter
    MemberType                 : Method
    MetadataToken              : 100664463
    Module                     : Sdl.LanguagePlatform.TranslationMemoryApi.dll
    IsSecurityCritical         : True
    IsSecuritySafeCritical     : False
    IsSecurityTransparent      : False
    MethodHandle               : System.RuntimeMethodHandle
    Attributes                 : PrivateScope, Public, HideBySig, SpecialName
    CallingConvention          : Standard, HasThis
    ReturnType                 : System.Void
    ReturnTypeCustomAttributes : Void
    ReturnParameter            : Void
    IsGenericMethod            : False
    IsGenericMethodDefinition  : False
    ContainsGenericParameters  : False
    MethodImplementationFlags  : Managed
    IsPublic                   : True
    IsPrivate                  : False
    IsFamily                   : False
    IsAssembly                 : False
    IsFamilyAndAssembly        : False
    IsFamilyOrAssembly         : False
    IsStatic                   : False
    IsFinal                    : False
    IsVirtual                  : False
    IsHideBySig                : True
    IsAbstract                 : False
    IsSpecialName              : True
    IsConstructor              : False
    CustomAttributes           : {[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]}

    ***

    Name                       : add_BatchExported
    DeclaringType              : Sdl.Core.TM.ImportExport.Exporter
    ReflectedType              : Sdl.LanguagePlatform.TranslationMemoryApi.TranslationMemoryExporter
    MemberType                 : Method
    MetadataToken              : 100663311
    Module                     : Sdl.Core.TM.ImportExport.dll
    IsSecurityCritical         : True
    IsSecuritySafeCritical     : False
    IsSecurityTransparent      : False
    MethodHandle               : System.RuntimeMethodHandle
    Attributes                 : PrivateScope, Public, HideBySig, SpecialName
    CallingConvention          : Standard, HasThis
    ReturnType                 : System.Void
    ReturnTypeCustomAttributes : Void
    ReturnParameter            : Void
    IsGenericMethod            : False
    IsGenericMethodDefinition  : False
    ContainsGenericParameters  : False
    MethodImplementationFlags  : Managed
    IsPublic                   : True
    IsPrivate                  : False
    IsFamily                   : False
    IsAssembly                 : False
    IsFamilyAndAssembly        : False
    IsFamilyOrAssembly         : False
    IsStatic                   : False
    IsFinal                    : False
    IsVirtual                  : False
    IsHideBySig                : True
    IsAbstract                 : False
    IsSpecialName              : True
    IsConstructor              : False
    CustomAttributes           : {[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]}

    So I would like to get some feedback from SDL... most probably a confirmation of the issue and also a suggestion for a temporary workaround, plus ideally some word about planned fix.

Children
  • Hello ,

    I have raised this issue to the development team that handles the APIs and as soon as I will have a response, I will come back to you and let you know.

    With kind regards,

    Florentina

  • Hi ,

    I've received this link https://stackoverflow.com/questions/25569566/net-events-in-powershell from the Studio dev team, can you please check if it helps you?

    Kind regards.

    Florentina.

  • Just to add a little more information we had from the development team which might explain why etc...

    "It appears that PowerShell’s approach to wiring up the event isn’t respecting the ‘new’ keyword on the event declaration in the derived TranslationMemoryExporter class, and neither is it type-aware enough to distinguish between the different types of argument (in totally different namespaces) used in the base class event versus the derived class event. If it did either of those, there would be no problem. So that’s pretty weak. The changes are a result of factoring-out import/export logic from the (desktop) TranslationMemoryApi component, into a Core component, so as to avoid the previous problems caused by having desktop dependencies in things like TM-S. I daresay there’s a workaround for the PowerShell issues."

  • Thanks for the effort, Florentina... sadly, that is pointing to a completely wrong direction...

    That discussion is about the asynchronous event processing, but here we are talking about synchronous processing, which is a completely different beast.

    That's why in my original post I mentioned this article talking about the technicalities related to synchronous event processing: wensveen.wordpress.com/.../

    EDIT:
    One more thing - there is no problem with the logic of registering the event handler as such, since the very same code runs fine with Studio 2011, 2014, 2015 and pre-CU13 Studio 2017.
    The problem starts only with newer Studio 2017 builds and Studio 2019, where the extra DLL with "duplicated code" exists.

  • Thanks, Paul... as I mentioned to Florentina, we are talking about two different things.
    I recommend doing some deeper research about Powershell and events processing.

    Powershell is very well type-aware, no doubts about that...

    But while you mention the factoring-out import/export logic - this would suggest that the import/export logic was MOVED from TranslationMemoryApi component to Core component..
    And if that would be true, everything would be okay... one would only need to reference a different library...

    But the problem is that so far it seems it WASN'T MOVED, BUT ONLY COPIED... i.e. it's now actually duplicated... being completely identical in both places, including the type of arguments.

    EDIT:
    I should perhaps add that at the beginning of my Powershell code I explicitly reference the "TranslationMemory" and "TranslationMemoryApi" DLL using the Add-Type command: https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/add-type.
    This follows both the original Powershell Toolkit code AND the current TM API documentation.
    Should I perhaps reference different DLL, the "Core" one?

    Saying all that I again publicly clearly declare that I'm not a developer and not completely familiar with all that namespaces etc. overcomplicated thingies... so it could be very well that I'm missing some fundamental knowledge and therefore my observations may be very well incorrect in various aspects.

    So I'd appreciate a pointer to appropriate direction if anyone would spot something like that.

  • Hi Evzen,

    The import / export functionality was moved into Sdl.Core.TM.ImportExport.dll and what is left in Sdl.LanguagePlatform.TranslationMemoryApi.dll is child class that overwrites the event for BatchExported. The TranslationMemoryApi.TranslationMemoryExporter also listens to the BatchExported event and relays it anyone who is listening. The reason behind this approach was not to disrupt the public APIs.

    What happens if you load Sdl.Core.TM.ImportExport.dll  at the beginning of your powershell script? Does that help in any way?

    Thank you, Iszabela

  • Hi,

    The add_?? event helper methods are autogenerated by the compiler and are seeming to be problematic in this case.

    I can't see an obvious way of resolving the ambiguity is in powershell.
    You could try registering the events manually with Register-ObjectEvent but as you say this may be not what you want.

    I did a test script and it seems that using the new core version resolves without error (no ambiguity), but I do not have a complete script to be able to test this properly.

    $coreapi = Add-Type -AssemblyName "C:\Program Files (x86)\SDL\SDL Trados Studio\Studio15\Sdl.Core.TM.ImportExport.dll" -PassThru
    $CoreExporter = New-Object Sdl.Core.TM.ImportExport.Exporter ($TM.LanguageDirection)
    $CoreExporter. Add_BatchExported($OnBatchExported)

    I think we may have to enter a bug and look at it in detail.
    Note I was able to easily add the event in c# with 

    var tme = new Sdl.LanguagePlatform.TranslationMemoryApi.TranslationMemoryExporter();

    tme.BatchExported += DavesEventHandler();

  • Thanks David and Iszabela, I will do some additional experiments this evening when I get to the machine with my "development" environment.

    Now that I know the logic described by Iszabela, this looks like the logical step.

    (I would probably have to add some additional logic to detect the presence of the new core DLL and "dynamically" use that one instead of TranslationMemoryApi... but that should not be a big deal)

    Note I was able to easily add the event in c# with

    Yes, I believe that in C# it works fine... due to the different mechanism it uses for adding event handlers.

  • Hmmm, no luck so far...

    There is no constructor for Sdl.Core.TM.ImportExport.Exporter which would accept the language direction parameter. There is only constructor without parameters. And there is no language direction property which could be set after instantiating the exporter object using the 'empty' constructor.
    At least not in my Studio 2017 SR1 CU17 dll...

    Check out the .NET Reflector screenshot below.

    BTW, you can find the entire code here: github.com/.../STraSAK