title: How to enable "Long Path Aware" behavior for setting the current directory in a C++ windows console app
body: <p>In a C++ console application on windows, i'm trying to break the <a href="https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation" rel="nofollow noreferrer">MAX_PATH restriction</a> for the <a href="https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setcurrentdirectory" rel="nofollow noreferrer">SetCurrentDirectoryW</a> function.</p>
  <p>There are many similar questions already asked but none got a usable answer:</p>
  <ul>
  <li><a href="https://stackoverflow.com/questions/53918205/how-to-enable-long-path-aware-behavior-via-manifest-in-a-c-executable">How to enable &quot;Long Path Aware&quot; behavior via manifest in a C++ executable?</a></li>
  <li><a href="https://stackoverflow.com/questions/40983329/are-long-path-behavior-per-app-can-be-enable-via-the-manifest">Are long path behavior per app can be enable via the manifest?</a></li>
  </ul>
  <h2>Doc Research</h2>
  <p>Apparently this might be possible by using <a href="https://docs.microsoft.com/en-us/windows/win32/sbscs/application-manifests" rel="nofollow noreferrer">application manifest files</a>. The docs for <a href="https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setcurrentdirectory#parameters" rel="nofollow noreferrer">SetCurrentDirectoryW</a> state:</p>
  <blockquote>
  <p><strong>Tip</strong>  Starting with Windows 10, version 1607, for the unicode version
  of this function (<strong>SetCurrentDirectoryW</strong>), you can opt-in to remove the
  <strong>MAX_PATH</strong> limitation. See <a href="https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file" rel="nofollow noreferrer">the &quot;Maximum Path Length Limitation&quot; section
  of Naming Files, Paths, and Namespaces</a> for details.</p>
  </blockquote>
  <p>And from <a href="https://docs.microsoft.com/en-us/windows/win32/sbscs/manifests" rel="nofollow noreferrer">the general docs about Manifests</a>:</p>
  <blockquote>
  <p>Manifests are XML files that accompany and describe side-by-side
  assemblies or isolated applications.
  ...
  <a href="https://docs.microsoft.com/en-us/windows/win32/sbscs/application-manifests" rel="nofollow noreferrer">Application Manifests</a> describe <a href="https://docs.microsoft.com/en-us/windows/win32/sbscs/isolated-applications" rel="nofollow noreferrer">isolated applications</a>. They are used to
  manage the names and versions of shared side-by-side assemblies that
  the application should bind to at run time. Application manifests are
  copied into the same folder as the application executable file or
  included as a resource in the application's executable file.</p>
  </blockquote>
  <p>The <a href="https://docs.microsoft.com/en-us/windows/win32/sbscs/assembly-manifests#file-location" rel="nofollow noreferrer">docs about Assembly Manifests</a> point out the difference to Application Manifests once more:</p>
  <blockquote>
  <p>As a resource in a DLL, the assembly is available for the private use
  of the DLL. An assembly manifest cannot be included as a resource in
  an EXE. An EXE file may include an <a href="https://docs.microsoft.com/en-us/windows/win32/sbscs/application-manifests" rel="nofollow noreferrer">Application Manifests</a> as a resource.</p>
  </blockquote>
  <p>The <a href="https://docs.microsoft.com/en-us/windows/win32/sbscs/application-manifests" rel="nofollow noreferrer">docs about Application Manifests</a> list the <a href="https://docs.microsoft.com/en-us/windows/win32/sbscs/application-manifests#assembly" rel="nofollow noreferrer">assembly</a> and <a href="https://docs.microsoft.com/en-us/windows/win32/sbscs/application-manifests#assemblyIdentity" rel="nofollow noreferrer">assemblyIdentity</a> elements as required:</p>
  <ul>
  <li><p>The <a href="https://docs.microsoft.com/en-us/windows/win32/sbscs/application-manifests#assembly" rel="nofollow noreferrer">assembly element</a> requires exactly one attribute:</p>
  <ul>
  <li><strong>manifestVersion</strong>
  <ul>
  <li>The manifestVersion attribute must be set to 1.0.</li>
  </ul>
  </li>
  </ul>
  </li>
  <li><p>The <a href="https://docs.microsoft.com/en-us/windows/win32/sbscs/application-manifests#assemblyIdentity" rel="nofollow noreferrer">assemblyIdentity element</a> requires the following attributes:</p>
  <ul>
  <li><strong>type</strong>
  <ul>
  <li>The value must be Win32 and all in lower case</li>
  </ul>
  </li>
  <li><strong>name</strong>
  <ul>
  <li>Use the following format for the name: Organization.Division.Name. For example Microsoft.Windows.mysampleApp.</li>
  </ul>
  </li>
  <li><strong>version</strong>
  <ul>
  <li>Specifies the application or assembly version. Use the four-part version format: mmmmm.nnnnn.ooooo.ppppp. Each of the parts separated by periods can be 0-65535 inclusive. For more information, see <a href="https://docs.microsoft.com/en-us/windows/win32/sbscs/assembly-versions" rel="nofollow noreferrer">Assembly Versions</a>.</li>
  </ul>
  </li>
  </ul>
  </li>
  </ul>
  <p>All other elements and attributes seem to be optional.</p>
  <p>Additional requirements for the <a href="https://docs.microsoft.com/en-us/windows/win32/sbscs/application-manifests#assembly" rel="nofollow noreferrer">assembly element</a> are:</p>
  <blockquote>
  <p>Its first subelement must be a noInherit or assemblyIdentity element.
  The assembly element must be in the namespace
  &quot;urn:schemas-microsoft-com:asm.v1&quot;. Child elements of the assembly
  must also be in this namespace, by inheritance or by tagging.</p>
  </blockquote>
  <p>Finally, there's the <a href="https://docs.microsoft.com/en-us/windows/win32/sbscs/application-manifests#longPathAware" rel="nofollow noreferrer">longPathAware element</a> which is optional but which should hopefully allow <a href="https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setcurrentdirectory" rel="nofollow noreferrer">SetCurrentDirectoryW</a> to use long paths:</p>
  <blockquote>
  <p>Enables long paths that exceed MAX_PATH in length. This element is
  supported in Windows 10, version 1607, and later. For more
  information, see <a href="https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation" rel="nofollow noreferrer">this article</a>.</p>
  </blockquote>
  <p>The section in the docs shows this example xml manifest:</p>
  <pre><code>&lt;assembly xmlns=&quot;urn:schemas-microsoft-com:asm.v1&quot; manifestVersion=&quot;1.0&quot; xmlns:asmv3=&quot;urn:schemas-microsoft-com:asm.v3&quot;&gt;
   ...
    &lt;asmv3:application&gt;
      &lt;asmv3:windowsSettings xmlns:ws2=&quot;http://schemas.microsoft.com/SMI/2016/WindowsSettings&quot;&gt;
        &lt;ws2:longPathAware&gt;true&lt;/ws2:longPathAware&gt;
      &lt;/asmv3:windowsSettings&gt;
    &lt;/asmv3:application&gt;
   ...
  &lt;/assembly&gt;
  </code></pre>
  <p>It doesn't seem to exactly follow the rules from the <a href="https://docs.microsoft.com/en-us/windows/win32/sbscs/application-manifests#assembly" rel="nofollow noreferrer">assembly element</a>:</p>
  <blockquote>
  <p>The assembly element must be in the namespace &quot;urn:schemas-microsoft-com:asm.v1&quot;.
  Child elements of the assembly must also be in this namespace, by inheritance or by tagging.</p>
  </blockquote>
  <h2>Tests</h2>
  <p>The test environment is:</p>
  <ul>
  <li>Windows 10 21H2 x64 19044.1586</li>
  <li>VS2022 17.1.1</li>
  <li>Windows SDK Version 10.0.20348.0</li>
  </ul>
  <p>The test application is a new c++ console application where i made the following change to the <a href="https://docs.microsoft.com/en-us/cpp/build/reference/manifest-tool-property-pages?view=msvc-170#additional-manifest-files" rel="nofollow noreferrer">Additional Manifest Files</a>:
  <a href="https://i.stack.imgur.com/TOQ9l.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/TOQ9l.png" alt="Additional Manifest Files" /></a></p>
  <p>The source code is very simple; it's also on <a href="https://godbolt.org/z/TK3WfG4G7" rel="nofollow noreferrer">godbolt</a> but without the manifest:</p>
  <pre><code>#include &lt;iostream&gt;
  #include &lt;string&gt;
  #include &lt;windows.h&gt; 
  
  int main() {
      std::wstring const path = LR&quot;(H:\test\longPaths\manySmallLongPaths\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\12345678\)&quot;;
      std::wstring const path2 = LR&quot;(\\?\)&quot; + path;
      if (!SetCurrentDirectoryW(path.c_str())) {
          printf(&quot;Exe SetCurrentDirectory failed 1 - (%d)\n&quot;, GetLastError());
          if (!SetCurrentDirectoryW(path2.c_str()))
              printf(&quot;Exe SetCurrentDirectory failed 2 - (%d)\n&quot;, GetLastError());
      }
  }
  </code></pre>
  <p>Trying to put this all together, i think the following file might be a valid <a href="https://docs.microsoft.com/en-us/windows/win32/sbscs/application-manifests" rel="nofollow noreferrer">Application Manifest</a>:</p>
  <pre><code>&lt;?xml version='1.0' encoding='UTF-8' standalone='yes'?&gt;
  &lt;assembly xmlns:asmv1='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'&gt;
      &lt;asmv1:assemblyIdentity type='win32' name='my.test.app' version='1.0.0.0' /&gt;
      &lt;asmv1:application&gt;
          &lt;asmv1:windowsSettings&gt;
              &lt;asmv1:longPathAware&gt;true&lt;/asmv1:longPathAware&gt;
          &lt;/asmv1:windowsSettings&gt;
      &lt;/asmv1:application&gt;
  &lt;/assembly&gt;
  </code></pre>
  <p>But compiling and starting the application results in the following error:</p>
  <blockquote>
  <p>The application has failed to start because its side-by-side
  configuration is incorrect. Please see the application event log or
  use the command-line sxstrace.exe tool for more detail.</p>
  </blockquote>
  <p>Using <code>sxstrace.exe</code> reveals:</p>
  <pre><code>INFO: Parsing Manifest File C:\test\longPaths.exe.
          INFO: Manifest Definition Identity is my.test.app,type=&quot;win32&quot;,version=&quot;1.0.0.0&quot;.
          ERROR: Line 2: The element ws1:longPathAware appears as a child of element urn:schemas-microsoft-com:asm.v1^windowsSettings which is not supported by this version of Windows.
  ERROR: Activation Context generation failed.
  </code></pre>
  <p>Maybe</p>
  <blockquote>
  <p><a href="https://docs.microsoft.com/en-us/windows/win32/sbscs/application-manifests#assembly" rel="nofollow noreferrer">Child elements of the assembly must also be in this namespace</a></p>
  </blockquote>
  <p>is not entirely true (anymore) or i interpreted this wrong. Trying with a completed example from the <a href="https://docs.microsoft.com/en-us/windows/win32/sbscs/application-manifests#longPathAware" rel="nofollow noreferrer">longPathAware element</a>:</p>
  <pre><code>&lt;assembly xmlns:asmv1=&quot;urn:schemas-microsoft-com:asm.v1&quot; manifestVersion=&quot;1.0&quot; xmlns:asmv3=&quot;urn:schemas-microsoft-com:asm.v3&quot;&gt;
      &lt;asmv1:assemblyIdentity type='win32' name='my.test.app' version='1.0.0.0' /&gt;
      &lt;asmv3:application&gt;
          &lt;asmv3:windowsSettings xmlns:ws2=&quot;http://schemas.microsoft.com/SMI/2016/WindowsSettings&quot;&gt;
              &lt;ws2:longPathAware&gt;true&lt;/ws2:longPathAware&gt;
          &lt;/asmv3:windowsSettings&gt;
      &lt;/asmv3:application&gt;
  &lt;/assembly&gt;
  </code></pre>
  <p>runs the application successfully, but without long path awareness (windows error code <a href="https://godbolt.org/z/TK3WfG4G7" rel="nofollow noreferrer">206</a> = <code>ERROR_FILENAME_EXCED_RANGE</code>):</p>
  <pre><code>Exe SetCurrentDirectory failed 1 - 206
  Exe SetCurrentDirectory failed 2 - 206
  </code></pre>
  <p>I checked the final embedded resource but it's definitively there:
  <a href="https://i.stack.imgur.com/26pyg.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/26pyg.png" alt="enter image description here" /></a></p>
  <h2>To finish</h2>
  <p>i can only say that i don't know what else to test or if adding <a href="https://docs.microsoft.com/en-us/windows/win32/sbscs/application-manifests#longPathAware" rel="nofollow noreferrer">longPathAware element</a> to the manifest is even possible with the type of application i'm trying to achieve that.</p>
  <p>Maybe there's another api to change the current working folder of my application to a long path, and i would be fine with it, but at least <a href="https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/chdir-wchdir?view=msvc-170" rel="nofollow noreferrer">_chdir</a> and <a href="https://en.cppreference.com/w/cpp/filesystem/current_path" rel="nofollow noreferrer">std::filesystem::current_path</a> have the same limitations.</p>
  <h2>Workarounds</h2>
  <p>Using short names aka. 8.3 aliases might provide a limited work around.</p>
  <p>For my cases this is often not feasible because short paths don't need to exists; they can be controlled system wide or per volume:</p>
  <ul>
  <li>The general state can be queried with <code>fsutil 8dot3name query</code></li>
  <li>The per volume setting can be queried with <code>fsutil behavior query disable8dot3 c:</code></li>
  </ul>
  <h2>Sidenotes</h2>
  <ul>
  <li>The manifest can be embedded in the executable or a dll.
  <ul>
  <li>It will be ignored when the dll containing it is <a href="https://docs.microsoft.com/en-us/cpp/build/reference/linker-support-for-delay-loaded-dlls?view=msvc-170" rel="nofollow noreferrer">delay loaded</a>.</li>
  <li>It will not be ignored by the delay loaded dll when the executable is containing it.</li>
  </ul>
  </li>
  <li>Because the Manifest is &quot;additional&quot; in the project settings, it doesn't need the <a href="https://docs.microsoft.com/en-us/windows/win32/sbscs/application-manifests#assemblyIdentity" rel="nofollow noreferrer">assemblyIdentity element</a>.</li>
  </ul>