Repository: pythonnet/pythonnet

Issue #1754: .NET Framework 4.6.2 Long Paths: Illegal Characters in path exception
Created: 2022-04-06T19:52:44Z
Environment

Pythonnet version: 2.5.2
Python version: 3.8.10
Operating System: Windows 10
.NET Runtime: 4.6.2

Details

.NET Framework 4.6.2 supports long paths by default. When calling an assembly that a targets .NET Framework 4.6.2, long path support is disabled and causes an Illegal characters in path exception when using a FileStream constructor:

System.ArgumentException: Illegal characters in path.
   at System.Security.Permissions.FileIOPermission.EmulateFileIOPermissionChecks(String fullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)

Workaround:
For now, the workaround is to create a python.exe.config application config file with the following:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version=".NETFramework,Version=v4.6.2"/>
  </startup>
  <runtime>
    <AppContextSwitchOverrides value="Switch.System.IO.UseLegacyPathHandling=false;Switch.System.IO.BlockLongPaths=false" />
  </runtime> 
</configuration>

This, however, creates a global solution which is not desired. An alternate workaround is to explicitly update the AppContext variables in the Python script before any code is executed (credit to https://stackoverflow.com/questions/53193280/long-path-workaround-not-working-on-some-installs):
type = Type.GetType("System.AppContext")
if type:
    AppContext.SetSwitch("Switch.System.IO.UseLegacyPathHandling", False)
    AppContext.SetSwitch("Switch.System.IO.BlockLongPaths", False)

    switchType = Type.GetType("System.AppContextSwitches")
    if switchType:
        # We also have to reach into System.AppContextSwitches and manually update the cached private versions of these properties (don't ask me why):

        legacyField = switchType.GetField("_useLegacyPathHandling", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)
        if legacyField:
            legacyField.SetValue(None, -1) # <- caching uses 0 to indicate no value, -1 for false, 1 for true.

        blockingField = switchType.GetField("_blockLongPaths", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)
        if blockingField:
            blockingField.SetValue(None, -1) # <- caching uses 0 to indicate no value, -1 for false, 1 for true.

Again, not an ideal solution because this uses reflection to set values of private variables by name.
Ideally, the CLR loader would load the proper AppContext defaults based on the version of target framework like is shown here:
https://referencesource.microsoft.com/#mscorlib/system/AppContext/AppContextDefaultValues.Defaults.cs,60

Duplicate issue #2103: Long file path support in .Net through pythonnet
Created: 2023-02-16T11:01:08Z
Environment

Pythonnet version: 3.0.1
Python version: 3.11
Operating System: Windows 10 Entreprise
.NET Runtime: Framework 4.8

Details
Hello,
We have a .Net Framework API (which is a collection of dlls) that is used by our customers through Python using pythonnet. Our .Net application is files based, and file paths are passed from Python to .Net, and .Net then opens and manipulates the files.
When using a .Net Framework exe client (no python involved), we are able to open files with long file paths (> 260 characters), either by making our exe longPathAware, or by using the \\?\ prefix.
However we cannot get this to work when calling our dlls from python using pythonnet. I understand that python.exe is itself longPathAware (since python 3.6), but using long paths does not seem to work, with or without the \\?\ prefix. Once in the .Net world, functions such as File.Exists would return false.
Would there be any difference in the .net runtime as loaded by pythonnet vs a .net framework exe that might explain this difference?
Many thanks for your help
Pierre Henry

Closing comment (2023-05-05T04:45:43Z): Not a bug. Duplicate of #1754