Skip to content

Reading configuration settings fails with System.UriFormatException: 'Invalid URI: The hostname could not be parsed.' #56897

Closed

Description

@RussKie

Description

Observed while using the new Windows Forms designer to design a migrated app from net461 to net5.0.
This doesn't appear to be a problem while running an app, but it is a problem when the code is executed in the Windows Forms designers (which is now run out of proc).

image

image

at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind)
at System.Uri..ctor(String uriString)
at System.Configuration.ClientConfigPaths..ctor(String exePath, Boolean includeUserConfig)
at System.Configuration.ClientConfigPaths.GetPaths(String exePath, Boolean includeUserConfig)
at System.Configuration.Internal.ConfigurationManagerInternal.System.Configuration.Internal.IConfigurationManagerInternal.get_ExeProductName()
at System.Configuration.ApplicationSettingsBase.get_Initializer()
at System.Configuration.ApplicationSettingsBase.CreateSetting(PropertyInfo propertyInfo)
at System.Configuration.ApplicationSettingsBase.EnsureInitialized()
at System.Configuration.ApplicationSettingsBase.get_Properties()
at System.Configuration.SettingsBase.GetPropertyValueByName(String propertyName)
at System.Configuration.SettingsBase.get_Item(String propertyName)
at System.Configuration.ApplicationSettingsBase.GetPropertyValue(String propertyName)
at System.Configuration.ApplicationSettingsBase.get_Item(String propertyName)
at GitCommands.Properties.Settings.get_IsPortable() in D:\Development\gitextensions2\GitCommands\Properties\Settings.Designer.cs:line 31

When I debugged in, for some strange reason AppDomain.CurrentDomain.BaseDirectory was returning \\?\C:\Users\igveliko\AppData\Local\Temp\WinFormsCache\exm5a4ew.gwt\
image

However when try run the same code locally AppDomain.CurrentDomain.BaseDirectory returns path without leading \\?\:
image

In essence this, what I think, is happening:

string baseDirectory = @"\\?\C:\Users\igveliko\AppData\Local\Temp\WinFormsCache\exm5a4ew.gwt\";
string manifestModuleName = @"DesignToolsServer.dll";
string configBasePath = Path.Combine(baseDirectory, manifestModuleName);
Uri uri = new Uri(configBasePath);
Console.WriteLine(uri.LocalPath);

image

Repro steps
  1. git clone -v --recurse-submodules --depth 1 --no-single-branch --progress "https://github.com/gitextensions/gitextensions.git" "<path>/gitextensions"
  2. dotnet restore
  3. Open GitExtensions.sln in VS
  4. Ignore Wix warning, trust all repos
  5. Navigate to AppSettings.IsPortable() and remove IsDesignMode
    diff --git a/GitCommands/Settings/AppSettings.cs b/GitCommands/Settings/AppSettings.cs
    
    -        public static bool IsPortable() => !IsDesignMode && Properties.Settings.Default.IsPortable;
    +        public static bool IsPortable() => Properties.Settings.Default.IsPortable;
  6. Compile
  7. Open FormAbout in designer
    image

Configuration

  • .NET 5.0.6
  • .NET: 6.0.0-rc.1.21401.1

Regression?

¯\_(ツ)_/¯ I struggle to tell what is the cause of this strange behaviour

Activity

  1. ghost added
    untriagedNew issue has not been triaged by the area owner
    on Aug 5, 2021
  2. added and removed
    untriagedNew issue has not been triaged by the area owner
    on Aug 9, 2021
  3. added this to the Future milestone on Aug 9, 2021
  4. RussKie commented on Aug 12, 2021

    @RussKie
    ContributorAuthor

    @JeremyKuhne @Shyam-Gupta whilst we're waiting for a proper fix, is there something that we're setting in the designer that's causing this?

  5. krwq commented on Aug 13, 2021

    @krwq
    Member

    @RussKie perhaps this help has some answers or workarounds: #3095

  6. RussKie commented on Aug 16, 2021

    @RussKie
    ContributorAuthor

    @krwq thank you, but I don't see any workarounds in that thread.

  7. RussKie commented on Aug 18, 2021

    @RussKie
    ContributorAuthor

    Added repro steps to the 1st post.

  8. Shyam-Gupta commented on Aug 18, 2021

    @Shyam-Gupta
    Member

    While launching server process, WinForms designer sets process path in long path format. This is because the server process is launched from a ShadowCacheFolder under temp directory and it can potentially run into max path issues. It seems this path is returned as is by AppDomain.CurrentDomain.BaseDirectory. On removing long path characters from process path, issue gets fixed.

    So I think AppDomain.CurrentDomain.BaseDirectory needs to account for long path format. Requesting @JeremyKuhne for his thoughts.

    /cc: @merriemcgaw

  9. RussKie commented on Aug 18, 2021

    @RussKie
    ContributorAuthor

    /cc: @jeffhandley @danmoseley - can this be fixed in .NET 6.0?

  10. jeffhandley commented on Aug 20, 2021

    @jeffhandley
    Member

    This is reasonable to target for RC2 given that it's a regression from .NET Framework and blocking a key scenario. We'll need to get the fix into main first though, and ideally validate the fix there before porting into the release/6.0 branch.

    The port PR template will need to cover the details of potential risks that this introduces.

  11. modified the milestones: Future, 6.0.0 on Aug 20, 2021
  12. krwq commented on Aug 23, 2021

    @krwq
    Member

    @Shyam-Gupta @RussKie I’ve just tried to repro the issue and I’m able to when I set ProcessStartInfo.FileName to anything starting with \\?\ - when I set separately WorkingDirectory to anything starting with \?\ and then FileName as just a file name that works for me because AppDomain.CurrentDomain.BaseDirectory doesn’t contain \\?\.

    However when I tried to setup the same thing with the actual long paths I'm not able to run either of them and getting different kinds of errors when starting another process, i.e.:

    Setting just FileName with long path starting with \\?\ gives me:

    Unhandled exception. System.ComponentModel.Win32Exception (206): The filename or extension is too long.
       at System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo)
       at System.Diagnostics.Process.Start()
       at System.Diagnostics.Process.Start(ProcessStartInfo startInfo)
       at ConsoleApp40.Program.Main(String[] args) in C:\Users\kwicher\source\repos\ConsoleApp40\x\ConsoleApp40\Program.cs:line 28
    

    which means the process is not even executed which wouldn't solve the issue.

    If I try to set WorkingDirectory with long path starting with \\?\ and FileName with just a file name I get:

    Unhandled exception. System.ComponentModel.Win32Exception (267): The directory name is invalid.
       at System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo)
       at System.Diagnostics.Process.Start()
       at System.Diagnostics.Process.Start(ProcessStartInfo startInfo)
       at ConsoleApp40.Program.Main(String[] args) in C:\Users\kwicher\source\repos\ConsoleApp40\x\ConsoleApp40\Program.cs:line 28
    

    on top of that trying to run any dotnet exe (hello world app) which is on a long path from a command line ends up with:

    C:\Users\kwicher\source\repos\ConsoleApp40\looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong\ConsoleApp40\bin\Debug\net5.0>ConsoleApp40.exe
    The current directory is invalid.
    

    I'm not sure fixing just this issue will help in the long path issue case anyway so I'd suggest just not prepend \\?\ for now. I'm guessing there will need to be more fixes done to get this fixed for long path.

    I've also tried the same on latest 6.0 and the output was same.

  13. JeremyKuhne commented on Aug 25, 2021

    @JeremyKuhne
    Member

    @krwq This stuff should work. Feel free to ping me on teams regarding long path technical details. :)

  14. RussKie commented on Aug 25, 2021

    @RussKie
    ContributorAuthor

    We've had a chat with @JeremyKuhne, and it won't be correct move to modify the designer start up sequence. The BCL and the .NET runtime must handle long paths correctly, and in general they are. Uri appears to be an outlier here.

    Here's a document outlining how to enable long paths https://docs.microsoft.com/windows/win32/fileio/maximum-file-path-limitation which you find helpful.

  15. krwq commented on Aug 25, 2021

    @krwq
    Member

    I'll sync with @JeremyKuhne - my registry already shows that long paths are enabled and I added manifest file with longPathAware=true (I wasn't aware I needed it before) and I'm still getting "The current directory is invalid." when I try to run from the command line - although this looks like it comes from cmd.exe and not my .exe itself

  16. self-assigned this
    on Sep 1, 2021
  17. krwq commented on Sep 1, 2021

    @krwq
    Member

    After syncing with @JeremyKuhne I believe I was correctly using manifest file and correctly enabled everything. I was able to run the app in cmd.exe from outside of the current directory (so that current directory is relatively short) and then using full path. For System.Diagnostics.Process I don't think it works with long paths, see the issue I've created - I've added potential workaround for long paths as well but it will only work if you don't pass any arguments to the exe:
    #58492

    If you use the workaround then after fixing this issue this scenario can be unblocked (assuming you don't pass any arguments to the app, if you do then last bullet point in #58492 has to be fixed as well)

  18. ghost added
    in-prThere is an active PR which will close this issue when it is merged
    on Sep 3, 2021
  19. RussKie commented on Sep 20, 2021

    @RussKie
    ContributorAuthor

    @krwq I've used the private binaries and followed the steps you have kindly provided, but either I'm doing something wrong, or the issue isn't quite fixed.

    Here's the stack trace I'm now getting (note it is not failing in System.Configuration.ClientConfigPaths.GetTypeAndHashSuffix(String exePath, Boolean isSingleFile)):

    at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind)
    at System.Uri..ctor(String uriString)
    at System.Configuration.ClientConfigPaths.GetTypeAndHashSuffix(String exePath, Boolean isSingleFile)
    at System.Configuration.ClientConfigPaths..ctor(String exePath, Boolean includeUserConfig)
    at System.Configuration.ClientConfigPaths.GetPaths(String exePath, Boolean includeUserConfig)
    at System.Configuration.ClientConfigPaths.get_Current()
    at System.Configuration.Internal.ConfigurationManagerInternal.System.Configuration.Internal.IConfigurationManagerInternal.get_ExeProductName()
    at System.Configuration.ApplicationSettingsBase.get_Initializer()
    at System.Configuration.ApplicationSettingsBase.CreateSetting(PropertyInfo propertyInfo)
    at System.Configuration.ApplicationSettingsBase.EnsureInitialized()
    at System.Configuration.ApplicationSettingsBase.get_Properties()
    at System.Configuration.SettingsBase.GetPropertyValueByName(String propertyName)
    at System.Configuration.SettingsBase.get_Item(String propertyName)
    at System.Configuration.ApplicationSettingsBase.GetPropertyValue(String propertyName)
    at System.Configuration.ApplicationSettingsBase.get_Item(String propertyName)
    at WinFormsApp3.Properties.Settings.get_IsPortable() in D:\Development\throwaway\WinFormsApp3\Properties\Settings.Designer.cs:line 31
    at WinFormsApp3.AppSettings.IsPortable() in D:\Development\throwaway\WinFormsApp3\Form1.cs:line 115
    at WinFormsApp3.AppSettings.<>c.<.cctor>b__1_0() in D:\Development\throwaway\WinFormsApp3\Form1.cs:line 57
    at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
    at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
    at System.Lazy`1.CreateValue()
    at System.Lazy`1.get_Value()
    at WinFormsApp3.AppSettings.get_SettingsFilePath() in D:\Development\throwaway\WinFormsApp3\Form1.cs:line 123
    at WinFormsApp3.AppSettings.<.cctor>g__CreateEmptySettingsFileIfMissing|1_2() in D:\Development\throwaway\WinFormsApp3\Form1.cs:line 98
    at WinFormsApp3.AppSettings..cctor() in D:\Development\throwaway\WinFormsApp3\Form1.cs:line 80  
    

    Here's a repro app (a butchered version of the real app that's exhibiting the issue): 56897.zip

    Repro steps:

    1. Launch WinFormsApp3.sln
    2. Build
    3. Open Form1 in the designer
  20. krwq commented on Sep 20, 2021

    @krwq
    Member

    @RussKie let's sync offline - the attached zip doesn't build for me

  21. ghost locked as resolved and limited conversation to collaborators on Nov 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area-System.Configurationbugin-prThere is an active PR which will close this issue when it is merged

Type

No type

Projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions