diff --git a/.gitattributes b/.gitattributes
index b8bc1f360..45cf1e579 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1 +1,45 @@
-*.cs diff=csharp
+# Set default behavior, in case users don't have core.autocrlf set.
+* text=auto
+
+# Explicitly declare text files we want to always be normalized and converted
+# to native line endings on checkout.
+*.config text
+*.cs text diff=csharp
+*.manifest text
+*.md text
+*.resx text
+*.txt text
+*.xml text
+*.xaml text
+*.yml text
+*.yaml text
+*.json text
+*.props text
+*.targets text
+
+# Declare files that will always have CRLF line endings on checkout.
+*.csproj text eol=crlf
+*.dbproj text eol=crlf
+*.fsproj text eol=crlf
+*.inf text eol=crlf
+*.lsproj text eol=crlf
+*.modelproj text eol=crlf
+*.sln text eol=crlf
+*.sqlproj text eol=crlf
+*.vbproj text eol=crlf
+*.vcproj text eol=crlf
+*.vcxproj text eol=crlf
+*.wixproj text eol=crlf
+*.wmaproj text eol=crlf
+
+# Denote all files that are truly binary and should not be modified.
+*.apk binary
+*.dll binary
+*.exe binary
+*.ico binary
+*.jpeg binary
+*.jpg binary
+*.otf binary
+*.pdf binary
+*.png binary
+*.snk binary
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 722313b1e..8f5fcedcf 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -1 +1 @@
-@mkaring
+@mcpolo99
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index 4d2a236fb..694356132 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,3 +1 @@
-github: mkaring
-open_collective: confuserex
-custom: ['http://buymeacoff.ee/fFUnXMCdW']
+github: mcpolo99
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index 2c923a8ae..1b275dd3f 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -1,5 +1,11 @@
blank_issues_enabled: false
contact_links:
- name: Question
- url: https://github.com/mkaring/ConfuserEx/discussions/categories/q-a
- about: Ask and answer questions about ConfuserEx
+ url: https://github.com/mcpolo99/ConfuserExx/discussions/categories/q-a
+ about: Ask and answer questions about ConfuserExx
+ - name: Ideas & Feature Requests
+ url: https://github.com/mcpolo99/ConfuserExx/discussions/categories/ideas
+ about: Suggest new features or improvements
+ - name: General Discussion
+ url: https://github.com/mcpolo99/ConfuserExx/discussions/categories/general
+ about: Chat about anything related to ConfuserExx
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 50713d395..95bd54cb1 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -3,13 +3,21 @@ name: ci
on:
push:
branches: [master, pre-release, feature/**, fix/**]
+ paths-ignore: ['**.md', 'docs/**', 'LICENSE*']
pull_request:
branches: [master, pre-release]
+ paths-ignore: ['**.md', 'docs/**', 'LICENSE*']
+
+concurrency:
+ group: ci-${{ github.ref }}
+ cancel-in-progress: true
jobs:
build:
- runs-on: windows-2022
- timeout-minutes: 15
+ runs-on: windows-2025
+ timeout-minutes: 10
+ env:
+ NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
steps:
- uses: actions/checkout@v5
with:
@@ -18,14 +26,13 @@ jobs:
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v2
- - name: Install .NET 4.6.1 targeting pack
- shell: pwsh
- run: |
- $url = 'https://download.microsoft.com/download/F/1/D/F1DEB8DB-D277-4EF9-9F48-3A65D4D8F965/NDP461-DevPack-KB3105179-ENU.exe'
- $installer = "$env:TEMP\ndp461-devpack.exe"
- Invoke-WebRequest -Uri $url -OutFile $installer -UseBasicParsing
- Start-Process -FilePath $installer -ArgumentList '/quiet','/norestart' -Wait
- Write-Host "Installed .NET 4.6.1 Developer Pack"
+ - name: Cache NuGet packages
+ uses: actions/cache@v4
+ with:
+ path: ${{ github.workspace }}/.nuget/packages
+ key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/*.vcxproj') }}
+ restore-keys: |
+ ${{ runner.os }}-nuget-
- name: Install nbgv
run: dotnet tool install -g nbgv
@@ -47,7 +54,7 @@ jobs:
- name: Package CLI
shell: pwsh
run: |
- $src = 'Confuser.CLI/bin/Release/net461'
+ $src = 'Confuser.CLI/bin/Release/net10.0'
$zip = 'ConfuserEx-CLI.zip'
Get-ChildItem $src -Exclude '*.pdb','*.xml' | Compress-Archive -DestinationPath $zip
Write-Host "Created $zip ($([math]::Round((Get-Item $zip).Length / 1MB, 1)) MB)"
@@ -55,7 +62,7 @@ jobs:
- name: Package GUI
shell: pwsh
run: |
- $src = 'ConfuserEx/bin/Release/net461'
+ $src = 'ConfuserEx/bin/Release/net10.0-windows'
$zip = 'ConfuserEx-GUI.zip'
Get-ChildItem $src -Exclude '*.pdb','*.xml' | Compress-Archive -DestinationPath $zip
Write-Host "Created $zip ($([math]::Round((Get-Item $zip).Length / 1MB, 1)) MB)"
@@ -66,13 +73,13 @@ jobs:
$zip = 'ConfuserEx.zip'
$tmp = 'combined'
New-Item -ItemType Directory -Path $tmp -Force | Out-Null
- Copy-Item 'Confuser.CLI/bin/Release/net461/*' $tmp -Exclude '*.pdb','*.xml' -Recurse
- Copy-Item 'ConfuserEx/bin/Release/net461/*' $tmp -Exclude '*.pdb','*.xml' -Recurse -Force
+ Copy-Item 'Confuser.CLI/bin/Release/net10.0/*' $tmp -Exclude '*.pdb','*.xml' -Recurse
+ Copy-Item 'ConfuserEx/bin/Release/net10.0-windows/*' $tmp -Exclude '*.pdb','*.xml' -Recurse -Force
Get-ChildItem $tmp | Compress-Archive -DestinationPath $zip
Remove-Item $tmp -Recurse -Force
Write-Host "Created $zip ($([math]::Round((Get-Item $zip).Length / 1MB, 1)) MB)"
- - name: Upload artifacts
+ - name: Upload packages
uses: actions/upload-artifact@v5
with:
name: confuserex-packages
@@ -86,7 +93,7 @@ jobs:
pre-release:
needs: build
if: github.event_name == 'push' && github.ref == 'refs/heads/pre-release'
- runs-on: windows-2022
+ runs-on: windows-2025
timeout-minutes: 5
permissions:
contents: write
@@ -136,7 +143,7 @@ jobs:
release:
needs: build
if: github.event_name == 'push' && github.ref == 'refs/heads/master'
- runs-on: windows-2022
+ runs-on: windows-2025
timeout-minutes: 5
permissions:
contents: write
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index a187c29d2..ef22fb1f3 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -17,14 +17,14 @@ permissions:
jobs:
analyze:
name: Analyze
- runs-on: windows-2022
+ runs-on: windows-2025
strategy:
fail-fast: false
steps:
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
with:
fetch-depth: 0
submodules: recursive
@@ -37,14 +37,6 @@ jobs:
- name: Setup MSBuild
uses: microsoft/setup-msbuild@v2
- - name: Install .NET 4.6.1 targeting pack
- shell: pwsh
- run: |
- $url = 'https://download.microsoft.com/download/F/1/D/F1DEB8DB-D277-4EF9-9F48-3A65D4D8F965/NDP461-DevPack-KB3105179-ENU.exe'
- $installer = "$env:TEMP\ndp461-devpack.exe"
- Invoke-WebRequest -Uri $url -OutFile $installer -UseBasicParsing
- Start-Process -FilePath $installer -ArgumentList '/quiet','/norestart' -Wait
-
- name: Restore
run: msbuild Confuser2.sln -t:Restore -verbosity:minimal
diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml
new file mode 100644
index 000000000..112a45e48
--- /dev/null
+++ b/.github/workflows/format.yml
@@ -0,0 +1,35 @@
+name: format
+
+on:
+ pull_request:
+ branches: [master, pre-release]
+ paths: ['**.cs', '**.vb', '.editorconfig']
+
+jobs:
+ check-format:
+ runs-on: windows-2025
+ timeout-minutes: 5
+ permissions:
+ contents: read
+ steps:
+ - uses: actions/checkout@v5
+
+ - name: Check formatting
+ run: dotnet format Confuser2.sln --verify-no-changes --verbosity diagnostic
+ continue-on-error: true
+ id: format-check
+
+ - name: Format diff
+ if: steps.format-check.outcome == 'failure'
+ shell: pwsh
+ run: |
+ dotnet format Confuser2.sln
+ git diff --stat
+ $diff = git diff --name-only
+ if ($diff) {
+ Write-Host "::warning::The following files need formatting:" -ForegroundColor Yellow
+ $diff | ForEach-Object { Write-Host " $_" }
+ Write-Host ""
+ Write-Host "Run 'dotnet format Confuser2.sln' locally and commit the changes."
+ exit 1
+ }
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
new file mode 100644
index 000000000..fd44def14
--- /dev/null
+++ b/.github/workflows/test.yml
@@ -0,0 +1,198 @@
+name: test
+
+on:
+ push:
+ branches: [master, pre-release, feature/**, fix/**]
+ paths-ignore: ['**.md', 'docs/**', 'LICENSE*']
+ pull_request:
+ branches: [master, pre-release]
+ paths-ignore: ['**.md', 'docs/**', 'LICENSE*']
+
+concurrency:
+ group: test-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ test:
+ runs-on: windows-2025
+ timeout-minutes: 15
+ permissions:
+ contents: read
+ pull-requests: write
+ env:
+ NUGET_PACKAGES: ${{ github.workspace }}/.nuget/packages
+ steps:
+ - uses: actions/checkout@v5
+ with:
+ fetch-depth: 0
+
+ - name: Setup .NET runtimes for cross-framework tests
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: |
+ 6.0.x
+ 8.0.x
+
+ - name: Setup MSBuild
+ uses: microsoft/setup-msbuild@v2
+
+ - name: Cache NuGet packages
+ uses: actions/cache@v4
+ with:
+ path: ${{ github.workspace }}/.nuget/packages
+ key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/*.vcxproj') }}
+ restore-keys: |
+ ${{ runner.os }}-nuget-
+
+ - name: Restore
+ run: msbuild Confuser2.sln -t:Restore -verbosity:minimal
+
+ - name: Build
+ run: msbuild Confuser2.sln -p:Configuration=Release -verbosity:minimal
+
+ - name: Run tests with coverage
+ id: tests
+ shell: pwsh
+ run: |
+ $resultsDir = 'test-results'
+ New-Item -ItemType Directory -Path $resultsDir -Force | Out-Null
+
+ $testProjects = Get-ChildItem -Path Tests -Filter '*.Test.csproj' -Recurse | Select-Object -Unique
+ $anyFailed = $false
+
+ foreach ($proj in $testProjects) {
+ $name = $proj.BaseName
+ Write-Host "`nTesting $name..." -ForegroundColor Cyan
+
+ dotnet test $proj.FullName -c Release --no-build --verbosity minimal `
+ --collect:"XPlat Code Coverage" `
+ --logger "trx;LogFileName=$name.trx" `
+ --results-directory "$resultsDir/$name"
+
+ if ($LASTEXITCODE -ne 0) { $anyFailed = $true }
+ }
+
+ # Parse TRX files
+ $allTests = @()
+ foreach ($trx in (Get-ChildItem -Path $resultsDir -Filter '*.trx' -Recurse)) {
+ [xml]$xml = Get-Content $trx.FullName
+ $ns = @{ t = 'http://microsoft.com/schemas/VisualStudio/TeamTest/2010' }
+ foreach ($r in (Select-Xml -Xml $xml -XPath '//t:UnitTestResult' -Namespace $ns)) {
+ $node = $r.Node
+ $errorMsg = ''
+ if ($node.Output -and $node.Output.ErrorInfo) { $errorMsg = $node.Output.ErrorInfo.Message }
+ $allTests += [PSCustomObject]@{
+ Name = $node.testName; Outcome = $node.outcome
+ Duration = $node.duration; Error = $errorMsg; TrxFile = $trx.BaseName
+ }
+ }
+ }
+
+ $passed = ($allTests | Where-Object { $_.Outcome -eq 'Passed' }).Count
+ $failed = $allTests | Where-Object { $_.Outcome -eq 'Failed' }
+
+ # Build markdown
+ $md = @('## Test Results', '')
+ if ($failed.Count -gt 0) {
+ $md += "> :x: **$($failed.Count) test(s) failed** out of $($allTests.Count) total"
+ } else {
+ $md += "> :white_check_mark: **All $passed tests passed**"
+ }
+ $md += ''
+ $md += '| Project | :white_check_mark: | :x: | Total |'
+ $md += '|---------|--------|--------|-------|'
+ foreach ($g in ($allTests | Group-Object TrxFile | Sort-Object Name)) {
+ $p = ($g.Group | Where-Object { $_.Outcome -eq 'Passed' }).Count
+ $f = ($g.Group | Where-Object { $_.Outcome -eq 'Failed' }).Count
+ $icon = if ($f -gt 0) { ':x:' } else { ':white_check_mark:' }
+ $md += "| $icon $($g.Name) | $p | $f | $($g.Group.Count) |"
+ }
+
+ # Cross-framework details
+ $crossTests = $allTests | Where-Object { $_.Name -match 'Console_Net|WinForms_Net|WPF_Net|Library_Net' }
+ if ($crossTests.Count -gt 0) {
+ $md += '', 'Cross-Framework Details
', ''
+ $md += '| Test | TFM | Type | Result |'
+ $md += '|------|-----|------|--------|'
+ foreach ($t in ($crossTests | Sort-Object Name)) {
+ $icon = if ($t.Outcome -eq 'Passed') { ':white_check_mark:' } else { ':x:' }
+ $tfm = ''; $appType = ''
+ if ($t.Name -match '_Net(\w+)_') { $tfm = $Matches[1] }
+ if ($t.Name -match '(Console|WinForms|WPF|Library)_') { $appType = $Matches[1] }
+ $md += "| ``$($t.Name)`` | $tfm | $appType | $icon |"
+ }
+ $md += '', ' '
+ }
+
+ # Failed details
+ if ($failed.Count -gt 0) {
+ $md += '', '### :x: Failed Tests', ''
+ foreach ($f in $failed) {
+ $md += "**``$($f.Name)``**"
+ if ($f.Error) {
+ $short = ($f.Error -split "`n")[0]
+ if ($short.Length -gt 200) { $short = $short.Substring(0, 200) + '...' }
+ $md += "> $short"
+ }
+ $md += ''
+ }
+ }
+
+ $md -join "`n" | Set-Content -Path 'test-results.md' -Encoding utf8
+ $md -join "`n" >> $env:GITHUB_STEP_SUMMARY
+ echo "any_failed=$anyFailed" >> $env:GITHUB_OUTPUT
+
+ - name: Generate coverage report
+ if: always()
+ shell: pwsh
+ run: |
+ dotnet tool install -g dotnet-reportgenerator-globaltool
+ $reports = (Get-ChildItem -Path test-results -Filter 'coverage.cobertura.xml' -Recurse).FullName -join ';'
+ if ($reports) {
+ reportgenerator "-reports:$reports" "-targetdir:coverage/report" "-reporttypes:HtmlInline_AzurePipelines;Cobertura;TextSummary;MarkdownSummaryGithub"
+ Get-Content coverage/report/Summary.txt
+ "`n---`n" >> $env:GITHUB_STEP_SUMMARY
+ Get-Content coverage/report/SummaryGithub.md >> $env:GITHUB_STEP_SUMMARY
+ }
+
+ - name: Post PR comment
+ if: always() && github.event_name == 'pull_request'
+ shell: pwsh
+ run: |
+ $comment = @()
+ if (Test-Path 'test-results.md') { $comment += Get-Content 'test-results.md' -Raw }
+ if (Test-Path 'coverage/report/SummaryGithub.md') {
+ $comment += "`n---`n"
+ $comment += Get-Content 'coverage/report/SummaryGithub.md' -Raw
+ }
+ $comment -join "`n" | Set-Content -Path 'pr-comment.md' -Encoding utf8
+
+ - name: Post PR comment (sticky)
+ if: always() && github.event_name == 'pull_request'
+ uses: marocchino/sticky-pull-request-comment@v2
+ with:
+ header: test-coverage-report
+ path: pr-comment.md
+
+ - name: Upload test results
+ if: always()
+ uses: actions/upload-artifact@v5
+ with:
+ name: test-results
+ path: test-results/
+ if-no-files-found: ignore
+
+ - name: Upload coverage report
+ if: always()
+ uses: actions/upload-artifact@v5
+ with:
+ name: coverage-report
+ path: coverage/report/
+ if-no-files-found: ignore
+
+ - name: Fail if tests failed
+ if: always() && steps.tests.outputs.any_failed == 'True'
+ shell: pwsh
+ run: |
+ Write-Host "::error::Tests failed."
+ exit 1
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index a26c85519..42a023fc3 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,23 +1,136 @@
-# Contributing
+# Contributing to ConfuserExx
-Contributions of any kind are in general always welcome.
+Contributions of any kind are welcome. For bugfixes and unit tests, you can submit a PR directly. For larger changes, please open an issue first to discuss the approach.
-When contributing to this repository, please first discuss the changes you wish
-to make via issue, email, discussions, or any other method with the owners of
-this repository before making a change.
+## Getting Started
-For contributions that contain only bugfixes or added unit tests, this
-discussion is not required before hand.
+1. Fork the repository
+2. Create a feature branch from `pre-release`: `git checkout -b feat/my-feature pre-release`
+3. Make your changes and ensure CI passes
+4. Open a PR targeting `pre-release`
-Please note we have a code of conduct, please follow it in all your
-interactions with the project.
+See [README.md](README.md#building-from-source) for build prerequisites.
+
+## Testing Policy
+
+Every PR must maintain or improve test coverage. We use a **ratchet strategy** — coverage only goes up, never down.
+
+### Coverage Targets
+
+| Assembly | Current Goal | Long-term Goal |
+|----------|-------------|----------------|
+| Confuser.Core | 40% | 70% |
+| Confuser.CLI | 50% | 70% |
+| Confuser.Protections | 30% | 60% |
+| Confuser.Renamer | 30% | 60% |
+| Confuser.DynCipher | 20% | 50% |
+
+These targets will be raised as coverage improves. CI reports coverage on every PR — check the comment.
+
+### What Must Be Tested
+
+**Always test:**
+- New protection implementations (integration test: obfuscate + run + verify)
+- Bug fixes (regression test proving the fix works)
+- Assembly resolution and path handling logic
+- CLI argument parsing and error handling
+- Project file (`.crproj`) parsing edge cases
+
+**Don't need tests:**
+- Simple property getters/setters
+- WPF UI layout or styling changes
+- Third-party library behavior (dnlib, CommunityToolkit)
+
+### Test Types
+
+| Type | Location | Framework | Purpose |
+|------|----------|-----------|---------|
+| Unit tests | `Tests/Confuser.Core.Test/` | xunit + Moq | Test individual classes in isolation |
+| Unit tests | `Tests/Confuser.Renamer.Test/` | xunit + Moq | Test renaming logic |
+| CLI e2e | `Tests/Confuser.CLI.Test/` | xunit | End-to-end CLI obfuscation |
+| GUI smoke | `Tests/Confuser.GUI.Test/` | xunit + FlaUI | WPF UI automation |
+| Integration | `Tests/*_*.Test/` | xunit | Obfuscate sample app, run it, verify output |
+
+### Writing a New Integration Test
+
+Each integration test has two projects:
+- **Subject** (`Tests/MyFeature/`): Small .NET Framework console app that prints `START`, some output, `END`, and returns exit code `42`
+- **Test** (`Tests/MyFeature.Test/`): References `Confuser.UnitTest` and the subject, calls `Run()` with the desired protections
+
+```csharp
+public class MyFeatureTest : TestBase {
+ public MyFeatureTest(ITestOutputHelper outputHelper) : base(outputHelper) { }
+
+ [Fact]
+ public Task MyProtection_SampleApp_RunsCorrectly() =>
+ Run("MyFeature.exe",
+ new[] { "expected output line" },
+ new SettingItem("my-protection-id"));
+}
+```
+
+### Writing a Unit Test
+
+```csharp
+[Fact]
+public void MethodName_Condition_ExpectedResult() {
+ // Arrange
+ var sut = new MyService();
+
+ // Act
+ var result = sut.DoSomething(input);
+
+ // Assert
+ Assert.Equal(expected, result);
+}
+```
+
+Test names follow `MethodName_Condition_ExpectedResult` convention.
+
+### Running Tests Locally
+
+```bash
+# All tests
+dotnet test Confuser2.sln -c Release
+
+# Specific test project
+dotnet test Tests/Confuser.CLI.Test/Confuser.CLI.Test.csproj -c Release
+
+# With coverage
+dotnet test Tests/Confuser.CLI.Test/Confuser.CLI.Test.csproj -c Release --collect:"XPlat Code Coverage"
+```
+
+### Coverage Reporting
+
+Every PR receives an automatic coverage comment showing per-assembly line and branch coverage. The full HTML drill-down report is downloadable as the `coverage-report` artifact from the test workflow.
+
+## Commit Conventions
+
+We use [Conventional Commits](https://www.conventionalcommits.org/):
+
+```
+feat(scope): add new feature
+fix(scope): fix a bug
+test(scope): add or update tests
+refactor(scope): code change that doesn't fix a bug or add a feature
+chore(scope): build, CI, dependency updates
+docs(scope): documentation changes
+```
+
+Always reference the issue number: `fix(renamer): handle FnPtr types (#6)`
## Pull Request Process
-1. Ensure that only the files that are part of your change are actually part of
- the pull request. Changes in unrelated files, unrelated additional files or
- binaries have to be removed.
-2. In case the pull request is created in response to a specific issue, please
- reference the issue in the description of the pull request.
-3. Pull-Requests are merged once they are signed-off by one other developer
- with the permission to merge changes into the repository.
+1. PRs target `pre-release`, not `master`
+2. CI must pass (build + tests + coverage)
+3. Coverage must not decrease
+4. Only include files that are part of your change — no unrelated modifications
+5. Reference the issue in the PR description
+6. If fixing a community-reported issue, tag the reporter to test
+7. Push fixes to the **same branch** — never close and create a replacement PR
+
+## Code Quality
+
+- Roslyn analyzers (NetAnalyzers + Roslynator) run during build — resolve all warnings
+- No `ResolveThrow` calls in new code — use null-safe `Resolve` + handle null
+- Follow existing code style (tabs, braces on same line, etc.)
diff --git a/Confuser.CLI/Confuser.CLI.csproj b/Confuser.CLI/Confuser.CLI.csproj
index 82743f158..d087b4871 100644
--- a/Confuser.CLI/Confuser.CLI.csproj
+++ b/Confuser.CLI/Confuser.CLI.csproj
@@ -4,7 +4,7 @@
Exe
- net461
+ net10.0
true
..\ConfuserEx.snk
@@ -24,6 +24,14 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/Confuser.CLI/Program.cs b/Confuser.CLI/Program.cs
index e7fac24a3..aff59c47c 100644
--- a/Confuser.CLI/Program.cs
+++ b/Confuser.CLI/Program.cs
@@ -13,8 +13,11 @@ internal class Program {
static int Main(string[] args) {
ConsoleColor original = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.White;
- string originalTitle = Console.Title;
- Console.Title = "ConfuserEx";
+ string originalTitle = null;
+ if (OperatingSystem.IsWindows()) {
+ originalTitle = Console.Title;
+ Console.Title = "ConfuserEx";
+ }
try {
bool noPause = false;
bool debug = false;
@@ -138,7 +141,8 @@ static int Main(string[] args) {
}
finally {
Console.ForegroundColor = original;
- Console.Title = originalTitle;
+ if (OperatingSystem.IsWindows() && originalTitle != null)
+ Console.Title = originalTitle;
}
}
diff --git a/Confuser.Core/API/APIStore.cs b/Confuser.Core/API/APIStore.cs
index b024aebf2..9cd06ef26 100644
--- a/Confuser.Core/API/APIStore.cs
+++ b/Confuser.Core/API/APIStore.cs
@@ -50,8 +50,8 @@ public IOpaquePredicateDescriptor GetPredicate(MethodDef method, OpaquePredicate
random.Shuffle(randomPredicates);
foreach (var predicate in randomPredicates) {
if (predicate.IsUsable(method) &&
- (type == null || predicate.Type == type.Value) &&
- (argCount == null || Array.IndexOf(argCount, predicate.ArgumentCount) != -1))
+ (type == null || predicate.Type == type.Value) &&
+ (argCount == null || Array.IndexOf(argCount, predicate.ArgumentCount) != -1))
return predicate;
}
return null;
@@ -95,4 +95,4 @@ public interface IAPIStore {
/// The suitable opaque predicate if found, or null if not found.
IOpaquePredicateDescriptor GetPredicate(MethodDef method, OpaquePredicateType? type, params int[] argCount);
}
-}
\ No newline at end of file
+}
diff --git a/Confuser.Core/API/IDataStore.cs b/Confuser.Core/API/IDataStore.cs
index e8aa12f3a..c96e70889 100644
--- a/Confuser.Core/API/IDataStore.cs
+++ b/Confuser.Core/API/IDataStore.cs
@@ -50,4 +50,4 @@ public interface IDataStoreAccessor {
/// An instruction sequence that returns the stored data.
Instruction[] Emit();
}
-}
\ No newline at end of file
+}
diff --git a/Confuser.Core/API/IOpaquePredicate.cs b/Confuser.Core/API/IOpaquePredicate.cs
index a1eef14b5..9f3b44129 100644
--- a/Confuser.Core/API/IOpaquePredicate.cs
+++ b/Confuser.Core/API/IOpaquePredicate.cs
@@ -76,4 +76,4 @@ public enum OpaquePredicateType {
///
Invariant
}
-}
\ No newline at end of file
+}
diff --git a/Confuser.Core/Annotations.cs b/Confuser.Core/Annotations.cs
index 5e2056d30..9b778b98f 100644
--- a/Confuser.Core/Annotations.cs
+++ b/Confuser.Core/Annotations.cs
@@ -189,4 +189,4 @@ public WeakReferenceKey(object target)
public int HashCode { get; private set; }
}
}
-}
\ No newline at end of file
+}
diff --git a/Confuser.Core/Confuser.Core.csproj b/Confuser.Core/Confuser.Core.csproj
index 0aed428c8..0e13ac77c 100644
--- a/Confuser.Core/Confuser.Core.csproj
+++ b/Confuser.Core/Confuser.Core.csproj
@@ -4,7 +4,7 @@
- net461;netstandard2.0
+ net48;netstandard2.0
true
..\ConfuserEx.snk
@@ -18,7 +18,6 @@
-
diff --git a/Confuser.Core/ConfuserAssemblyResolver.cs b/Confuser.Core/ConfuserAssemblyResolver.cs
index 0b6a39da3..500d3f92e 100644
--- a/Confuser.Core/ConfuserAssemblyResolver.cs
+++ b/Confuser.Core/ConfuserAssemblyResolver.cs
@@ -84,7 +84,7 @@ public void Clear() {
InternalFuzzyResolver.Clear();
}
- public IEnumerable GetCachedAssemblies() =>
+ public IEnumerable GetCachedAssemblies() =>
InternalExactResolver.GetCachedAssemblies().Concat(InternalFuzzyResolver.GetCachedAssemblies());
public void AddToCache(ModuleDefMD modDef) {
@@ -105,13 +105,13 @@ private sealed class TeeList : IList {
///
public void Add(string item) {
- foreach (var list in _lists)
+ foreach (var list in _lists)
list.Add(item);
}
///
public void Clear() {
- foreach (var list in _lists)
+ foreach (var list in _lists)
list.Clear();
}
@@ -136,13 +136,13 @@ public bool Remove(string item) =>
///
public void Insert(int index, string item) {
- foreach (var list in _lists)
+ foreach (var list in _lists)
list.Insert(index, item);
}
///
public void RemoveAt(int index) {
- foreach (var list in _lists)
+ foreach (var list in _lists)
list.RemoveAt(index);
}
diff --git a/Confuser.Core/ConfuserComponent.cs b/Confuser.Core/ConfuserComponent.cs
index 105211392..7d554c6f5 100644
--- a/Confuser.Core/ConfuserComponent.cs
+++ b/Confuser.Core/ConfuserComponent.cs
@@ -41,4 +41,4 @@ public abstract class ConfuserComponent {
/// The processing pipeline.
protected internal abstract void PopulatePipeline(ProtectionPipeline pipeline);
}
-}
\ No newline at end of file
+}
diff --git a/Confuser.Core/ConfuserContext.cs b/Confuser.Core/ConfuserContext.cs
index 94092bec1..a8c7a1c76 100644
--- a/Confuser.Core/ConfuserContext.cs
+++ b/Confuser.Core/ConfuserContext.cs
@@ -166,7 +166,7 @@ public NativeModuleWriterOptions RequestNative(bool optimizeImageSize) {
return null;
if (CurrentModuleWriterOptions == null)
CurrentModuleWriterOptions = new NativeModuleWriterOptions(CurrentModule, optimizeImageSize);
-
+
// Clone the current options to the new options
var newOptions = new NativeModuleWriterOptions(CurrentModule, optimizeImageSize) {
AddCheckSum = CurrentModuleWriterOptions.AddCheckSum,
diff --git a/Confuser.Core/ConfuserEngine.cs b/Confuser.Core/ConfuserEngine.cs
index 2b90fb315..a4e737cce 100644
--- a/Confuser.Core/ConfuserEngine.cs
+++ b/Confuser.Core/ConfuserEngine.cs
@@ -11,11 +11,11 @@
using dnlib.DotNet.Emit;
using dnlib.DotNet.Writer;
using Microsoft.Win32;
-using InformationalAttribute = System.Reflection.AssemblyInformationalVersionAttribute;
-using ProductAttribute = System.Reflection.AssemblyProductAttribute;
using CopyrightAttribute = System.Reflection.AssemblyCopyrightAttribute;
+using InformationalAttribute = System.Reflection.AssemblyInformationalVersionAttribute;
using MethodAttributes = dnlib.DotNet.MethodAttributes;
using MethodImplAttributes = dnlib.DotNet.MethodImplAttributes;
+using ProductAttribute = System.Reflection.AssemblyProductAttribute;
using TypeAttributes = dnlib.DotNet.TypeAttributes;
namespace Confuser.Core {
@@ -93,7 +93,7 @@ static void RunInternal(ConfuserParameters parameters, CancellationToken token)
new SettingItem(WatermarkingProtection._Id)
});
- var asmResolver = new ConfuserAssemblyResolver {EnableTypeDefCache = true};
+ var asmResolver = new ConfuserAssemblyResolver { EnableTypeDefCache = true };
asmResolver.DefaultModuleContext = new ModuleContext(asmResolver);
context.InternalResolver = asmResolver;
context.BaseDirectory = Path.GetFullPath(context.Project.BaseDirectory).TrimEnd(Path.DirectorySeparatorChar) + Path.DirectorySeparatorChar;
@@ -320,7 +320,7 @@ static void CheckStrongName(ConfuserContext context, ModuleDef module) {
else if (isKeyProvided && !moduleIsSignedOrDelayedSigned)
context.Logger.WarnFormat("[{0}] SN Key or SN public Key is provided for an unsigned module, the output may not be working.", module.Name);
else if (snPubKeyBytes != null && moduleIsSignedOrDelayedSigned &&
- !module.Assembly.PublicKey.Data.SequenceEqual(snPubKeyBytes))
+ !module.Assembly.PublicKey.Data.SequenceEqual(snPubKeyBytes))
context.Logger.WarnFormat("[{0}] Provided SN public Key and signed module's public key do not match, the output may not be working.",
module.Name);
}
@@ -375,7 +375,7 @@ static void BeginModule(ConfuserContext context) {
}
}
- static void ProcessModule(ConfuserContext context) =>
+ static void ProcessModule(ConfuserContext context) =>
context.CurrentModuleWriterOptions.WriterEvent += (sender, e) => context.CheckCancellation();
static void OptimizeMethods(ConfuserContext context) {
@@ -396,7 +396,8 @@ static void EndModule(ConfuserContext context) {
context.Logger.WarnFormat("Input file is not inside the base directory. Relative path can't be created. Placing file into output root." +
Environment.NewLine + "Responsible file is: {0}", output);
output = Path.GetFileName(output);
- } else {
+ }
+ else {
output = relativeOutput;
}
}
diff --git a/Confuser.Core/ConfuserParameters.cs b/Confuser.Core/ConfuserParameters.cs
index ad30f8bab..f3e05a2c1 100644
--- a/Confuser.Core/ConfuserParameters.cs
+++ b/Confuser.Core/ConfuserParameters.cs
@@ -56,4 +56,4 @@ internal Marker GetMarker() {
return Marker ?? new ObfAttrMarker();
}
}
-}
\ No newline at end of file
+}
diff --git a/Confuser.Core/CoreComponent.cs b/Confuser.Core/CoreComponent.cs
index 7ae6d7a82..31ca4b15e 100644
--- a/Confuser.Core/CoreComponent.cs
+++ b/Confuser.Core/CoreComponent.cs
@@ -42,11 +42,9 @@ public class CoreComponent : ConfuserComponent {
readonly Marker marker;
readonly ConfuserContext _context;
-
///
/// Initializes a new instance of the class.
///
- /// The parameters.
/// The marker.
internal CoreComponent(ConfuserContext context, Marker marker) {
_context = context;
diff --git a/Confuser.Core/DependencyResolver.cs b/Confuser.Core/DependencyResolver.cs
index c7c694525..8c0bca6a3 100644
--- a/Confuser.Core/DependencyResolver.cs
+++ b/Confuser.Core/DependencyResolver.cs
@@ -146,4 +146,4 @@ internal CircularDependencyException(Protection a, Protection b)
///
public Protection ProtectionB { get; private set; }
}
-}
\ No newline at end of file
+}
diff --git a/Confuser.Core/DnlibUtils.cs b/Confuser.Core/DnlibUtils.cs
index 7570da946..440b1af97 100644
--- a/Confuser.Core/DnlibUtils.cs
+++ b/Confuser.Core/DnlibUtils.cs
@@ -544,7 +544,7 @@ public static bool IsEntryPoint(this TypeDef typeDef) {
return typeDef == typeDef.Module.EntryPoint?.DeclaringType;
}
-
+
///
/// Merges a specified call instruction into the body.
///
diff --git a/Confuser.Core/Helpers/ControlFlowGraph.cs b/Confuser.Core/Helpers/ControlFlowGraph.cs
index 54127be3b..aeea27dfa 100644
--- a/Confuser.Core/Helpers/ControlFlowGraph.cs
+++ b/Confuser.Core/Helpers/ControlFlowGraph.cs
@@ -91,7 +91,7 @@ void PopulateBlockHeaders(HashSet blockHeaders, HashSet {1} {2}", Id, Type, string.Join(", ", Targets.Select(block => block.Id.ToString()).ToArray()));
}
}
-}
\ No newline at end of file
+}
diff --git a/Confuser.Core/Helpers/InjectHelper.cs b/Confuser.Core/Helpers/InjectHelper.cs
index 6cb066c23..6c5f931fe 100644
--- a/Confuser.Core/Helpers/InjectHelper.cs
+++ b/Confuser.Core/Helpers/InjectHelper.cs
@@ -99,7 +99,7 @@ static void CopyMethodDef(MethodDef methodDef, InjectContext ctx) {
newMethodDef.Signature = ctx.Importer.Import(methodDef.Signature);
newMethodDef.Parameters.UpdateParameterTypes();
-
+
foreach (var paramDef in methodDef.ParamDefs)
newMethodDef.ParamDefs.Add(new ParamDefUser(paramDef.Name, paramDef.Sequence, paramDef.Attributes));
@@ -112,16 +112,14 @@ static void CopyMethodDef(MethodDef methodDef, InjectContext ctx) {
if (methodDef.HasBody)
CopyMethodBody(methodDef, ctx, newMethodDef);
}
-
- static void CopyMethodBody(MethodDef methodDef, InjectContext ctx, MethodDef newMethodDef)
- {
+
+ static void CopyMethodBody(MethodDef methodDef, InjectContext ctx, MethodDef newMethodDef) {
newMethodDef.Body = new CilBody(methodDef.Body.InitLocals, new List(),
- new List(), new List()) {MaxStack = methodDef.Body.MaxStack};
+ new List(), new List()) { MaxStack = methodDef.Body.MaxStack };
var bodyMap = new Dictionary