How to access binary before msbuild packs it to single file

I’m using ConfuserEx to obfuscate my app, but it requires whole .dll binary file.
So, is there a way to obfuscate it using cli and then pack it to single file, or
access binary before compressing it to single file, so i can obfuscate it

I tried to do exclude main binary by ExcludeFromSingleFile, but it didn’t work

My .crproj file

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <OutputType>exe</OutputType>
        <AssemblyName>jay-$(RuntimeIdentifier)</AssemblyName>
        <PublishSingleFile>true</PublishSingleFile>
        <IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
        <IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
        <TargetFramework>net5.0</TargetFramework>
    </PropertyGroup>

    <ItemGroup>
        <Content Update="$(AssemblyName).dll">
            <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
            <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
        </Content>
    </ItemGroup>

    <ItemGroup>
      <PackageReference Include="CloudFlareUtilities" Version="1.3.0" />
      <PackageReference Include="Colorful.Console" Version="1.2.15" />
      <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
      <PackageReference Include="YamlDotNet" Version="9.1.4" />
    </ItemGroup>

</Project>

Answer

You need to add it as a post-build event, for example:

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <OutputType>exe</OutputType>
        <AssemblyName>jay-$(RuntimeIdentifier)</AssemblyName>
        <PublishSingleFile>true</PublishSingleFile>
        <IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
        <IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
        <TargetFramework>net5.0</TargetFramework>
    </PropertyGroup>

    <!-- runs: TheAppToPassItTo.exe "<path to dll>" -->
    <Target Name="PostBuild" AfterTargets="PostBuildEvent">
      <Exec Command="TheAppToPassItTo.exe &quot;$(TargetPath)&quot;" />
    </Target>

    <ItemGroup>
      <PackageReference Include="CloudFlareUtilities" Version="1.3.0" />
      <PackageReference Include="Colorful.Console" Version="1.2.15" />
      <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
      <PackageReference Include="YamlDotNet" Version="9.1.4" />
    </ItemGroup>

</Project>

Edited To Add

So, it turns out that the new “single file” executable option doesn’t build it’s executable from the bin directory, but from the obj directory. This has to be a simple oversight from the .NET team. There are many times where you’d want to modify your executable code before packing it up. What you are asking for is not unreasonable.

We can accomplish this by implementing a kludge until this gets rectified. We will still use the “post-build” job, but we are going to do some string replacement to build the correct path to the executable you want to modify.

This is the new script:

@ECHO off
SET tp=$(TargetPath)
SET tp=%tp:bin=obj% 
ECHO Target file to modify: %tp%
YourObfuscatorEngine.exe "%tp%"

This will get the target path, in my case it is:

D:RepositoriesSourceConsoleApp2ConsoleApp2binReleasenetcoreapp3.1win-x64ConsoleApp2.dll

Then we do a string replace. We replace bin with obj. The path will then be:

D:RepositoriesSourceConsoleApp2ConsoleApp2objReleasenetcoreapp3.1win-x64ConsoleApp2.dll

Now when you call your obfuscator engine, it will modify the correct file.

Please keep in mind that if you turn on the PublishReadyToRun option, your path will change to:

D:RepositoriesSourceConsoleApp2ConsoleApp2objReleasenetcoreapp3.1win-x64R2RConsoleApp2.dll

Which will make this a tad more complicated. So just keep that in mind if you decide you want to do this.

At the end of the day, your post-build script will look like this:

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <OutputType>exe</OutputType>
        <AssemblyName>jay-$(RuntimeIdentifier)</AssemblyName>
        <PublishSingleFile>true</PublishSingleFile>
        <IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
        <IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
        <TargetFramework>net5.0</TargetFramework>
    </PropertyGroup>

  <Target Name="PostBuild" AfterTargets="PostBuildEvent">
    <Exec Command="@ECHO off&#xD;&#xA;SET tp=$(TargetPath)&#xD;&#xA;SET tp=%25tp:bin=obj%25 &#xD;&#xA;ECHO Target file to modify: %25tp%25&#xD;&#xA;YourObfuscatorEngine.exe &quot;%25tp%25&quot;" />
  </Target>

    <ItemGroup>
      <PackageReference Include="CloudFlareUtilities" Version="1.3.0" />
      <PackageReference Include="Colorful.Console" Version="1.2.15" />
      <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
      <PackageReference Include="YamlDotNet" Version="9.1.4" />
    </ItemGroup>

</Project>