Sitelet https://github.com/NLog/NLog/pull/6148
Skip to content

AppEnvironmentWrapper - Return Unknown_ProcessId when empty ProcessName - #6148

Merged
snakefoot merged 2 commits into
NLog:devfrom
snakefoot:CurrentProcessBaseName
Aug 11, 2026
Merged

snakefoot merged 2 commits into
NLog:devfrom
snakefoot:CurrentProcessBaseName

Conversation

@snakefoot

@snakefoot snakefoot commented Apr 10, 2026 •

Copy link
Copy Markdown
Contributor

Mostly for restricted platforms (Ex. Android / iOS / etc.)

  • Waiting for NLog v6.2

Added ${basedir} as fallback for ${processdir} to increase chance of working on Linux.

@snakefoot snakefoot added breaking behavior change Same API, different result enhancement Improvement on existing feature labels Apr 10, 2026
@coderabbitai

coderabbitai Bot commented Apr 10, 2026 •

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Lookup helpers in AppEnvironmentWrapper now return nullable strings instead of the "[unknown]" sentinel; public properties synthesize defaults (entry-assembly filename from process base name, process-name fallback using PID) and an extra assembly-file-path fallback was added for entry/process resolution.

Changes

Cohort / File(s) Summary
App environment lookups
src/NLog/Internal/AppEnvironmentWrapper.cs
Removed UnknownProcessName sentinel and changed several lookup helpers to return string?. EntryAssemblyFileName now uses LookupEntryAssemblyFileName() ?? (CurrentProcessBaseName + ".dll"). CurrentProcessBaseName uses LookupCurrentProcessNameWithFallback() ?? $"Unknown_ProcessId_{CurrentProcessId}". LookupCurrentProcessNameWithFallback() now returns null on final failure and resolves name in order: managed process name → file-path-derived name → entry-assembly-friendly name; native helper removed and native/path logic inlined. LookupCurrentProcessFilePathWithFallback() adds fallback to AssemblyHelpers.GetAssemblyFileLocation(Assembly.GetEntryAssembly()). LookupAppDomainFriendlyName() now returns string?; AppDomainFriendlyName still falls back to CurrentProcessBaseName.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped through lookups, keen and spry,
I dropped the sentinel and let nulls fly,
When names go missing, I craft a .dll,
I probe assembly paths and stitch them well —
A tidy rabbit's fix, then off I fly.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the main change: modifying AppEnvironmentWrapper to return Unknown_ProcessId when process name lookup fails.
Description check ✅ Passed The PR description mentions fallbacks and platform support, which aligns with the changeset's refactoring of helper methods to return null and synthesize defaults, including a new 'Unknown_ProcessId' pattern for process name resolution.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@snakefoot snakefoot closed this Apr 11, 2026
@snakefoot snakefoot reopened this Apr 11, 2026
@snakefoot snakefoot changed the title AppEnvironmentWrapper - Return Unknown_ProcessId when failing to lookup ProcessName AppEnvironmentWrapper - Return Unknown_ProcessId when failing to resolve ProcessName Apr 11, 2026
@snakefoot snakefoot changed the title AppEnvironmentWrapper - Return Unknown_ProcessId when failing to resolve ProcessName AppEnvironmentWrapper - Return Unknown_ProcessId when empty ProcessName Apr 11, 2026
@snakefoot snakefoot closed this Apr 11, 2026
@snakefoot snakefoot reopened this Apr 11, 2026
@pull-request-size pull-request-size Bot added size/M and removed size/S labels Apr 13, 2026
@snakefoot
snakefoot force-pushed the CurrentProcessBaseName branch from f80f850 to 189f5f1 Compare April 13, 2026 18:48

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/NLog/Internal/AppEnvironmentWrapper.cs (1)

414-425: ⚠️ Potential issue | 🟠 Major

Use the native file-path fallback before giving up on the process name.

Line 416 only consults LookupCurrentProcessFilePath(). On Windows/.NET Framework, Process.MainModule.FileName can fail while LookupCurrentProcessFilePathNative() still succeeds, so CurrentProcessFilePath resolves but CurrentProcessBaseName still falls through to Unknown_ProcessId_*.

🐛 Proposed fix
 private static string? LookupCurrentProcessNameNative()
 {
     var currentProcessFilePath = LookupCurrentProcessFilePath();
+    if (string.IsNullOrEmpty(currentProcessFilePath))
+        currentProcessFilePath = LookupCurrentProcessFilePathNative();
     if (!string.IsNullOrEmpty(currentProcessFilePath))
     {
         var currentProcessName = Path.GetFileNameWithoutExtension(currentProcessFilePath);
         if (!string.IsNullOrEmpty(currentProcessName))
             return currentProcessName;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/NLog/Internal/AppEnvironmentWrapper.cs` around lines 414 - 425, The
fallback logic in LookupCurrentProcessNameNative prematurely gives up on finding
a process name by only calling LookupCurrentProcessFilePath(); update
LookupCurrentProcessNameNative to also call LookupCurrentProcessFilePathNative()
(or check CurrentProcessFilePath which may already use the native resolver)
before falling back to LookupEntryAssemblyFileName() so that on Windows/.NET
Framework the native file-path is consulted and used to derive
currentProcessName (affecting CurrentProcessFilePath/CurrentProcessBaseName
resolution).
🧹 Nitpick comments (1)
src/NLog/Internal/AppEnvironmentWrapper.cs (1)

233-242: Reuse LookupEntryAssemblyFriendlyName() instead of reimplementing it.

Lines 374-379 now duplicate the basename extraction that already lives in LookupEntryAssemblyFriendlyName(). Keeping that normalization in one helper will make future fallback tweaks less error-prone.

♻️ Proposed refactor
-                processName = LookupEntryAssemblyFileName();
-                if (!string.IsNullOrEmpty(processName))
-                {
-                    var friendlyName = Path.GetFileNameWithoutExtension(processName);
-                    return string.IsNullOrEmpty(friendlyName) ? processName : friendlyName;
-                }
+                processName = LookupEntryAssemblyFriendlyName();
+                if (!string.IsNullOrEmpty(processName))
+                    return processName;

Also applies to: 374-379

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/NLog/Internal/AppEnvironmentWrapper.cs` around lines 233 - 242, Replace
the duplicated basename extraction with a call to the existing helper
LookupEntryAssemblyFriendlyName(): locate the block that manually computes
Path.GetFileNameWithoutExtension(fileName) (the duplicate logic present around
the other assembly lookup) and remove the reimplementation, invoking
LookupEntryAssemblyFriendlyName() instead and returning its result (or handling
its null) so normalization is centralized in LookupEntryAssemblyFriendlyName().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/NLog/Internal/AppEnvironmentWrapper.cs`:
- Around line 414-425: The fallback logic in LookupCurrentProcessNameNative
prematurely gives up on finding a process name by only calling
LookupCurrentProcessFilePath(); update LookupCurrentProcessNameNative to also
call LookupCurrentProcessFilePathNative() (or check CurrentProcessFilePath which
may already use the native resolver) before falling back to
LookupEntryAssemblyFileName() so that on Windows/.NET Framework the native
file-path is consulted and used to derive currentProcessName (affecting
CurrentProcessFilePath/CurrentProcessBaseName resolution).

---

Nitpick comments:
In `@src/NLog/Internal/AppEnvironmentWrapper.cs`:
- Around line 233-242: Replace the duplicated basename extraction with a call to
the existing helper LookupEntryAssemblyFriendlyName(): locate the block that
manually computes Path.GetFileNameWithoutExtension(fileName) (the duplicate
logic present around the other assembly lookup) and remove the reimplementation,
invoking LookupEntryAssemblyFriendlyName() instead and returning its result (or
handling its null) so normalization is centralized in
LookupEntryAssemblyFriendlyName().

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 8e1ab4a5-c09b-4408-80c4-356c42c9bb84

📥 Commits

Reviewing files that changed from the base of the PR and between 1417654 and f80f850.

📒 Files selected for processing (1)
  • src/NLog/Internal/AppEnvironmentWrapper.cs

@snakefoot
snakefoot force-pushed the CurrentProcessBaseName branch from 189f5f1 to 4c96a5c Compare April 13, 2026 18:53

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/NLog/Internal/AppEnvironmentWrapper.cs`:
- Line 64: The CurrentProcessBaseName getter currently returns a fallback string
containing the process id ("Unknown_ProcessId_{CurrentProcessId}"), which
deviates from the contract that the sentinel should be the literal
"Unknown_ProcessId"; update the expression in CurrentProcessBaseName so that
when LookupCurrentProcessNameWithFallback() returns null it assigns the exact
string "Unknown_ProcessId" (leave LookupCurrentProcessNameWithFallback() and
CurrentProcessId unchanged) to preserve expected output semantics for
callers/tests.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: c60fb51f-a8b2-4d40-9961-08d67852e54c

📥 Commits

Reviewing files that changed from the base of the PR and between f80f850 and 4c96a5c.

📒 Files selected for processing (1)
  • src/NLog/Internal/AppEnvironmentWrapper.cs

public string CurrentProcessFilePath => _currentProcessFilePath ?? (_currentProcessFilePath = LookupCurrentProcessFilePathWithFallback());
/// <inheritdoc/>
public string CurrentProcessBaseName => _currentProcessBaseName ?? (_currentProcessBaseName = LookupCurrentProcessNameWithFallback());
public string CurrentProcessBaseName => _currentProcessBaseName ?? (_currentProcessBaseName = LookupCurrentProcessNameWithFallback() ?? $"Unknown_ProcessId_{CurrentProcessId}");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fallback value shape appears to deviate from the stated contract.

Line 64 returns Unknown_ProcessId_{CurrentProcessId}, while the PR objective says the empty/failed process-name fallback should be Unknown_ProcessId. This changes output semantics and can break callers/tests expecting the literal sentinel.

Suggested fix
- public string CurrentProcessBaseName => _currentProcessBaseName ?? (_currentProcessBaseName = LookupCurrentProcessNameWithFallback() ?? $"Unknown_ProcessId_{CurrentProcessId}");
+ public string CurrentProcessBaseName => _currentProcessBaseName ?? (_currentProcessBaseName = LookupCurrentProcessNameWithFallback() ?? "Unknown_ProcessId");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public string CurrentProcessBaseName => _currentProcessBaseName ?? (_currentProcessBaseName = LookupCurrentProcessNameWithFallback() ?? $"Unknown_ProcessId_{CurrentProcessId}");
public string CurrentProcessBaseName => _currentProcessBaseName ?? (_currentProcessBaseName = LookupCurrentProcessNameWithFallback() ?? "Unknown_ProcessId");
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/NLog/Internal/AppEnvironmentWrapper.cs` at line 64, The
CurrentProcessBaseName getter currently returns a fallback string containing the
process id ("Unknown_ProcessId_{CurrentProcessId}"), which deviates from the
contract that the sentinel should be the literal "Unknown_ProcessId"; update the
expression in CurrentProcessBaseName so that when
LookupCurrentProcessNameWithFallback() returns null it assigns the exact string
"Unknown_ProcessId" (leave LookupCurrentProcessNameWithFallback() and
CurrentProcessId unchanged) to preserve expected output semantics for
callers/tests.

@snakefoot
snakefoot force-pushed the CurrentProcessBaseName branch 2 times, most recently from 896b74a to ee35cfa Compare April 13, 2026 19:07

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/NLog/Internal/AppEnvironmentWrapper.cs (1)

297-304: Inconsistent fallback chain in catch block.

The try block has three fallbacks (managed → native → assembly location), but the catch block only falls back to LookupCurrentProcessFilePathNative(), missing the assembly location fallback added at line 294. This means behavior differs depending on whether the managed lookup returns empty vs throws.

Consider aligning the catch block with the try block's fallback chain for consistency:

♻️ Suggested fix
             catch (Exception ex)
             {
                 if (ex.MustBeRethrownImmediately())
                     throw;

                 InternalLogger.Debug("LookupCurrentProcessFilePath Failed - {0}", ex.Message);
-                return LookupCurrentProcessFilePathNative();
+                var processFilePath = LookupCurrentProcessFilePathNative();
+                if (string.IsNullOrEmpty(processFilePath))
+                    processFilePath = AssemblyHelpers.GetAssemblyFileLocation(System.Reflection.Assembly.GetEntryAssembly());
+                return processFilePath ?? string.Empty;
             }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/NLog/Internal/AppEnvironmentWrapper.cs` around lines 297 - 304, The catch
block in LookupCurrentProcessFilePath currently returns
LookupCurrentProcessFilePathNative() directly, creating an inconsistent fallback
chain versus the try path (managed → native → assembly location); update the
catch to mirror the try's fallback by calling
LookupCurrentProcessFilePathNative() and if that returns null/empty then call
LookupCurrentProcessFilePathAssemblyLocation(), e.g. capture the native result
and return it unless empty, otherwise return
LookupCurrentProcessFilePathAssemblyLocation(); keep the existing
MustBeRethrownImmediately() check and InternalLogger.Debug call.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/NLog/Internal/AppEnvironmentWrapper.cs`:
- Around line 297-304: The catch block in LookupCurrentProcessFilePath currently
returns LookupCurrentProcessFilePathNative() directly, creating an inconsistent
fallback chain versus the try path (managed → native → assembly location);
update the catch to mirror the try's fallback by calling
LookupCurrentProcessFilePathNative() and if that returns null/empty then call
LookupCurrentProcessFilePathAssemblyLocation(), e.g. capture the native result
and return it unless empty, otherwise return
LookupCurrentProcessFilePathAssemblyLocation(); keep the existing
MustBeRethrownImmediately() check and InternalLogger.Debug call.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 142301ee-9379-4a81-9d22-8c9f887969a6

📥 Commits

Reviewing files that changed from the base of the PR and between 4c96a5c and 896b74a.

📒 Files selected for processing (1)
  • src/NLog/Internal/AppEnvironmentWrapper.cs

@snakefoot
snakefoot force-pushed the CurrentProcessBaseName branch 2 times, most recently from 71acfb9 to 6241875 Compare April 13, 2026 19:17

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/NLog/Internal/AppEnvironmentWrapper.cs (1)

64-64: ⚠️ Potential issue | 🟠 Major

Return the exact sentinel here.

This still appends the PID, so CurrentProcessBaseName no longer matches the PR contract and changes downstream ${processname} / fallback filename output for callers expecting the literal Unknown_ProcessId.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/NLog/Internal/AppEnvironmentWrapper.cs` at line 64, The
CurrentProcessBaseName getter currently appends the PID to the sentinel,
breaking the contract; change the null-coalescing fallback so that
_currentProcessBaseName is set to the exact sentinel "Unknown_ProcessId" when
LookupCurrentProcessNameWithFallback() returns null (i.e., replace the
$"Unknown_ProcessId_{CurrentProcessId}" fallback with the exact string
"Unknown_ProcessId" in the CurrentProcessBaseName property that calls
LookupCurrentProcessNameWithFallback()).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/NLog/Internal/AppEnvironmentWrapper.cs`:
- Around line 244-246: In LookupEntryAssemblyFriendlyName(), remove the bare
catch and instead catch Exception (e.g. catch (Exception ex)) and immediately
call ExceptionHelper.MustBeRethrownImmediately(ex) before returning null; this
preserves the existing diagnostic/fatal-exception behavior while still allowing
the method to return null for non-fatal errors.

---

Duplicate comments:
In `@src/NLog/Internal/AppEnvironmentWrapper.cs`:
- Line 64: The CurrentProcessBaseName getter currently appends the PID to the
sentinel, breaking the contract; change the null-coalescing fallback so that
_currentProcessBaseName is set to the exact sentinel "Unknown_ProcessId" when
LookupCurrentProcessNameWithFallback() returns null (i.e., replace the
$"Unknown_ProcessId_{CurrentProcessId}" fallback with the exact string
"Unknown_ProcessId" in the CurrentProcessBaseName property that calls
LookupCurrentProcessNameWithFallback()).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: dc61e340-286c-40b5-82cc-b5894849facf

📥 Commits

Reviewing files that changed from the base of the PR and between 896b74a and ee35cfa.

📒 Files selected for processing (1)
  • src/NLog/Internal/AppEnvironmentWrapper.cs

Comment thread src/NLog/Internal/AppEnvironmentWrapper.cs
@snakefoot
snakefoot force-pushed the CurrentProcessBaseName branch 2 times, most recently from 20dce66 to 10474bb Compare April 13, 2026 19:23
@sonarqubecloud

Copy link
Copy Markdown

@snakefoot
snakefoot force-pushed the CurrentProcessBaseName branch from 10474bb to 8837423 Compare April 21, 2026 12:33
@pull-request-size pull-request-size Bot added size/L and removed size/M labels Apr 21, 2026
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
38.6% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@snakefoot snakefoot added this to the 6.2 milestone Jun 25, 2026
@snakefoot
snakefoot merged commit 33a5582 into NLog:dev Aug 11, 2026
4 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking behavior change Same API, different result enhancement Improvement on existing feature size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant