Hangfire – Creating a new DirectorySearcher object with a DirectoryEntry as an argument throws NullReferenceException

huangapple go评论81阅读模式
英文:

Hangfire - Creating a new DirectorySearcher object with a DirectoryEntry as an argument throws NullReferenceException

问题

I am trying to create a DirectorySearcher object using an existing DirectoryEntry object, but when I do it throws a System.NullReferenceException on that line. The following works in a standalone .NET 6.0 Console application, but not in a .Net 6.0 Console application that is doing work as a worker for a Hangfire Server. Here is the class and method that I get the exception with:

public class LocalADConnector : IADConnector
{
    public void GetUserADInfo(string username, string saGUID)
    {
        if (string.IsNullOrWhiteSpace(username)) { throw new ArgumentNullException(nameof(username), $"Argument {nameof(username)} of type {username.GetType()} may not be null or empty."); }    
        using (DirectoryEntry dirEntry = new DirectoryEntry(_adServer, _adUser, _adPass))
        {
            using (DirectorySearcher dirSearcher = new DirectorySearcher(dirEntry)) //Exception is thrown here.
            {
                dirSearcher.Filter = $"(&(objectClass=user)(SAMAccountName={username}))";

                using (DirectoryEntry adUser = dirSearcher.FindOne().GetDirectoryEntry())
                {
                    if (adUser == null)
                    {
                        throw new ArgumentException($"User with the username {username} does not exist!");
                    }

                    foreach (string property in adUser.Properties.PropertyNames)
                    {
                        Console.WriteLine($"{property}: {adUser.Properties[property].Value}");
                    }
                }
            }
        }
    }
}

Here is the method that will get enqueued by Hangfire through the web project, and then executed by a Windows service:

public void UpdateUser(string employeeID, IHRConnector hrConnector, IADConnector adConnector, string saGUID)
{
    try
    {
        adConnector.GetUserADInfo(employeeID, saGUID);

        //There is other stuff here, but it's not relevant.
    }
    catch (Exception ex)
    {
        Log.Error(ex);
        throw;
    }
}

And here is the serialization settings for Hangfire:

builder.Services.AddHangfire(config =>
    config.SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
    .UseSimpleAssemblyNameTypeSerializer()
    .UseDefaultTypeSerializer()
    .UseSerializerSettings(new Newtonsoft.Json.JsonSerializerSettings
    {
        TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Auto
    })
    .UseSqlServerStorage($"{builder.Configuration.GetConnectionString("HangfireDB")}uid={Environment.GetEnvironmentVariable("LGN_HF_USR", EnvironmentVariableTarget.Machine)};pwd={Environment.GetEnvironmentVariable("LGN_HF_PWD", EnvironmentVariableTarget.Machine)}", new Hangfire.SqlServer.SqlServerStorageOptions { SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5) })
);

I have tried creating the objects and then applying the properties after, but the exception occurs at the

dirSearcher.SearchRoot = dirEntry;

line. Creating a DirectorySearcher object in the immediate window using dirEntry works just fine.

Thanks in advance.

UPDATE:

The NullReferenceException occurred on a different logging line when I tried creating a default DirectorySearcher, so I think the actual object that this method is in is getting cleaned up/set to null for some reason.

UPDATE 2:

I'm convinced this issue is coming from having an interface as one of the arguments for the method enqueued by Hangfire. I have updated the code above to show more of the problem.

英文:

I am trying to create a DirectorySearcher object using an existing DirectoryEntry object, but when I do it throws a System.NullReferenceException on that line. The following works in a standalone .NET 6.0 Console application, but not in a .Net 6.0 Console application that is doing work as a worker for a Hangfire Server. Here is the class and method that I get the exception with:

public class LocalADConnector : IADConnector
{
    public void GetUserADInfo(string username, string saGUID)
    {
        if (string.IsNullOrWhiteSpace(username)) { throw new ArgumentNullException(nameof(username), $"Argument {nameof(username)} of type {username.GetType()} may not be null or empty."); }    
        using (DirectoryEntry dirEntry = new DirectoryEntry(_adServer, _adUser, _adPass))
        {
            using (DirectorySearcher dirSearcher = new DirectorySearcher(dirEntry)) //Exception is thrown here.
            {
                dirSearcher.Filter = $"(&(objectClass=user)(SAMAccountName={username}))";

                using (DirectoryEntry adUser = dirSearcher.FindOne().GetDirectoryEntry())
                {
                    if (adUser == null)
                    {
                        throw new ArgumentException($"User with the username {username} does not exist!");
                    }

                    foreach (string property in adUser.Properties.PropertyNames)
                    {
                        Console.WriteLine($"{property}: {adUser.Properties[property].Value}");
                    }
                }
            }
        }
    }
}

Here is the method that will get enqueued by Hangfire through the web project, and then executed by a Windows service:

public void UpdateUser(string employeeID, IHRConnector hrConnector, IADConnector adConnector, string saGUID)
{
    try
    {
        adConnector.GetUserADInfo(employeeID, saGUID);

        //There is other stuff here, but it's not relevant.
    }
    catch (Exception ex)
    {
        Log.Error(ex);
        throw;
    }
}

And here is the serialization settings for Hangfire:

builder.Services.AddHangfire(config =>
    config.SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
    .UseSimpleAssemblyNameTypeSerializer()
    .UseDefaultTypeSerializer()
    .UseSerializerSettings(new Newtonsoft.Json.JsonSerializerSettings
    {
        TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Auto
    })
    .UseSqlServerStorage($"{builder.Configuration.GetConnectionString("HangfireDB")}uid={Environment.GetEnvironmentVariable("LGN_HF_USR", EnvironmentVariableTarget.Machine)};pwd={Environment.GetEnvironmentVariable("LGN_HF_PWD", EnvironmentVariableTarget.Machine)}", new Hangfire.SqlServer.SqlServerStorageOptions { SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5) })
);

I have tried creating the objects and then applying the properties after, but the exception occurs at the

dirSearcher.SearchRoot = dirEntry;

line. Creating a DirectorySearcher object in the immediate window using dirEntry works just fine.

Thanks in advance.

UPDATE:

The NullReferenceException occurred on a different logging line when I tried creating a default DirectorySearcher, so I think the actual object that this method is in is getting cleaned up/set to null for some reason.

UPDATE 2:

I'm convinced this issue is coming from having an interface as one of the arguments for the method enqueued by Hangfire. I have updated the code above to show more of the problem.

答案1

得分: 0

这有点尴尬,但问题在于我在Release模式下调试,而不是Debug模式,所以它没有给我正确的System.NullReferenceException发生的代码行。具体来说,异常是因为尝试获取一个不存在的AD属性的值而引发的。感谢所有人的帮助,以及Bing Chat指引我走向正确的方向。

英文:

This is embarrassing, but the issue was that I was debugging in Release and not Debug, so it wasn't giving me the correct line that the System.NullReferenceException was happening on. Specifically, the exception was from trying to get the value of an AD property that didn't exist. Thanks for everyone's help, and Bing Chat for pointing me in the right direction.

huangapple
  • 本文由 发表于 2023年5月11日 01:06:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76220980.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定