NetBeauty 2

repository·master·Indexed 19 days ago

https://github.com/nulastudio/netbeauty2

A tool for organizing .NET Framework and .NET Core application runtime components and dependencies into sub-directories to reduce file clutter. It supports various deployment models (FDD, SCD, FDE), shared runtime architectures for managed assemblies and locales, and AppHost patching for software suites. Available as a NuGet package (nulastudio.NetBeauty) for integration into .csproj files or as a .NET Core global tool (nbeauty2) for published projects.

Tokens
4.8K
Snippets
15
Records
15
Agent score
68%

What's inside NetBeauty 2

  1. Understand the Shared Runtime Structure

    master

    NetBeauty 2 supports a shared runtime architecture that allows multiple applications to share common managed assemblies and satellite assemblies (locales) to save space.

    In this structure:

    • A central libraries directory (name is customizable) holds shared managed DLLs and locales.
    • Locales are organized by language (e.g., en, zh-Hans) and use MD5-based subdirectories to allow multiple versions of the same resource files to coexist between different apps.
    • Native DLLs (srm_native) are not shared and must remain within each individual application's folder.
    • Each application maintains its own main folder containing its specific .deps.json, .dll, and .runtimeconfig.json files.
    ├── libraries                   # Shared runtime DLLs (customizable name)
    │   ├── locales                 # Satellite assemblies
    │   │   ├── en
    │   │   │   └── *.resources.dll
    │   │   │       ├── MD5_1       # Allows multiple runtimes between apps
    │   │   │       │   └── *.resources.dll
    │   │   │       └── MD5_2
    │   │   │           └── *.resources.dll
    │   │   └── ...
    │   ├── *.dll                   # Shared managed assemblies
    │   │   ├── MD5_1
    │   │   │   └── *.dll
    │   │   └── MD5_2
    │   │       └── *.dll
    │   └── srm_native              # Native DLLs (not shared; each app has its own copy)
    │       ├── APPID_1
    │       │   └── *.dll
    │       └── APPID_2
    │           └── *.dll
    ├── app1                        # Main folder for app1
    │   ├── hostfxr.dll ...
    │   ├── libloader.dll           # Loader (moved if using patch)
    │   ├── app1.deps.json
    │   ├── app1.dll
    │   ├── app1.exe
    │   ├── app1.runtimeconfig.json
    │   └── ...
    └── app2                        # Main folder for app2
        ├── hostfxr.dll ...
        ├── libloader.dll
        ├── app2.deps.json
        ├── app2.dll
        ├── app2.exe
        ├── app2.runtimeconfig.json
        └── ...
  2. Customize AppHost for Software Suites

    master

    NetBeauty 2 can patch the imprinted entry path of the AppHost to provide a cleaner, more user-friendly folder structure. This is particularly useful for software suites where you want the executable (.exe) to reside in the root directory alongside other applications, rather than inside a specific application folder.

    When using a customized AppHost, the application's main logic and dependencies are moved into a subfolder, but the .exe remains in the root, allowing it to launch the application from a centralized location.

    # Shared Runtime with Customized AppHost
    ├── libraries                   # Shared runtime DLLs (customizable name)
    ├── app1                        # Main folder for app1
    │   ├── hostfxr.dll ...
    │   ├── app1.deps.json
    │   ├── app1.dll
    │   ├── app1.runtimeconfig.json
    │   └── ...
    ├── app2                        # Main folder for app2
    │   ├── hostfxr.dll ...
    │   ├── app2.deps.json
    │   ├── app2.dll
    │   ├── app2.runtimeconfig.json
    │   └── ...
    ├── app1.exe
    └── app2.exe
  3. Install NetBeauty via NuGet

    master

    To integrate NetBeauty into a .NET Core project, add the nulastudio.NetBeauty package via NuGet. Once added, you can configure its behavior directly in your .csproj file. After configuration, NetBeauty runs automatically during dotnet build or dotnet publish.

    dotnet add package nulastudio.NetBeauty
  4. Configure NetBeauty in .csproj

    master

    NetBeauty is configured using MSBuild properties within your .csproj file. These properties allow you to control dependency directories, shared runtime modes, file exclusions, and more.

    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>netcoreapp3.0</TargetFramework>
      </PropertyGroup>
    
      <PropertyGroup>
        <!-- Disable NetBeauty (set to True to turn off all features). -->
        <DisableBeauty>False</DisableBeauty>
    
        <!-- Enable shared runtime mode (set to True to share libraries across apps). -->
        <BeautySharedRuntimeMode>False</BeautySharedRuntimeMode>
    
        <!-- Directory for dependencies; default is 'libraries'. Use quotes if the path contains spaces. -->
        <BeautyLibsDir Condition="$(BeautySharedRuntimeMode) == 'True'">../libraries</BeautyLibsDir>
        <BeautyLibsDir Condition="$(BeautySharedRuntimeMode) != 'True'">./libraries</BeautyLibsDir>
    
        <!-- DLLs you want to exclude from being moved (e.g., critical or custom files). -->
        <!-- <BeautyExcludes>dll1.dll;lib*;...</BeautyExcludes> -->
    
        <!-- Files to hide from end users (e.g., runtime or config files). Only supported on Windows. -->
        <!-- <BeautyHiddens>hostfxr;hostpolicy;*.deps.json;*.runtimeconfig*.json</BeautyHiddens> -->
    
        <!-- Only run NetBeauty on publish (set to True to skip on build). -->
        <BeautyOnPublishOnly>False</BeautyOnPublishOnly>
    
        <!-- Internal option: do not modify. -->
        <BeautyNoRuntimeInfo>False</BeautyNoRuntimeInfo>
    
        <!-- Loader version policy: auto, with, or without. -->
        <BeautyNBLoaderVerPolicy>auto</BeautyNBLoaderVerPolicy>
    
        <!-- Enable debugging support for third-party debuggers (e.g., dnSpy). -->
        <BeautyEnableDebugging>False</BeautyEnableDebugging>
    
        <!-- Use the patch to minimize file count (SCD mode only). Set to False to disable. -->
        <BeautyUsePatch>True</BeautyUsePatch>
    
        <!-- Customize AppHost entry point (relative to AppHostDir). See documentation for details. -->
        <!-- <BeautyAppHostEntry>bin/MyApp.dll</BeautyAppHostEntry> -->
    
        <!-- Customize AppHost directory (relative to BeautyDir). See documentation for details. -->
        <!-- <BeautyAppHostDir>..</BeautyAppHostDir> -->
    
        <!-- Specify custom MSBuild tasks to run after NetBeauty completes. -->
        <!-- <BeautyAfterTasks></BeautyAfterTasks> -->
    
        <!-- Log verbosity: Error, Detail, or Info. -->
        <BeautyLogLevel>Info</BeautyLogLevel>
    
        <!-- Use a mirror for GitHub resources if needed. -->
        <!-- <BeautyGitCDN>https://gitee.com/liesauer/HostFXRPatcher</BeautyGitCDN> -->
    
        <!-- Specify a branch or tag for the patcher repository. -->
        <!-- <BeautyGitTree>master</BeautyGitTree> -->
      </PropertyGroup>
    
      <ItemGroup>
        <PackageReference Include="nulastudio.NetBeauty" Version="2.1.5.0" />
      </ItemGroup>
    </Project>
  5. Prevent debugging using the --enabledebug option

    master

    NetBeauty includes an anti-debugging mechanism that can be activated via the --enabledebug option. When enabled, NetBeauty removes the mscordaccore and mscordbi libraries, which prevents the debugger from initializing.

    Note: This is a limited protection measure designed to deter specific groups of crackers. For robust security, it is recommended to combine this with static and runtime protections provided by professional software-protection tools.

    # Example usage of the anti-debugging flag
    # (Note: The exact command context depends on your NetBeauty implementation)
    [command] --enabledebug
  6. Use the NetBeauty CLI for published projects

    master

    If your project is already published, you can use the nbeauty2 binary to organize files. You can use the --hiddens option to hide specific files (like runtime or config files) from end users, though this is supported on Windows only and only hides the files rather than moving them.

    # Usage:
    nbeauty2 [--loglevel=(Error|Detail|Info)] [--srmode] [--enabledebug] [--usepatch] [--hiddens=hiddenFiles] [--noruntimeinfo] [--roll-forward=<rollForward>] [--nbloaderverpolicy=(auto|with|without)] [--apphostentry=<appHostEntry>] [--apphostdir=<appHostDir>] <beautyDir> [<libsDir> [<excludes>]]
    
    # Example:
    nbeauty2 --usepatch --loglevel Detail --hiddens "hostfxr;hostpolicy;*.deps.json;*.runtimeconfig*.json" "/path/to/publishDir" libraries "dll1.dll;lib*;..."
  7. Fix exe.config assembly bindings

    master

    For legacy or specific .NET configurations, use FixExeConfig to update the *.exe.config file. This function:

    • Adds missing assemblies to the <assemblyBinding> section.
    • Updates the <probing> element's privatePath to include the directory where your new libraries reside.
    • Scans the directory for additional .dll files and .resources.dll (satellite assemblies) to include them in the dependency list.
    // Fix exe.config and return the list of discovered dependencies
    deps, ok := manager.FixExeConfig("MyApp.exe.config", "./libs")
    if ok {
        for _, d := range deps {
            fmt.Printf("Found dependency: %s\n", d.Name)
        }
    }
  8. Modify runtimeconfig.json and deps.json

    master

    To integrate custom loaders or startup hooks into a .NET application, you can programmatically modify its configuration files:

    1. AddStartUpHookToDeps: Injects a startup hook into the deps.json file. It adds the hook to the targets and libraries sections so the runtime recognizes the new dependency.
    2. AddStartUpHookToRuntimeConfig: Sets the STARTUP_HOOKS property in runtimeconfig.json to trigger the hook during application startup.
    3. FixRuntimeConfig: A comprehensive function to update runtimeconfig.json with new library directories (NetBeautyLibsDir), probing paths, and Shared Runtime Mode (SRM) mappings.
    4. FixDeps: Analyzes and rewrites deps.json to ensure all necessary dependencies (Assemblies, Resources, or Native libs) are correctly mapped, especially when using a patch-based approach.
    // Add a startup hook to deps.json
    manager.AddStartUpHookToDeps("deps.json", "MyHook", "1.0.0")
    
    // Add a startup hook to runtimeconfig.json
    manager.AddStartUpHookToRuntimeConfig("runtimeconfig.json", "MyHook")
  9. Configure the default CDN

    master

    You can manage the default Content Delivery Network (CDN) used for downloading artifacts using the following functions:

    • SetCDN(cdn string) bool: Sets the default CDN URL by writing it to the configuration file.
    • GetCDN() string: Retrieves the current default CDN URL. Returns an empty string if no CDN is set.
    • DelCDN() bool: Removes the default CDN configuration.
    // Set a custom CDN
    SetCDN("https://my-custom-cdn.com")
    
    // Get the current CDN
    currentCdn := GetCDN()
  10. Extract FXR version from deps.json

    master

    The FindFXRVersion function parses a deps.json file to identify the HostFXR version and the Runtime Identifier (RID) used by the application. This is useful for determining which version of the runtime patch is required.

    It supports multiple pattern formats used by different .NET versions (2.x, 3.0.x, and ≥3.1.x).

    // Returns (version, rid)
    version, rid := manager.FindFXRVersion("deps.json")
    // Example output: "v3.1", "win-x64"
  11. Find a compatible RID for a given runtime

    master

    Use FindCompatibleRID(rid string) string to resolve a requested Runtime Identifier (RID) to a compatible RID supported by the online environment. It looks up the compatibility mapping from the internal runtime compatibility configuration. If no compatible RID is found, it returns an empty string.

    // Returns a compatible RID string if found
    compatibleRid := FindCompatibleRID("win-x64")