Browse Source

Fix #2038: Add proper support for Long paths on Windows 10 and limit path segments to 255 characters (with long path support) or 30 characters. If a PathTooLongException is thrown display a better error message on project export.

pull/2431/head
Siegfried Pammer 4 years ago
parent
commit
07199e2ecf
  1. 2
      ICSharpCode.Decompiler.Tests/TestCases/PdbGen/ForLoopTests.xml
  2. 2
      ICSharpCode.Decompiler.Tests/TestCases/PdbGen/HelloWorld.xml
  3. 2
      ICSharpCode.Decompiler.Tests/TestCases/PdbGen/LambdaCapturing.xml
  4. 95
      ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs
  5. 2
      ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs
  6. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  7. 1
      ILSpy/ILSpy.csproj
  8. 11
      ILSpy/Properties/Resources.Designer.cs
  9. 5
      ILSpy/Properties/Resources.resx
  10. 7
      ILSpy/SolutionWriter.cs
  11. 46
      ILSpy/TextView/DecompilerTextView.cs
  12. 4
      ILSpy/TreeNodes/AssemblyTreeNode.cs
  13. 94
      ILSpy/app.manifest

2
ICSharpCode.Decompiler.Tests/TestCases/PdbGen/ForLoopTests.xml

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<symbols>
<files>
<file id="1" name="ICSharpCode.Decompiler.Tests.TestCases.PdbGen\ForLoopTests.cs" language="C#" checksumAlgorithm="SHA256"><![CDATA[using System;
<file id="1" name="ICSharpCode\Decompiler\Tests\TestCases\PdbGen\ForLoopTests.cs" language="C#" checksumAlgorithm="SHA256"><![CDATA[using System;
namespace ICSharpCode.Decompiler.Tests.TestCases.PdbGen
{

2
ICSharpCode.Decompiler.Tests/TestCases/PdbGen/HelloWorld.xml

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<symbols>
<files>
<file id="1" name="ICSharpCode.Decompiler.Tests.TestCases.PdbGen\HelloWorld.cs" language="C#" checksumAlgorithm="SHA256"><![CDATA[using System;
<file id="1" name="ICSharpCode\Decompiler\Tests\TestCases\PdbGen\HelloWorld.cs" language="C#" checksumAlgorithm="SHA256"><![CDATA[using System;
namespace ICSharpCode.Decompiler.Tests.TestCases.PdbGen
{

2
ICSharpCode.Decompiler.Tests/TestCases/PdbGen/LambdaCapturing.xml

@ -1,7 +1,7 @@ @@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<symbols>
<files>
<file id="1" name="ICSharpCode.Decompiler.Tests.TestCases.PdbGen\LambdaCapturing.cs" language="C#" checksumAlgorithm="SHA256"><![CDATA[using System;
<file id="1" name="ICSharpCode\Decompiler\Tests\TestCases\PdbGen\LambdaCapturing.cs" language="C#" checksumAlgorithm="SHA256"><![CDATA[using System;
namespace ICSharpCode.Decompiler.Tests.TestCases.PdbGen
{

95
ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs

@ -36,6 +36,8 @@ using ICSharpCode.Decompiler.Solution; @@ -36,6 +36,8 @@ using ICSharpCode.Decompiler.Solution;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
using Microsoft.Win32;
using static ICSharpCode.Decompiler.Metadata.MetadataExtensions;
namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
@ -126,7 +128,6 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -126,7 +128,6 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
// per-run members
HashSet<string> directories = new HashSet<string>(Platform.FileNameComparer);
readonly IProjectFileWriter projectWriter;
public void DecompileProject(PEFile moduleDefinition, string targetDirectory, CancellationToken cancellationToken = default(CancellationToken))
@ -252,7 +253,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -252,7 +253,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
#region WriteResourceFilesInProject
protected virtual IEnumerable<(string itemType, string fileName)> WriteResourceFilesInProject(Metadata.PEFile module)
{
foreach (var r in module.Resources.Where(r => r.ResourceType == Metadata.ResourceType.Embedded))
foreach (var r in module.Resources.Where(r => r.ResourceType == ResourceType.Embedded))
{
Stream stream = r.TryOpenStream();
stream.Position = 0;
@ -268,7 +269,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -268,7 +269,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
{
foreach (var (name, value) in resourcesFile)
{
string fileName = Path.Combine(name.Split('/').Select(p => CleanUpFileName(p)).ToArray());
string fileName = CleanUpFileName(name)
.Replace('/', Path.DirectorySeparatorChar);
string dirName = Path.GetDirectoryName(fileName);
if (!string.IsNullOrEmpty(dirName) && directories.Add(dirName))
{
@ -359,8 +361,15 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -359,8 +361,15 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
string GetFileNameForResource(string fullName)
{
string[] splitName = fullName.Split('.');
string fileName = CleanUpFileName(fullName);
// Clean up the name first and ensure the length does not exceed the maximum length
// supported by the OS.
fullName = CleanUpDirectoryName(fullName);
// The purpose of the below algorithm is to "maximize" the directory name and "minimize" the file name.
// That is, a full name of the form "Namespace1.Namespace2{...}.NamespaceN.ResourceName" is split such that
// the directory part Namespace1\Namespace2\... reuses as many existing directories as
// possible, and only the remaining name parts are used as prefix for the filename.
string[] splitName = fullName.Split(Path.DirectorySeparatorChar);
string fileName = fullName;
string separator = Path.DirectorySeparatorChar.ToString();
for (int i = splitName.Length - 1; i > 0; i--)
{
@ -368,7 +377,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -368,7 +377,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
if (directories.Contains(ns))
{
string name = string.Join(".", splitName, i, splitName.Length - i);
fileName = Path.Combine(ns, CleanUpFileName(name));
fileName = Path.Combine(ns, name);
break;
}
}
@ -526,10 +535,50 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -526,10 +535,50 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
}
#endregion
static readonly Lazy<(bool longPathsEnabled, int maxPathLength, int maxSegmentLength)> longPathSupport =
new Lazy<(bool longPathsEnabled, int maxPathLength, int maxSegmentLength)>(GetLongPathSupport, isThreadSafe: true);
static (bool longPathsEnabled, int maxPathLength, int maxSegmentLength) GetLongPathSupport()
{
try
{
switch (Environment.OSVersion.Platform)
{
case PlatformID.MacOSX:
case PlatformID.Unix:
return (true, int.MaxValue, int.MaxValue);
case PlatformID.Win32NT:
const string key = @"SYSTEM\CurrentControlSet\Control\FileSystem";
var fileSystem = Registry.LocalMachine.OpenSubKey(key);
var value = (int?)fileSystem.GetValue("LongPathsEnabled");
if (value == 1)
{
return (true, int.MaxValue, 255);
}
return (false, 200, 30);
default:
return (false, 200, 30);
}
}
catch
{
return (false, 200, 30);
}
}
/// <summary>
/// Cleans up a node name for use as a file name.
/// </summary>
public static string CleanUpFileName(string text)
{
return CleanUpFileName(text, separateAtDots: false);
}
/// <summary>
/// Cleans up a node name for use as a file system name. If <paramref name="separateAtDots"/> is active,
/// dots are seen as segment separators. Each segment is limited to 255 characters.
/// </summary>
static string CleanUpFileName(string text, bool separateAtDots)
{
int pos = text.IndexOf(':');
if (pos > 0)
@ -540,16 +589,38 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -540,16 +589,38 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
text = text.Trim();
// Whitelist allowed characters, replace everything else:
StringBuilder b = new StringBuilder(text.Length);
int currentSegmentLength = 0;
var (supportsLongPaths, maxPathLength, maxSegmentLength) = longPathSupport.Value;
foreach (var c in text)
{
currentSegmentLength++;
if (char.IsLetterOrDigit(c) || c == '-' || c == '_')
b.Append(c);
{
// if the current segment exceeds 255 characters,
// skip until the end of the segment.
if (currentSegmentLength <= maxSegmentLength)
b.Append(c);
}
else if (c == '.' && b.Length > 0 && b[b.Length - 1] != '.')
b.Append('.'); // allow dot, but never two in a row
{
// if the current segment exceeds 255 characters,
// skip until the end of the segment.
if (separateAtDots || currentSegmentLength <= maxSegmentLength)
b.Append('.'); // allow dot, but never two in a row
// Reset length at end of segment.
if (separateAtDots)
currentSegmentLength = 0;
}
else
b.Append('-');
if (b.Length >= 200)
break; // limit to 200 chars
{
// if the current segment exceeds 255 characters,
// skip until the end of the segment.
if (currentSegmentLength <= maxSegmentLength)
b.Append('-');
}
if (b.Length >= maxPathLength && !supportsLongPaths)
break; // limit to 200 chars, if long paths are not supported.
}
if (b.Length == 0)
b.Append('-');
@ -567,7 +638,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -567,7 +638,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
/// </summary>
public static string CleanUpDirectoryName(string text)
{
return CleanUpFileName(text).Replace('.', Path.DirectorySeparatorChar);
return CleanUpFileName(text, separateAtDots: true).Replace('.', Path.DirectorySeparatorChar);
}
static bool IsReservedFileSystemName(string name)

2
ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs

@ -66,7 +66,7 @@ namespace ICSharpCode.Decompiler.DebugInfo @@ -66,7 +66,7 @@ namespace ICSharpCode.Decompiler.DebugInfo
string BuildFileNameFromTypeName(TypeDefinitionHandle handle)
{
var typeName = handle.GetFullTypeName(reader).TopLevelTypeName;
return Path.Combine(WholeProjectDecompiler.CleanUpFileName(typeName.Namespace), WholeProjectDecompiler.CleanUpFileName(typeName.Name) + ".cs");
return Path.Combine(WholeProjectDecompiler.CleanUpDirectoryName(typeName.Namespace), WholeProjectDecompiler.CleanUpFileName(typeName.Name) + ".cs");
}
foreach (var sourceFile in reader.GetTopLevelTypeDefinitions().GroupBy(BuildFileNameFromTypeName))

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -53,6 +53,7 @@ @@ -53,6 +53,7 @@
<Import Project="..\packages.props" />
<ItemGroup>
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageReference Include="System.Collections.Immutable" Version="$(SystemCollectionsImmutableVersion)" />
<PackageReference Include="System.Reflection.Metadata" Version="$(SystemReflectionMetadataVersion)" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0">

1
ILSpy/ILSpy.csproj

@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<ApplicationIcon>Images\ILSpy-Large.ico</ApplicationIcon>
<ApplicationManifest>app.manifest</ApplicationManifest>
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.snk</AssemblyOriginatorKeyFile>

11
ILSpy/Properties/Resources.Designer.cs generated

@ -2010,6 +2010,17 @@ namespace ICSharpCode.ILSpy.Properties { @@ -2010,6 +2010,17 @@ namespace ICSharpCode.ILSpy.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Failed to decompile the assemblies {0} because the namespace directory structure is nested too deep.
///
///If you are using Windows 10.0.14393 (Windows 10 version 1607) or later, you can enable &quot;Long path support&quot; by creating a REG_DWORD registry key named &quot;LongPathsEnabled&quot; with value 0x1 at &quot;HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem&quot; (see https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation for more information)..
/// </summary>
public static string ProjectExportPathTooLong {
get {
return ResourceManager.GetString("ProjectExportPathTooLong", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to for ex. property getter/setter access. To get optimal decompilation results, please manually add the missing references to the list of loaded assemblies..
/// </summary>

5
ILSpy/Properties/Resources.resx

@ -691,6 +691,11 @@ Please disable all filters that might hide the item (i.e. activate "View &gt; Sh @@ -691,6 +691,11 @@ Please disable all filters that might hide the item (i.e. activate "View &gt; Sh
<data name="ProjectExportFormatSDKHint" xml:space="preserve">
<value>A SDK-style project was generated. Learn more at https://docs.microsoft.com/en-us/nuget/resources/check-project-format.</value>
</data>
<data name="ProjectExportPathTooLong" xml:space="preserve">
<value>Failed to decompile the assemblies {0} because the namespace directory structure is nested too deep.
If you are using Windows 10.0.14393 (Windows 10 version 1607) or later, you can enable "Long path support" by creating a REG_DWORD registry key named "LongPathsEnabled" with value 0x1 at "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem" (see https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation for more information).</value>
</data>
<data name="PropertyManuallyMissingReferencesListLoadedAssemblies" xml:space="preserve">
<value>for ex. property getter/setter access. To get optimal decompilation results, please manually add the missing references to the list of loaded assemblies.</value>
</data>

7
ILSpy/SolutionWriter.cs

@ -229,6 +229,13 @@ namespace ICSharpCode.ILSpy @@ -229,6 +229,13 @@ namespace ICSharpCode.ILSpy
statusOutput.Add("-------------");
statusOutput.Add($"Failed to decompile the assembly '{loadedAssembly.FileName}':{Environment.NewLine}{e.Message}");
}
catch (PathTooLongException e)
{
statusOutput.Add("-------------");
statusOutput.Add(string.Format(Properties.Resources.ProjectExportPathTooLong, loadedAssembly.FileName)
+ Environment.NewLine + Environment.NewLine
+ e.ToString());
}
catch (Exception e) when (!(e is OperationCanceledException))
{
statusOutput.Add("-------------");

46
ILSpy/TextView/DecompilerTextView.cs

@ -1079,26 +1079,40 @@ namespace ICSharpCode.ILSpy.TextView @@ -1079,26 +1079,40 @@ namespace ICSharpCode.ILSpy.TextView
{
bool originalProjectFormatSetting = context.Options.DecompilerSettings.UseSdkStyleProjectFormat;
context.Options.EscapeInvalidIdentifiers = true;
AvalonEditTextOutput output = new AvalonEditTextOutput {
EnableHyperlinks = true,
Title = string.Join(", ", context.TreeNodes.Select(n => n.Text))
};
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
using (StreamWriter w = new StreamWriter(fileName))
try
{
try
using (StreamWriter w = new StreamWriter(fileName))
{
DecompileNodes(context, new PlainTextOutput(w));
}
catch (OperationCanceledException)
{
w.WriteLine();
w.WriteLine(Properties.Resources.DecompilationWasCancelled);
throw;
try
{
DecompileNodes(context, new PlainTextOutput(w));
}
catch (OperationCanceledException)
{
w.WriteLine();
w.WriteLine(Properties.Resources.DecompilationWasCancelled);
throw;
}
catch (PathTooLongException pathTooLong) when (context.Options.SaveAsProjectDirectory != null)
{
output.WriteLine(Properties.Resources.ProjectExportPathTooLong, string.Join(", ", context.TreeNodes.Select(n => n.Text)));
output.WriteLine();
output.WriteLine(pathTooLong.ToString());
tcs.SetResult(output);
return;
}
}
}
stopwatch.Stop();
AvalonEditTextOutput output = new AvalonEditTextOutput {
EnableHyperlinks = true,
Title = string.Join(", ", context.TreeNodes.Select(n => n.Text))
};
finally
{
stopwatch.Stop();
}
output.WriteLine(Properties.Resources.DecompilationCompleteInF1Seconds, stopwatch.Elapsed.TotalSeconds);
if (context.Options.SaveAsProjectDirectory != null)
@ -1106,9 +1120,13 @@ namespace ICSharpCode.ILSpy.TextView @@ -1106,9 +1120,13 @@ namespace ICSharpCode.ILSpy.TextView
output.WriteLine();
bool useSdkStyleProjectFormat = context.Options.DecompilerSettings.UseSdkStyleProjectFormat;
if (useSdkStyleProjectFormat)
{
output.WriteLine(Properties.Resources.ProjectExportFormatSDKHint);
}
else
{
output.WriteLine(Properties.Resources.ProjectExportFormatNonSDKHint);
}
output.WriteLine(Properties.Resources.ProjectExportFormatChangeSettingHint);
if (originalProjectFormatSetting != useSdkStyleProjectFormat)
{

4
ILSpy/TreeNodes/AssemblyTreeNode.cs

@ -342,11 +342,11 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -342,11 +342,11 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
HandleException(badImage, "This file does not contain a managed assembly.");
}
catch (FileNotFoundException fileNotFound)
catch (FileNotFoundException fileNotFound) when (options.SaveAsProjectDirectory == null)
{
HandleException(fileNotFound, "The file was not found.");
}
catch (DirectoryNotFoundException dirNotFound)
catch (DirectoryNotFoundException dirNotFound) when (options.SaveAsProjectDirectory == null)
{
HandleException(dirNotFound, "The directory was not found.");
}

94
ILSpy/app.manifest

@ -1,10 +1,10 @@ @@ -1,10 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC Manifest Options
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<!-- UAC Manifest Options
If you want to change the Windows User Account Control level replace the
requestedExecutionLevel node with one of the following.
@ -16,62 +16,62 @@ @@ -16,62 +16,62 @@
Remove this element if your application requires this virtualization for backwards
compatibility.
-->
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<requestedExecutionLevel level="asInvoker" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on and is
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!-- A list of the Windows versions that this application has been tested on and is
is designed to work with. Uncomment the appropriate elements and Windows will
automatically selected the most compatible environment. -->
<!-- Windows Vista -->
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
<!-- Windows Vista -->
<!--<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />-->
<!-- Windows 7 -->
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->
<!-- Windows 7 -->
<!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />-->
<!-- Windows 8 -->
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
<!-- Windows 8 -->
<!--<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />-->
<!-- Windows 8.1 -->
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
<!-- Windows 8.1 -->
<!--<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />-->
<!-- Windows 10 -->
<!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />-->
<!-- Windows 10 -->
<!--<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />-->
</application>
</compatibility>
</application>
</compatibility>
<!-- Indicates that the application is DPI-aware and will not be automatically scaled by Windows at higher
<!-- Indicates that the application is DPI-aware and will not be automatically scaled by Windows at higher
DPIs. Windows Presentation Foundation (WPF) applications are automatically DPI-aware and do not need
to opt in. Windows Forms applications targeting .NET Framework 4.6 that opt into this setting, should
also set the 'EnableWindowsFormsHighDpiAutoResizing' setting to 'true' in their app.config. -->
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<!-- Enable per-monitor DPI awareness: https://github.com/Microsoft/WPF-Samples/tree/master/PerMonitorDPI -->
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True</dpiAware>
<!-- Enable long path support: https://blogs.msdn.microsoft.com/jeremykuhne/2016/07/30/net-4-6-2-and-long-paths-on-windows-10/ -->
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
</windowsSettings>
</application>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<!-- Enable per-monitor DPI awareness: https://github.com/Microsoft/WPF-Samples/tree/master/PerMonitorDPI -->
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True</dpiAware>
<!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
<!-- Enable long path support: https://blogs.msdn.microsoft.com/jeremykuhne/2016/07/30/net-4-6-2-and-long-paths-on-windows-10/ -->
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">True</longPathAware>
</windowsSettings>
</application>
<!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</dependentAssembly>
</dependency>
</assembly>

Loading…
Cancel
Save