OpenFileDialog to show files in Isolated Storage directory - winforms

This is a dotnet 4.5 winforms program (full trust).
I have a number of files stored in a directory in isolated storage (FormatFiles).
I would like to use the OpenFileDialog to allow the user to select one of these files and once that is solved use SaveFileDialog to allow them to name a file to be saved there.
Can I point the dialogs to this directory in isolated storage? If so, sample code.

Related

Packaged WPF app returns wrong AppData path when used as argument for a new process

I have a WPF .NET Core 3.1 app packaged as an MSIX app. The app downloads some assets from S3 to the AppData folder and at some point, it starts another process (another app) with one of the arguments being the path to one of the downloaded assets (a Settings.xml file).
I'm facing two problems:
The app sometimes downloads the assets to the "real" AppData path (C:\Users\my_user\AppData\Local\some_created_folder), sometimes to the virtualized path (C:\Users\my_user\AppData\Local\Packages\package_id\LocalCache\Local\some_created_folder). I noticed the latter only recently in 3 different releases (3 consecutive versions): 1st used "real", 2nd used virtualized, 3rd used "real" once again. I'm pretty sure there was no code change that could cause this.
I'm composing the download paths using Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData). When the assets are being downloaded to the virtualized path, the 2nd app is not starting correctly, because the settings file path set as an argument when starting the process is pointing to the "real" path (always!). No exceptions or errors are thrown!
var appData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
var settingsFilePath = Path.Combine(appData, "Settings", "Settings.xml");
...
var settingsFile = new FileInfo(settingsFilePath);
if (settingsFile.Exists)
{
var arguments = $"-l \"{settingsFile.FullName}\"";
var fileInfo = new FileInfo(_options.ExePath);
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = fileInfo.FullName,
WorkingDirectory = fileInfo.DirectoryName ?? string.Empty,
Arguments = arguments
}
};
if (process.Start())
{
process.WaitForInputIdle();
}
_logger.LogDebug("Started {name} {arguments}", fileInfo.FullName, arguments);
}
else
{
throw new FileNotFoundException($"Settings file not found at path '{settingsFile.FullName}'!", Path.GetFileName(settingsFile.Name));
}
I read this, but I don't understand why the app is acting this unpredictable. Or am I missing something? The package manifest file has the EntryPoint="Windows.FullTrustApplication". I'm also aware that UWP Desktop Bridge virtualizes some File System paths, but I'm expecting it to be predictable.
Questions
How can I make sure that my downloaded assets are always on the same path, either the "real" one or the virtualized one?
How can I set the argument for the 2nd app to always point to where the file really exists ("real" vs virtualized)?
I don't have an anwer yet, but I need more details from you to further investigate this:
Are you sure the files under the "real" appdata folder are not created accidentally by you when debugging the app from VS?
From what I know, packaged apps work with the plain, real AppData resource and path when they open a folder or file already present in that location. If the Appdata folder/files are created from scratch then it should use the virtualized location.
This behavior is useful when migrating from MSI to MSIX, until the user chooses to uninstall the MSI version, the MSI and MSIX variant can be used in parallel both having access to the same AppData files.
Then again, if this is not the first version of your app, and you have previously deployed it as an MSI to your users, you will not be able to know for sure which AppData folder you are working with when running from inside the container.
C:\Users\my_user\AppData\Local\some_created_folder
However, while researching this I found that you can also use Windows.Storage.ApplicationData.Current.LocalFolder.Path to write your appdata. Maybe this would work?
Windows.Storage.ApplicationData.Current.LocalFolder.Path changes the path during normal debug and a test
The second app, is that an EXE from the same MSIX package or another separate application (deployed with its own MSI/MSIX) from the machine? I might be wrong, but if remember correctly the virtualized AppData folder is accessible only inside your app container, so other apps from the machine can't access those files.
If that is the case, you could try saving the data in the CommonApplicationData folder, if this isn't user-specific data.
Related question:
How to allow for editable .Net generated config files with MSIX?
I read this, but I don't understand why the app is acting this
unpredictable. Or am I missing something? The package manifest file
has the EntryPoint="Windows.FullTrustApplication". I'm also aware that
UWP Desktop Bridge virtualizes some File System paths, but I'm
expecting it to be predictable.
From that link you provided, the details for the reasons why it appears "unpredictable" (note: the behaviour is slightly different before and after Windows 10 1903):
In response to a file open command, the OS will open the file from the
per-user, per-package location first. If this location doesn't exist,
the OS will attempt to open the file from the real AppData location.
If the file is opened from the real AppData location, no
virtualization for that file occurs.
And
All newly created files and folders in the user's AppData folder
(e.g., C:\Users\user_name\AppData) are written to a private per-user,
per-app location but merged at runtime to appear in the real AppData
location. ...
Modifications to existing files under the user's AppData folder is
allowed to provide a higher degree of compatibility and interactivity
between applications and the OS. ...
State separation also allows packaged desktop applications to pick up
where a non-packaged version of the same application left off.
The affected directories are:
Local
Local\Microsoft
Roaming
Roaming\Microsoft
Roaming\Microsoft\Windows\Start Menu\Programs
So, to answer you questions:
How can I make sure that my downloaded assets are always on the same path, either the "real" one or the virtualized one?
To always use the virtualized directories, look at the Windows.Storage.ApplicationData API. The function Local[Cache]Folder will always return the virtualized path.
Failing that, you must make sure that you (or a user) have never written to the non-virtualized AppData locations (e.g. C:\Users\user_name\AppData\MyCompany) as that will always be used in preference to the virtualized location (e.g. C:\Users\user_name\AppData\Local\Packages\MyCompany.MyApp_PublisherId\LocalCache\). That way, you will only ever read and write to the virtualized location.
How can I set the argument for the 2nd app to always point to where the file really exists ("real" vs virtualized)?
The virtualized path to the file is the "real" file.
However, files in this location are only visible to the packaged app itself (see https://learn.microsoft.com/en-us/windows/msix/desktop/flexible-virtualization):
Files in the virtualized location are visible only to the app.
One final thing to note. When a user uninstalls an MSIX package, it will delete all of the virtualized AppData that your application wrote.

File path in app.config file ? Window application?

In window application, I am accessing one file and the file path is declared in app.config file. After that I create exe for that application. Now the problem is when path is changed in app.config file when setup is created is this changes updated in setup or not?. If yes, how can I do that?
Its better to use relative paths, but As I understand, you cant use they.
So, only one possible solution in my opinion - define file path during instalation or add special dialog on programm first run to let user to define the path.

saving file in "Program Files/myApplication" folder with fopen_s

My application saves its settings under its executable folder, which happens to be where it is installed under Windows(C:\ProgramFiles). The problem I'm having is that I use fopen_s and open the file as binary but when my application saves the settings Windows doesn't allow it. I'm thinking it has to do something with permissions but I'm not sure where to look. Maybe I should change the directory to where it saves the settings to something like users/Documents.
Any thoughts on this, and why it isn't working? Why is fopen_s not allowed to save a file where my application is installed?
Applications running under normal user privileges have read-only access to the %ProgramFiles% directory. This is by design. If it was possible to save files to this directory, then multiple users sharing the same PC (with different accounts) would overwrite each other's settings file.
Adjust your code to save it's settings to the %LOCALAPPDATA% directory. Use SHGetKnownFolderPath API to get this directory path.

Include data files in a Silverlight app

I have some XML files marked as "Content" that should be copied into the application's XAP file. How can I read these files from within Silverlight?
I know how to read files normally in .NET. So what I'm looking for is a way to find where Windows stuck the files and any realavent security issues.
This is not exactly how to read files from within the xap but if you just want to be able to load the files at runtime then this will work.
You can set the files to be embedded resources. You then get access to them using the following:
GetType().Assembly.GetManifestResourceStream(resourceName)
resourceName is the name of the file with a full namespace. E.g. if your assembly default namespace (set in project settings) is "foo" and your file is in a folder called "bar" then resourceName would be something like "foo.bar.MyFile.xml"
You should just be able to do an XDocument.Load an pass in the name of your file.

Access a local file in Silverlight

I want to get the string from a local file (probably a Csharp file), which is attached to current project and its build action was set to Compile. Is there any way to do that. I cannot set the files' build action into Resource.
Regards,
Jawahar
I'm not clear which of these two questions you're asking:
Question 1) Can I get the text of a source file used during compilation, after compilation?
Answer 1) You'd need to set the build action to Content or Resource to do that, but realize that means you'd be shipping your source with your xap, so make sure that's what you want to do (i.e. most employers probably wouldn't like this).
You can have the file added to the xap twice by using "Add -> Existing Item -> (pick the file) -> Add As Linked Item (the little drop-down arros next to Add buton)" and set one to Compile and one to Content/Resource to accomplish this.
Question 2) Can I access a local file on the hard drive of a user of the Silverlight application?
Answer 2) Yes, by using OpenFileDialog and having the user choose the file.
Or, if you're in a Trusted Out of Browser Application (SL4 and above), then you can use the System.IO APIs to access files in My Documents, My Pictures, My Videos or My Music (on Windows an Mac) without needing to prompt the user.
Or, if you're in a Trusted OOB app, running on Windows, you can use COM and access the full file system (up to what the user can see permission-wise), again without prompt.

Resources