ADP opened read-only

R

Robert Morley

Hi everyone,

I occasionally accidentally launch and ADP file when I've already got it
opened, and I'm sure some of my users do it as well. Access, of course,
informs the user that it's opening the project read-only. Does anybody know
off-hand if there's a way to:

a) suppress that message, and/or
b) detect that condition once my code is running to pop up a friendlier
error message?



Thanks,
Rob
 
N

Norman Yuan

I do not know how to suppress that memmage, but isn't it that the
recommended way to use an Access front-end app (*.mdb/*.mde/*.adp/*.ade) is
to install the front-end app on each user's computer? This will avoid it
caused bu multiple users using the same copy of ADP/ADE file. Of course if
you open it more than once on the same computer, you still get that message.
However, if you cannot avoid users opeing the same adp/ade file or user
insists on opeing it onthe same computer more than once, then the
"Read-only" in the message does not mean much. You can still update change
made in ADP/ADE to SQL Server back end.
 
R

Robert Morley

As I said in the original message, I was referring to accidentally opening
the same local file twice, not users sharing a network file. While I tend
to do it once in a while and go "doh!", several of my users have done it and
simply don't have the technical expertise to figure out why it's giving them
the read-only error message, and then they start thinking that their DATA is
read-only.

Even if I can't suppress the original message, I'd at least like to be able
to detect the condition that the database has been opened in read-only mode
and prompt the user to quit (with a more understandable error message
explaining what they've done).


Rob
 
V

Vayse

Hi Rob
I know what you're looking for, but I don't have the code to hand. I've done
it before for an mdb - if the user trys to open it a second time, he gets a
message that he is only allowed open the database once.
I'm guessing the same code would work for an adp.
It was something about getting the windows handle of each open file, and
checking that the name didn't match.

I'll bring that code to work tomorrow, and post it here.

I just tried doing a google search, but all I got was links to 'Open
Access'!

Diarmuid
 
R

Robert Morley

Thanks Diarmuid,

I'd considered the possibility that I might have to do it this way, but was
hoping there was something more elegant in Access. :) I'll give it a few
more days to see if anybody else throws me something miraculous, and if not,
I'll use the code in the article...at least I'll be able to cut & paste it
rather than having to code it from scratch!



Thanks again,
Rob
 
V

Vadim Rapp

Hello Robert,
You wrote in conference microsoft.public.access.adp.sqlserver on Thu, 13
Jul 2006 09:09:36 -0400:

RM> I'd considered the possibility that I might have to do it this way, but
RM> was hoping there was something more elegant in Access. :)

Const ERROR_ALREADY_EXISTS = 183&
Private Declare Function CreateMutex Lib "kernel32" Alias "CreateMutexA"
(lpMutexAttributes As Any, ByVal bInitialOwner As Long, ByVal lpName As
String) As Long
Private Declare Function ReleaseMutex Lib "kernel32" (ByVal hMutex As Long)
As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long)
As Long
Public hMutex As Long
Private Const MyClass As String = "{9C7725E9-10BA-41CC-A99F-1F4825DEEF97}" '
come up with yours


' on opening:

hMutex = CreateMutex(ByVal 0&, 1, MyClass)
If (Err.LastDllError = ERROR_ALREADY_EXISTS) Then <get out>

' on closing:
If hMutex <> 0 Then
ReleaseMutex hMutex
CloseHandle hMutex
hMutex = 0
End If


======

Not exactly in Access, but more elegant I think. Also, checking for the 2nd
instance by going through all windows in the system has significant drawback:
if any of those windows (i.e. totally different applications) does not
respond, then your application will hang.

Vadim
 
R

Robert Morley

Interesting method, and yes, definitely more elegant than enumerating all
the system windows. For the MyClass constant, what do I use, just any
random GUID (like from...what is it, CreateGUID or something like that...I
know there's a system call for that, I just can't remember the name of it
off-hand), or should I be using something specific? I mean, I understand
that whatever I use has to be the same between one instance and the next,
I'm just wondering if there's something specific I need to do to establish
the value in the first place.


Thanks,
Rob
 
R

Robert Morley

Oh, another question about this method: what if Access terminates
abnormally? Is the user then stuck having to reboot before launching the
app again because the mutex was never properly closed?


Thanks,
Rob
 
V

Vadim Rapp

Hello Robert,
You wrote in conference microsoft.public.access.adp.sqlserver on Thu, 13
Jul 2006 21:59:10 -0400:

RM> Interesting method, and yes, definitely more elegant than enumerating
RM> all the system windows. For the MyClass constant, what do I use, just
RM> any random GUID (like from...what is it, CreateGUID or something like
RM> that...I know there's a system call for that, I just can't remember the
RM> name of it off-hand), or should I be using something specific?

No, it can be any string, up to your own home address. The only requirement
is that is has to be unique across your system, and, potentially, systems of
all users of this applicaiton, if it's in plans.

RM> Oh, another question about this method: what if Access terminates
RM> abnormally? Is the user then stuck having to reboot before launching
RM> the app again because the mutex was never properly closed?

No, the system follows good Arab tradition: with the death of the husband,
all wives (mutexes) are killed automatically. Try it out to make sure.

Vadim
 
R

Robert Morley

Apparently nobody at Microsoft follows good Arab tradition. With the
unexpected death of the husband (via "End Process"), the wives live on,
grieving eternally...or at least until the next reboot. Suggestions?



Rob
 
R

Robert Morley

Right now, the way I have it set up is that Access is calling a wrapper
function for CreateMutex in a class in a VB6 ActiveX EXE, so I'm thinking
that maybe the CreateMutex is being fooled by the fact that the actual call
is being done by a library EXE, or maybe my EXE isn't shutting down when the
app is terminated...I've never really been all that concerned about it
before, as it's fully re-entrant (and if that's the case, I'll be damned if
I'm gonna start trying to poll any and all apps that launch my EXE to see if
they're still running...WAY too much effort for a 20-user database front-end
plus one or two utilities). Anyway, tomorrow I'll play around and try
moving the CreateMutex out of my EXE and directly into Access and see what
happens.


Thanks,
Rob
 
R

Robert Morley

Works fine now that I've moved everything to Access. Probably my EXE was
just staying in memory and not releasing the mutex.


Thanks for all the help!
Rob
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top