I am developing a WinForms application that uses OleDB (along with NPOI) extensively to read and write Excel workbooks. I will preface this by saying that if I just launch the app and close it immediately, the application and the EXE terminate fine. The first action the user can perform is to click on a button to open an XLSX file. I then initialize a datatable in memory and use the following code to populate it :
Open connection :
public static OleDbConnection GetConnection(string filePath)
{
var url = @"Provider=Microsoft.ACE.OLEDB.12.0;"
"Data Source=" filePath ";"
"Extended Properties='Excel 12.0 Xml; HDR=YES; IMEX=1;';";
try
{
var con = new OleDbConnection(url);
con.Open();
return con;
}
catch (Exception e)
{
throw new ArgumentException($"Unable to open connection to workbook with url \"{url}\"", e);
}
}
Fill datatable :
public static void PopulateDataTable(string filePath, DataTable dt)
{
using var con = GetConnection(filePath);
using var sda = new OleDbDataAdapter(new OleDbCommand("Select * From [" GetSheetName(con) "]", con));
sda.Fill(dt);
sda.Dispose();
con.Close();
con.Dispose();
}
The first method is only used to validate the headers of the file and IS closed and disposed explicitly by the calling code. It is also in a using block, I do realize there is some redundancy there but I am desperate.
Once the file is proven valid against a pre-determined list of column headers, the second method is called. As soon as this action is performed, closing the main form SEEMS to close the app but there is still a lingering process in task manager with a single thread in it.
I have tried adding Application.Exit()
and Environment.Exit(0)
to the FormClosing method which does kill the process but not before showing an hourglass and logging the following error in event viewer :
Faulting application name: SomeApp.exe, version: 1.0.0.0, time stamp: 0x62cf0b31
Faulting module name: mso20win32client.dll, version: 0.0.0.0, time stamp: 0x62df2f51
Exception code: 0xc000041d
Fault offset: 0x000185ed
Faulting process id: 0x27f24
Faulting application start time: 0x01d8bc7d9dd155ac
Faulting application path: C:\Dev\VisualStudioProjects\SomeApp\Final\SomeApp.exe
Faulting module path: C:\Program Files (x86)\Common Files\Microsoft Shared\Office16\mso20win32client.dll
Report Id: 4a58bd92-6541-4def-a04d-01ed0668d38b
Faulting package full name:
Faulting package-relative application ID:
A second event is also logged that is identical except for the exception code which is 0xc0000005. I suspect this issue is also responsible for a false positive detection from Windows Defender. I cannot figure out what this lingering thread is and how to get the code to properly kill it.
CodePudding user response:
I fixed this by implementing a purely NPOI-based reading solution without using OleDB (good riddance) :
public static void PopulateDatatableNPOI(string filePath, DataTable dt, bool createHeaders)
{
using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
var sheet = new XSSFWorkbook(stream).GetSheetAt(0);
if (createHeaders)
{
var headerRow = sheet.GetRow(0);
foreach (var headerCell in headerRow)
dt.Columns.Add(headerCell.ToString());
}
for (int i = 1; i < sheet.PhysicalNumberOfRows; i )
{
var sheetRow = sheet.GetRow(i);
var dtRow = dt.NewRow();
dtRow.ItemArray = dt.Columns
.Cast<DataColumn>()
.Select(c => sheetRow.GetCell(c.Ordinal, MissingCellPolicy.CREATE_NULL_AS_BLANK).ToString())
.ToArray();
dt.Rows.Add(dtRow);
}
}
The EXE terminates properly now!