I have a pretty old Windows Forms application for which I'm currently trying to build a ClickOnce installer.
Everything is fine except that any attempt to access ApplicationDeployment.CurrentDeployment from within the application results in:
Application identity is not set.
I found a lot of posts of this kind on web and particularly here on Stack Overflow, but people run their application under a debugger or simply not network-deployed local versions.
I emphasize that in my case the application is network-deployed (available offline). I'm running it by clicking the desktop icon created by ClickOnce installer. Update works fine (tried to publish an update to make sure it works).
Nevertheless, ApplicationDeployment.CurrentDeployment is not accessible.
What I'm doing wrong?
In fact, I'm only trying to read the application's version as it appears in the "Programs and Features" applet. Is there a way to read this information without using of ClickOnce API, for example, directly from the registry (I understand that it is not nice).
The code is very simple:
[STAThread]
static void Main(string[] argv)
{
System.Windows.Forms.MessageBox.Show(ApplicationDeployment.CurrentDeployment.CurrentVersion.ToString()); // Crash here
DoSomethingUseful();
}
I have done this using a property and bound its value in XAML directly. I am using WPF, but I hope this helps.
private string _verSion = ApplicationDeployment.CurrentDeployment.CurrentVersion.ToString();
public string verion
{
get
{
return _verSion;
}
set
{
_verSion = value;
OnPropertyChanged(() => verion);
}
}
I have not done this using a message box. You can try the same. Open a window "About Us" or something. Take a string and bind it to this property.
Related
I'm working on a project that involves the rewriting of legacy Windows applications for a modern .NET environment. The structure of these applications requires that there is one "Master" application running locally on the user's machine that fetches the others from a network share, along with required DLLs, and then runs them locally. This is not a problem per se, but I'm running into issues when I try to use the current user's AppData folder structure for this, whether it's local or roaming.
Thing is though, I can create a subfolder without a problem, I can copy files over (via a call to System.IO.File.Copy) and run them (via creating and starting an instance of System.Diagnostics.Process), but still the applications complain that they can't find the needed DLLs. This probably is related to the fact that the subfolder doesn't show up in the file system at all, which leads me to believe that files are not being copied over there in a fully conventional sense, but rather exist in some sort of limbo that prevents them from being "aware" of each other. When I do the copying and running to a standard filesystem folder, it all works fine. I've been trying to Google this issue as I was sure that this was a known problem, but I'm having a hard time finding anything on this subject. Hence this question.
Any ideas as to what might be going on? Or is my approach of using AppData for this particular purpose perhaps misguided to begin with?
EDIT: Comments asked for a viable code sample that reproduces the problem. I did have some interesting results trying to reproduce the issue as simply as I could. I created a fresh console app and could not reproduce it there. I then tried a fresh WinUI 3 app (which is what I'm trying to work with for my project) and I reproduced it there - the code seems to create the directory and then the file, without complaints (I run without the subfolder being there), but they don't show up in Explorer. For comparison, I then tried a fresh WPF app that does the exact same thing but this behaves the same as the console app, no issue with the subfolder and file showing up after running the app. So my issue seems to be confined to WinUI only.
You should be able to reproduce by placing this code inside the main window of a fresh application (and creating a button called myButton if VS doesn't do that automatically) and comparing WinUI 3 with WPF.
public MainWindow()
{
InitializeComponent();
}
private void myButton_Click(object sender, RoutedEventArgs e)
{
// See https://aka.ms/new-console-template for more information
var destinationPath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Subfolder");
string sourceFilename = "C:\\Data\\Textfile.txt";
CopyFileToLocalExecutionPath(sourceFilename, destinationPath);
}
private string CopyFileToLocalExecutionPath(string sourceFilename, string destinationPath)
{
// Make sure that destination path exists before copying file
if (!Directory.Exists(destinationPath))
Directory.CreateDirectory(destinationPath);
// Assign full destination filename - local path + same as source filename
var destinationFilename = System.IO.Path.Combine(destinationPath, System.IO.Path.GetFileName(sourceFilename));
// Do not overwrite file if it's already there
if (!File.Exists(destinationFilename))
File.Copy(sourceFilename, destinationFilename);
return destinationFilename;
}
I am trying to convert a windows desktop application from WinUI 2 to WinUI 3. However, I am having a problem with the Windows.Storage.ApplicationData class. When I call ApplicationData.Current (so I can access a file in the app's local data store or to get a local setting) a System.TypeInitializationException exception is thrown.
The following screenshot shows the problem:
System.TypeInitializationException
(This is a default application that I created in Visual Studio 2022 using the project template "Blank App, Packaged (WinUI 3 in Desktop)", the only change I made was to add the line to get the current ApplicationData object in the App class's OnLaunched() method:
var appData = Windows.Storage.ApplicationData.Current;)
Any idea what I am doing wrong here? I think maybe there is a trust or cababilities issue, or I should use other methods to get the app's local data folder or settings for a WinUI 3 desktop application.
I encountered the same problem recently. No matter where I made the call in my WinUI 3 application, whenever I invoked a call to the ApplicationData API, I would always encounter the same exact exception (System.TypeInitializationException with an inner COMException). I failed to find an answer in the API documentation, particularly where one would hope to find such an answer. (If it's there, it's buried or perhaps easily overlooked by someone who is not as familiar with .NET programming, such as myself.) The following line of code always threw an exception for me:
ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings;
The solution that worked for me was something I learned from a response to an issue on the WindowsAppSDK GitHub repository. To quote the information I found most relevant to the issue I was having:
A client that is not running in an App Container must open ApplicationData using this API: https://learn.microsoft.com/en-us/uwp/api/Windows.Management.Core.ApplicationDataManager?view=winrt-22000, while a client that is running in an App Container must open ApplicationData using this API instead: https://learn.microsoft.com/en-us/uwp/api/windows.storage.applicationdata?view=winrt-22000
Basically, I learned that I needed to open ApplicationData using the ApplicationDataManager class. As noted from the GitHub link, the solution I found was to replace the offending line of code with the following:
var localSettings = ApplicationDataManager.CreateForPackageFamily(Package.Current.Id.FamilyName).LocalSettings;
From there I can save and load app settings as usual, which is suitably explained here:
localSettings.Values["test setting"] = "a device specific setting";
String localValue = localSettings.Values["test setting"] as string;
Hopefully this helps anyone who finds themselves facing the same issue.
Scratch that, the problem only happens if in the debugger I put a breakpoint on the "ApplicationData.Current" line. Very weird. I think I am having the same problem as here:
Getting values of ApplicationData.Current.LocalSettings in static context
I'm using Settings.Settings to store settings at run-time. It was very helpful for my earlier application to store data. But in my current project its not saving the settings data. My application have some tab and each tab contains some TextBox. Im using textBox Text to store string values.
Properties.Settings.Default.Setting1 = textBox2.Text;
Properties.Settings.Default.Save();
It is a working method for my all previous application.But I can't understand why its not working in my current project.
Since your question does not include many details, I've tried to answer as much as possible:
Try to perform a Properties.Settings.Default.Upgrade() and then saved settings get loaded.
You have to call the Upgrade method of ApplicationSettingsBase derived class (that is normally called Settings and is created for you by Visual Studio)
Properties.Settings.Default.Upgrade();
When/where to call the Upgrade method? There is a simple trick you can apply: define a user setting called UpgradeRequired (example) as bool (the easiest way is through IDE). Make sure its default value is true.
Insert this code snipped at the start of the application:
if (Properties.Settings.Default.UpgradeRequired)
{
Properties.Settings.Default.Upgrade();
Properties.Settings.Default.UpgradeRequired = false;
Properties.Settings.Default.Save();
}
So the Upgrade method will be called only after the version changes and only one time (since you disable further upgrades by setting UpgradeRequired = false until a version change - when the property regains default value of true).
Check the scope of your settings [USER/APPLICATION]
Try this out, and if it doesn't work check the below conditions.
Also, a more detailed question next time would be much appreciated.
Permission (NTFS permission)
Or Active directory permission
Or capacity of windows drive is full.
Or there exist two or more user folders and you checked another.
For example: There are two or three folders, user.domain, user.workgroupname, user.
Despite all this, I suggest you to learn about System.Reflection and develop your personalized method to save settings, the option provided by the Visual Studio isn't very dependable.
Hope this was helpful.
I have the following strange behaviour in my Windows phone 8, C# App.
I am saving a Setting with:
private void SaveProperty<T>(T property, string propertyName)
{
if (IsolatedStorageSettings.ApplicationSettings.Contains(propertyName))
IsolatedStorageSettings.ApplicationSettings[propertyName] = property;
else
IsolatedStorageSettings.ApplicationSettings.Add(propertyName, property);
IsolatedStorageSettings.ApplicationSettings.Save();
}
When the app runs, I can read all settings I stored in IsolatedStorageSettings.ApplicationSettings.
But when I re-open my app (open it from the app list), the IsolatedStorageSettings.ApplicationSettings-Dictionary contains Zero (0) Keys and Values.
Am I missing something?
I used the ISETool.exe to take snapshots of the IsolatedStorage of my app (thanks to chepene).
I saw this behaviour: when I wrote the Settings (that means after the SaveProperty<T>() function finished), and the app is still running, I have the Settings saved in _ApplicationSettings. This agrees with my Observation that I can read from the IsolatedStorageSettings.ApplicationSettings when the app is running.
The _ApplicationSettings-file also exists when the is tombstoned or not running (when I can Access it by Holding the back-button of the phone and when the app is closed with the back-button).
But when the app is opened again (via the app list), the _ApplicationSettings-file is gone...
I also see that, when I'm writing a file into the IsolatedStorage with:
SharedStorageAccessManager.CopySharedFileAsync(
Windows.Storage.ApplicationData.Current.LocalFolder, fileName+"orig",
Windows.Storage.NameCollisionOption.ReplaceExisting, fileID);
and when I then don't read this file, it is gone when I open the app the next time.
By the way, to avoid confusion: I am not reinstalling the app each time I open it.
If you need more Information please ask.
Any help appreciated.
With AppSettings, I've seen something similar on WP7/7.5, but it happened only when my property-value's type was a class that was not known to the serializer.
Are you sure that there were no exceptions:
during Save
during App Exit (since the App may dump the settings at that point)
during the time that App loads the settings for the first time after launch?
Note that this doesn't necessarily must mean the app crashing. I mean, any exceptions, those internally silenced or user-handled too. Please check the VisualStudio's Output panel for "first chance exceptions" log. If any I/O or security or serialization exception shows up, then investigate there. If i remember well, there's even a whole set of isolated-storage exceptions that are easily interceptable from debug/exceptions menu.
However, the issues I had with unknown or nonserializable types does not explain at all why your extra non-appsettings files would evaporate.
Another thought: maybe some additional tool performs something like 'clean deploy' for you? I don't remember exactly, but I think that VisualStudio's deployment cycle was quite plain:
rebuild
remove/uninstall old app from device -- so probably purges isolatedstorage
install new app onto device
So, maybe that's the cause? Hm.. on afterthought and re-reading your question again, you've said about running the app from the applist, so that rather is not the case. Be sure to check firstchance exceptions then!
Thanks to quetzalcoatl I found the solution:
I am storing all my files in the root Folder of my app. At the start I am then reading all my files (via a DataContractSerializer) and casting it to my model. Since it happens sometimes that my files get corrupt, I delete every file which throws a SerialzationException. But as I read every file, and since _ApplicationSettings is not castable to my model, I am deleting _ApplicationSettings automatically.... So I learned that the ApplicationSettings are,just a file in the root folder, which I am allowed to read and delete. So the quintessence is to never write into the root Folder.
I'm building a digital signage application and I want to deploy it using ClickOnce. (I feel this is the best approach.) When I start the application from Visual Studio (VS) it works great. The application downloads a lot of images from my web service and saves them to disk:
string saveDir = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory.FullName;
When I start my deployed application, it shows the splash screen and then disappears. The process keeps running, but the UI doesn't display. I'm wondering if my saveDir as shown above is giving me trouble?
How do I locate my installed application? (I need to make license files, etc.)
I'm not sure if this is the root of your problem, but I highly recommend you change the structure of how you store your application information.
When an application is installed through ClickOnce, the application is installed within the User's folder, and it's considerably obfuscated. Furthermore, locations may change with subsequent application updates, so you can not be guarantee than any cached, downloaded file will exist from update to update.
To solve this problem, ClickOnce does provide a Data directory, that is not obfuscated and can be used for caching local data. The only caveat is this directory is not available for non-ClickOnce instances of your application (like the version that is running within the VS debugger.)
To get around this, you should write a function that you can use to get your data directory, regardless of your method of distribution or execution. The following code is a sample of what the function should look like:
//This reference is necessary if you want to discover information regarding
// the current instance of a deployed application.
using System.Deployment.Application;
//Method to obtain your applications data directory
public static string GetAppDataDirectory()
{
//The static, IsNetworkDeployed property let's you know if
// an application has been deployed via ClickOnce.
if (ApplicationDeployment.IsNetworkDeployed)
//In case of a ClickOnce install, return the deployed apps data directory
// (This is located within the User's folder, but differs between
// versions of Windows.)
return ApplicationDeployment.CurrentDeployment.DataDirectory;
//Otherwise, return another location. (Application.StartupPath works well with debugging.)
else return Application.StartupPath;
}