How to clear the data stored after logging out in C#? - c#

Is there any way to clear all the data stored on the memory after logging out in such a way that it looks like the condition when the application is run for the first time?
In my Winform project, there are different user levels that have different access to different forms and different controls.
After I click the log out button, the previous settings remain.
Is there any way to reset everything back to zero without having to set the all the setting of each form and every control ?

I finally found the answer.
It was very simple.
Application.Restart();
It shuts down the application and starts a new instance immediately.

You might need to manually nullify static variables if any are being used to store data on logout click.
To delete cookies:
foreach (string cookieFile in Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.Cookies)))
{
try
{
File.Delete(cookieFile);
}
catch (Exception)
{
}
}

Related

Approach for Load Menu from Json/XML file with good memory utilization

I have a menu file "navigationMenu.json" for my asp.net MVC application. Here is how i read the json file
public static class NavigationMenu
{
public static List<NavigationMenuViewModel> Get()
{
string jsonMenu = File.ReadAllText(HostingEnvironment.MapPath("/navigationmenu.json"));
var menu = JsonConvert.DeserializeObject<List<NavigationMenuViewModel>>(jsonMenu);
return menu;
}
}
So now when a page loads this method NavigationMenu.Get() called everytime and used in the view to display the menu.
My concern is, if this is the right way. Should i be using a static List Object to store the menu and use the list instead of reading everytime from the file? Also any changes in the menu file needs to show up instantly too.
It can depend on various things. If this file is accessed by 4 people every hour, there's no point over-engineering. Reading from a file is acceptable.
If you can ensure a single point of access to the file which is from your application (no other process touches it, like notepad), you can easily cache the contents and invalidate/refresh when accessing from said single point of access.
If there's a lot of traffic and can't ensure controlled access, you could also have a cache with a few seconds of expiration. I assume the users can live for 3 seconds with stale data. Also if the app only requests the navigation at the initial load, a lot of users will miss out on the update until they do a full-page refresh.

Ensure data deserialization / serialization

I have 3 ObservableCollections in my ViewModel and one Class which I load when you run an app.
To ensure ObservableCollections are deserialized I just got.
if(SomeCollection.Count == 0)
ThisCollection = await deserializationMethod<ObservableColletion<T>>(filename);
If there is no file, deserializationMethod will create new object with
return Activator.CreateInstance<T>();
That works fine - no problem with that.
And for class I have
if(ClassObject.Loaded != true)
ThisObject = await deserializationMethod<T>(filename);
I added a property - if file is deserialized then it's true.
It looks like it works but it is NOT. It happens very rarely but sometimes file is not deserialized and when you use an app this file is overwritten so every data are destroyed. I cannot find what is causing the problem. It is that you just run an app and it happens - like once per 100 runs.
How to be very sure that if file exist then it will be deserialized for sure?
Or maybe I should make List of these ObservableCollections + Class and serialize it to one file? Is there any good practice with that?
EDIT:
I used SemaphoreSlim to ensure that everything is used as it supposed to, but today it happened again.
The thing is it happens when app is started and nothing else is even tapped. There is no way that something is writing at this moment. It looks like data is not deserialized or is not reading the file that exist. Because every changes are written with closing an app then everything is gone.
Any other ideas what it might be or how to be sure that data are deserialized?
EDIT FINAL - reproduced problem:
I finally reproduced what is going on. So I've removed edits with code that wasn't necessary here.
I have BackPressed event to handle when user is going back or want to exit an app (if on MainPage).
This part of code apparently was causing the problem. What is going on exactly.
First thing is that problem isn't possible to be reproduced using emulator.
My BackPressed method contained await with serializing method that saved the data that were later gone (so as Ondrej Svejdar has written it was writing before reading). BUT I started to test it and there is strange behaviour and I still have some questions about it.
How it happens.
When I started an app (by accident e.g.) and loading screen occurs I start to tap back button few times -> app isn't running it is closing ASAP and I can't even see a UI (sometimes I am able to see AppBar for a moment). Then when I try to open app again (doesn't matter if immediately or later) it is "resuming" and after this exact moment my data are gone. But not all of the data. Only the last one saved with await within BackPressed method. Only this one. I tried to save One, Two and Three ObservableCollections with and without this Class and ALWAYS the last one was saved "empty". After this awaits I got Application.Current.Exit() method that might cause this, but I'm not sure if this should matter when serializing method is Task and only the last one is wrongly serialized.
When I remove this awaits from BackPressed method I can't reproduce this issue so this is it.
Questions I still have are: Is this behavior expected? Is there better method to close an app and ensure serializing data or I just should save it during using an app not while exiting it?
If someone is interested how to do it properly I was thinking about it and come up with few conclusions.
Keep in mind that this are my suggestions and there might be better approach.
While handling BackPressedButton event (the hardware one) I had an implementation of GoBack to previous page (if not on MainPage) or leave an app if on MainPage.
I was closing an app using Application.Current.Exit() and that wasn't causing problems (because I was saving very small files) until I started doing strange things (read "EDIT FINAL - reproduced problem:" of the question for more details).
Thing was the file wasn't saved because an app was closed before writing has finished. Solution is actually very simple. To my Save method which is a Task it just should return true value when writing is finished and this value should be checked while closing an app.
bool saved = await saveDataAsync<T>(whichData, dataFileName)
if(saved)
Application.Current.Exit();
and serializing method looks like this (I'm using semaphoreSlim in case there is possibility to two methods trying to reach the same file)
public async Task<bool> saveDataAsync<T>(T whichData, string dataFileName)
{
var Serializer = new DataContractSerializer(typeof(T));
await mySemaphoreSlim.WaitAsync();
try
{
using (var stream = await ApplicationData.Current.LocalFolder.OpenStreamForWriteAsync(dataFileName, CreationCollisionOption.ReplaceExisting))
{
Serializer.WriteObject(stream, whichData);
}
}
finally
{
mySemaphoreSlim.Release();
}
return true;
}

Prevent Silverlight Out-Of-Browser App from opening twice

i'm trying to prevent a Silverlight OOB App from opening twice, but i have no idea how.
I tried with creating a FileStream direct after app launch with "FileShare.None", to throw an error when the App is open twice and tries to open the file, but its ugly and doesn't work because the FileStream seems to be released after about 30 seconds..
FileStream s2 = new FileStream(path, FileMode.OpenOrCreate,FileAccess.ReadWrite, FileShare.None);
Any idea how i could approach this?
Thanks, phil
One way to achieve this is to use the local messaging channel between Silverlight applications. This scenario is mentioned in the MSDN, I will expand a little bit more here.
The LocalMessageReceiver class allow you to register to a messaging service primarily intended to communicate between different Silverlight applications.
The trick is that you can only register once with the same name in a particular scope. So as a consequence, if the first instance registers itself using your application name, any other instance doing the same afterwards will trigger an exception. Then you just have to catch that exception and deal with it, depending on what you want to do (close the instance, display a message, etc.)
Here's the code I use:
private bool CheckSingleInstance()
{
try
{
var receiver = new LocalMessageReceiver("application name", ReceiverNameScope.Global, LocalMessageReceiver.AnyDomain);
receiver.Listen();
return true;
}
catch (ListenFailedException)
{
// A listener with this name already exists
return false;
}
}
An advantage of this solution is that it works whether your instances are in-browser or out-of-browser.

ShareLinkTask Serialization.InvalidDataContractException WP8

I'm having an issue with the ShareLinkTask function from WP8.
I have an app with different pages (to view Comics - one to navigate through the Comics and one page to list a thumbnailpreview of all Comics).
The ShareLinkTask function works just fine as long as I stay in the MainPage.xaml. But when I switch to the Thumbnails.xaml (via NavigationService.Navigate...), select a new cartoon and share it the ShareLinkTask.Show() will show the sharing page and then crash the whole app.
If I make a try-catch around the ShareLinkTask.Show() no exception is thrown.
Here is the ShareLink function - it's called via the "Hold gesture":
ShareLinkTask shareLink = new ShareLinkTask();
shareLink.Title = "a";
shareLink.LinkUri = new Uri(b);
shareLink.Message = "Look at that handsome cartoon!";
try
{
shareLink.Show();
}
catch (Exception a)
{
MessageBox.Show(a.ToString());
}
From the console I get this error line: "System.Runtime.Serialization.InvalidDataContractException" occoured in System.Runtime.Serialization.ni.dll
Now Google doesn't now anything about this problem somehow - to be honest I don't really get / understand what's happening - I don't think that I serialize anything anywhere...
I suggest that I do something wrong by switching back to the MainPage.xaml. All indices etc. are correct and every other function of the app is just working fine.
Does anyone know where to look for the error?
Thanks in advance.
When you call Show, your application is put into a dormant state and may be terminated if the user navigates away instead of completing the task.
When your app is put into a dormant state your data gets serialized, but only classes with "DataContact" attributes can be serialized correctly. So the problem is - you are holding some UNSERIALIZABLE data in you app (Like in PhoneApplicationService.Current.State) . Find out what class causes exception.
Your exception should be like this:
System.Runtime.Serialization.InvalidDataContractException: Type 'TYPE HERE' cannot be serialized.
That will give you a hint of what's going on.

Better Technique: Reading Data in a Thread

I've got a routine called GetEmployeeList that loads when my Windows Application starts.
This routine pulls in basic employee information from our Active Directory server and retains this in a list called m_adEmpList.
We have a few Windows accounts set up as Public Profiles that most of our employees on our manufacturing floor use. This m_adEmpList gives our employees the ability to log in to select features using those Public Profiles.
Once all of the Active Directory data is loaded, I attempt to "auto logon" that employee based on the System.Environment.UserName if that person is logged in under their private profile. (employees love this, by the way)
If I do not thread GetEmployeeList, the Windows Form will appear unresponsive until the routine is complete.
The problem with GetEmployeeList is that we have had times when the Active Directory server was down, the network was down, or a particular computer was not able to connect over our network.
To get around these issues, I have included a ManualResetEvent m_mre with the THREADSEARCH_TIMELIMIT timeout so that the process does not go off forever. I cannot login someone using their Private Profile with System.Environment.UserName until I have the list of employees.
I realize I am not showing ALL of the code, but hopefully it is not necessary.
public static ADUserList GetEmployeeList()
{
if ((m_adEmpList == null) ||
(((m_adEmpList.Count < 10) || !m_gotData) &&
((m_thread == null) || !m_thread.IsAlive))
)
{
m_adEmpList = new ADUserList();
m_thread = new Thread(new ThreadStart(fillThread));
m_mre = new ManualResetEvent(false);
m_thread.IsBackground = true;
m_thread.Name = FILLTHREADNAME;
try {
m_thread.Start();
m_gotData = m_mre.WaitOne(THREADSEARCH_TIMELIMIT * 1000);
} catch (Exception err) {
Global.LogError(_CODEFILE + "GetEmployeeList", err);
} finally {
if ((m_thread != null) && (m_thread.IsAlive)) {
// m_thread.Abort();
m_thread = null;
}
}
}
return m_adEmpList;
}
I would like to just put a basic lock using something like m_adEmpList, but I'm not sure if it is a good idea to lock something that I need to populate, and the actual data population is going to happen in another thread using the routine fillThread.
If the ManualResetEvent's WaitOne timer fails to collect the data I need in the time allotted, there is probably a network issue, and m_mre does not have many records (if any). So, I would need to try to pull this information again the next time.
If anyone understands what I'm trying to explain, I'd like to see a better way of doing this.
It just seems too forced, right now. I keep thinking there is a better way to do it.
I think you're going about the multithreading part the wrong way. I can't really explain it, but threads should cooperate and not compete for resources, but that's exactly what's bothering you here a bit. Another problem is that your timeout is too long (so that it annoys users) and at the same time too short (if the AD server is a bit slow, but still there and serving). Your goal should be to let the thread run in the background and when it is finished, it updates the list. In the meantime, you present some fallbacks to the user and the notification that the user list is still being populated.
A few more notes on your code above:
You have a variable m_thread that is only used locally. Further, your code contains a redundant check whether that variable is null.
If you create a user list with defaults/fallbacks first and then update it through a function (make sure you are checking the InvokeRequired flag of the displaying control!) you won't need a lock. This means that the thread does not access the list stored as member but a separate list it has exclusive access to (not a member variable). The update function then replaces (!) this list, so now it is for exclusive use by the UI.
Lastly, if the AD server is really not there, try to forward the error from the background thread to the UI in some way, so that the user knows what's broken.
If you want, you can add an event to signal the thread to stop, but in most cases that won't even be necessary.

Categories

Resources