I am working on an application that monitors when a memory card is inserted or removed from a card reader. using the following code:
Private Sub StartDriveChange()mMediaConnectWatcher.Start()
AddHandler mMediaConnectWatcher.EventArrived, AddressOf mCardReader.CardInsertRemoveEventWhen the CarInsertRemovedEvent fires I run the logout method on my PHPrincipal class which does log the user out, but when CardInsertRemoveEvent finishes csal.ApplicationContext.User is restored to what it was before I logged out.
The logout method is:
Private Sub Logout() If Me.InvokeRequired Then Me.Invoke(New MethodInvoker(AddressOf Logout)) ElseCommon.Security.PHPrincipal.Logout()
mLogout =
True End IfAny ideas how to keep the users logged outwhen the event finishes? I currently use the mLogout = true and check it later on to see if the logout function has been run but this is just a hack to get around the problem.
You may want to use the threads window in the debugger to make sure you really are running the logout code on the UI thread.
Doesn't the me.InvokeRequired take care of that in the logout method?
All login/logout calls are taking place on the same thread ID. I even checked which thread the whole application is starting under when the form first loads and it is the same.
For some reason csla.applicationcontext.user it is being reset to before the logout is called when the cardInsertRemovedEvent method finishes running.
Interesting.
Csla.ApplicationContext.User (when not running in ASP.NET) gets/sets the principal value at System.Threading.Thread.CurrentPrincipal.
That value is owned by .NET, and there are some things that can affect it. Both WPF and VB will alter this value based on some policy settings, and you can specify that it default to a WindowsPrincipal in any environment by calling a method on the AppDomain.
However, to my knowledge, only WPF alters the value during runtime - meaning after application startup. The AppDomain setting only affects startup, and that's true for the VB policy as well (they rely on the core AppDomain value and then add some extra functionality - but it all happens at startup).
I assume you aren't using WPF?
So that should eliminate all the automatic principal changing that I'm aware of - leaving only your code as a culprit
So what I'd recommend at this point, is putting a breakpoint in your login and logout methods. You should see the logout occur - which should set the value. Then something must be setting the System.Threading.Thread.CurrentPrincipal value back, which you'd think would be the login method?
When I check the value right after the logout csla.applicationcontext.user is logged out as expected. Even checking this value with a break point on the End Sub of the CardInsertRemovedEvent shows it logged out. as soon as you step past the End Sub the value is reset back to what it was before I logged out, no other code of mine gets run until the user presses a button on the form.
What you suggest I have already done many times and the login is not getting called. And I am not using WPF.
Then I have no idea, sorry.
If you are on the correct thread, and you’ve set the
value, then something is setting the value back.
If you are in WPF I’ve seen the runtime change the value
back.
If you are in VB it can change the value, but I think that only
happens on app startup.
Beyond that, I just don’t have any idea.
Rocky
From: odie
[mailto:cslanet@lhotka.net]
Sent: Monday, September 10, 2007 3:04 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] logout reset after event finishes
When I check the value right after the logout csla.applicationcontext.user
is logged out as expected. Even checking this value with a break point on the
End Sub of the CardInsertRemovedEvent shows it logged out. as soon as you step
past the End Sub the value is reset back to what it was before I logged out, no
other code of mine gets run until the user presses a button on the form.
What you suggest I have already done many times and the login is not getting
called.
I'll put together a small project with the approprate code that reproduced the problem for you to have a look at when you have time and see if you can find out what I am missing.
Hi Odie... did you ever figure this out??? I just ran into it on my dev machine (in debug mode). Tried all your tests and something is setting the user object back to it's original value after the function finishes up. Really Weird!
and nothing is calling the Login Method at all...
I have not tested in production yet (or not with this latest release) but something is happening (the currentIdentity is getting set back) and I can not track it down.
Any Thoughts?
ward0093
I had a discussion with Kathleen Dollard, as she ran into
something similar.
In her case the assemblies were VB assemblies, and she’d
referenced one EXE from another EXE (using the first one more like a DLL).
VB’s My namespace includes some functionality to simplify
the use of principal objects in an EXE. Interestingly enough, it turns out that
calling one EXE from another EXE (like you would a DLL) also triggers this
functionality and resets the principal based on the security policy set in that
referenced EXE project.
Maybe a clue?
As I’ve said in previous posts – WPF will do this to
you as well, in VB or C#. And WCF will do it under specific circumstances as I
discuss in Using CSLA .NET 3.0.
Rocky
From: ward0093
[mailto:cslanet@lhotka.net]
Sent: Wednesday, October 10, 2007 2:07 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] RE: logout reset after event finishes
Hi Odie... did you ever figure this out??? I just ran into it on my
dev machine (in debug mode). Tried all your tests and something is
setting the user object back to it's original value after the function finishes
up. Really Weird!
and nothing is calling the Login Method at all...
I have not tested in production yet (or not with this latest release) but
something is happening (the currentIdentity is getting set back) and I can
not track it down.
Any Thoughts?
ward0093
Well... I am not calling external EXE but i do use multiple threads frequently. Could that be causing it?
Is there a way to fix it?
ward0093
.NET keeps the principal object attached to a thread. So if you
switch threads, you are responsible for ensuring that each of those threads has
the right principal.
When you set the principal (using Csla.ApplicationContext.User,
HttpContext.Current.User, System.Threading.Thread.CurrentPrincipal or My.User)
the principal is only set for the current thread. That’s how .NET works.
Everything else (with multiple threads) is entirely up to you.
Rocky
I sort of used a hack. I set a variable inside the thread event indicating that the user should be logged out and then force a log out the next time a user performs any other action, outside any threads. This is not a big deal in my application as there are only 4 things a user can actually do.
Not the nicest solution but it does work.
I think I’m doing something similar in PTWpf :)
Because WPF resets the principal (when it shouldn’t imo),
I store the current principal in a Shared/static field (thus making it
available at the AppDomain level). The data portal now has a new (to version
3.0) init event that I then handle in the same code module where that
Shared/static field is declared (the app’s main form in my case). In that
event handler I see if the current principal is the same as my _principal field
(using ReferenceEquals()) and if they are not the same, I set the thread’s
principal to _principal.
The _principal field is changed only in my LoginOut() method, so
it reflects the correct value according to my application.
This technique not only addresses the WPF need, but would
resolve most multi-threading scenarios as well – at least from the data
portal perspective.
Rocky
From: odie
[mailto:cslanet@lhotka.net]
Sent: Wednesday, October 10, 2007 2:32 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] RE: RE: logout reset after event finishes
I sort of used a hack. I set a variable inside the thread event indicating
that the user should be logged out and then force a log out the next time a
user performs any other action, outside any threads. This is not a big
deal in my application as there are only 4 things a user can actually do.
Not the nicest solution but it does work.
Hey rocky,
I was using this thread just now: http://forums.lhotka.net/forums/thread/11358.aspx
but realized we discussed this already... above you mention transferring the principal to the server but i am still trying to figure out why the principal object gets reset on the Main UI thread after a successful login?
ward0093
Something is really strange with the Multi-Threading and the current principal object.
I write out to the EventLog the user credentials (UserID, IsAuth., etc) both inside the "DoWork" event and in the "ProgressChanged" event (part of the Background Worker object). The ProgressChanged method is on the UI thread and confirmed it with the ProcessID... but shows that the User is not set even after we successfully log on.
However, when we check the User Credentials in other places in the program on the UI thread, the user shows up and everything is fine?!?!?!
this there some sort of Refresh issue going on with the "ProgressChanged" Method that we fire from within the background worker component background thread?
very strange that is does not pull the current User from the CSLA.ApplicationContext module for the main UI thread that the "ProgressChanged" method is running on?
ward0093
P.S. I am still on CSLA V2.1.2
I don't know. It sure sounds like the BackgroundWorker may be "helping" you to manage the principal somehow...
Not to be too flippant, but I look forward to hearing what you find as you research this
Is this something you can isolate into a very small demo that illustrates the problem? That might help debug the issue. Just the process of creating such an isolated demo might help reveal the issue.
Hey Rocky... I will see what I can do to create a small app and duplicate it... but one thing is for sure... in my dev environment, in debug mode... the "ProgressChanged" method on the UI Thread is not updating the User Object (the Principal object) and that has to be a bug! (or I am missing something)
I will keep you posted when I get the app done... also I am going to leave my EventLog writeouts in the app and release it to production and see if that happens in a compiled format.
ward0093
Copyright (c) Marimer LLC