Obfuscating multiple runtimes

If you want to publish separate single-file applications for different runtimes, for example win-x64 and win-x86, you won't need two separate SmartAssembly project files as it's possible to set the assembly input and output paths automatically using MSBuild properties which are later passed to SmartAssembly. This can be achieved with a single SmartAssembly project (.saproj) when using MSBuild integration.

Step 1: Creating a SmartAssembly project

  1. Make sure your project is already built in Release mode.
  2. Open SmartAssembly.
  3. Click New Project.
  4. Click Browse Assembly.
  5. Navigate to your application's output directory, then choose the appropriate assembly (for example: \ConsoleApp\bin\Release\netcoreapp3.1\win-x64\ConsoleApp.dll) and click Open.

    If your application targets multiple runtimes (e.g. win-x64 and win-x86) you need to pick just one of them (either will work).

    This is just to set-up the SmartAssembly project. The exact paths matching all required runtimes will be adjusted at a later stage.

  6. Click Set Destination, pick the output location and click Save.

    You can pick any destination for your assembly. At this stage the goal is to make sure the assembly is built correctly with the protections enabled in SmartAssembly.

    The exact paths matching all required runtimes will be adjusted at a later stage.

  7. Configure the project as needed. Enable any protections your application may need.
  8. Click Save to save the project. It's recommended to save the project in the same location as Visual Studio's project file, under the same name (for example, if your application's project file is called ConsoleApp.csproj, then save the SmartAssembly project in the same directory as ConsoleApp.saproj).

"Dependencies Merging" and "Dependencies Embedding" should not be used when protecting a single-file assembly. Merging or embedding assemblies can result in unexpected behavior and isn't recommended for this type of applications.

Step 2: Integrating SmartAssembly into the publish process

  1. Open your application's project in Visual Studio.
  2. Right-click the project name and select Manage NuGet packages...
  3. Switch to the Browse tab.
  4. Type RedGate.SmartAssembly.MSBuild and click Install next to it.
  5. Add a target with any name that executes before a "BuildWithSmartAssembly" target, and:
    1. sets the property SmartAssemblyInput to $(TargetPath)
    2. sets the property SmartAssemblyOutput to $(IntermediateOutputPath)$(TargetName)$(TargetExt)

At the end, your application's project file should look something like this:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="RedGate.SmartAssembly.MSBuild" Version="7.4.0.3402">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>

  <!-- Add the following target: -->
  <Target Name="SetAssemblyPathsForSA" BeforeTargets="BuildWithSmartAssembly">
    <PropertyGroup>
      <SmartAssemblyInput>$(TargetPath)</SmartAssemblyInput>
      <SmartAssemblyOutput>$(IntermediateOutputPath)$(TargetName)$(TargetExt)</SmartAssemblyOutput>
    </PropertyGroup>
  </Target>
</Project>

Now let's issue the publish command for any desired runtime:

dotnet publish .\ConsoleApp.csproj -c Release -r win-x64 -p:PublishSingleFile=true
dotnet publish .\ConsoleApp.csproj -c Release -r win-x86 -p:PublishSingleFile=true

Because of the changes made to the project file, SmartAssembly will automatically use the correct input and output path for each target runtime.


Didn't find what you were looking for?