Skip to content

Commit 8d12365

Browse files
authored
fix: Add null guards for .NET Framework MSBuild compatibility (#37)
On .NET Framework MSBuild hosts, certain properties like ProjectDirectory, ProjectReferences, and other MSBuild-set values may be null instead of empty strings. This caused NullReferenceExceptions in: - PathUtils.FullPath when baseDir was null - ResolveSqlProjWithValidation when ProjectReferences or ItemSpec was null - ResourceResolutionChain when searching directories with null paths - ConnectionStringResolutionChain when checking for config files with null directory This fix adds defensive null checks to handle these edge cases, ensuring the build works correctly on both .NET Framework and .NET Core MSBuild hosts.
1 parent e769e9a commit 8d12365

4 files changed

Lines changed: 54 additions & 13 deletions

File tree

src/JD.Efcpt.Build.Tasks/Chains/ConnectionStringResolutionChain.cs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,23 @@ private static bool HasExplicitConfigFile(string explicitPath, string projectDir
9999
}
100100

101101
private static bool HasAppSettingsFiles(string projectDirectory)
102-
=> Directory.GetFiles(projectDirectory, "appsettings*.json").Length > 0;
102+
{
103+
// Guard against null - can occur on .NET Framework MSBuild
104+
if (string.IsNullOrWhiteSpace(projectDirectory) || !Directory.Exists(projectDirectory))
105+
return false;
106+
107+
return Directory.GetFiles(projectDirectory, "appsettings*.json").Length > 0;
108+
}
103109

104110
private static bool HasAppConfigFiles(string projectDirectory)
105-
=> File.Exists(Path.Combine(projectDirectory, "app.config")) ||
106-
File.Exists(Path.Combine(projectDirectory, "web.config"));
111+
{
112+
// Guard against null - can occur on .NET Framework MSBuild
113+
if (string.IsNullOrWhiteSpace(projectDirectory))
114+
return false;
115+
116+
return File.Exists(Path.Combine(projectDirectory, "app.config")) ||
117+
File.Exists(Path.Combine(projectDirectory, "web.config"));
118+
}
107119

108120
#endregion
109121

@@ -130,6 +142,10 @@ private static bool HasAppConfigFiles(string projectDirectory)
130142
string connectionStringName,
131143
BuildLog log)
132144
{
145+
// Guard against null - can occur on .NET Framework MSBuild
146+
if (string.IsNullOrWhiteSpace(projectDirectory) || !Directory.Exists(projectDirectory))
147+
return null;
148+
133149
var appSettingsFiles = Directory.GetFiles(projectDirectory, "appsettings*.json");
134150

135151
if (appSettingsFiles.Length > 1)
@@ -158,6 +174,10 @@ private static bool HasAppConfigFiles(string projectDirectory)
158174
string connectionStringName,
159175
BuildLog log)
160176
{
177+
// Guard against null - can occur on .NET Framework MSBuild
178+
if (string.IsNullOrWhiteSpace(projectDirectory))
179+
return null;
180+
161181
var configFiles = new[] { "app.config", "web.config" };
162182
foreach (var configFile in configFiles)
163183
{

src/JD.Efcpt.Build.Tasks/Chains/ResourceResolutionChain.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,9 @@ public static string Resolve(
7070
: throw overrideNotFound($"Override not found: {path}", path);
7171
}
7272

73-
// Branch 2: Search project directory
74-
if (TryFindInDirectory(context.ProjectDirectory, context.ResourceNames, exists, out var found))
73+
// Branch 2: Search project directory (if provided)
74+
if (!string.IsNullOrWhiteSpace(context.ProjectDirectory) &&
75+
TryFindInDirectory(context.ProjectDirectory, context.ResourceNames, exists, out var found))
7576
return found;
7677

7778
// Branch 3: Search solution directory (if enabled)
@@ -99,6 +100,13 @@ private static bool TryFindInDirectory(
99100
ExistsPredicate exists,
100101
out string foundPath)
101102
{
103+
// Guard against null inputs - can occur on .NET Framework MSBuild
104+
if (string.IsNullOrWhiteSpace(directory) || resourceNames == null || resourceNames.Count == 0)
105+
{
106+
foundPath = string.Empty;
107+
return false;
108+
}
109+
102110
var matchingCandidate = resourceNames
103111
.Select(name => Path.Combine(directory, name))
104112
.FirstOrDefault(candidate => exists(candidate));

src/JD.Efcpt.Build.Tasks/PathUtils.cs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,26 @@ namespace JD.Efcpt.Build.Tasks;
33
internal static class PathUtils
44
{
55
public static string FullPath(string path, string baseDir)
6-
=> string.IsNullOrWhiteSpace(path)
7-
? path
8-
: Path.GetFullPath(Path.IsPathRooted(path)
9-
? path
10-
: Path.Combine(baseDir, path));
6+
{
7+
if (string.IsNullOrWhiteSpace(path))
8+
return path;
9+
10+
if (Path.IsPathRooted(path))
11+
return Path.GetFullPath(path);
12+
13+
// Handle null/empty baseDir by using current directory
14+
// This can happen when MSBuild sets properties to null on .NET Framework
15+
if (string.IsNullOrWhiteSpace(baseDir))
16+
return Path.GetFullPath(path);
17+
18+
return Path.GetFullPath(Path.Combine(baseDir, path));
19+
}
1120

1221
public static bool HasValue(string? s) => !string.IsNullOrWhiteSpace(s);
1322

1423
public static bool HasExplicitPath(string? s)
1524
=> !string.IsNullOrWhiteSpace(s)
16-
&& (Path.IsPathRooted(s)
17-
|| s.Contains(Path.DirectorySeparatorChar)
25+
&& (Path.IsPathRooted(s)
26+
|| s.Contains(Path.DirectorySeparatorChar)
1827
|| s.Contains(Path.AltDirectorySeparatorChar));
1928
}

src/JD.Efcpt.Build.Tasks/ResolveSqlProjAndInputs.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,11 @@ private ResolutionState BuildResolutionState(BuildLog log)
450450

451451
private string ResolveSqlProjWithValidation(BuildLog log)
452452
{
453-
var sqlRefs = ProjectReferences
453+
// ProjectReferences may be null on some .NET Framework MSBuild hosts
454+
var references = ProjectReferences ?? [];
455+
456+
var sqlRefs = references
457+
.Where(x => x?.ItemSpec != null)
454458
.Select(x => PathUtils.FullPath(x.ItemSpec, ProjectDirectory))
455459
.Where(SqlProjectDetector.IsSqlProjectReference)
456460
.Distinct(StringComparer.OrdinalIgnoreCase)

0 commit comments

Comments
 (0)