仕事用に内部ユーザーの非アクティブ モニターを作成しています。これを行うために、Windows フォームを topshelf サービスと組み合わせて使用しています。コードは RabbitMQ サーバーに書き込み、サービスはメッセージを消費して、データベース、現状の私のコードは、次のエラーで例外をスローしています。
Missing type map configuration or unsupported mapping.
Mapping types:
LogData -> DbLogData
AccessEye.LogData -> AccessEye.DbLogData
これは私のサービスのコードです
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using NLog;
using IWshRuntimeLibrary;
using Topshelf;
using System.Data.Odbc;
using EasyNetQ;
using RabbitMQ;
using EasyNetQ.Topology;
using System.Threading.Tasks;
using System.Windows.Forms;
using AccessEye;
using System.ComponentModel;
namespace LogService
{
public class WindowsServiceHost : ServiceControl, ServiceShutdown
{
public static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public static void WriteLogDataToDb(LogData data)
{
using (var db = new LogService.UserActivityDataContext())
{
DbLogData logData = AutoMapper.Mapper.Map<LogData, DbLogData>(data);
int t = (int)data.EventType;
EventType eventType = db.EventTypes.FirstOrDefault(r => r.Id == t);
if (eventType == null)
{
eventType = db.EventTypes.Add(new EventType
{
Event = GetEnumDescriptionAttributeValue(data.EventType),
Id = (int)data.EventType
});
db.SaveChanges();
}
logData.EventTypeId = eventType.Id;
db.LogEvents.Add(logData);
db.SaveChanges();
}
}
public static string GetEnumDescriptionAttributeValue(Enum value)
{
var fieldInfo = value.GetType().GetField(value.ToString());
var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
return attributes.Length > 0 ? attributes[0].Description : value.ToString();
}
public bool Start(HostControl hostControl)
{
Program.bus = RabbitHutch.CreateBus("host=*****;virtualHost=*****;username=***;password=***").Advanced;
//var bus = RabbitHutch.CreateBus("host=*******;virtualHost=******;username=****;password=******").Advanced;
var queue = Queue.Declare(true, false, true, null);
var exchange = Exchange.DeclareFanout("UserActivityFanout", true, false, null);
var exchangeTopic = Exchange.DeclareTopic("UserActivity", true, false, null);
queue.BindTo(exchange, "#");
exchange.BindTo(exchangeTopic, "#");
Program.bus.Subscribe<AccessEye.LogData>(queue, (msg, messageRecInfo) => Task.Factory.StartNew(() =>
{
var data2 = LogDataFactory.CollectData();
data2.EventType = AccessEye.UserStateEvents.Logon;
WriteLogDataToDb(data2);
//AppForm.WriteLogDataToDb(data);
//Console.WriteLine(msg.Body.UserName + " -- " + msg.Body.ComputerName + " -- " + msg.Body.EventType + " -- " + msg.Body.TeamviewerId);
}));
return true;
}
public bool Stop(HostControl hostControl)
{
Logger.Trace("STOP");
Program.bus.Dispose();
return true;
}
public void Shutdown(HostControl hostControl)
{
Logger.Trace("SHUTDOWN");
Program.bus.Dispose();
}
}
}
そしてフォームについて
using System;
using System.IO;
using System.Windows.Forms;
using System.ComponentModel;
using AccessEye;
using System.Linq;
using EasyNetQ;
using EasyNetQ.Topology;
using Microsoft.Win32;
using MySql.Data.MySqlClient;
using NLog;
using ProtoBuf;
using System.Threading;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Runtime.InteropServices;
using System.Reflection;
namespace LogProgram
{
public partial class AppForm : Form
{
public static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private Screensaver watcher;
public Inactivity inactivity;
IAdvancedBus bus;
IExchange exchange;
public AppForm()
{
InitializeComponent();
ConfigureForm();
// todo: should be in setting
int pollingInterval = 5000;
inactivity = new Inactivity(pollingInterval);
inactivity.Inactive += inactivity_Inactive;
inactivity.Active += inactivity_Active;
inactivity.InactivityThresholdMs = 5 * 1000; // todo: should be in setting
inactivity.Start();
watcher = new Screensaver(pollingInterval);
watcher.ScreensaverOff += watcher_ScreensaverOff;
watcher.ScreensaverOn += watcher_ScreensaverOn;
watcher.Start();
SystemEvents.SessionEnding += SystemEvents_SessionEnding;
SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
LogManager.ThrowExceptions = true;
// todo: connection string should be in setting
bus = RabbitHutch.CreateBus("host=as01.access.local;virtualHost=DEV-Reece;username=reece;password=reece").Advanced;
exchange = Exchange.DeclareTopic("UserActivity", true, false, null);
var fanout = Exchange.DeclareFanout("FanoutExchange", true, false, null);
fanout.BindTo(exchange, new[] { "#" });
}
public void ConfigureForm()
{
this.Hide();
TrayDisplayer.Visible = false;
}
public static void WriteLogDataToDb(LogData data)
{
using (var db = new LogService.UserActivityDataContext())
{
DbLogData logData = AutoMapper.Mapper.Map<LogData, DbLogData>(data);
int t = (int)data.EventType;
EventType eventType = db.EventTypes.FirstOrDefault(r => r.Id == t);
if (eventType == null)
{
eventType = db.EventTypes.Add(new EventType
{
Event = GetEnumDescriptionAttributeValue(data.EventType),
Id = (int)data.EventType
});
db.SaveChanges();
}
logData.EventTypeId = eventType.Id;
db.LogEvents.Add(logData);
db.SaveChanges();
}
}
public static string GetEnumDescriptionAttributeValue(Enum value)
{
var fieldInfo = value.GetType().GetField(value.ToString());
var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
return attributes.Length > 0 ? attributes[0].Description : value.ToString();
}
private void AppForm_Load(object sender, EventArgs e)
{
}
void watcher_ScreensaverOn(object sender, EventArgs e)
{
var data = LogDataFactory.CollectData();
data.EventType = AccessEye.UserStateEvents.ScreensaverOn;
PublishLogData(data);
}
void watcher_ScreensaverOff(object sender, EventArgs e)
{
var data = LogDataFactory.CollectData();
data.EventType = AccessEye.UserStateEvents.ScreensaverOff;
PublishLogData(data);
}
void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
{
var data = LogDataFactory.CollectData();
switch (e.Reason)
{
case SessionSwitchReason.SessionLock:
data.EventType = UserStateEvents.Lock;
break;
case SessionSwitchReason.SessionUnlock:
data.EventType = UserStateEvents.Unlock;
break;
}
PublishLogData(data);
}
public void PublishLogData(AccessEye.LogData LogData)
{
WriteLogDataToDb(LogData);
if (!bus.IsConnected) return;
try
{
using (var publishChannel = bus.OpenPublishChannel())
{
publishChannel.Publish(exchange, LogData.EventType.ToString(), new Message<LogData>(LogData));
}
}
catch (EasyNetQException)
{
//todo: handle
}
}
public static byte[] Serialize<T>(T instance)
{
using (var stream = new MemoryStream())
{
Serializer.Serialize(stream, instance);
return stream.ToArray();
}
}
private static T DeSerialize<T>(byte[] data)
{
using (var stream = new MemoryStream(data))
{
return Serializer.Deserialize<T>(stream);
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
bus.Dispose();
}
public void inactivity_Active(object sender, EventArgs e)
{
inactivity.Stop();
var data = LogDataFactory.CollectData();
data.EventType = UserStateEvents.Active;
PublishLogData(data);
inactivity.Start();
}
public void inactivity_Inactive(object sender, EventArgs e)
{
inactivity.Stop();
var data = LogDataFactory.CollectData();
data.EventType = UserStateEvents.Inactive;
PublishLogData(data);
inactivity.Start();
}
public void SystemEvents_SessionEnding(object sender, EventArgs e)
{
var data = LogDataFactory.CollectData();
data.EventType = UserStateEvents.Logoff;
PublishLogData(data);
Logger.Trace("Logged off");
}
}
}
LogData クラス
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ProtoBuf;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace AccessEye
{
public class DbLogData : LogData
{
[Key]
public int Id { get; set; }
public int? EventTypeId { get; set; }
[ForeignKey("EventTypeId")]
public virtual EventType EventTypeTest { get; set; }
}
}