Issue #24: create mxaccess com object on sta

This commit is contained in:
Joseph Doherty
2026-04-26 17:34:01 -04:00
parent 5511609880
commit 451dccf7e3
12 changed files with 607 additions and 13 deletions
@@ -0,0 +1,97 @@
using System;
using System.Runtime.InteropServices;
using Google.Protobuf.WellKnownTypes;
using MxGateway.Contracts.Proto;
namespace MxGateway.Worker.MxAccess;
public sealed class MxAccessSession : IDisposable
{
private readonly object mxAccessComObject;
private readonly IMxAccessEventSink eventSink;
private bool disposed;
private MxAccessSession(
object mxAccessComObject,
IMxAccessEventSink eventSink,
int creationThreadId)
{
this.mxAccessComObject = mxAccessComObject ?? throw new ArgumentNullException(nameof(mxAccessComObject));
this.eventSink = eventSink ?? throw new ArgumentNullException(nameof(eventSink));
CreationThreadId = creationThreadId;
}
public int CreationThreadId { get; }
public WorkerReady CreateWorkerReady(int workerProcessId)
{
return new WorkerReady
{
WorkerProcessId = workerProcessId,
MxaccessProgid = MxAccessInteropInfo.ProgId,
MxaccessClsid = MxAccessInteropInfo.Clsid,
ReadyTimestamp = Timestamp.FromDateTime(DateTime.UtcNow),
};
}
public static MxAccessSession Create(
IMxAccessComObjectFactory factory,
IMxAccessEventSink eventSink)
{
if (factory is null)
{
throw new ArgumentNullException(nameof(factory));
}
if (eventSink is null)
{
throw new ArgumentNullException(nameof(eventSink));
}
object? mxAccessComObject = null;
try
{
mxAccessComObject = factory.Create();
if (mxAccessComObject is null)
{
throw new InvalidOperationException("MXAccess COM factory returned null.");
}
eventSink.Attach(mxAccessComObject);
return new MxAccessSession(
mxAccessComObject,
eventSink,
Environment.CurrentManagedThreadId);
}
catch (Exception exception)
{
eventSink.Detach();
if (mxAccessComObject is not null && Marshal.IsComObject(mxAccessComObject))
{
Marshal.FinalReleaseComObject(mxAccessComObject);
}
throw MxAccessCreationException.From(exception);
}
}
public void Dispose()
{
if (disposed)
{
return;
}
eventSink.Detach();
if (Marshal.IsComObject(mxAccessComObject))
{
Marshal.FinalReleaseComObject(mxAccessComObject);
}
disposed = true;
}
}