Safe design pattern for creating and closing COM interop instances + support e.g. MS Office/Excel/Word/Powerpoint Interop without Microsoft's interop assemblies + access to COM object's public members with Reflection (instead of late binding (which often fails))
$ dotnet add package CompuMaster.ComInteropCOM interop library with safe design pattern for COM instancing
CreateObject("Excel.Application"), .NET isn't able to call many methods/properties/fields on COM objects using LateBinding, e.g. MsExcelAppViaCom.Quit()MsExcelAppViaCom.Quit() again)See full sample at https://www.github.com/CompuMasterGmbH/CompuMaster.Excel/
<details> <summary>First code impressions from https://www.github.com/CompuMasterGmbH/CompuMaster.Excel/</summary> </details>Public Class ExcelApplication
Inherits ComObjectBase
Public Sub New()
MyBase.New(Nothing, CreateObject("Excel.Application"))
Me.Workbooks = New ExcelWorkbooksCollection(Me, Me)
End Sub
Public ReadOnly Property Workbooks As ExcelWorkbooksCollection
Public Property UserControl As Boolean
Get
Return InvokePropertyGet(Of Boolean)("UserControl")
End Get
Set(value As Boolean)
InvokePropertySet("UserControl", value)
End Set
End Property
Public Property DisplayAlerts As Boolean
Get
Return InvokePropertyGet(Of Boolean)("DisplayAlerts")
End Get
Set(value As Boolean)
InvokePropertySet("DisplayAlerts", value)
End Set
End Property
Public Property Visible As Boolean
Get
Return InvokePropertyGet(Of Boolean)("Visible")
End Get
Set(value As Boolean)
InvokePropertySet("Visible", value)
End Set
End Property
Public Function Dialogs(type As Enumerations.XlBuiltInDialog) As ExcelDialog
Return New ExcelDialog(Me, InvokePropertyGet("Dialogs", CType(type, Integer)))
End Function
Public Function Run(vbaMethodNameInclWorkbookName As String) As Object
Return InvokeFunction("Run", New Object() {vbaMethodNameInclWorkbookName})
End Function
Public Function Run(workbookName As String, vbaMethod As String) As Object
Return InvokeFunction("Run", New Object() {"'" & workbookName & "'!" & vbaMethod})
End Function
Public ReadOnly Property IsClosed As Boolean
Get
Return MyBase.IsDisposedComObject
End Get
End Property
Public Sub Close()
Me.Quit()
End Sub
Public Sub Quit()
If Not IsDisposedComObject Then
UserControl = True
MyBase.CloseAndDisposeChildrenAndComObject()
End If
End Sub
Private AdditionalDisposeChildrenList As New List(Of ComObjectBase)
Protected Overrides Sub OnDisposeChildren()
If Me.Workbooks IsNot Nothing Then Me.Workbooks.Dispose()
End Sub
Protected Overrides Sub OnClosing()
InvokeMethod("Quit")
End Sub
Protected Overrides Sub OnClosed()
GC.Collect(2, GCCollectionMode.Forced, True)
End Sub
End ClassPublic Class ExcelWorkbooksCollection
Inherits ComObjectBase
Friend Sub New(parentItemResponsibleForDisposal As ComObjectBase, app As ExcelApplication)
MyBase.New(parentItemResponsibleForDisposal, app.InvokePropertyGet("Workbooks"))
Me.Parent = app
End Sub
Friend ReadOnly Parent As ExcelApplication
Public Workbooks As New List(Of ExcelWorkbook)
Public Function Open(path As String) As ExcelWorkbook
Dim wb As New ExcelWorkbook(Me, Me, path)
Me.Workbooks.Add(wb)
Return wb
End Function
Protected Overrides Sub OnDisposeChildren()
For MyCounter As Integer = Workbooks.Count - 1 To 0 Step -1
Workbooks(MyCounter).Dispose()
Next
End Sub
Protected Overrides Sub OnClosing()
End Sub
Protected Overrides Sub OnClosed()
End Sub
End ClassUsualy provides for your custom implementation
base.CloseAndDisposeChildrenAndComObject()base.Invoke...base.ComObjectbase.IsDisposedComObjectUsualy requires you to implement
Sub New in VisualBasic)OnDisposeChildren()
OnClosing()
OnClosed()
//An application wrapper class for safe COM object handling and release for COM servers,
//properly releasing the COM object
//forcefully killing the application process on end if required
var ExcelEngine = new CompuMaster.ComInterop.ComApplication<Microsoft.Office.Interop.Excel.Application>(
new Microsoft.Office.Interop.Excel.Application,
(x) => x.ComObjectStronglyTyped.Hwnd,
(x) => x.ComObjectStronglyTyped.Quit(),
"EXCEL");
//do some nice things...
//quit (if you don't run Dispose method manually here, the garbage collector will do the job automatically to the given time)
ExcelEngine.Dispose();//An application wrapper class for safe COM object handling and release for COM servers,
//forcefully killing the application process on end if required
var ExcelEngine = new CompuMaster.ComInterop.ComApplication<Object>(
"Excel.Application",
(x) => x.InvokePropertyGet<Int32>("Hwnd"),
(x) => x.InvokeMethod("Quit"),
"EXCEL");
//do some nice things...
//quit (if you don't run Dispose method manually here, the garbage collector will do the job automatically to the given time)
ExcelEngine.Dispose();