Skip to content

[Correctness] Multiple files — Process.MainModule!.FileName! pattern repeated in 7 locations (follow-up to #724) #757

@Christophe-Rogiers

Description

@Christophe-Rogiers

Severity: Info
Related: Follow-up to #724

#724 flagged the Process.GetCurrentProcess().MainModule!.FileName! null-forgiving pattern in RotatingStreamWriter.cs:449 and explicitly noted: "The same fallback pattern is worth reusing anywhere else the codebase needs 'the app's install directory'."

Seven additional callsites use the same (or a weaker, unguarded) pattern and are still unfixed:

# File Line Form
1 src/Servy.Service/Service.cs 287 Process.GetCurrentProcess().MainModule!.FileName!
2 src/Servy.UI/Bootstrapping/AppBootstrapper.cs 198 Process.GetCurrentProcess().MainModule!.FileName!
3 src/Servy.CLI/Program.cs 97 Process.GetCurrentProcess().MainModule!.FileName!
4 src/Servy.Restarter/Program.cs 72 Process.GetCurrentProcess().MainModule!.FileName!
5 src/Servy.Service/Helpers/ServiceHelper.cs 291 Process.GetCurrentProcess().MainModule!.FileName!
6 src/Servy/App.xaml.cs 172 Process.GetCurrentProcess().MainModule.FileName (unguarded — will NRE)
7 src/Servy.Manager/App.xaml.cs 214 Process.GetCurrentProcess().MainModule.FileName (unguarded — will NRE)

Callsites 6 and 7 are arguably worse than #724 because they do not even suppress the warning — any null MainModule surfaces as a plain NullReferenceException inside App.OnStartup, crashing the WPF application before the dispatcher unhandled-exception handler is wired.

Suggested fix:

Extract the fallback chain from #724 into a shared helper (e.g. AppConfig.GetAppBaseDirectory() or PathHelper.GetAppInstallDirectory()) and replace all eight callsites (the original plus these seven) with a single call. This also removes the duplication that would otherwise force a seven-copy fix when #724 is addressed.

public static string GetAppInstallDirectory()
{
    try
    {
        var fileName = Process.GetCurrentProcess().MainModule?.FileName;
        if (!string.IsNullOrEmpty(fileName))
        {
            var dir = Path.GetDirectoryName(fileName);
            if (!string.IsNullOrEmpty(dir)) return dir;
        }
    }
    catch { /* restricted session */ }

    return AppContext.BaseDirectory;
}

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions