Skip to content
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

GetAssemblyByName Bug - Sequence contains more than one matching element #1

Closed
p1xel8ted opened this issue Aug 23, 2024 · 4 comments · Fixed by #2
Closed

GetAssemblyByName Bug - Sequence contains more than one matching element #1

p1xel8ted opened this issue Aug 23, 2024 · 4 comments · Fixed by #2
Assignees
Labels
bug Something isn't working

Comments

@p1xel8ted
Copy link

Using this plugin for Cult of the Lamb - but it was erroring every exception due to it finding multiple of the same assembly name.

image

[Error  :UnityDebuggerAssistant] The exception handler failed while running. Please report the next line to Robyn:
[Error  :UnityDebuggerAssistant] System.TypeInitializationException: The type initializer for 'UnityDebuggerAssistant.Utils.UDAExceptionHandler' threw an exception. ---> System.InvalidOperationException: Sequence contains more than one matching element
  at System.Linq.Enumerable.SingleOrDefault[TSource] (System.Collections.Generic.IEnumerable`1[T] source, System.Func`2[T,TResult] predicate) [0x0004a] in <1c318258bf0843289b0e2cbe692fee39>:0
  at UnityDebuggerAssistant.Utils.UDAExceptionHandler.GetAssemblyByName (System.String name) [0x0000e] in ./src/UnityDebuggerAssistant/Utils/ExceptionHandler.cs:177
  at UnityDebuggerAssistant.Utils.UDAExceptionHandler..cctor () [0x00000] in ./src/UnityDebuggerAssistant/Utils/ExceptionHandler.cs:5
   --- End of inner exception stack trace ---
  at UnityDebuggerAssistant.Patches.ExceptionProcessor.Run (System.Exception __instance) [0x00059] in ./src/UnityDebuggerAssistant/Patches/Exception.cs:51

Original code:

    static Assembly GetAssemblyByName(string name)
    {
        return AppDomain.CurrentDomain.GetAssemblies().
               SingleOrDefault(assembly => assembly.GetName().Name.Equals(name, StringComparison.InvariantCultureIgnoreCase));
    }

Replacement code:

    private static Assembly GetAssemblyByName(string name)
    {
#if DEBUG
        var list = AppDomain.CurrentDomain.GetAssemblies().Where(assembly => assembly.GetName().Name.Equals(name, StringComparison.InvariantCultureIgnoreCase)).ToList();
        list = list.Distinct().ToList();
        foreach (var assembly in list)
        {
            Plugin.Log.LogWarning($"Found assembly: {assembly.FullName} - {assembly.Location}");
        }
#endif
        //changed this to FirstOrDefault because it was throwing an exception using SingleOrDefault (as it was finding multiple assemblies with the same name)
        var toBeReturned = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(assembly => assembly.GetName().Name.Equals(name, StringComparison.InvariantCultureIgnoreCase));
#if DEBUG
        Plugin.Log.LogWarning($"Returning assembly: {toBeReturned?.FullName} - {toBeReturned?.Location}");
#endif
        return toBeReturned;
    }
@RobynLlama
Copy link
Member

I just tested 1.3.2 before I pushed it to the TS and did not notice this in my log. I just now booted the game up and let it idle for a minute or two on the main menu and my player.log does not contain the word "warning" at all. The only time I log a warning in the whole project is when the processor is busy so I dunno how you got this message or where to start working on it.

@RobynLlama RobynLlama added the question Further information is requested label Aug 23, 2024
@p1xel8ted
Copy link
Author

I just tested 1.3.2 before I pushed it to the TS and did not notice this in my log. I just now booted the game up and let it idle for a minute or two on the main menu and my player.log does not contain the word "warning" at all. The only time I log a warning in the whole project is when the processor is busy so I dunno how you got this message or where to start working on it.

No...I added it so I could see what duplicates it was complaining about. Using SingleOrDefault when there is more than one result (why there is more than one, I haven't looked too deeply) is the cause of the exception.

The code in the "Replacement Code" box resolves the issue.

@AlbinoGeek
Copy link
Member

AlbinoGeek commented Aug 24, 2024

Your error message can't exist in either our, nor your code. Your code shows "Found Assembly" printing both the name and location of each Assembly, yet the screenshot shows no locations. If you can reproduce this issue, please show output which matches the code you show, versus at the moment where the screenshot does not match the shown code.

Neither the original nor replacement code could possibly result in the screenshot provided.

This means your installation specifically has two Assembly which call themselves Assembly-CSharp However, yes, you are correct, in the non-standard case where multiple assemblies of the same name exist, FirstOrDefault is more suitable.

Thank you for pointing this out.

2c2
<                SingleOrDefault(assembly => assembly.GetName().Name.Equals(name, StringComparison.InvariantCultureIgnoreCase));
---
>                 FirstOrDefault(assembly => assembly.GetName().Name.Equals(name, StringComparison.InvariantCultureIgnoreCase));

@AlbinoGeek AlbinoGeek added bug Something isn't working and removed question Further information is requested labels Aug 24, 2024
@p1xel8ted
Copy link
Author

Your error message can't exist in either our, nor your code. Your code shows "Found Assembly" printing both the name and location of each Assembly, yet the screenshot shows no locations. If you can reproduce this issue, please show output which matches the code you show, versus at the moment where the screenshot does not match the shown code.

Neither the original nor replacement code could possibly result in the screenshot provided.

This means your installation specifically has two Assembly which call themselves Assembly-CSharp However, yes, you are correct, in the non-standard case where multiple assemblies of the same name exist, FirstOrDefault is more suitable.

Thank you for pointing this out.

2c2
<                SingleOrDefault(assembly => assembly.GetName().Name.Equals(name, StringComparison.InvariantCultureIgnoreCase));
---
>                 FirstOrDefault(assembly => assembly.GetName().Name.Equals(name, StringComparison.InvariantCultureIgnoreCase));

As you can see from the thread, I added the logging specifically to capture the assemblies being found. The screenshot was taken before I updated the code to display the locations.

The line below is what produces the output shown in the screenshot:

Plugin.Log.LogWarning($"Found assembly: {assembly}");

I added the location because I too suspected I had a duplicate assembly, but of the two found, one assembly had a location, and one didn't.

Regardless, FirstOrDefault resolves it either way.

Hopefully, this explanation resolves any confusion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants