问题
I'm trying to connect to an access DB and retrieve information.
Everything is going well the project is almost complete but I need to figure out how to quit interop.
I start by creating my access application then I make sure visible is set to false. (I don't see Access) but as soon as my code get to line app.Quit() (verified using step though) Access flashes on the screen just to disappear again.
For added information: If I do a step through the Access window doesn't disappear and I can't manual close it (red x top right). The application just reopens blank. I have to force close it.
As you can see in my commented out code I use a Process Kill to make sure that nothing flashes on the screen but that causes my application to become unstable (so many access DB backups created due to crash).
If you are experiences the normal (blank stare). Please at least let me know where to start digging if you have a gut feeling.
static public DataTable ExecuteSQLToDataTable(string sql)
{
DataTable dt = new DataTable();
lock (Locks.AccessDB)
{
Microsoft.Office.Interop.Access.Application accApp = new Microsoft.Office.Interop.Access.Application();
accApp.Visible = false;
Microsoft.Office.Interop.Access.Dao.Recordset rst = null;
Microsoft.Office.Interop.Access.Dao.Database cdb = null;
try
{
accApp.OpenCurrentDatabase(ConnectionDatabase.DatabasePath, false, @"[somepassword]");
cdb = accApp.CurrentDb();
rst =
cdb.OpenRecordset(sql,
Microsoft.Office.Interop.Access.Dao.RecordsetTypeEnum.dbOpenSnapshot);
rst.MoveLast();
int recordCount = rst.RecordCount;
rst.MoveFirst();
object[,] recordsArray = (object[,])rst.GetRows(recordCount);
var rowCount = recordsArray.GetLength(1);
var columnCount = recordsArray.GetLength(0);
var dtTemp = new DataTable();
foreach (Microsoft.Office.Interop.Access.Dao.Field fld in rst.Fields)
dt.Columns.Add(fld.Name, typeof(string));
foreach (var r in Enumerable.Range(1, rowCount))
dt.Rows.Add(Enumerable.Range(1, columnCount)
.Select(c => recordsArray[c - 1, r - 1]).ToArray());
}
catch
{
//TODO Add catch
}
finally
{
GetWindowThreadProcessId(accApp.hWndAccessApp(), out int id);
if (rst != null) { Marshal.ReleaseComObject(rst); }
if (cdb != null) { Marshal.ReleaseComObject(cdb); }
if (accApp != null) { accApp.Quit(); Marshal.ReleaseComObject(accApp); }
rst = null;
cdb = null;
accApp = null;
//Process.GetProcessById(id).Kill();
}
return dt;
}
}
Locks is a static class Locks.AccessDB is just an empty object
回答1:
I am inclined to believe that Access is doing something of its own to show itself on screen when you call all Quit().
You can workaround the issue by using SetWindowPos to move the Access window off the screen so you never see it when you call Quit().
来源:https://stackoverflow.com/questions/58176221/quit-causes-access-to-become-visible-for-a-moment