System.TypeInitializationException 发生在 MassTransit.dll

System.TypeInitializationException occurred in MassTransit.dll

我一直在使用 MassTransit 和 RabbitMQ.Client NuGet 包将消息发布到我的 RabbitMQ 队列。这几个月来一直很好用。突然之间(没有更改代码),我无法再创建 ServiceBus。这是我几个月来一直在使用的代码:

public class RabbitBus
{
    private IServiceBus bus;

    public void Start(Action<ServiceBusConfigurator> moreInitialization)
    {
        const string host = "rabbitmq://localhost/testqueue";

        bus = ServiceBusFactory.New(x =>
        {
            x.UseRabbitMq(r =>
            {
                r.ConfigureHost(new Uri("rabbitmq://localhost/testqueue"), h =>
                {
                    h.SetUsername("user");
                    h.SetPassword("password");
                });
            });
            x.ReceiveFrom(host);
            moreInitialization(x);
        });
    }

    public void Stop()
    {
        bus.Dispose();
    }

    public void Publish<T>(T message)
    {
        bus.Publish(message, x => { x.SetDeliveryMode(DeliveryMode.Persistent); });
    }
}

然后我会发布这样一条消息:

var bus = new RabbitBus();
bus.Start((x) => {});
bus.Publish("Test");
bus.Stop();

就像我说的,这段代码几个月来一直很好。就在昨天,我在通过 ServiceBusFactory.New 调用创建我的 ServiceBus 时开始收到 System.TypeInitializationException

An unhandled exception of type 'System.TypeInitializationException' occurred in MassTransit.dll

Additional information: The type initializer for 'MassTransit.Monitoring.ServiceBusPerformanceCounters' threw an exception.

Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

这是 StackTrace:

  • at Microsoft.Win32.Win32Native.RegQueryValueEx(SafeRegistryHandle hKey, String lpValueName, Int32[] lpReserved, Int32& lpType, Byte[] lpData, Int32& lpcbData)
    • at Microsoft.Win32.RegistryKey.InternalGetValue(String name, Object defaultValue, Boolean doNotExpand, Boolean checkSecurity)
    • at Microsoft.Win32.RegistryKey.GetValue(String name)
    • at System.Diagnostics.PerformanceMonitor.GetData(String item)
    • at System.Diagnostics.PerformanceCounterLib.GetPerformanceData(String item)
    • at System.Diagnostics.PerformanceCounterLib.get_CategoryTable()
    • at System.Diagnostics.PerformanceCounterLib.CounterExists(String category, String counter, Boolean& categoryExists)
    • at System.Diagnostics.PerformanceCounterLib.CounterExists(String machine, String category, String counter)
    • at System.Diagnostics.PerformanceCounterCategory.CounterExists(String counterName, String categoryName, String machineName)
    • at System.Diagnostics.PerformanceCounterCategory.CounterExists(String counterName, String categoryName)
    • at MassTransit.Monitoring.ServiceBusPerformanceCounters.b__1(RuntimePerformanceCounter counter) in d:\BuildAgent\work\aa063b4295dfc097\src\MassTransit\Monitoring\ServiceBusPerformanceCounters.cs:line 151
    • at System.Linq.Enumerable.WhereArrayIterator`1.MoveNext()
    • at System.Linq.Enumerable.Count[TSource](IEnumerable`1 source)
    • at MassTransit.Monitoring.ServiceBusPerformanceCounters.InitiatizeCategory() in d:\BuildAgent\work\aa063b4295dfc097\src\MassTransit\Monitoring\ServiceBusPerformanceCounters.cs:line 150
    • at MassTransit.Monitoring.ServiceBusPerformanceCounters..ctor() in d:\BuildAgent\work\aa063b4295dfc097\src\MassTransit\Monitoring\ServiceBusPerformanceCounters.cs:line 91
    • at MassTransit.Monitoring.ServiceBusPerformanceCounters..cctor() in d:\BuildAgent\work\aa063b4295dfc097\src\MassTransit\Monitoring\ServiceBusPerformanceCounters.cs:line 30

我已经在 Whosebug 和其他网站上搜索了几个小时,但没有取得任何进展。如果有人有任何见解,我很乐意提供帮助。谢谢!

我终于找到了解决我问题的答案。我在文章How to Read Performance Counters Without Administrator Privileges中找到了答案。如果文章被删除,以下是关键部分:

Windows 2003, Windows XP x64 Edition, and Vista require that the user be part of the Performance Monitor Users group to read performance counter data. Simply adding your non admin user to this group will fix this problem.

Accessing counters remotely is another story though. On Windows 2003, Windows XP x64 Edition, and Vista you still must be part of the Performance Monitor Users group on the remote machine but there is a problem with the PerformanceCounter class where it tries to read some registry keys on the remote machine that a non admin users do not have access to. To give your user read access to these keys without having to be an admin on the remote machine complete the following steps on the remote machine:

  1. Open the Registry Editor by going to the Start Menu and selecting Run…, then type “regedit”, and click the OK button.
  2. Navigate to the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurePipeServers\winreg registry key.
  3. Right click on the “winreg” key and select Permissions. Add users or groups to which you want to grant Read access.
  4. Exit Registry Editor and restart Windows.

我不得不这样做很奇怪,特别是因为我是 Windows 7 机器上的管理员,但这个修复解决了我的问题。