We created a .NET application that collects data from IBM (Lotus) Notes. It connects to Notes via COM objects (Lotus Domino Objects).
In general, it works and do all the operations we need, but then, after some hours of work, the app stops working. I mean, it kinda freezes and stops doing any job. It happens on different databases in unpredictable time, so I couldn't find any regularity
The last log message we got from the app either:
System.Runtime.InteropServices.COMException (0x80010105): Creating an instance of the COM component with CLSID {29131539-2EED-1069-BF5D-00DD011186B7} from the IClassFactory failed due to the following error: 80010105 The server threw an exception. (Exception from HRESULT: 0x80010105 (RPC_E_SERVERFAULT)). at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) at System.Activator.CreateInstance(Type type, Boolean nonPublic) at System.Activator.CreateInstance(Type type) at MyMethod(NotesServerConfig notesServerConfig, String mailBox) in D:...\MyClass.cs:line 164
or
System.Runtime.InteropServices.COMException (0x80040FA1): Exception from HRESULT: 0x80040FA1 at Domino.ISession.Initialize(String pPassword) at MyMethod(NotesServerConfig notesServerConfig, String mailBox) in D:...\MyClass.cs:line 164
The fact that they both have link to the line 164 of MyClass, which is just an invocation of a session's constructor:
var session = new NotesSession();
My real app works as a Windows Service via Topshelf, so there are a lot of code in it since the project has became pretty big already. So let me try to put here a simplified version without any extra code and 3rd party libraries to show how I use Lotus Domino Objects:
using Domino;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace LotusTest
{
class Program
{
private const int _maxClientReCreateAttempts = 10;
private const string _password = "qwerty";
private const string _server = "test.server.ru";
private static readonly List<string> _dbNames = new List<string>
{
"mail\\test1", "mail\\test2", "mail\\test3"
};
static void Main(string[] args)
{
foreach (var dbName in _dbNames)
{
var folders = GetFolders(dbName);
foreach (var folder in folders)
{
var mailSubjects = GetEmailSubjects(folder, dbName);
foreach (var mailSubject in mailSubjects)
{
Console.WriteLine($"Mail {mailSubject} in {folder}, db: {dbName}");
}
}
}
}
private static List<string> GetFolders(string dbName)
{
var result = new List<string>();
var session = new NotesSession();
session.Initialize(_password);
var db = session.GetDatabase(_server, dbName, false);
if (db == null)
{
Console.WriteLine($"Can't read the database: {dbName}");
return result;
}
foreach (var view in db.Views)
{
if (!view.IsFolder) { continue; }
result.Add(view.Name);
}
return result;
}
private static List<string> GetEmailSubjects(string viewName, string dbName)
{
var result = new List<string>();
var session = new NotesSession();
session.Initialize(_password);
var db = session.GetDatabase(_server, dbName, false);
if (db == null)
{
Console.WriteLine($"Can't read the database: {dbName}");
return result;
}
var cv = db.GetView(viewName);
if (cv == null)
{
Console.WriteLine($"Can't read '{viewName}' folder of '{dbName}' database");
return result;
}
return ReadFolder(cv, session, dbName, viewName);
}
private static List<string> ReadFolder(NotesView cv, NotesSession session, string folder, string mailBox)
{
var result = new List<string>();
var doc = cv.GetFirstDocument();
int i = 0;
int errCount = 0;
bool lastGetWithError = false;
int totalAmount = cv?.AllEntries?.Count ?? 0;
int clientReCreateAttempts = 0;
while (doc != null)
{
try
{
if (!lastGetWithError)
{
result.Add(doc.GetItemValue("Subject")[0]);
Console.WriteLine($"Folder: {folder}, processed: {i + 1 - errCount} of {totalAmount}");
}
doc = cv.GetNextDocument(doc);
lastGetWithError = false;
}
catch (COMException ex)
{
Console.WriteLine($"Error on reading folder {folder} of mailbox {mailBox}.\r\n{ex}");
if (clientReCreateAttempts > _maxClientReCreateAttempts)
{
throw new Exception("Reading mail doc error: ", ex);
}
Console.WriteLine($"Trying to re-create Notes session");
session = new NotesSession();
clientReCreateAttempts++;
}
catch (Exception ex)
{
Console.WriteLine($"Error on reading folder {folder} of mailbox {mailBox}.\r\n{ex}");
lastGetWithError = true;
}
finally
{
i++;
}
}
return result;
}
}
}
So, according to freezing - maybe it's just a bug in my exception handling. But there are a couple of things I wanna ask:
Is it possible to understand what exactly happens behind those
0x80010105 (RPC_E_SERVERFAULT)
and 0x80040FA1
errors?
Based on the code I've put here, do I use NotesSession and other Lotus COM objects right? I mean, do I need to dispose/release/close the session (or other objects) somehow after I make some operation etc?
Thanks in advance!
User contributions licensed under CC BY-SA 3.0