 |

|
Excellent, worked like a charm. Thanks.
|
|
|
|

|
Hi,
when I run this code, I get the follwing exception:
{System.Runtime.InteropServices.COMException (0x80040E4D): Cannot start your application. The workgroup information file is missing or opened exclusively by another user.
at JRO.IJetEngine.CompactDatabase(String SourceConnection, String Destconnection)
I have tried al different codes, but I am unabe to get this error resolved.
Please help.
Thanks,
Pk
|
|
|
|

|
Hello,
Alexander.
Thank you for this code.
I have problem with repair database when it is corrupted(only openning by Access).
I will pay for code, that perform compact and repair without installing Access on computer.
Thanks,
Oleg
|
|
|
|
|

|
Create MDB database using ASP/VBScript:
There are two ways to create MDB database using VBScript.
1. Create MDB by ADO (ADOX):
The following code is for creating a new Access2000 database by ADO and for the code to execute MDAC2.0 is required to be installed in the machine.
2. Compact (compress) MDB database using ASP/VBS script.
We can compact MDB database directly from the ASP (VBS) by DAO or JRO.
3.Convert MDB database to another format(JET,access conversion) using ASP/VBScript:
We can convert the MDB database to another format by using the following VB script.
Let's assume F:\MyDB97.MDB is the source database which needs to be converted to the database F:\MyDB2000.MDB
const jet4x = 5
DoConvertMDB "F:\MyDB97.MDB", "F:\MyDB2000.MDB", Jet4x
Sub DoConvertMDB(SourceDB, DestDB, Format)
Dim Engine
Set Engine = CreateObject("JRO.JetEngine")
Engine.CompactDatabase "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & SourceDB, _
"Provider=Microsoft.Jet.OLEDB.4.0;Jet OLEDB:Engine Type=" & Format & ";Data Source=" & DestDB
End Sub
http://www.mindfiresolutions.com/CreateCompactCompress-and-Convert-MDB-database-using-ASPVBScript-312.php[^]Cheers,
Eliza
|
|
|
|

|
Create MDB by ADO (ADOX):
The following code is for creating a new Access2000 database by ADO and for the code to execute MDAC2.0 is required to be installed in the machine.
const jet4x = 5
DoCreateNewMDB "F:\MyAccessDB2000.MDB", Jet4x
Sub DoCreateNewMDB(FileName, Format)
Dim Catalog
Set Catalog = CreateObject("ADOX.Catalog")
Catalog.Create "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Jet OLEDB:Engine Type=" & Format & _
";Data Source=" & FileName
End Sub
Hope this would be useful
http://bit.ly/bXH1KV[^]
Cheers,
Eliza
|
|
|
|

|
Really useful code. Thanks. Keep up the good work.
|
|
|
|

|
I used this code for VS2008 (C#).
I setup on windows XP SP2 and run OK.
But it can not run on windows 7.
|
|
|
|

|
I know this is an old question, but I will reply in the hope that this saves someone else some time. One issue is that Windows 7 is more restrictive on where files can be written; in particular, the root of C: is protected by default. You can fix this by using something like the following C# example to construct a reasonable path for the tempDB: string tempFolder = System.Windows.Forms.Application.LocalUserAppDataPath; string tempDB = System.IO.Path.Combine(tempFolder, "tempdb.accdb");
|
|
|
|

|
Hallo,
in yours code with the function:
object objJRO =
Activator.CreateInstance(Type.GetTypeFromProgID("JRO.JetEngine"));
objJRO of type object is instantiated.
Is it possible to instantiate object of type JRO.JetEngine?
something like-pseudo code:
JRO.JetEngine objJRO = (JRO.JetEngine)Activator.CreateInstance (MathType,false);
Thanks!
Milan
|
|
|
|

|
hi,
Alexander Yumashev
First of all thanks for this code.
but there is some problem if database size is bigger than its not performing properly.
Thanks
Raj
|
|
|
|

|
Thank your for the example. The code works nicely, without throwing an error, but each time it re-writes my Access '97 database, the database INCREASES in size! (and yes, I tried switching the dbEngine type, to no avail).
My environment incorporates Access '97 databases to run factory operations, print invoices, generate reports, etc., and it all works fine. I just thought it would be really convenient to have a utility that shrinks these databases kind of 'automatically' (31 of them reside in a number of buildings). The databases belong to the IT department, not the users. Have you tried using an Access '97 DB with this code? (In case you are wondering why not upgrade to a later Access version.. my company is not about to pay for upgrading licenses just for this convenience, since these '97 databases have been doing their job for a decade with little maintenance other than manually compacting them monthly.)
|
|
|
|

|
Great.. Many Thanks
Cheers!
Divide and Conquer.
|
|
|
|

|
Hey ur code is GR8.
But while running i am getting an error saying.
"Exception has been thrown by the target of an invocation."
Plz help
|
|
|
|

|
I was having trouble copying tables to MS Access (within C#), and was able to put together your late-binding code with other bits and pieces I found along the way. It works like a charm now.
If anyone is trying to import large amounts of data from an ODBC source into MS Access, there is a very fast way to do it: http://www.codeproject.com/useritems/MSAccessTableCopyInCSharp.asp
|
|
|
|

|
ok, that's it
thanks for great code
thanks 4 all
it's really simple...
with Best Regards
M.S. Babaei
|
|
|
|

|
Be careful when using this CompactDatabase API. I have found that sometimes CompactDatabase will trash a perfectly good Access Database file. Before you call CompactDatabase, you should make a backup copy of the file just in case the processed database file is damaged by the CompactDatabase call. An alternative to using CompactDatabase is jetcomp.exe which is available from Microsoft here http://support.microsoft.com/kb/295334[^]. My experience has shown that jetcomp.exe is much safer to use than CompactDatabase. This of course is not as clean or easy as using CompactDatabase since you have to launch the jetcomp.exe with command line parameters to get it to do what you want.
|
|
|
|

|
how can i make an operation like dive or mode etc. on file excel by using c#
gardinea
|
|
|
|

|
How to set the adodb.connection.OpenSchema parameters in c#?
ADODB.Recordset OpenSchema(ADODB.SchemaEnum Schema, object Restrictions, object SchemaID)
I can't set the right parameters with "object Restrictions & object SchemaID"
Thanks!
|
|
|
|

|
I get an exception on this line:
objJRO.GetType().InvokeMember("CompactDatabase", System.Reflection.BindingFlags.InvokeMethod,
null,
objJRO,
oParams);
It says:
"Exception has been thrown by the target of an invocation"
and the inner exception is:
"You attempted to open a database that is already opened exclusively by user 'Admin' on machine . Try again when the database is available."
But I checked and the DB is closed.
Can any one help?...
Thanks,
Roee.
|
|
|
|

|
Hi,
I was wondering why not giving the source and destination the same database connection to avoid the harassing 'Delete' issue. After a few tries discovered that it was not possible with both OLE DB and ADO. So I googled a bit and found a different but more compact way usin ODBC:
[System.Runtime.InteropServices.DllImport("ODBCCP32.dll")]
private static extern bool SQLConfigDataSource(IntPtr parent, int request, string driver, string attributes);
private const int ODBC_ADD_DSN = 1;
public static bool Compact(string mdbFileName)
{
string cmd = string.Format("COMPACT_DB={0} {0}\0\0", mdbFileName);
return SQLConfigDataSource((IntPtr)0, ODBC_ADD_DSN, "Microsoft Access Driver (*.MDB)", cmd);
}
public static bool Compact(string mdbFileName, string password)
{
string cmd = string.Format("COMPACT_DB={0} {0}\0PWD={1}\0\0", mdbFileName, password);
return SQLConfigDataSource((IntPtr)0, ODBC_ADD_DSN, "Microsoft Access Driver (*.MDB)", cmd);
}
NOTE:
It works with my current OS configuration but from the MSDN Library I also found this old article:
BUG: Database Compaction with SQLConfigDataSource Fails when Access Database is Password Protected
|
|
|
|

|
Smooth solution! Works like a charm, much cleaner...
=====================
Lars [Large] Werner
lars@werner.no
http://lars.werner.no
Have you tried the ultimate tool for filling your CD/DVDs? http://lars.werner.no/sizeme/
=====================
|
|
|
|

|
the old mdb has a password... but after compacting and repaired the password has gone...
why?
JoeAdrianBlack
|
|
|
|

|
joeblack wrote: the old mdb has a password... but after compacting and repaired the password has gone...
Same for me,
does anyone have a clue how to set an access password programmatically?
THX
Sebastian Lorenz
|
|
|
|

|
Hi,
you won't believe how easy it is...
Just set the OLEDB:Database Password=yourpass in the oParams array, and there you are!
Hope this helps you out, it did for me.
Sebastian Lorenz
|
|
|
|

|
Hi,
thanks for this example
I just have a little question : is it REALLY safe to use this code, I mean, in production environment ? Because it delete the original file... maybe there are some RARE situations where the database could be completely swept ?
|
|
|
|
|

|
Hi
I need to repair access file in c++ program, so I should write this function in c++. Because I do not know c# so someone help me with this function written in c++. Tha nks.
|
|
|
|

|
you just type "www.codeproject.com/c++" the web page will show you the C++ Source.
|
|
|
|

|
If the JRO is not registered .... it will not work....
but you can modify the code to automatically register the com-object
Type typJRO=Type.GetTypeFromProgID("JRO.JetEngine");
if (typJRO==null)
{
//phps. msjro is not registered
string strMsjrodll=Path.Combine(Environment.GetEnvironmentVariable("ProgramFiles"),@"Common Files\System\ado\msjro.dll");
if (File.Exists(strMsjrodll))
{
//start a process to register the dll
Process procRegisterMsjro=Process.Start("regsvr32.exe",string.Concat("/s \"",strMsjrodll,"\""));
procRegisterMsjro.WaitForExit();
typJRO=Type.GetTypeFromProgID("JRO.JetEngine");
}
}
if (typJRO==null)
{
throw new InvalidOperationException("JRO.JetEngine can not be created... please check if it is installed");
}
//create an inctance of a Jet Replication Object
object objJRO =
Activator.CreateInstance(typJRO);
|
|
|
|

|
Very helpful article, but when I run my program I get an exception. The error message says "Format of the initialization string does not conform to the OLE DB specification". I have no idea why it is not working. I have tried messing around with the connection string but nothing seems to help. Most of my code is exactly how you have it:
object[] oParams;
object objJRO = Activator.CreateInstance(Type.GetTypeFromProgID("JRO.JetEngine"));
string conn="C:\\";
oParams = new object[] {conn, "Provider=Microsoft.Jet.OLEDB.4.0;Data" +
"Source=C:\\tempdb.mdb;Jet OLEDB:Engine Type=5"};
\\ This is where it is crashing on me
objJRO.GetType().InvokeMember("CompactDatabase",
System.Reflection.BindingFlags.InvokeMethod,null,objJRO,oParams);
Thank you so much,
Ben
|
|
|
|

|
You killed a space in the string
use "Data Source=C:\\..." instead of "DataSource=C:\\..."
|
|
|
|

|
Your code was great. I made what I think are some enhancements to the cod. Thanks!!!
Public Sub CompactAccessDB(ByVal mdbToCompact As String) 'Boilerplate for connection strings Const JET_CONNECTION_STRING As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data" + " Source={0};Jet OLEDB:Engine Type=5" Dim objJRO As Object Dim tempFile As String Dim oParams As Object() Try 'Get temp filename for compacted MDB 'HACK: To prevent "Database Already Exists" error we add "FOO" to the end of system generated filename. The CompactDB fuction will then create a new compcated DB with the system generateed name with "FOO" appended. Function Path.GetTempFileName() gets filename AND creates file which causes a problem here tempFile = Path.GetTempFileName() & "FOO" 'Setup object arrary to hold connection strings for CompactDatabase meathod on JRO.JetEngine object oParams = New Object() {String.Format(JET_CONNECTION_STRING, mdbToCompact), String.Format(JET_CONNECTION_STRING, tempFile)} 'Get instanct of JRO.JetEngine object which will do the actual work of compacted the MDB objJRO = Activator.CreateInstance(Type.GetTypeFromProgID("JRO.JetEngine")) 'Compact the database... objJRO.GetType.InvokeMember("CompactDatabase", System.Reflection.BindingFlags.InvokeMethod, Nothing, objJRO, oParams) 'Delete the old database System.IO.File.Delete(mdbToCompact) 'Replace it with the new compacted mdb System.IO.File.Move(tempFile, mdbToCompact)
Catch ex As Exception 'Just send the exception up to the caller Throw ex Finally 'Release memory System.Runtime.InteropServices.Marshal.ReleaseComObject(objJRO) objJRO = Nothing End Try
End Sub "I don't know were I'm goin' but I'm on the way" - Me
|
|
|
|

|
I'm new to VB, Thanks for the VB syntax conversion
|
|
|
|

|
Excellent code, easy to learn!!!!
|
|
|
|

|
Hi, I'm new to c# but can't see how exactly to call the CompactAccessDB method and pass in the parameters. How do I run this code for a database located at c:\compact.mdb
Thanks
|
|
|
|

|
if the initial dataase has a password in the connection string, the replacement database doesnt have the database... do you know how to set a password programaticly?
|
|
|
|

|
Hmmm, can’t actually believe I wrote that!!! Must have been real late… what I mean to illustrate is that the method you uses would actually remove the password from the database.. do you know how to set it programmatically?
|
|
|
|

|
I get the expetion when i use try - catch. It is :[System.Runtime.InteropServices.COMExeption(0x80004005). Invalid Argument]
I use access 2000 database and my connString is:
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:\\database\\mydb.mdb;Jet OLEDB:Database Password=mypass;";
I tried a lot of things... like use the Database password=mypass to destination db... and still get tge same message.
Milan Ristic
|
|
|
|

|
Works great, saved me some late working hours!!
Magnus Hauge
|
|
|
|

|
Great article, but I keep getting an exception on the "InvokeMember" call. The error message simply says "Exception has been thrown by the target of an invocation". Could it have something to do with the connection string? My Access MDB has no security, so all I am putting in the connection string "FIL=MS Access;DSN=AcclaroDB" which our C# programs use to open the MDB file. It is in Access 2000 format.
Any ideas? Any help would be appreciated.
Michael Greene
|
|
|
|

|
Hi Michael.
Catch your exception and look at the InnerException. You will get a COM-exception, which will explain, what is wrong.
Like this:
try
{
}
catch(Exception ex)
{
MessageBox.Show(ex.InnerException.ToString());
}
|
|
|
|

|
Hello,
I get a program exception as well. The inner exception I am getting is "Unrecognized database format" This is the exception that I use to know that the database needs a repair.
The database is in this state due to a loss of connection when writing previously. I want my application to recognize that the database is in this state and perform a repair.
Any idea why the compact will not work?
Regards,
Mike Gardiner
|
|
|
|

|
After applying try...catch as you guided, I got this message:
"System.Runtime.InteropServices.COMException (0x80040E4D): Authentication failed"
How can I fix this error?
Pham Toan Thang
|
|
|
|

|
Shooted. Exactly what I was looking for. You've got my 5.
|
|
|
|

|
No I will create a scheduled task that will call a webservice that will compact & repair, en then email me my DBase.
( My Host was defaced once )
Any Idea on how to kill all my connections?
|
|
|
|

|
Hi
do you have example of getting a progress feedback from JET?
|
|
|
|
|

|
You just saved me some time searching for this sort of code!
Thanks
|
|
|
|
 |