-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Settings for a single-file WinForms app goes into new folders for every publish #31959
Comments
@Vino-Wang can you check to see if this happens with only self-contained or both self-contained and framework dependent apps. Chat with @dreddy-work if you need help. |
@merriemcgaw , sorry for the delay, will check it |
@felizk, can you help elaborate on step "Change and save some Settings (using the WinForms style .settings)" what exactly you changes and how? we are trying to repro on our side. @Vino-Wang |
I'm concerned there's a designer component and perhaps a build component to this issue. I don't think we are going to have time to get a fix put together for 3.1. More likely 5.0 |
Hello all, sorry I missed the request for elaboration. I used the settings designer to add some settings for my project. Then I have a tickbox and when it is ticked I do "Settings.Default.tickBoxTicked = true;" and save the settings like this "Settings.Default.Save();" |
Isn't the Settings filename/folder just determined by the assembly identity? I never noticed anything in VS design/build time influencing the settings. The fact that it gets an URL suffix looks odd though, almost as if it were treated as a clickonce app or something. It probably picks a wrong codepath because .NET Core neither has a managed .exe nor a .exe.config file. This is destined to confuse the old logic. I'm not up to date what the state of the .exe.config files is, but if they are gone you need to put the whole settings logic through a major rewrite because it is intertwined deeply with that config file. I would say there are potentially two issues here:
|
@AdamYoblick and @RussKie need to work together to make sure this is working, and that we're able to create/update this in the designer. |
I think we need dotnet/winforms#1143 fixed first, then look at whether this is still an issue. |
This only happens when you republish. Running a self-contained executable multiple times does keep the same user settings file. User settings files are, by design, using the location of the entry assembly to generate their hash (see The self-extracting logic is using something to generate it's temp folder name that doesn't appear to be the time stamps of the outer exe. It seems like this issue is totally contained to publishing and as such isn't something an end-user would see. Windows Forms has nothing to do with it and the issue should move over to the runtime repo for tracking as a hosting issue. @swaroop-sridhar, I believe this is in your area? @maryamariyan, this is a System.Configuration related issue. There currently isn't a way to configure the user file location. |
@JeremyKuhne By design, the single-file apps are published with a new ID each time they are published. This ensures that files different builds/configurations/versions of the same app do not get their extracted files mixed up. The SDK's support for incremental compilation on publish is limited, so we may end up generating the single-file with a new ID even on a publish with no actual changes. There are work-items filed to support generating bundles with fixed IDs for limited testing purposes, but in this case the burden of ensuring correct extraction is on the user. I think the correct action for files that contain settings that survive across builds is to exclude them from being bundled into the single-file. |
The app itself has the settings, which is the problem. It would be nice if there was a way to see that we're running under this scenario and be able to take the location of the launching wrapped exe in some way. |
Why would an end user ever want to lose their settings when a app is upgraded? Is this ever the correct behavior and if it is there is a very easy solution (don't have/use an Upgrade Setting)? @swaroop-sridhar this is not something a developer or end-user should have to deal with. I don't know of a single app I have worked with that does not have any settings. The biggest complaint people have with the Facebook app on Apple is it loses its sound setting on every upgrade and it continues to get negative reviews because of it (not the fault of WinForms just a data point of getting this correct). |
I understand the problem better now -- I suggested that the settings file be excluded because I thought that it was a build time artifact. But I get that the app generates it as part of its execution. When an app is published as a single-file, there's no guaranteed "location" of the app.dll. The fact that the application.dll is extracted to a temporary directory on disk is a matter of implementation. The extraction location can change with builds of the app, or with releases of .net. In fact, from .net 5, the app will be loaded directly from the app, and not extracted at all. So, assuming that the The only file that is guaranteed to have a location is the single-file app itself. So, the settings should be written wrt that location. Looks like this path can be obtained via |
Beyond the fact that Windows Forms is above System.Configuration, we can't do that without risking breaking other users of System.Configuration (there are over 50 million downloads of the System.Configuration.ConfigurationManager package, we need to be very careful with changes to heuristics). We need to have a way to programmatically and definitively know that we're in this special state to make this seamless for users. If we're changing the behavior in .NET 5 that the entry assembly always gives the same path and changes accordingly when it moves around then that will "fix" the issue. In any case, this issue has nothing to do with WinForms. It's a breaking change in a formerly constant setting ( Apologies in advance, but I'm going on vacation and won't be able to reply for a bit. I'll be back on the 18th. :) |
Are you talking about this - dotnet/winforms#2801?
@livarcocc can you move the issue to the Runtime? |
@swaroop-sridhar This is not something a developer has any control over. Settings are part of the infrastructure at least for VB in Core as of what is publicly available (3.1 and WinForms). I think they are stored in ...App.dll.config. If "the app will be loaded directly from the app, and not extracted at all" how are assets found, does everything have to be a resource and loaded with resource manager? |
Per request from @JeremyKuhne I'll move to the runtime repo. |
@paul1956, Yes, in .net 5 single-file apps, it is recommended that assets be stored as resources and loaded through resource handling API. However, this configuration will not work for app-configuration that should service across updates. The settings should be stored elsewhere, separate from the app, which will be replaced in each build. |
There are two levels of problem/solutions to this problem: In .net 5 single-file apps, the (2) Assemblies loaded from within single-file apps will be treated as if loaded from a memory-stream. So CC: @jkotas |
This is a variant of #3704 |
@swaroop-sridhar OK, for now storing new things in Resources doesn't work in Visual Studio for Core apps (I assume that will be fixed). Settings are the things that need to be preserved across apps and are handled by the run-time so it should just work. Finding files in other places, sounds like should be discouraged, though some examples might be needed dealing with application files in Single-File Apps. If I remember correctly in WPF "assets" are stored in a relative directory not in a resource so that might still be an issue. FYI Some of the solutions you find on StackOverflow below but it sounds like both are wrong going forward Private Function GetAssetPath() As String
Using processModule As ProcessModule = Process.GetCurrentProcess().MainModule
Return Path.GetDirectoryName(processModule?.FileName)
End Using
End Function and 'To get the location the assembly normally resides on disk or the install directory
Dim CodeBasePath As String = Reflection.Assembly.GetExecutingAssembly().CodeBase
'once you have the path you get the directory with:
Dim AssetsPath As String = Path.GetDirectoryName(CodeBasePath) |
@swaroop-sridhar only 1 area label per issue please - see why. |
This should be fixed now that apps are not extracted. |
From @felizk on Saturday, September 28, 2019 9:41:57 PM
Steps to reproduce
Expected behavior
To be able to persist settings between versions of the application.
Actual behavior
Every time you publish, settings are effectively wiped.
Copied from original issue: dotnet/cli#12749
The text was updated successfully, but these errors were encountered: