Skip to content

Instantly share code, notes, and snippets.

@ardalis
Created December 15, 2025 18:52
Show Gist options
  • Select an option

  • Save ardalis/b9afb7e15c63df8ef1598ed3d1ae3d70 to your computer and use it in GitHub Desktop.

Select an option

Save ardalis/b9afb7e15c63df8ef1598ed3d1ae3d70 to your computer and use it in GitHub Desktop.
Remove <TargetFramework> elements from csproj files
// 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