MS Access MDB-File keeps becoming corrupted - vba

We got a problem with Microsoft Access .mdb-files. After some time working with an .mdb-file in a multiuser environment the file becomes corrupted and has to be repaired. After it's repaired it takes less time to become corrupted again. And at some point after multiple reperations the file isn't usable at all anymore.
This problem started to appear after we changed from MS Access Runtime 2010 to MS Access Runtime 2013.
I've already spent some time looking into this problem and this is my theory:
The mdb-file appearently contains a "Database Header Page" (described in a White Paper from Microsoft called "Understanding Microsoft Jet Locking" from 1996) which saves information about the commit bytes of Users (important: 0000 = writing to disk, 0100 = accessed a corrupted page). And there is a paragraph in the white paper about this Database Header Page which explains exactly what is happening in our problem:
"[...]Therefore, if a value of 00 00 is present without corresponding user lock [this would be an entry in the corresponding .ldb-file I think], or a value of 0100 is present, users will not be allowed to connect to the database without first executing the repair utility."
So my guess is, that after some amount of loosing connection to the mdb/breaking the connection this Database Header Page overflows and you have to repair the file but the repair doesn't remove every entry inside of this Database Header Page, so the amount of broken connections needed for the file to become corrupted decreases until the file completely breaks.
Now I would like to know if this theory is any good and if it is I would like to know:
How can I test this theory (how can I read this Database Header Page of the mdb-file)?
Can I modify the Database Header Page?
Can I modify the Database Header Page while someone is working with the mdb?
I know it's a very specific problem but I hope you guys can help me!
P.S. I can't find a link to the white paper but the "LDBViewer"-packet contains this white paper.

A few quick and dirty tricks that I often use are enabled by creating a small database which serves one purpose: control how the desired target database is opened.
This database is copied to the desktop of every user, so every user/session has its own.
So I would have
* 1 database on a server-location : [TheBigOne.mdb]
* 1 database copied to several desktops : [TheCaller.mdb]
--01-- :
Every morning, call a function which will perform the following steps :
* rename [TheCaller.mdb] to [TheCaller-xxx.mdb]
* create and open [TheCaller-NEW.mdb]
* for all tables, queries, forms, reports, macros, modules
DoCmd.TransferDatabase acImport, , [TheCaller-xxx.mdb], _
acTable-acQuery-acForm-acReport-acMacro-acModule, "y", "y", False
* rename [TheCaller-NEW.mdb] to [TheCaller.mdb]
--02--
Create a form in [TheCaller.mdb] with one button, with an OnClick-event like :
If Dir(ServerLocation & "\TheBigOnd.ldb") = "" Then
'open [TheBigOne.mdb]
Then
Msgbox "Database already in use!"
End If
This is prone to a lot of headaches, because it will happen that the [TheBigOnd.ldb] file does exists, while no one is using the database. But at least, you will have less database-corruption.
--03--
An alternative for this procedure --02-- can be achieved by using a command-line switch /excl. At any given time, only one user will be able to work in the database.
--04--
Create a second button on the form from point --02--, which will open [TheBigOne.mdb] with command-line switch /ro. This will open the database in a read-only mode for this user, avoiding the corruption of the database.
--05--
Create a small backend database db_sessions.mdb on a server-location, with
a table in it like T_Sessions(id, whois, started_at_timestamp, ended_at_timestamp, excl_or_ro, troubles) for keeping track [who] [opens] and [closes] [when] the database [TheBigOne.mdb].
If a user wants more priviliges then read-only, the following test has to be true: DCount("*","T_Sessions","ended_at_timestamp is null AND excl_or_ro = 'excl'") = 0. If this test results in false, the field troubles can be used to dispatch messages to other users.

Related

File create time doesn't change even after it is deleted

I am using the following code:
from datetime import datetime
import time, pandas as pd, os, pickle
df = pd.DataFrame(np.arange(1,200))
fn = r'C:\z1.p'
pickle.dump(df, open(fn, 'wb'))
print(datetime.fromtimestamp(os.stat(fn).st_ctime))
os.remove(fn)
time.sleep(5)
pickle.dump(df, open(fn, 'wb'))
print(datetime.fromtimestamp(os.stat(fn).st_ctime))
But I get the same create time from both print statements as:
2022-03-16 08:43:30.885011
2022-03-16 08:43:30.885011
How do I make sure that new time gets printed for second print statement?
This is a Windows feature, called "file system tunnelling".
The apocryphal history of file system tunnelling
One of the file system features you may find yourself surprised by is
tunneling, wherein the creation timestamp and short/long names of a
file are taken from a file that existed in the directory previously.
In other words, if you delete some file “File with long name.txt” and
then create a new file with the same name, that new file will have the
same short name and the same creation time as the original file. You
can read this KB article for details on what operations are sensitive
to tunnelling.
Why does tunneling exist at all?
When you use a program to edit an existing file, then save it, you
expect the original creation timestamp to be preserved, since you’re
editing a file, not creating a new one. But internally, many programs
save a file by performing a combination of save, delete, and rename
operations (such as the ones listed in the linked article), and
without tunneling, the creation time of the file would seem to change
even though from the end user’s point of view, no file got created.
...
See this archived copy of Windows NT Contains File System Tunneling Capabilities:
When a name is removed from a directory (rename or delete), its
short/long name pair and creation time are saved in a cache, keyed by
the name that was removed. When a name is added to a directory (rename
or create), the cache is searched to see if there is information to
restore. The cache is effective per instance of a directory. If a
directory is deleted, the cache for it is removed.
These paired operations can cause tunneling on "name."
delete(name)/create(name)
delete(name)/rename(source, name)
rename(name, newname)/create(name)
rename(name, newname)/rename(source, name)
The idea is to mimic the behavior MS-DOS programs expect when they use
the safe save method. They copy the modified data to a temporary file,
delete the original and rename the temporary to the original. This
should seem to be the original file when complete. Windows performs
tunneling on both FAT and NTFS file systems to ensure long/short file
names are retained when 16-bit applications perform this safe save
operation.
One Windows function related to file tunneling is FltGetTunneledName():
The FltGetTunneledName routine retrieves the tunneled name for a file, given the normalized name returned for the file by a previous call to FltGetFileNameInformation, FltGetFileNameInformationUnsafe, or FltGetDestinationFileNameInformation.
...
To disable tunnelling:
Open regedit
Navigate here:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem
On the Edit menu, point to New and then click DWORD Value
Type MaximumTunnelEntries and then press Enter
On the Edit menu, click Modify
Type 0 and then click OK
Restart your computer
Done

Someone injecting to my website and running update scripts on my site

I have found that all data of my 5 YEARS old site tables was suddenly mixed up
some data that cannot be updated via any existing sp is updated.
After long search of sp i came to conclusion that somebody messing with my site.
I assume that its done via sql injections.
I have huge amount of trafic on my site 24/7 ,site has more than 100 pages, and the logs are now just showing what user entered what page...more logs will slow down the site even more. so now i need to act efficiently.
1.What is the best way to find where someone injecting
2.how to log his ip and time of injection
never done this before, read lots of mixed opinions on google. please advice your best practise.
Instead of tracking down the "bad guys" you should focus on restoring your database and making your code resistant or invulnerable to injections, not sure whats the best way for asp.net but in java it is well known that prepared statements make it impossible to have somebody peform a sql injection on your data.
Check out this link for how to improve your code in asp.net:
Classic ASP SQL Injection Protection
This is some code I use on my page as a "catch all" attempt for injection attempts via query strings (ie, data sent through a URL):
trap = 0
ref = lcase(request.querystring)
if ref <> "" then
badChars = array("OR 1=1", "select", "drop", "shutdown", "--", "insert", "delete", "waitfor", "union", "0x31", "convert", "truncate", "sysobjects")
cn = 0
for i = 0 to uBound(badChars)
if instr(ref,badchars(i)) > 1 then cn=cn+1
next
if cn >=2 then trap = 1
end if
if trap = 1 then .... ban user ip code here
You could simply put "if trap = 1 then response.end" which would stop any further action on the page. I prefer to ban the IP for an hour.
This should also work with request.form for form input.
You may also want to sanitize your variables that take form input.
data=request.form("emailaddress")
data = replace(data,"'","")
data = replace(data,"union","")
etc.

Linked SQL table in Access 2003 (!) not updatable

I'm working in a legacy app for the moment, upgrading Access 2003 to link to SQL Server tables (2008 R2 or later). With tables linked by code, I can insert, but not update or delete. I've tried everything on the web, no dice. Details below.
Being terse so not tl;dr.
Tables first created using upsizing wizard. In use, app has to connect to different ones in same schema, so can't just set and forget. Can't do local DSN's, many installs, though DSN file is possible. But problems there too, DSN not found. Details later.
Before the rest: Soon I'm further updating this app to Access 2016 or so. If this is different enough / easier there, I'll wait a few days. Maybe someone could suggest the best refsite for that.
* problem details follow *
Using a DSN and the UI to link a table, I get an editable table. Hurray.
But when I use the code below (found on every refsite), link is made but only selecting and inserting work. Everything else fails fails fails, no matter what.
Public Function LinkToSqlTable(sqlInstance As String, sqlDb As String,
sqlTableName As String, localTableName As String)
Dim linked As New TableDef
' ***factored-out functionality, known to work: reader can ignore*** '
DeleteTable localTableName
' connection-string steps, placeholders replaced by args '
Dim sCnx As String
sCnx = "ODBC;Driver=SQL Server;Server=_instance_;" & _
"Database=_db_;Integrated Security=SSPI"
sCnx = Replace(sCnx, "_instance_", sqlInstance)
sCnx = Replace(sCnx, "_db_", sqlDb)
' linked-table steps '
Set linked = CurrentDb.CreateTableDef(localTableName)
linked.Connect = sCnx
linked.SourceTableName = sqlTableName
CurrentDb.TableDefs.Append linked
' ui '
RefreshDatabaseWindow
End Function
* ID column or permissions? *
I thought the problem was lack of identity column originally, I added one, but no change. At least now I have a PK field like I should. ;-)
When I manually link table, UI demands to know the ID column. So could it still be it? Fine, but how do I set that in code? Searches revealed nothing.
I assume then it's permissions as sites etc. say. I also took all the steps I could think of to fix that. No dice.
* things I've tried *
Aside from the ID-column stuff I said before, these things (not in order):
Since DSN saved as a file, tried using it as exampled, in cnx string. Fail.
Used DSN contents, carefully winnowed & translated, in cnx string. Fail.
Used connection string from the table that I had connected manually with DSN. Fail.
Changed driver in cnx string across all major options, even omitted it. Fail.
Changed security in cnx to Integrated Security=SSPI and other options, and omitted entirely. Fail.
I added my actual local user as exampled, with and without password. Fail.
(Previous few options tried across earlier options, though not 100% coverage.)
In SQL Server, using SSMS, I tried security power:
Added SQS-authentication login to the instance
Matching user to the default db seen here
Gave that login-user read and write permissions in db here (plus others, sometimes)
Added matching id & pw to the cnx string. Fail.
I tried setting up this db in SQS to have let-everyone-do-everything "security" temporarily. Fail.
This, that, and the other thing. Everything fail!!
So a permissions issue? Some way to use DSN file after all? Mismatched permission settings in my cnx string? Boneheaded oversight? Something else that I've missed? I'm pretty good at both SQL Server and Access, but only at a basic level in their security stuff and connection strings are the devil.
* retrieved table properties *
Just in case they help, I retrieved these (after objects added to TableDefs collection).
** This one, done in UI and with DSN and this-is-ID-field, worked with editing: **
Name = dbo_tblSendTo
Updatable = False
DateCreated = 4/19/2016 11:11:40 AM
LastUpdated = 4/19/2016 11:11:42 AM
Connect = ODBC;Description=SQL Server tables for TeleSales 5;DRIVER=SQL Server Native Client 10.0;SERVER=(local)\sqlexpress;Trusted_Connection=Yes;APP=Microsoft Office 2003;WSID=CMSERVER;DATABASE=TS5_General;
Attributes = 536870912
SourceTableName = dbo.tblSendTo
RecordCount = -1
ValidationRule =
ValidationText =
ConflictTable =
ReplicaFilter =
** And this one, from table linked via code, didn't: **
Name = tblSendTo
Updatable = False
DateCreated = 4/19/2016 11:17:51 AM
LastUpdated = 4/19/2016 11:17:51 AM
Connect = ODBC;Description=SQL Server tables for TeleSales 5;DRIVER=SQL Server Native Client
> 10.0;SERVER=(local)\sqlexpress;Trusted_Connection=Yes;APP=Microsoft Office 2003;WSID=CMSERVER;DATABASE=TS5_General;
Attributes = 536870912
SourceTableName = dbo.tblSendTo
RecordCount = -1
ValidationRule =
ValidationText =
ConflictTable =
ReplicaFilter =
* my plea *
So..... Please someone help me out. I don't like feeling stupid like this, and regrettably I need to do this instead of replacing it with .NET code or similar.
Thanks, anyone who can...
Ed.
Alas, I am able to answer my own question.
edited a little since first posted in reply to HansUp's comments
I had added an identity column to the table that I couldn't edit. However, I had not set it up as a primary key. It turns out that using identity doesn't make something a primary key automatically.
But the latter, making it primary key using either of the 2 possible DDL syntaxes, is crucial. Since I thought I had dealt with the no edits without unique key problem, I focused on permissions.
All of the permissions things here, then, are just a sideshow.
The upshot of this is to be sure to add an identity column and make it a primary key if for some reason your original table schema didn't have that.
If I have the time, I will be trimming the question to reflect what I've discovered.

Creating a document in Domino Data Service(REST api)

I am trying to create a document in Reservation form using Domino Data Service(REST api), response is showing document is created but when i am trying to access that reservation(xyz's) using Notes client it is not showing up.
URL : http://server/Conf.nsf/api/data/documents?form=Reservation
Payload: {
"#authors":
["server",""
],
"#form":"Reservation",
"From":"xyz",
"AltFrom":"xyz",
"Chair":"xyz",
"AltChair":"xyz",
"Principal":"xyz",
"SequenceNum":1,
"ORGState":"5",
"ResourceType":"1",
"ResourceName":"BELLA VISTA/Building15",
"Room":"BELLA VISTA/Building15",
"Capacity":2,
"_ViewIcon":133,
"AppointmentType":"3",
"StartTimeZone":"Z=-3005$DO=0$ZN=India",
"EndTimeZone":"Z=-3005$DO=0$ZN=India",
"Topic":"Test Meeting",
"SendTo":"CN=BELLA VISTA/O=Building15",
"Encrypt":"0",
"Categories":"",
"RouteServers":"server",
"StartDate":"2015-03-28T06:30:00Z",
"StartTime":"2015-03-28T07:30:00Z",
"StartDateTime":"2015-03-28T06:30:00Z",
"EndDate":"2015-03-28T07:30:00Z",
"EndTime":"2015-03-28T07:30:00Z",
"EndDateTime":"2015-03-28T07:30:00Z",
"UpdateSeq":1,
"Author":"xyz",
"ResourceOwner":"",
"ReservedFor":"xyz",
"ReservedBy":"xyz",
"RQStatus":"A",
"Purpose":"Test from REST",
"NoticeType":"A",
"Step":3,
"Site":"Building15",
"ReserveDate":"2015-03-28T06:30:00Z"
}
If you're successfully creating the document but unable to see it, that suggests that you have a problem with a Reader Names or Author Names field that is denying you access to the document.
Do you have Manager access to the conf.nsf database, and Full Access Administrator rights on the server? If so, activate your full access rights via Domino Administrator, before opening conf.nsf and see if you can find your document, then check the document properties and examine all fields with SUMMARY READ-ACCESS NAMES or SUMMARY READ/WRITE-ACCESS NAMES types to determine what you've put there. Compare to manually created documents to see what should be there.
(If you lack the necessary permissions for this, either work with an administrator who has the rights, or set up a test server as AFAIK, there's no way to test the Domino Data Service with a local replica.)

SSIS Connection Error - File name not valid

I'm seeing an issue with an SSIS (SQL Server 2005) job where I'm getting the following error:
The file name "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=\UNC\FOLDERS\filename.xls;Extended Properties="EXCEL 8.0;HDR=YES";" specified in the connection was not valid.
My searching around this site and others indicates that the most common cause of this is a permissions error but I don't believe that's the case in this situation since any number of files have successfully been processed through this implementation.
Here's an overview of the setup:
Vendors FTP files to us on a daily basis that a Windows service picks up, copies to a temporary directory and then calls SSIS jobs on those files. There are two SSIS jobs for each vendor one for a snapshot data feed and one for a transaction listing.
There are currently over 50 different SSIS jobs in the overall process. All of them work except for one specific transaction job which fails with the above error in a script task step. Files come in at least daily with unique file names so I grab the job, determine the vendor based off the source directory and then the file type based off indicators in the file name to determine which SSIS job to call. Since file names change every day, when the service calls the SSIS job, I pass in a series of parameters including the vendor file name so it can properly connect to the file.
Each job begins with a script task that sets necessary variable values for the rest of the job. For example, since the vendor file name changes with each run, I pass in the vendor file name through the SSIS variables collection then set the connection string of a datasource using that file name as the DataSource in the string. It is at that point of the script task that the above error occurs. Here's the task script code where the error occurs:
Dts.Connections("Transactions File").ConnectionString = _
Dts.Variables("ConnectionString").Value.ToString().Replace("##FILE_PATH##", sourceFilePath)
The ConnectionString value is: Provider=Microsoft.Jet.OLEDB.4.0;Data Source=##FILE_PATH##;Extended Properties="EXCEL 8.0;HDR=YES";
The sourceFilePath is the full UNC path to the vendor file in the processing directory
I don't believe it's a permissions error since all the other files going through this process (using the same holding directory for processing) are working. It shouldn't be an issue of the file not existing since again it follows the same process as every other file and I have verified the file properly ends up in the correct directory. I also considered that the connection string might be too long, but the filepath ends up at 109 characters and even with a shorter (<90) full path, the same error occurs.
Is there anything else you can you think of for me to look at? Thanks for any help.
Based on the information presented, you are doing everything correct. If you're new to SSIS, one thing I'd suggest, is that you get a copy of the excellent add-in BIDSHelper. It has great features that can really save you time especially with regard to configurations and expressions.
I created a reference package that had an Excel Connection Manager pointing to C:\ssisdata\so_paulsmithjr.xls and wired everything up.
At this point, I know things are working so it was time to make the package move. I created the following variables and their values
CurrentFile - C:\ssisdata\so_paulsmithjr.xls
PlaceHolder - ##FILE_PATH##
TemplateConnection - Provider=Microsoft.Jet.OLEDB.4.0;Data Source=##FILE_PATH##;Extended Properties="Excel 8.0;HDR=YES";
A fourth variable is set to be an expression (Right click on variable, properties window. Set Evaluate as Expression = True & Expression is below)
CurrentConnection - REPLACE(#[User::TemplateConnection], #[User::PlaceHolder], #[User::CurrentFile])
I compared the CurrentConnection value to the ReferenceConnection (which is the original value of the Excel Connection Manager's connection string) and things were a match. At this point, if I were to change the value of CurrentFile to C:\ssisdata\so_paulsmithjr - Copy.xls, that would automatically be reflected in the value of CurrentConnection.
The final trick would be to use an Expression on the Excel Connection Manager. Again, right click on the CM and under Properties, there will be Expressions. It won't expand as there is nothing under it. Instead click the ellipses and then select ConnectionString property and select the ellipses again and this time drag down the #[User::CurrentFile] variable. Click OK x2 and now your connection manager is set to use wherever the CurrentConnection variable specifies.
Does that work any better?