diff --git a/BrokenEvent.ILStrip.CLI/CommandLineOptions.cs b/BrokenEvent.ILStrip.CLI/CommandLineOptions.cs index 240eccf..0c93f32 100644 --- a/BrokenEvent.ILStrip.CLI/CommandLineOptions.cs +++ b/BrokenEvent.ILStrip.CLI/CommandLineOptions.cs @@ -30,19 +30,19 @@ public string InputFilename [Command("s", "Suppresses logging.", alias: "silent", isFlag:true)] public bool Silent { get; set; } - [Command("e", "User defined entry point classes list to start analysis. Multiple values.", "MyAssembly.MyNamespace.MyClass")] + [Command("e", "User defined entry point classes list to start analysis. Multiple values.", "MyNamespace.MyClass")] public List EntryPoints { get; set; } = new List(); [Command("h", "Hide public API with internal access modifier.", alias:"hide", isFlag:true)] public bool HideApi { get; set; } - [Command("he", "Exclusions for -h option. Multiple values.", "MyAssembly.MyNamespace.MyClass")] + [Command("he", "Exclusions for -h option. Multiple values.", "MyNamespace.MyClass")] public List HideExclusions { get; set; } = new List(); [Command("u", "Removes all unknown resources.", isFlag:true)] public bool RemoveUnknownResources { get; set; } - [Command("re", "Resource exclusions for -u option. Multiple values.", "MyAssembly.MyNamespace.MyResource")] + [Command("re", "Resource exclusions for -u option. Multiple values.", "MyNamespace.MyResource")] public List ResourceExclusions { get; set; } = new List(); [Command("we", "WPF Resource exclusions for -u option. Multiple values.", "resources/myresource.png")] diff --git a/BrokenEvent.ILStrip/ILStrip.cs b/BrokenEvent.ILStrip/ILStrip.cs index 7329897..cbb5545 100644 --- a/BrokenEvent.ILStrip/ILStrip.cs +++ b/BrokenEvent.ILStrip/ILStrip.cs @@ -476,9 +476,9 @@ private bool CheckIfResourceShouldRemain(Resource resource, int i) /// Gets the list of entry points to start the used classes search. /// /// - /// Use assembly-qualified names for classes. - /// Example of class: MyAssembly.MyNamespace.MyClass - /// Example of nested class: MyAssembly.MyNamespace.MyClass/MyNestedClass + /// Use namespace-qualified names for classes. + /// Example of class: MyNamespace.MyClass + /// Example of nested class: MyNamespace.MyClass/MyNestedClass /// public HashSet EntryPoints { @@ -489,8 +489,8 @@ public HashSet EntryPoints /// Gets the list of exclusions to remain public if is used. /// /// - /// Use assembly-qualified names for classes. - /// Example of class: MyAssembly.MyNamespace.MyClass + /// Use namespace-qualified names for classes. + /// Example of class: MyNamespace.MyClass /// public HashSet MakeInternalExclusions { diff --git a/README.md b/README.md index 9b5d5d2..6f243b1 100644 --- a/README.md +++ b/README.md @@ -12,12 +12,14 @@ C# Assembly unused classes/references/resources cleaner. * Unused classes cleanup. * Unused references clanup. * Unused resources cleanup. -* Entry points support (points to start the usage anaylsis). -* Hide public API with **internal** access modifier. +* Custom entry points for types that don't refernced, but should remain. +* Hide private types with `internal` access modifier. +* WPF/BAML support. ## Usecase -The main goal is to filter .NET assemblies from unused classes after merging with [ILRepack](https://github.com/ststeiger/ILRepack). It will not optimize your code or somehow change its behavior, but will erase all that is not used in current assembly. +The main goal is to filter .NET assemblies from unused classes after merging with [ILRepack](https://github.com/ststeiger/ILRepack). +It will not optimize your code or somehow change its behavior, but will erase all that is not used in current assembly. *ILStrip* works only on class level. If class is used somehow, all its members will remain even if they are not used. @@ -36,12 +38,12 @@ ILStrip stripper = // add whatever you want by name. // executable's Main(string[] args) will be added automatically stripper.EntryPoints.Add("MyNamespace.MyClass"); +stripper.EntryPointBamls.Add("ui/mywindow.baml"); -// walk the assembly opcodes to find all types, references and resources used -// all resources named "%usedType%.resources" will be counted as used +// walk the assembly opcodes to find all types and references used stripper.ScanUsedClasses(); -// walk the assembly types to find all that is not used +// walk the assembly types to build list of all types that aren't used stripper.ScanUnusedClasses(); // remove all unused types @@ -50,7 +52,10 @@ stripper.CleanupUnusedClasses(); // exclude necessary resources from cleanup stripper.UnusedResourceExclusions.Add("MyNamespace.MyImage.png"); -// remove all unused WinForms resources +// exclude necessary WPF resources from cleanup +stripper.UnusedWpfResourceExclusions.Add("res/myimage.png"); + +// remove all unused WinForms and WPF resources stripper.CleanupUnusedResources(); // remove all unused references @@ -60,7 +65,7 @@ stripper.CleanupUnusedReferences(); stripper.MakeInternalExclusions.Add("MyNamespace.MyClass"); // hide all other with internal -stripper.MakeNotPublic(); +stripper.MakeInternal(); stripper.Save(outputPath); // stripper.Save(outputStream); @@ -68,31 +73,71 @@ stripper.Save(outputPath); ### Commandline Tool -In reasons of convenience there is a commandline tool, built from improvised means. This makes the ILStrip to work as standalone or as a part of any build script. +In reasons of convenience there is a commandline tool, built from improvised means. +This makes the ILStrip to work as standalone or as a part of any build script. Usage: - Syntax: BrokenEvent.ILStrip.CLI.exe /i:%inputFile /o:%outputFile [options] + Syntax: + BrokenEvent.ILStrip.CLI.exe input output [-s] [-e MyNamespace.MyClass] [-h] [-he MyNamespace.MyClass] [-u] [-re MyNamespace.MyResource] [-we resources/myresource.png] + + Arguments: + input Input assembly filename to process. + output Output assembly filename to save processed assembly. + -s, -silent Suppresses logging. Optional. + -e User defined entry point classes list to start analysis. Multiple values. Optional. + -h, -hide Hide public API with internal access modifier. Optional. + -he Exclusions for -h option. Multiple values. Optional. + -u Removes all unknown resources. Optional. + -re Resource exclusions for -u option. Multiple values. Optional. + -we WPF Resource exclusions for -u option. Multiple values. Optional. - /?, /Help - Displays the help message - /classes, /c - Clean unused classes. - /entry - User defined entry points list to start analysis. Multiple values. - /exclude - Exclusions from hiding list. Multiple values. - /hide, /h - Hide public API with internal. - /input, /i - Input assembly filename to process. - /output, /o - Output assembly filename to save. - /refs, /r - Clean unused references. - /res, /rs - Clean unused WinForms resources. - /s, /silent - Suppress logging. ### Analysis/How it works -The *ILStrip* will parse all the methods of classes and find all the types that was used. Then parse them and so on. The starting points of the scanning are called *entry points*. If the assembly is executable, the main entry method is is used as entry point automatically. +The *ILStrip* will parse all the methods of classes and find all the types that was used. Then parse them and so on. +The starting points of the scanning are called *entry points*. If the assembly is executable, the main entry method is used as entry point automatically. -You may add another *entry points* for classes, that will be instantinated with *reflection* or somehow else. It is used for classes, that have no internal references, but you want them to remain in assembly. +You may add another *entry points* for classes, that will be instantinated with *reflection* or somehow else. +It is used for classes, that have no internal references, but you want them to remain in assembly. After building this list (`stripper.ScanUsedClasses()`) anything that isn't listed as used is trash. `ScanUnusedClasses()` builds the complete list of it. +Parsing of XAML/BAML is also supported. Any class which is referenced in BAML will be counted as used even if is the only reference. +Including ResourceDictionaries will work same way. Loading ResourceDictionary from code can't be detected. You should add such BAMLs as entry points. + +### WPF +The WPF `Application` doesn't use XAML for startup. The startup window is called from code with XAML resource name in string. +This couldn't be detected so in this case you should manually add window class (or window BAML) to entry points. + +However, if the window is started from code manually (`new MyWindow().Show()` or something like this) it will be detected as usual type reference. + +### Resources + +#### Default + +By default ILStrip will try to cleanup only the resources that are known as unused. By default the following resources will be removed: + +* Any `%className%.resources` embedded resource for class that is surely known as unused. These are mostly WinForms forms and controls. +* Any `.baml` from WPF resource which isn't built for some class (like XAMLs for windows and controls) and isn't referenced by other used BAML. + +All other resources will remain in result assembly. + +#### Full Cleanup + +You can enable `RemoveUnknownResources` option which will remove everything which isn't surely known as used. In this case the following resources will NOT be removed: + +* Any `%className%.resources` embedded resource for class that is surely known as used. These are mostly WinForms forms and controls. +* Any embedded resource, which name is added to `UnusedResourceExclusions`. +* Any `.baml` from WPF resource which is used by another BAML or related with used class. +* Any WPF resource, which name was added to `UnusedWpfResourceExclusions`. + +Any other resource will be removed. Be very careful when using this option. + +Both cases are not related with .NET resource manager, which is generated by Visual Studio. This resource will remain as is in any case. + ## Credits -Uses [Mono.Cecil](https://github.com/jbevain/cecil). +Uses [Mono.Cecil](https://github.com/jbevain/cecil) from Mono project. + +Uses [BamlParser](https://github.com/timotei/bamlparser) from Confuser. © 2017-2019 Broken Event. [brokenevent.com](https://brokenevent.com)