Created
December 15, 2025 18:52
-
-
Save ardalis/b9afb7e15c63df8ef1598ed3d1ae3d70 to your computer and use it in GitHub Desktop.
Remove <TargetFramework> elements from csproj files
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // removeTargetFramework.cs | |
| // Usage: | |
| // dotnet run removeTargetFramework.cs -- [start-directory] [--dry-run|-n] | |
| // Examples: | |
| // dotnet run removeTargetFramework.cs -- . --dry-run | |
| // dotnet run removeTargetFramework.cs -- ../src | |
| // dotnet run removeTargetFramework.cs -- ../src -n | |
| using System; | |
| using System.IO; | |
| using System.Collections.Generic; | |
| var argsSpan = args.AsSpan(); | |
| string startDirectory = Directory.GetCurrentDirectory(); | |
| bool dryRun = false; | |
| if (argsSpan.Length > 0) | |
| { | |
| for (int i = 0; i < argsSpan.Length; i++) | |
| { | |
| var arg = argsSpan[i]; | |
| if (arg.Equals("--help", StringComparison.OrdinalIgnoreCase) || | |
| arg.Equals("-h", StringComparison.OrdinalIgnoreCase) || | |
| arg.Equals("/?")) | |
| { | |
| PrintUsage(); | |
| return; | |
| } | |
| if (arg.Equals("--dry-run", StringComparison.OrdinalIgnoreCase) || | |
| arg.Equals("-n", StringComparison.OrdinalIgnoreCase)) | |
| { | |
| dryRun = true; | |
| continue; | |
| } | |
| // First non-option argument is treated as the start directory | |
| if (startDirectory == Directory.GetCurrentDirectory()) | |
| { | |
| startDirectory = arg; | |
| continue; | |
| } | |
| Console.Error.WriteLine($"Unrecognized argument: {arg}"); | |
| PrintUsage(); | |
| return; | |
| } | |
| } | |
| if (!Directory.Exists(startDirectory)) | |
| { | |
| Console.Error.WriteLine($"Error: Directory does not exist: {startDirectory}"); | |
| return; | |
| } | |
| Console.WriteLine($"Starting search in: {Path.GetFullPath(startDirectory)}"); | |
| Console.WriteLine(dryRun | |
| ? "Dry run mode: will only list files that would be modified." | |
| : "Live mode: matching <TargetFramework> lines will be removed."); | |
| Console.WriteLine(); | |
| int filesScanned = 0; | |
| int filesModified = 0; | |
| foreach (var csprojFile in Directory.EnumerateFiles(startDirectory, "*.csproj", SearchOption.AllDirectories)) | |
| { | |
| filesScanned++; | |
| string[] lines; | |
| try | |
| { | |
| lines = File.ReadAllLines(csprojFile); | |
| } | |
| catch (Exception ex) | |
| { | |
| Console.Error.WriteLine($"Failed to read {csprojFile}: {ex.Message}"); | |
| continue; | |
| } | |
| var newLines = new List<string>(lines.Length); | |
| bool removedAnyLine = false; | |
| foreach (var line in lines) | |
| { | |
| if (line.Contains("<TargetFramework>", StringComparison.OrdinalIgnoreCase) && | |
| line.Contains("</TargetFramework>", StringComparison.OrdinalIgnoreCase)) | |
| { | |
| // Drop this line | |
| removedAnyLine = true; | |
| continue; | |
| } | |
| newLines.Add(line); | |
| } | |
| if (!removedAnyLine) | |
| { | |
| // No <TargetFramework> line found in this file | |
| continue; | |
| } | |
| filesModified++; | |
| if (dryRun) | |
| { | |
| Console.WriteLine(csprojFile); | |
| } | |
| else | |
| { | |
| try | |
| { | |
| File.WriteAllLines(csprojFile, newLines); | |
| Console.WriteLine($"Updated: {csprojFile}"); | |
| } | |
| catch (Exception ex) | |
| { | |
| Console.Error.WriteLine($"Failed to write {csprojFile}: {ex.Message}"); | |
| } | |
| } | |
| } | |
| Console.WriteLine(); | |
| Console.WriteLine($"Scanned {filesScanned} *.csproj files."); | |
| Console.WriteLine(dryRun | |
| ? $"Would modify {filesModified} file(s)." | |
| : $"Modified {filesModified} file(s)."); | |
| static void PrintUsage() | |
| { | |
| Console.WriteLine("Remove <TargetFramework> line from .csproj files"); | |
| Console.WriteLine(); | |
| Console.WriteLine("Usage:"); | |
| Console.WriteLine(" dotnet run removeTargetFramework.cs -- [start-directory] [--dry-run|-n]"); | |
| Console.WriteLine(); | |
| Console.WriteLine("Options:"); | |
| Console.WriteLine(" start-directory Root directory to search (defaults to current directory)."); | |
| Console.WriteLine(" --dry-run, -n Show which files would be changed without modifying them."); | |
| Console.WriteLine(" --help, -h Show this help message."); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment