Ciao a tutti,
ho un problemino con la gestione apertura/chiusura un database access.
Da VB.NET apro il DB con la seguente funzione:
codice:
Public Sub ApriFileAccess(ByRef accApp As Access.Application, ByVal file As String, ByVal visibile As Boolean)
accApp = New Access.ApplicationClass()
accApp.OpenCurrentDatabase(file, True)
accApp.Visible = visibile
End Sub
Dopo aver aperto correttamente il file scarico l'elenco di tutte le tabelle, query e macro presenti nel file con questa funzione (posto tutto il codice, magari puo' interessare a qualcuno):
codice:
Dim connessione As ADOX.Catalog = New ADOX.Catalog
Dim contRighe As Integer
Dim xlsApp As Excel.Application
Dim xlsBook As Excel.Workbook
Dim accApp As Access.Application
Public Const PercorsoMacro As String = "C:\ChannelStrategy\MacroTestuali\"
Public Structure Tabella
Dim Nome As String
Dim Link As String
End Structure
Public Const QUERY_SELECT As Integer = 1
Public Const QUERY_CROSS As Integer = 2
Public Const QUERY_DELETE As Integer = 3
Public Const QUERY_UPDATE As Integer = 4
Public Const QUERY_APPEND As Integer = 5
Public Const QUERY_MAKE As Integer = 6
Public Structure Query
Dim Nome As String
Dim SQL As String
Dim Tipo As Integer
End Structure
Public Const AZIONE_SETWARNING As Integer = 1
Public Const AZIONE_OPENQUERY As Integer = 2
Public Const AZIONE_CLOSE As Integer = 3
Public Const AZIONE_TRANSFERSPREADSHEET As Integer = 4
Public Const AZIONE_SENDOBJECT As Integer = 5
Public Const AZIONE_MSGBOX As Integer = 6
Public Structure Azione
Dim NomeAzione As String
Dim TipoAzione As Integer
Dim ListaArgument() As Object
Dim ContArgument As Integer
End Structure
Public Structure Macro
Dim NomeMacro As String
Dim ListaAzioni() As Azione
Dim ContAzioni As Integer
End Structure
Public ListaTabelle() As Tabella
Public ListaQuery() As Query
Public ListaMacro() As Macro
Public contTabelle As Integer
Public contQuery As Integer
Public contMacro As Integer
Public contAzioni As Integer
Public contArgument As Integer
Private Sub DammiDatiDataBase()
Dim Contenitore As Container
Dim Documento As Document
Dim sr As StreamReader = Nothing
Dim riga As String
Dim arrRiga() As String
Dim i, j As Integer
' Apro il file access invisibile
lblAttesaOperazione.Text = "Connessione al db in corso"
Me.Update()
ApriFileAccess(accApp, ProprietaFile.PercorsoLocale & ProprietaFile.NomeFile, False)
accApp.Visible = False
' Ottengo la lista di tutte le tabelle
lblAttesaOperazione.Text = "Ottengo la lista di tutte le tabelle"
Me.Update()
contTabelle = 0
For i = 0 To accApp.CurrentDb.TableDefs.Count - 1
If Not accApp.CurrentDb.TableDefs(i).Name.StartsWith("MSys") Then
contTabelle = contTabelle + 1
Array.Resize(ListaTabelle, contTabelle)
ListaTabelle(contTabelle - 1).Nome = accApp.CurrentDb.TableDefs(i).Name
If accApp.CurrentDb.TableDefs(i).Connect = "" Then
ListaTabelle(contTabelle - 1).Link = ""
Else
arrRiga = accApp.CurrentDb.TableDefs(i).Connect.Split("=")
If arrRiga(0).StartsWith("Text") Then
ListaTabelle(contTabelle - 1).Link = arrRiga(arrRiga.GetUpperBound(0)) & ".txt"
Else
ListaTabelle(contTabelle - 1).Link = arrRiga(arrRiga.GetUpperBound(0))
End If
End If
End If
Next
' Ottengo la lista di tutte le query
lblAttesaOperazione.Text = "Ottengo la lista di tutte le query"
Me.Update()
contQuery = accApp.CurrentDb.QueryDefs.Count
Array.Resize(ListaQuery, contQuery)
For i = 0 To contQuery - 1
ListaQuery(i).Nome = accApp.CurrentDb.QueryDefs(i).Name
ListaQuery(i).SQL = accApp.CurrentDb.QueryDefs(i).SQL
If StrComp("SELECT", ListaQuery(i).SQL.Substring(0, 6)) Then
ListaQuery(i).Tipo = QUERY_SELECT
ElseIf StrComp("TRANSFORM", ListaQuery(i).SQL.Substring(0, 9)) Then
ListaQuery(i).Tipo = QUERY_CROSS
ElseIf StrComp("DELETE", ListaQuery(i).SQL.Substring(0, 6)) Then
ListaQuery(i).Tipo = QUERY_DELETE
ElseIf StrComp("UPDATE", ListaQuery(i).SQL.Substring(0, 6)) Then
ListaQuery(i).Tipo = QUERY_UPDATE
ElseIf StrComp("INSERT", ListaQuery(i).SQL.Substring(0, 6)) Then
ListaQuery(i).Tipo = QUERY_APPEND
ElseIf ListaQuery(i).SQL.Contains("INTO") Then
ListaQuery(i).Tipo = QUERY_MAKE
End If
Next
' Scarico i contenuti di tutte le macro presenti
lblAttesaOperazione.Text = "Ottengo la lista di tutte le macro"
Me.Update()
Directory.CreateDirectory(PercorsoMacro)
contMacro = 0
Contenitore = accApp.CurrentDb.Containers("Scripts")
For j = 0 To Contenitore.Documents.Count - 1
Documento = Contenitore.Documents(j)
If Not Documento.Name.StartsWith("~") Then
contAzioni = 0
contMacro = contMacro + 1
Array.Resize(ListaMacro, contMacro)
' Salvo la macro come file di testo
accApp.Application.SaveAsText(Access.AcObjectType.acMacro, Documento.Name, PercorsoMacro & Documento.Name & ".txt")
ListaMacro(contMacro - 1).NomeMacro = Documento.Name
sr = New StreamReader(PercorsoMacro & Documento.Name & ".txt")
riga = sr.ReadLine()
While Not riga Is Nothing
If riga = "Begin" Then
contArgument = 0
contAzioni = contAzioni + 1
Array.Resize(ListaMacro(contMacro - 1).ListaAzioni, contAzioni)
riga = sr.ReadLine()
arrRiga = riga.Split("=")
riga = arrRiga(1).Substring(1, arrRiga(1).Length - 2)
ListaMacro(contMacro - 1).ListaAzioni(contAzioni - 1).NomeAzione = riga
Select Case riga
Case "SetWarnings"
ListaMacro(contMacro - 1).ListaAzioni(contAzioni - 1).TipoAzione = AZIONE_SETWARNING
contArgument = 1
ListaMacro(contMacro - 1).ListaAzioni(contAzioni - 1).ContArgument = contArgument
Array.Resize(ListaMacro(contMacro - 1).ListaAzioni(contAzioni - 1).ListaArgument, contArgument)
Do
riga = sr.ReadLine()
arrRiga = riga.Split("=")
Loop While Not arrRiga(0).Contains("Argument")
ListaMacro(contMacro - 1).ListaAzioni(contAzioni - 1).ListaArgument(contArgument - 1) = arrRiga(1).Substring(1, arrRiga(1).Length - 2)
'vado fino a end
Do
riga = sr.ReadLine()
arrRiga = riga.Split("=")
Loop While arrRiga(0) <> "End"
Case "OpenQuery"
' mi interessa solamente il primo Argument
ListaMacro(contMacro - 1).ListaAzioni(contAzioni - 1).TipoAzione = AZIONE_OPENQUERY
contArgument = 1
ListaMacro(contMacro - 1).ListaAzioni(contAzioni - 1).ContArgument = contArgument
Array.Resize(ListaMacro(contMacro - 1).ListaAzioni(contAzioni - 1).ListaArgument, contArgument)
Do
riga = sr.ReadLine()
arrRiga = riga.Split("=")
Loop While Not arrRiga(0).Contains("Argument")
ListaMacro(contMacro - 1).ListaAzioni(contAzioni - 1).ListaArgument(contArgument - 1) = arrRiga(1).Substring(1, arrRiga(1).Length - 2)
'vado fino a end
Do
riga = sr.ReadLine()
arrRiga = riga.Split("=")
Loop While arrRiga(0) <> "End"
Case "Close"
Case "MsgBox"
ListaMacro(contMacro - 1).ListaAzioni(contAzioni - 1).TipoAzione = AZIONE_OPENQUERY
contArgument = 4
ListaMacro(contMacro - 1).ListaAzioni(contAzioni - 1).ContArgument = contArgument
Array.Resize(ListaMacro(contMacro - 1).ListaAzioni(contAzioni - 1).ListaArgument, contArgument)
Do
riga = sr.ReadLine()
arrRiga = riga.Split("=")
Loop While Not arrRiga(0).Contains("Argument")
ListaMacro(contMacro - 1).ListaAzioni(contAzioni - 1).ListaArgument(0) = arrRiga(1).Substring(1, arrRiga(1).Length - 2)
riga = sr.ReadLine()
arrRiga = riga.Split("=")
ListaMacro(contMacro - 1).ListaAzioni(contAzioni - 1).ListaArgument(1) = arrRiga(1).Substring(1, arrRiga(1).Length - 2)
riga = sr.ReadLine()
arrRiga = riga.Split("=")
ListaMacro(contMacro - 1).ListaAzioni(contAzioni - 1).ListaArgument(2) = arrRiga(1).Substring(1, arrRiga(1).Length - 2)
riga = sr.ReadLine()
arrRiga = riga.Split("=")
ListaMacro(contMacro - 1).ListaAzioni(contAzioni - 1).ListaArgument(3) = arrRiga(1).Substring(1, arrRiga(1).Length - 2)
'vado fino a end
Do
riga = sr.ReadLine()
arrRiga = riga.Split("=")
Loop While arrRiga(0) <> "End"
End Select
End If
riga = sr.ReadLine()
End While
ListaMacro(contMacro - 1).ContAzioni = contAzioni
sr.Close()
sr = Nothing
End If
System.Runtime.InteropServices.Marshal.ReleaseComObject(Documento)
Documento = Nothing
Next j
Directory.Delete(PercorsoMacro, True)
' Chiudo il file access
lblAttesaOperazione.Text = "Chiusura DataBase"
Me.Update()
System.Runtime.InteropServices.Marshal.ReleaseComObject(Contenitore)
Contenitore = Nothing
ChiudiFileAccess(accApp)
End Sub
Alla fine c'è la funzione ChiudiFileAccess che dovrebbe chiudere l'applicazione aperta accApp:
codice:
Public Sub ChiudiFileAccess(ByRef accApp As Access.Application)
accApp.CurrentDb.Close()
accApp.CloseCurrentDatabase()
accApp.Quit(Access.AcQuitOption.acQuitSaveNone)
System.Runtime.InteropServices.Marshal.ReleaseComObject(accApp)
accApp = Nothing
GC.Collect()
GC.WaitForPendingFinalizers()
End Sub
PROBLEMA:
Quando arrivo al comando GC.Collect() viene visualizzata la schermata di access senza nessun DB aperto e se controllo nel Task Manager il processo MSACCESS è ancora in uso.
Quindi quando ritento per qualche ragione a riaprire il file (sono in modalità esclusiva) ovviamente mi da errore.
Cosa sbaglio? Grazie in anticipo
Andrea