Commit Graph
62 Commits
Author SHA1 Message Date
Siegfried Pammer bb1d830ee6 Fix #2040: escape BAML strings that XML cannot represent
Obfuscators put arbitrary characters into BAML strings, and XML 1.0 has no
representation for most control characters - a numeric character reference is invalid
for them too. Writing such a document threw ArgumentException from XmlWriter, which
loses the resource on project export and shows an exception instead of the page in the
UI. The escapes are spelled the way the C# output spells them, so one convention covers
both languages. Namespace URIs have to be escaped where the XNamespace is created rather
than in the final pass: the URI is baked into every element name built from it, so
patching only the xmlns declaration would desync the two. Characters XML can carry stay
untouched, so ordinary documents decompile byte-identically.

Every BAML stream of an assembly lives in one .resources container, and the recovery
around resource writing sat outside the loop over its entries, so a single page that
could not be written discarded every other page sharing the container with it.

Assisted-by: Claude:claude-opus-5:Claude Code
2026-09-01 06:50:11 +02:00
Siegfried Pammer 3cb27b0dcc Fix #3510: keep exporting a project when a member cannot be decompiled
One member the decompiler could not handle aborted the whole export, so a
single unsupported method in a large assembly left the user with nothing: no
sources, no .csproj, no way around it. Recovering silently would trade that
for a worse outcome - broken output nobody knows is broken - so every failure
is recorded, written where the content would have gone, and pointed at the
issue tracker.

The recovery has to hold for anything the export touches, not just method
bodies: a file that cannot be created, a resource that cannot be decoded, an
output visitor that throws mid-type. Each of those costs its own unit and
nothing else, and the units behind a failure are still produced - dropping
them would make the export look complete when it is not.

Consumers that relied on the exception keep their failure signal: ilspycmd
exits non-zero and lists the failures, the PowerShell cmdlets raise an error
record per failure, and the round-trip suite asserts the export reported none
- otherwise a crash on a method its own tests never call would ship green.

Assisted-by: Claude:claude-opus-5[1m]:Claude Code
2026-08-10 21:00:47 +02:00
Siegfried Pammer 590793fd21 Document the two roles of the language version in the settings API
The language version appears in two places that share a name but not a
concept, which repeatedly reads as one confused API: on
DecompilerSettings it is a construction shortcut (SetLanguageVersion
initializes the feature flags once and the version is not stored, so
the flags are the only state and the call is deliberately one-way),
while on WholeProjectDecompiler it is an export parameter (the
LangVersion stamped into the project file, defaulting to
GetMinimumRequiredVersion() and rejected below it as a safety net
against exporting uncompilable projects). Spell both roles out in the
XML docs so the distinction no longer has to be reverse-engineered.

Assisted-by: Claude:claude-fable-5:Claude Code
2026-08-09 17:11:41 +02:00
Siegfried Pammer b3bf04ebd9 Re-validate the explicit LanguageVersion when project export starts
The LanguageVersion setter's InvalidOperationException is a safety net
against exporting a project whose LangVersion cannot compile the
emitted code, but it only fires at assignment time: Settings is mutable
and shared, so enabling a feature after assigning the version slipped
past the check. Re-validating at the start of DecompileProject closes
that gap while keeping the setter's immediate feedback.

Assisted-by: Claude:claude-fable-5:Claude Code
2026-08-09 17:11:41 +02:00
ds5678 e3f45c8c39 Enable nullable in WholeProjectDecompiler.cs 2026-07-29 23:17:35 -07:00
ds5678 616dc1d702 Provide a WholeProjectDecompiler constructor with no default parameter values 2026-07-29 22:59:50 -07:00
Jeremy Pritts 5fe8c1a21f Publicize IProjectFileWriter implementations (#3934)
* Make IProjectFileWriter implementations public and extensible

* Fix nullable error

* Fix delegate invocation to prevent race conditions

Refactored code to assign WriteCustomPropertyGroup and WriteCustomItemGroup delegates to local variables before null checks and invocation. This ensures thread safety by avoiding race conditions if the delegates are modified by other threads.

* Replace events with a GetCustomProperties virtual method

* Remove I prefix
2026-07-30 07:22:33 +02:00
Christoph Wille c8474419c4 Redesign DecompilerEventSource with Start/Stop tracing and keyword gating
The events introduced in #2519 timed only the five per-entity DoDecompile
overloads, allocated a Stopwatch and the member's FullName even when no
trace session was attached, and reported whole milliseconds, which rounds
almost every member to zero. Flat one-shot events also gave PerfView and
dotnet-trace no way to show durations or nesting, and the actually
expensive stages (type system initialization, assembly resolution probing,
the IL/AST transform pipelines, whole-project decompilation) were not
instrumented at all.

Start/Stop event pairs let trace viewers derive duration and nesting from
event timestamps, keywords let a session enable only the areas of
interest, and every call site is gated on IsEnabled() so tracing costs a
branch when disabled. Per-transform events are Verbose because of their
volume; unlike the STEP/Stepper mechanism they work in Release builds.
EventSource is in-box for netstandard2.0 and flows over both ETW and
EventPipe, so this stays cross-platform with no new dependency.

Assisted-by: Claude:claude-fable-5:Claude Code
2026-07-22 21:10:41 +02:00
Siegfried Pammer 83879c4a07 Fix #3775: escape reserved Windows device names in output file names
Windows maps CON, PRN, AUX, NUL, COM1-9 and LPT1-9 to devices -- on many
builds even with an extension appended, so a type named Con made both
whole-project export and the save dialog fail with IOException '\\.\Con'.
CleanUpName only checked for reserved names after re-appending the file
extension, where they never match, and the save-dialog default-name
helpers did not check them at all. The escape appends the underscore to
the base name (con_.txt, not con.txt_) because device-name parsing
ignores everything after the first dot, and is applied per path segment
so reserved directory names produced by namespaces are covered too. The
ILSpy.Tests.Windows fixture verifies on a real Windows filesystem that
the escaped names are creatable.

Assisted-by: Claude:claude-fable-5:Claude Code
2026-06-12 18:58:31 +02:00
Siegfried Pammer 1579a1698c Fix #3612: WholeProjectDecompiler.CleanUpName does not count bytes on Unix. 2025-12-15 19:26:09 +01:00
Peter Crabtree e1e16b64f5 dev: Strip BOM mark from text files 2025-08-28 20:56:19 -04:00
Siegfried Pammer fac0e5eb5f Fix #3489: Make WholeProjectDecompiler.CreateDecompiler protected virtual to make the decompilation pipeline extensible. 2025-06-18 21:06:05 +02:00
ds5678 4e21aedce7 Emit property in project file 2025-05-29 15:10:52 -07:00
ds5678 9827405f02 Fix null reference exception when writing resource files 2025-05-06 09:00:57 -07:00
ds5678 fb180b0010 Add tests 2025-04-08 11:16:14 -07:00
ds5678 db45fc70a2 Fix regression: UseNestedDirectoriesForNamespaces 2025-04-08 11:16:14 -07:00
Siegfried Pammer 53522c45f8 #3401: fix missing file extension if name contains ':' 2025-02-21 15:52:11 +01:00
Siegfried Pammer 31bbcf41bc Fix handling of file extensions in project export. 2025-02-21 09:14:23 +01:00
Siegfried Pammer 292c21d68e #3401: Treat class name as single name and not as path. 2025-02-21 07:32:32 +01:00
Siegfried Pammer 0096994679 Fix #3401: normalize directory separators to use the current platform separator 2025-02-20 10:00:59 +01:00
Siegfried Pammer e8a9227483 Fix #3264: Do not allow zero-length segments in CleanUpName: Escape path separator characters at the start of a segment. 2024-08-17 19:38:53 +02:00
Siegfried Pammer 67eade3e05 Merge pull request #3191 from icsharpcode/file-loaders
Add IFileLoader API
2024-04-01 11:08:50 +02:00
Siegfried Pammer 1fca3da27b Fix #3072: Ignore resources have the same name as a namespace. 2024-03-31 18:51:05 +02:00
Siegfried Pammer 963ff7cb3d Fix #3151: Make IProjectFileWriter API public 2024-03-31 18:46:46 +02:00
Siegfried Pammer 2d90c457c8 Lift some artificial restrictions to PEFile in WholeProjectDecompiler and ReflectionDisassembler. 2024-03-28 20:42:11 +01:00
Siegfried Pammer ca78d4a14d Use MetadataFile instead of PEFile in TypeSystem. 2024-03-24 15:35:13 +01:00
Siegfried Pammer 7cb8e6534d Fix #2850: Make sure that type names longer than 255 characters are handled correctly by WholeProjectDecompiler.GetFileNameForHandle 2022-12-03 21:44:22 +01:00
Siegfried Pammer cedad6d5e8 #2850: swap try-catch and using statement so that exception handling shows the file being decompiled causing the IOException. 2022-12-03 18:42:18 +01:00
Siegfried Pammer ff0e929866 - Introduce ProjectItemInfo instead of tuples in WholeProjectDecompiler project item generation.
- Set 'LogicalName' attribute for all decompiled resources. This makes it possible to correctly recompile projects with resource names that are not valid filenames.
- Set Generator and SubType properties for XAML files.
2022-12-03 16:55:45 +01:00
Siegfried Pammer 4eea4bf353 Fix #2830: Can't decompile project with / in resource name on Windows 2022-12-03 16:55:45 +01:00
Daniel Grunwald 6fd5ca1e60 Merge pull request #2832 from icsharpcode/roslyn-440
Update Roslyn used for tests to 4.4.0
2022-11-10 23:00:47 +01:00
Siegfried Pammer c3d0e5ecc2 Fix #1784: Move RemoveEmbeddedAttributes transform to ICSharpCode.Decompiler and do no longer decompile embedded attributes in WholeProjectDecompiler and PortablePdbWriter. 2022-11-04 21:20:45 +01:00
Siegfried Pammer 71e4d51786 Fix #2807: Detect when a compiler-generated/hidden type needs to be decompiled in WholeProjectDecompiler. 2022-11-04 13:02:38 +01:00
Siegfried Pammer 343694c549 Generalize progress reporting for decompilation and PDB generation. 2022-10-21 10:18:05 +02:00
Siegfried Pammer 5046e4cf60 Fix #2718, Fix #2719, Fix #2725: Remove WPF compiler-generated code. 2022-07-15 18:17:27 +02:00
Siegfried Pammer 8dd721aee3 Fix #2706: Filenames and directories truncated to 30 characters.
With the built-in support for long paths in .NET 6.0, we no longer need to check for the registry key. The only limitation that remains is maxSegmentLength, which seems to be 255 on all commonly used file systems/all platforms. Also there is no need to differentiate between Windows and other platforms.

- Windows Explorer in Windows 10 seems to be fine with files generated by ILSpy that have names longer than 260 characters.
- Notepad++ and other applications seem to use 8.3 path syntax to access the file.
- Visual Studio 2022 does not like the long path names, affected users should raise an issue with MS. ILSpy generates proper paths.
2022-06-15 23:04:56 +02:00
Siegfried Pammer 2646265069 #2565: Improve GetFileNameForResource: Assume that input is already a filename. 2021-12-08 23:30:58 +01:00
Siegfried Pammer 37456672d7 WholeProjectDecompiler: set segment length for Unix to 255. 2021-12-07 19:25:23 +01:00
Siegfried Pammer a48f0d311c Fix #2330: Add conditional sub directory support 2021-12-05 16:33:39 +01:00
Siegfried Pammer bf336d85cf Fix second issue mentioned in #2565: resource names such as path/to/file.ext are now properly handled as relative paths. 2021-12-03 15:50:06 +01:00
Siegfried Pammer 849161e362 - Replace DecompilerTextView.CleanUpName with direct uses of WholeProjectDecompiler.CleanUpFileName
- Add file extension handling to WholeProjectDecompiler.CleanUpName
- Add WholeProjectDecompiler.SanitizeFileName, which respects file extensions
2021-12-03 14:10:45 +01:00
Siegfried Pammer 19d5ea4095 Fix #2505: Do treat whole resource name as file name without directory at the start of GetFileNameForResource. 2021-09-18 12:32:20 +02:00
Siegfried Pammer 07199e2ecf 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. 2021-09-06 21:02:31 +02:00
Siegfried Pammer 635013329a Fix #2358: use current Path.DirectorySeparatorChar instead of hard-coded backslashes. 2021-04-30 22:11:56 +02:00
Siegfried Pammer 2a9a5237d1 Fix exception when trying to export project for which no target-framework moniker was detected. 2021-04-16 14:08:24 +02:00
Siegfried Pammer c75ead8212 Merge pull request #2201 from wwh1004/fix1
fix GetFileNameForResource not in accordance with new directory style
2020-11-05 20:47:14 +01:00
Daniel Grunwald 0de6238d65 Support resolving assembly references within a bundle. 2020-11-01 15:56:16 +01:00
文煌 77dc975f9b fix GetFileNameForResource not in accordance with https://github.com/icsharpcode/ILSpy/pull/2157 2020-10-28 00:53:46 +08:00
文煌 4b27bb5427 copy file overwrite 2020-10-14 22:16:28 +02:00
文煌 908c3081e9 don't write app.manifest if it is default 2020-10-14 22:15:01 +02:00