Reputation: 282
when I run a .net exe, a corresponding folder is created is created C:\Users\UserName\AppData\Local\AppName
inside this folder, another folder is created AppName_Url_ABCXYZ
inside this folder, yet another folder is created for the assembly version of the .net exe 0.2.28.0
can anyone explain how windows decide to create the second level folder AppName_Url_ABCXYZ
?
i am having an issue when i increment my assembly version and perform a single file publish and run the resulting exe, a new AppName_Url_ABCXYZ
folder is created containing the new assembly version folder.
this causes issues because it breaks the functionality of Properties.Settings.Default.Upgrade()
as the settings to upgrade from are no longer in the expected directory
Good:
-AppData
-Local
-MyApp
-MyApp_Url_ABCXYZ
-0.2.13.0
-0.2.14.0
-0.2.15.0
Bad:
-AppData
-Local
-MyApp
-MyApp_Url_ABC1
-0.2.13.0
-MyApp_Url_ABC2
-0.2.14.0
-MyApp_Url_ABC3
-0.2.15.0
Update:
The information provided by @Richard Deeming indicates that the hash portion of the appdata folder is generated like so:
var uri = "file:///" + fullExePath; //or 'assemblyName.CodeBase' if vshost (you can check the 'FriendlyName')
uri = uri.ToUpperInvariant();
var ms = new MemoryStream();
var bSer = new BinaryFormatter();
bSer.Serialize(ms, uri);
ms.Position = 0;
var sha1 = new SHA1CryptoServiceProvider();
var hash = sha1.ComputeHash(ms);
var hashstring = ToBase32StringSuitableForDirName(hash);
which makes no sense as the exe path is not changing
this issue does not occur with a brand new WPF .net 6 app and incrementing the assembly version, so its something specific to my application.
examining the resulting exe's in windows explorer does not help, they seem identical.
Update:
I have been unable to determine why this is occurring in my project. I don't even know how to debug it. I've never made any intentional changes to this behavior.
Upvotes: 8
Views: 1749
Reputation: 1110
If my understanding is correct, the folder in question (C:\Users\UserName\AppData\Local\AppName\AppName_Url_ABCXYZ
)is used to store the user.config
settings. Please check the following threads:
How to change the predefined userconfig directory of my .NET application?
Custom path of the user.config
Here is the quote from the FAQ: https://learn.microsoft.com/en-us/archive/blogs/rprabhu/client-settings-faq
The exact path of the
user.config
files looks something like this:
<Profile Directory>\<Company Name>\<App Name>_<Evidence Type>_<Evidence Hash>\<Version>\user.config
where
<Profile Directory>
- is either the roaming profile directory or the local one. Settings are stored by default in the local user.config file. To store a setting in the roaming user.config file, you need to mark the setting with the SettingsManageabilityAttribute with SettingsManageability set to Roaming.
<Company Name>
- is typically the string specified by the AssemblyCompanyAttribute (with the caveat that the string is escaped and truncated as necessary, and if not specified on the assembly, we have a fallback procedure).
<App Name>
- is typically the string specified by the AssemblyProductAttribute (same caveats as for company name).
<Evidence Type>
and<Evidence Hash>
- information derived from the app domain evidence to provide proper app domain and assembly isolation.
<Version>
- typically the version specified in the AssemblyVersionAttribute. This is required to isolate different versions of the app deployed side by side.The file name is always simply
user.config
.If you want to get to the path programmatically, you can do it using the Configuration Management API (you need to add a reference to System.Configuration.dll).
The path construction algorithm has to meet certain rigorous requirements in terms of security, isolation and robustness. While we tried to make the path as easily discoverable as possible by making use of friendly, application supplied strings, it is not possible to keep the path totally simple without running into issues like collisions with other apps, spoofing etc.
The LocalFileSettingsProvider does not provide a way to change the files in which settings are stored. Note that the provider itself doesn't determine the config file locations in the first place - it is the configuration system. If you need to store the settings in a different location for some reason, the recommended way is to write your own SettingsProvider.
It looks like Microsoft intentionally did not provide the way to configure the path to the config file to avoid collisions.
The SO threads mentioned above seem to provide some instructions on implementing the custom SettingsProvider
.
In your case, the <Evidence Hash>
part is different after updating the version. Here's one more thread describing the possible cause:
https://social.msdn.microsoft.com/Forums/vstudio/en-US/d87a0add-00ba-4074-8ef3-cf085e1122eb/userscope-settings-path-changed-after-upgrade?forum=netfxbcl
the Evidence Hash is changed, because this values is affected by two things, for a details, please check this link,
1.StrongName
2.URL
If neither of these is available, use the .exe path.
<Evidence Type>
can be the URL, StrongName, or Path, based on the evidence available to hash. In the path in question, I can see it set to Url. As I have found in the book "Programming .NET Security", the Url evidence represents the URL from which the assembly was loaded from. If it was loaded from the disk, it would be the file:// URL. Have not checked it with the example though.
Probably, the URL change or EXE path change affected the hash value.
In addition, it's necessary to check if the assembly strong name has changed.
A strong name consists of the assembly's identity—its simple text name, version number, and culture information (if provided)—plus a public key and a digital signature. It is generated from an assembly file using the corresponding private key. (The assembly file contains the assembly manifest, which contains the names and hashes of all the files that make up the assembly.) https://learn.microsoft.com/en-us/dotnet/standard/assembly/create-use-strong-named
Upvotes: 1
Reputation: 1982
Download the entire project package here – ConsoleApp1.zip
To demonstrate, let's create a simple console application:
and add a link to it:
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0" />
We will also add the Settings.settings project properties file. As a result, we get a project in the following configuration:
After compiling in debug mode and running the result of ConsoleApp1.exe, we get the following picture along the path C:\Users\Administrator\AppData\Local\ConsoleApp1:
inside this folder there will be a folder with the version number of the program:
When compiling the release version and running the result of ConsoleApp1.exe, we get the following picture along the path C:\Users\Administrator\AppData\Local\ConsoleApp1:
inside this new folder there will also be a folder with the version number of the program:
It should be noted that the debug and release versions of the program create different folders.
When you change the project version, new versions will appear in the debug and release folders, respectively:
The debug and release programs are different compilation "versions" of the same project, and different URLs are created to separate them.
Download the entire project package here – ConsoleApp1.zip
Upvotes: 2