Access 2007 compact DB - vb.net

Sorry for my English, I write from Italy.
I use the Access 2007 DB in a business data management procedure in VB Net.
As is known, Access DBs expand during use and consequently I need to compact them when the program is closed.
I perform the compaction in this way
Dim MioEngine As New Microsoft.Office.Interop.Access.Dao.DBEngine
MioEngine.CompactDatabase(myAccesDB, newAccessDB,)
Application.DoEvents()
but often and not on all PCs on the network, the compaction does not finish and gives me the following error message:
The process cannot access the 'C:\myAccesDB.accdb' file because it is being used by another process
Analyzing in depth what happens, I see that when the error occurs, the .laccdb file is not closed at the time of compacting.
Is there any way other than the one I used to do the compacting safely?
I specify that all the PCs in our network are Windows 10 pro and all updated; when Windows 10 was in its infancy, I didn't get this error.

Since my comment was not enough, here's an answer:
The idea is to try to opetn .laccdb file before you try to compact the database. You can do something like this:
Dim file as System.IO.FileInfo = New System.IO.FileInfo("c:\myAccesDB.laccdb")
Dim stream As FileStream = Nothing
Try
stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None)
stream.Close()
'if stream is successfully closed, file is not in use and database can be compacted
MioEngine.CompactDatabase(myAccesDB, newAccessDB,)
Catch ex As Exception
'show some message to user that file is in use so it can try again
End Try
I worked with VB and Access ages ago, so this is only a direction that you should take.

Thanks, I'll try.
I also had a look to this:
https://support.microsoft.com/en-us/topic/office-error-accdb-remains-locked-after-oledb-connection-is-closed-37d42348-9edf-4493-a5f4-35c685af3160?ui=en-us&rs=en-us&ad=us
Where I find:
This issue is now fixed. If you launch Access, click 'File', then 'Account', then 'Update Options', and 'Update Now', this will ensure that you have the latest version, and all versions should have the fix available.
But I'm not able to find 'File' opening Access,....

Related

FileVersionInfo.GetVersionInfo not letting go of file

I'm trying to check the version of the Windows application the user is running against the version that is on the server to see if the local version needs to be updated. I do this by calling
FileVersionInfo.GetVersionInfo("path to file on server")
and reading the version information. This works fine for what I need, however, when I look at open files on the server from the computer management console, I see many instances of my file open in Read mode. This causes a problem when I need to copy a new version to the server. I first have to close all of the open files before it will let me write to it. Even though they are only open in Read mode, it still makes me close them.
Is there a better way to get the file version from the server? Or is there a way to dispose of the FileInfo variable that I am using so it disconnects?
I have not found a good resolution using FileVersionInfo. And from my research using FileVersionInfo does not release the variable as you would expect so I changed to getting the file information from a PowerShell script. This allows me to dispose the object and release the file as I have tested successfully. So here is the code that gets the information:
Dim server_version As String = ""
Dim invoker As New RunspaceInvoke
Dim command As String = "(Get-Item path_to_file_no_quotes_needed).VersionInfo.FileVersion"
Try
Dim outputObjects As Collection(Of PSObject) = invoker.Invoke(command)
For Each result As PSObject In outputObjects
server_version = result.ToString
Next
Catch ex As Exception
End Try
invoker.dispose
When this is run from my app, I see the file get opened in Read mode on the server but it disappears after about 3 seconds. So I can see the object is being properly disposed. Just FYI, there is no FileVersionInfo.dispose method.
In addition, for this to work you need:
Imports System.Management.Automation
which needs a reference in your project. It can be found in:
C:\Windows\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\System.Management.Automation.dll
In the Shown event I have code that looks like this,
Try
If My.Application.IsNetworkDeployed AndAlso My.Application.Deployment.CheckForUpdate Then
'update available - the update will happen when app is closed
End If
Catch ex As Exception
'error while checking for update or update is corrupt
End Try
I do this so I can provide the user an indication that an update is available.
In the FormClosed event I do,
Try
'see if update is available, and install if it is
If My.Application.IsNetworkDeployed Then
If My.Application.Deployment.CheckForUpdate Then
My.Application.Deployment.Update()
End If
End If
Catch ex As Exception
End Try

Access to path is denied when trying to import from the client's desktop with SSIS

I'm creating a html page that will import an excel file in to a tracking system. On a button click event excel file is located / ssis package is fired / data imported then closed out. Thats the idea work flow. Problem is the excel file access is being denied before the package even executes
Here is the exact error :
I've tried :
excel file properties have been shared to everyone
identity impersonate set to true
hard coding the path
here is the VB code
Protected Sub bntExecute_Click(sender As Object, e As EventArgs) Handles btnExecute.Click
Dim app As Application = New Application()
Dim package As Package = Nothing
'Dim fileName As String = "C:\Users\Desktop\T. Bryant III\PTSID_Update_Template"'
Try
Dim fileName As String = Server.MapPath(System.IO.Path.GetFileName(FileUpload1.PostedFile.FileName.ToString()))
FileUpload1.PostedFile.SaveAs(fileName)
package = app.LoadPackage("#C:\Users\Desktop\T.Bryant III\KitImport", Nothing)
'excel connection from package'
package.Connections("SourceConnectionExcel").ConnectionString = "provider=Microsoft.Jet.OLEDB.4.0data source =" + fileName + "Extended Properties = Excel 8.0"
'Execute the pakage'
Dim results As Microsoft.SqlServer.Dts.Runtime.DTSExecResult = package.Execute()
Catch ex As Exception
Throw ex
Finally
package.Dispose()
package = Nothing
End Try
End Sub
Thanks in advance or if there is an easier way to do this please let me know. The package when executing it in ssis works fine with its own connection manager etc.
A few things to try. If they don't work for you as permanent solutions, they should at least confirm that your code is working and you are dealing with a persmissions issue (which appears to be the case).
Move your file to the public folder (C:\Users\Public).
Run your application (or web browser) as an administrator (if applicable to your version of Windows).
If you are using a web browser, try using a different one.
If nothing else works, try pasting your code into a Windows Form Application.
If you still get the same error after trying all of this, it's time to take another look at your code. Remove the Try/Catch block to determine precisely which line is throwing the error. If you've tried hard coding, I'm guessing it's the SaveAs method. I'm not sure what class FileUpload1 is, but some SaveAs methods won't overwrite existing files unless you explicitly tell them to. Check the appropriate documentation and see if you don't need to pass a True value somewhere along with filename.
Update us with the results. At the very least, this should narrow down your problem and allow for a better diagnosis of it.

Releasing an .MDF File in VB.NET

I have an application that checks to see if it's the most recent version. If not, it updates itself by using File.Copy to replace the DB attached to the application with a fresh one (that may or may not have had changes made to it). In an attempt to keep the data from being deleted, I created a backup system that writes all the data to an XML file before the database is deleted and restores the data once the database has been copied.
I am having a problem with the File.Copy method, however, in that an error pops up telling me the .MDF is being used by another process.
I was told that stopping SQL Server would work, but it hasn't. I've also been told I can use SMO, but also have not been able to make that work. With this seeming so close to complete, SMO also seems like it won't be necessary.
My code is this:
'This is the backup. I make sure to close the SQL Connection when the process is complete.
Dim db As String = "C:\ACE DB\localACETest.mdf"
Dim dbLog As String = "C:\ACE DB\localACETest_log.ldf"
If File.Exists(db) = True Then
'Backup process
'...
End If
'"Data/localACETest.mdf" referenced below is the file located inside of my application that is used to overwrite the other MDF; it is NOT the .MDF I'm looking to replace.
Directory.CreateDirectory("C:\Random Directory\")
File.Copy("Data/localACETest.mdf", db, True) 'This is the line where I get the error
File.Copy("Data/localACETest_log.ldf", dbLog, True)
success = False
...
EDITS:
I have narrowed the issue down to the method that backs up my data. I'm using the following connection string:
Private Const _sqlDB As String = "Data Source=(localdb)\v11.0;Initial Catalog=localACETest;Integrated Security=True; _
AttachDbFileName=C:\ACE DB\localACETest.mdf"
I open SQL, run a command, and then close it:
Using connection = New SqlConnection(_sqlDB)
connection.Open()
...
connection.close()
Why does this not release the MDF from the process? (When I don't run it, I have no problems)
You are better off sending a command to SQL server telling it to make a backup for you. This SO article has a great (command line) script that you can copy/paste:
SQL Server command line backup statement
Put that into a batch and launch it like this.
System.Diagnostics.Process.Start("C:\Ace Db\MakeADBBackup.bat")
If you would prefer to make your program wait till the backup finishes, read about launching processes: http://support.microsoft.com/kb/305368
If you are REALLY insistent on making a copy of the .mdf (which is not a good idea), then you need to ask the server to stop the SQL service before you make a copy. You could run a batch that says
NET STOP MSSQLSERVER
Assuming that your SQL Server is running under the name "MSSQLSERVER". To check the names of running services, open a command prompt and type-in "NET START". It will give a list of services that are running. One of them will be the "process name" of your SQL Server's running service.
Better still, here is an article (for VB.NET) that shows the source code for starting/stopping SQL Server. http://msdn.microsoft.com/en-us/library/ms162139(v=SQL.90).aspx
I strongly recommend that you try the first approach that I suggested.

How to release MS Access LDB lock file after created it

sorry for long text.
Problem: I have difficulty in removing the LDB generated by the "CREATE" method of ADOX in the following code segment. Please provides some hints/pointers to the solutions, and thanks.
Aims: Create (on the fly) a new access database and then export data (says Arena modules) to that newly created database.
Expected: The newly created access database should be able to be used by some external operations, say Access.exe, after the end of the subroutine and without exiting the current VB program.
I tested that the "Arena code" do nothing about the create/release of the ldb file.
I tested the "Exclusive Mode" in connection string, but the access file is still locked by the vb program.
I tested under both inside the VB environment, and directly invoke the generated from Explorer, and same results.
Other database formats is not the options to me. (due to Arena export limit)
It is not a web app.
Code:
Sub Method1()
Dim logs As New System.Collections.Generic.List(Of String)
Dim arenaApp As Arena.Application = Nothing
Try
logs.Add("Creating access database")
Try
Dim cat As New ADOX.Catalog
cat.Create("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=new.mdb;Jet OLEDB:Engine Type=5")
cat = Nothing
Catch ex As Exception
logs.Add(ex.Message)
logs.Add(ex.StackTrace)
Finally
logs.Add("End creating access database")
End Try
'Opening Arena model"
arenaApp = New Arena.Application()
arenaApp.Models.Open(fileName)
arenaApp.ActiveModel.ExportModules("", "new.mdb", "TableName", "", Arena.smExportType.smExportAll)
Catch ex As Exception
logs.Add(ex.Message)
logs.Add(ex.StackTrace)
Finally
...
End Try
End Sub
Platform:
Windows 7 64bit, Office 2010 (32)
VB 2010 express
Lib: MS ADO Ext. 2.8 for DDL and Security
What about closing the mdb after creation, then reopening it ?
I am not a VS expert, but in Access, many things in "Design mode" put the mdb in Exclusive mode...and you can't switch back without closing it first i suspect.
If you want to create a database, its probably simpler to PInvoke SQLConfigDataSource. Then you can connect to it via ADODB, ADO.NET or your VB.NET data access methodology of choice.
I don't have an example of doing it in VB.NET, but this C# class and this powershell script demonstrate how to call the function.
I know it's an old question. I encountered exactly the same issue today. Some comments ask why use ADOX, that's because first, it's from legacy code, and second, I didn't find any other ways to dynamically create mdb file.
In VB6, whenever you set adox = Nothing, this com object will be released immediately and so is the ldb file.
In .Net, you have to rely on GC to collect the adox before ldb file is unlocked.
So, I made the following trick. I know it's ugly, but I didn't find any other ways, and at least my trick worked.
Dim t As New Thread(
Sub
'All adox code should be here
'....
'....
adox = Nothing
End Sub
)
t.Start()
t.Join()
t = Nothing
GC.Collect()
Sleep(50)

Intermittent error when attempting to control another database

I have the following code:
Dim obj As New Access.Application
obj.OpenCurrentDatabase (CurrentProject.Path & "\Working.mdb")
obj.Run "Routine"
obj.CloseCurrentDatabase
Set obj = Nothing
The problem I'm experimenting is a pop-up that tells me Access can't set the focus on the other database. As you can see from the code, I want to run a Subroutine in another mdb. Any other way to achieve this will be appreciated.
I'm working with MS Access 2003.
This is an intermittent error. As this is production code that will be run only once a month, it's extremely difficult to reproduce, and I can't give you the exact text and number at this time. It is the second month this happened.
I suspect this may occur when someone is working with this or the other database.
The dataflow is to update all 'projects' once a month in one database and then make this information available in the other database.
Maybe, it's because of the first line in the 'Routines' code:
If vbNo = MsgBox("Do you want to update?", vbYesNo, "Update") Then
Exit Function
End If
I'll make another subroutine without the MsgBox.
I've been able to reproduce this behaviour. It happens when the focus has to shift to the called database, but the user sets the focus ([ALT]+[TAB]) on the first database. The 'solution' was to educate the user.
This is an intermittent error. As this is production code that will be run only once a month, it's extremely difficult to reproduce, and I can't give you the exact text and number at this time. It is the second month this happened.
I suspect this may occur when someone is working with this or the other database.
The dataflow is to update all 'projects' once a month in one database and then make this information available in the other database.
Maybe, it's because of the first line in the 'Routines' code:
If vbNo = MsgBox("Do you want to update?", vbYesNo, "Update") Then
Exit Function
End If
I'll make another subroutine without the MsgBox.
I've tried this in our development database and it works. This doesn't mean anything as the other code also workes fine in development.
I guess this error message is linked to the state of one of your databases. You are using here Jet connections and Access objects, and you might not be able, for multiple reasons (multi-user environment, unability to delete LDB Lock file, etc), to properly close your active database and open another one. So, according to me, the solution is to forget the Jet engine and to use another connexion to update the data in the "other" database.
When you say "The dataflow is to update all 'projects' once a month in one database and then make this information available in the other database", I assume that the role of your "Routine" is to update some data, either via SQL instructions or equivalent recordset updates.
Why don't you try to make the corresponding updates by opening a connexion to your other database and (1) send the corresponding SQL instructions or (2) opening recordset and making requested updates?
One idea would be for example:
Dim cn as ADODB.connexion,
qr as string,
rs as ADODB.recordset
'qr can be "Update Table_Blablabla Set ... Where ...
'rs can be "SELECT * From Table_Blablabla INNER JOIN Table_Blobloblo
set cn = New ADODB.connexion
cn.open
You can here send any SQL instruction (with command object and execute method)
or open and update any recordset linked to your other database, then
cn.close
This can also be done via an ODBC connexion (and DAO.recordsets), so you can choose your favorite objects.
If you would like another means of running the function, try the following:
Dim obj As New Access.Application
obj.OpenCurrentDatabase (CurrentProject.Path & "\Working.mdb")
obj.DoCmd.RunMacro "MyMacro"
obj.CloseCurrentDatabase
Set obj = Nothing
Where 'MyMacro' has an action of 'RunCode' with the Function name you would prefer to execute in Working.mdb
I've been able to reproduce the error in 'development'.
"This action cannot be completed because the other application is busy. Choose 'Switch To' to activate ...."
I really can't see the rest of the message, as it is blinking very fast. I guess this error is due to 'switching' between the two databases. I hope that, by educating the user, this will stop.
Philippe, your answer is, of course, correct. I'd have chosen that path if I hadn't developed the 'routine' beforehand.
"I've been able to reproduce this behaviour. It happens when the focus has to shift to the called database, but the user sets the focus ([ALT]+[TAB]) on the first database. The 'solution' was to educate the user." As it is impossible to prevent the user to switch application in Windows, I'd like to close the subject.