ClickOnce and IsolatedStorage - c#

The Winform application is release with ClickOnce in our Intranet. We store personal preference for the GUI in the Isolated Storage. All works pretty fine :)
The problem is when we have a new version of the application, we publish... all preferences are lost! User need to setup their preference over and over each version.
Is there a way to freeze the isolation for the whole application instead of the version?

You need to use application scoped, rather than domain scoped, isolated storage. This can be done by using one of IsolatedStorageFileStream's overloaded constructors.
Example:
using System.IO;
using System.IO.IsolatedStorage;
...
IsolatedStorageFile appScope = IsolatedStorageFile.GetUserStoreForApplication();
using(IsolatedStorageFileStream fs = new IsolatedStorageFileStream("data.dat", FileMode.OpenOrCreate, appScope))
{
...
However, now you will run into the issue of this code only working when the application has been launched via ClickOnce because that's the only time application scoped isolated storage is available. If you don't launch via ClickOnce (such as through Visual Studio), GetUserStoreForApplication() will throw an exception.
The way around this problem is to make sure AppDomain.CurrentDomain.ActivationContext is not null before trying to use application scoped isolated storage.

I was working on a ClickOnce app a while ago and used Environment.GetFolderPath(ApplicationData) - e.g. roaming app data folder, to store all settings. Worked fine and survived numerous updates. Just create a subdireectory with the name of your app or CompanyName/AppName or whatever and store everything in there.

a summary from the other answers:
IsolatedStorageFile isolatedStorage = IsolatedStorageFile.GetUserStoreForAssembly();//for visual studio
if (System.Deployment.Application.ApplicationDeployment.IsNetwor‌​kDeployed)
{
isolatedStorage = IsolatedStorageFile.GetUserStoreForApplication();//for click once applications
}

You have to store a permanent version of user settings in a more durable store like database. Your application can decide to use the isolated storage if it is available. If it is not available (because of a newer version), the app should get the settings from database and use it to re-initialize the settings in isolated storage. If settings are changed, you should update both places. Unless there is a newer version of the app, your app should not have to get the settings from DB.

Related

File system issue in Azure app service - Unable to create Directories

We have a dotnet core application hosted in Azure app service (Windows machine) in our production environment. It consists of two components -
Email Service
Business Rules Engine
The Email service downloads all emails first to a folder Attachments in the same directory where the application is hosted (D:\home\wwwroot\). For each email, a separate directory (with a guid value) is created under the Attachments directory.
The Business Rules engine accesses that folder and uses the email and it's attachments. Once done, we clear out all contents from the Attachments directory.
The problem we're seeing is that after a certain number of emails are processed, all of a sudden our application is unable to create directories under the Attachments folder. The statement
Directory.CreateDirectory({path})
throws an error saying the specified path could not be found.
The only way we've been able to resolve this is to restart the app service and it again happily goes on it's way creating directories, processing emails until it fails again in a day or so 8-|
What we've tried -
Ours was a multithreaded app, so assuming that maybe one thread is holding a lock on the filesystem due to incorrect or incomplete disposing of resources, we changed it to single threaded processing
Where the directories were being created, we used DirectoryInfo, so tried using DirectoryInfo.Refresh() after every directory deletion, creation etc
Wherever FileStream was being used, we've added explicit .Dispose() statements to dispose of the FileStream
Called GC.Collect() at the end of each run of our service
I suspect this issue is due to the Azure environment but we've not been able to identify what is causing this issue. Has anybody had any such issues and if so how was it resolved?
I made some changes to my code based on what I read in these links here which gives a good summary of the storage system in Azure app service -
https://www.thebestcsharpprogrammerintheworld.com/2017/12/13/how-to-manually-create-a-directory-on-your-azure-app-service/
https://github.com/projectkudu/kudu/wiki/Understanding-the-Azure-App-Service-file-system
D:\local directory points to a folder that is accessible only to that instance of the service, instead of what I was using earlier which is shared among instances - D:\home.
So I changed the code to resolve the %Temp% environment variable, which resolved to D:\local\Temp and then used that location to store the downloaded Emails.
So far multiple testing runs have been executed without any exceptions related to the file system.
Yes, based on your issue description,it does look to be a sandbox restriction. To provide more more on this, the standard/native Azure Web Apps run in a secure environment called a sandbox. Each app runs inside its own sandbox, isolating its execution from other instances on the same machine as well as providing an additional degree of security and privacy which would otherwise not be available.
Azure App Service provides pre-defined application stacks on Windows like ASP.NET or Node.js, running on IIS. The preconfigured Windows environment locks down the operating system from administrative access, software installations, changes to the global assembly cache, and so on (see Operating system functionality on Azure App Service). If your application requires more access than the preconfigured environment allows, you can deploy a custom Windows container instead.
Symbolic link creation: While sandboxed applications can follow/open existing symbolic links, they cannot create symbolic links (or any other reparse point) anywhere.
Additionally, you can check if the files has read-only attribute, to check for this, go to Kudu Console (({yoursite}.scm.azurewebsites.net)) and run attrib somefile.txt, and check if it includes the R (read-only) attribute.

WinRT - Roaming App Settings - Are they persisted across versions?

I was reading the MSDN article about "Accessing App Data with WinRT":
http://msdn.microsoft.com/en-us/library/windows/apps/hh464917.aspx
In the section Roaming App Data it says:
If the app data on a device is updated to a new version because the
user installed a newer version of the app, its app data is copied to
the cloud. The system does not update app data to other devices on
which the user has the app installed until the app is updated on those
devices as well.
It also says that the Roaming App Data is deleted if the app is not used for 30 days.
I think that "Roaming App Data" refers to ApplicationData.Current.RoamingFolder.
I don't understand if the same thing applies to Roaming Settings (ApplicationData.Current.RoamingSettings.Values). Are they also not shared across versions? Are they also deleted after not using app for 30 days?
RoamingSettings use the same engine as the roaming application folder. So, the same restrictions apply. Data may be expired after 30 days if not accessed.
I'd suggest you consider the roaming settings as a convenience, and if the 30 days will be an issue, keep important settings locally and consider the roaming as a convenient way to synchronize settings when the application is used more frequently. You could also potentially use something like OneDrive to store settings if needed.
There are group policy settings that can disable roaming and OneDrive though.

local vs roaming vs temporary windows app data

I am trying to use the correct class for storing data in my windows app. I used IsolatedStorageSettings on the Windows Phone app, but I need to use the Windows.Storage class in my Windows store App begin written with VS Express 2013
I need the data to remain secure on the device when the app is not in use and don't want it to be saved in the cloud or removed unless the use logs out of the app. SO it just need to stay secure while the user remains logged in regardless if they are using the app or its in the background or Windows shut it down for memory reasons.
I suspect roaming is not the way to go but which should I use: local or temporary?
OK, after some more research I found this.
http://msdn.microsoft.com/en-us/library/windows/apps/hh464917.aspx
Looks like local app data is the correct method as temporary data can be removed by the device at any time. Roaming as it says is for data that you want to use across devices that is stored on OneDrive(old Skydrive).
And if someone needs the example code then here is the link for a simple example.
local
Data that exists on the current device and is backed up in the cloud.
roaming
Data that exists on all devices on which the user has installed the app.
temporary
Data that could be removed by the system at any time.
localcache
Persistent data that exists only on the current device.

Where can I store executable code downloaded from a site and run it?

In my C# application, if I wanted to be able to download an "add-in" from our website and store it locally on the user's computer, and then run it (assume it's an assembly DLL or EXE, doesn't matter), I assume I can't store it in a subdirectory of my Program Files folder, and that's not really the right place for it since add-ins are user-specific. Where should I store these, and what kinds of trust/security issues might I run into?
The application data directory of the current user would be one place to store them.
string basePath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
basePath = System.IO.Path.Combine(basePath, "MyProgram");
if (!Directory.Exists(basePath))
Directory.CreateDirectory(basePath);
Trying to write anything inside of Program files after installation will run into problems in Vista, Windows 2008 server, Windows 7 and later. Unless of course your application requires elevation. Also you mentioned your files are specific per user.
Use the IsolatedStorage class provided in .NET for storing user specific stuff.
More information: Working with Isolated Storage in .NET

Are there any issues with Isolated Storage and Windows Vista?

My problem is similar but not the same as that exhibited in:
"Could not find file" when using Isolated Storage
I've written an application that saves user settings in a file in isolated storage, I'm using the user store for assembly storage.
The application checks for a file in Isolated Storage on startup, and if it's not there assumes that it's the first time the application has been run and asks the user to configure it, this process then saves to Isolated Storage.
In Windows XP this works fine, I've not seen any issues whatsoever. However, I was running a demonstration to the client on their Windows Vista laptop and when I ran the client for the 2nd time to show that the settings were saved the application couldn't find the file.
Are there any known issues that might cause this to happen in Windows Vista and not Windows XP?
Both references to retrieve Isolated Storage are in the same .cs file, so it's definitely the same assembly that is making the call, and I didn't log in as another user, so I know it's the same user.
Isolated storage location will change as soon as you change the application version.
The proper place to store application configuration is in \ProgramData for all users and \Users\\AppData for user settings.

Categories