Skip to content

Commit 1c06221

Browse files
committed
v2.0.0: Rename to ProjectedFSLib.Managed, reclaim original NuGet ID, add LibraryImport
Project rename: - ProjectedFSLib.Managed.CSharp/ -> ProjectedFSLib.Managed/ - ProjectedFSLib.Managed.CSharp.csproj -> ProjectedFSLib.Managed.csproj - Updated solution, project references, README, and docs Package identity: - PackageId reverted to Microsoft.Windows.ProjFS (original ID, superseding the old C++/CLI v1.2 package) - Version 2.0.0 via Directory.Build.props - Added SourceLink, symbol packages (.snupkg), PackageReadmeFile - NuGet publishing handled by internal CI/CD pipeline LibraryImport for .NET 7+: - ProjFSNative.cs uses tactical #if NET7_0_OR_GREATER per method: LibraryImport (source-generated) on .NET 7+, DllImport on netstandard2.0 - Single file, no duplication of function signatures or parameters - All 23 P/Invokes covered Testing: - Added net48 target to test and sample projects (validates netstandard2.0 path) - Test timeout restored to 10s (was 600s for debugging) - All tests pass: net48 12/12, net8.0 16/16, net10.0 16/16 Other: - global.json updated to pin .NET 10 SDK - Restored InitializeEnvironment.bat and NukeBuildOutputs.bat from main - Scripts solution folder with all build/test/pack scripts - README: restored build badge, powershell code blocks, NuGet install docs - Design doc and presentation updated with LibraryImport and v2.0.0 info
1 parent a2e8368 commit 1c06221

18 files changed

Lines changed: 346 additions & 29 deletions

Directory.Build.props

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<Project>
2+
3+
<PropertyGroup>
4+
<ProjFSManagedVersion>2.0.0</ProjFSManagedVersion>
5+
<LangVersion>latest</LangVersion>
6+
<Nullable>enable</Nullable>
7+
</PropertyGroup>
8+
9+
</Project>

ProjectedFSLib.Managed.Test/BasicTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ public class BasicTests
3535
[OneTimeSetUp]
3636
public void ClassSetup()
3737
{
38-
// Default timeout for wait handles — extended for debugging
39-
helpers = new Helpers(600 * 1000);
38+
// Default timeout for wait handles
39+
helpers = new Helpers(10 * 1000);
4040
}
4141

4242
[SetUp]

ProjectedFSLib.Managed.Test/ProjectedFSLib.Managed.Test.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>net8.0-windows10.0.17763.0;net10.0-windows10.0.17763.0</TargetFrameworks>
4+
<TargetFrameworks>net48;net8.0-windows10.0.17763.0;net10.0-windows10.0.17763.0</TargetFrameworks>
55
<IsPackable>false</IsPackable>
66
<GenerateProgramFile>false</GenerateProgramFile>
77
<PlatformTarget>x64</PlatformTarget>
@@ -15,7 +15,7 @@
1515
</ItemGroup>
1616

1717
<ItemGroup>
18-
<ProjectReference Include="..\ProjectedFSLib.Managed.CSharp\ProjectedFSLib.Managed.CSharp.csproj" />
18+
<ProjectReference Include="..\ProjectedFSLib.Managed\ProjectedFSLib.Managed.csproj" />
1919
<ProjectReference Include="..\simpleProviderManaged\SimpleProviderManaged.csproj" />
2020
</ItemGroup>
2121

ProjectedFSLib.Managed.sln

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
33
# Visual Studio Version 17
44
VisualStudioVersion = 17.0.0.0
55
MinimumVisualStudioVersion = 10.0.40219.1
6-
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProjectedFSLib.Managed.CSharp", "ProjectedFSLib.Managed.CSharp\ProjectedFSLib.Managed.CSharp.csproj", "{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}"
6+
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProjectedFSLib.Managed", "ProjectedFSLib.Managed\ProjectedFSLib.Managed.csproj", "{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}"
77
EndProject
88
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProjectedFSLib.Managed.Test", "ProjectedFSLib.Managed.Test\ProjectedFSLib.Managed.Test.csproj", "{B4018C7F-BF11-47BC-8770-72B05C9437EE}"
99
EndProject
@@ -14,6 +14,15 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
1414
README.md = README.md
1515
EndProjectSection
1616
EndProject
17+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripts", "Scripts", "{80F77524-CD14-4BD0-A197-8E7D5DD7B6E0}"
18+
ProjectSection(SolutionItems) = preProject
19+
scripts\BuildProjFS-Managed.bat = scripts\BuildProjFS-Managed.bat
20+
scripts\InitializeEnvironment.bat = scripts\InitializeEnvironment.bat
21+
scripts\NukeBuildOutputs.bat = scripts\NukeBuildOutputs.bat
22+
scripts\RunTests.bat = scripts\RunTests.bat
23+
scripts\Pack-NuGet.ps1 = scripts\Pack-NuGet.ps1
24+
EndProjectSection
25+
EndProject
1726
Global
1827
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1928
Debug|Any CPU = Debug|Any CPU

ProjectedFSLib.Managed.CSharp/DirectoryEnumerationResults.cs renamed to ProjectedFSLib.Managed/DirectoryEnumerationResults.cs

File renamed without changes.
File renamed without changes.

ProjectedFSLib.Managed.CSharp/ProjFSNative.cs renamed to ProjectedFSLib.Managed/ProjFSNative.cs

Lines changed: 122 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ namespace Microsoft.Windows.ProjFS
66
/// <summary>
77
/// Native P/Invoke declarations for ProjectedFSLib.dll.
88
/// This replaces the C++/CLI mixed-mode ProjectedFSLib.Managed.dll with pure C# P/Invoke.
9+
/// On .NET 7+, uses LibraryImport source generators for AOT compatibility.
10+
/// On .NET Standard 2.0, falls back to traditional DllImport.
911
/// </summary>
10-
internal static class ProjFSNative
12+
internal static partial class ProjFSNative
1113
{
1214
private const string ProjFSLib = "ProjectedFSLib.dll";
1315

@@ -17,108 +19,180 @@ internal static class ProjFSNative
1719
// Core virtualization lifetime
1820
// ============================
1921

22+
#if NET7_0_OR_GREATER
23+
[LibraryImport(ProjFSLib, StringMarshalling = StringMarshalling.Utf16)]
24+
internal static partial int PrjStartVirtualizing(
25+
#else
2026
[DllImport(ProjFSLib, CharSet = CharSet.Unicode, ExactSpelling = true)]
2127
internal static extern int PrjStartVirtualizing(
28+
#endif
2229
string virtualizationRootPath,
2330
ref PRJ_CALLBACKS callbacks,
2431
IntPtr instanceContext,
2532
ref PRJ_STARTVIRTUALIZING_OPTIONS options,
2633
out IntPtr namespaceVirtualizationContext);
2734

35+
#if NET7_0_OR_GREATER
36+
[LibraryImport(ProjFSLib)]
37+
internal static partial void PrjStopVirtualizing(IntPtr namespaceVirtualizationContext);
38+
#else
2839
[DllImport(ProjFSLib, ExactSpelling = true)]
2940
internal static extern void PrjStopVirtualizing(IntPtr namespaceVirtualizationContext);
41+
#endif
3042

3143
// ============================
3244
// Placeholder management
3345
// ============================
3446

47+
#if NET7_0_OR_GREATER
48+
[LibraryImport(ProjFSLib, StringMarshalling = StringMarshalling.Utf16)]
49+
internal static partial int PrjWritePlaceholderInfo(
50+
#else
3551
[DllImport(ProjFSLib, CharSet = CharSet.Unicode, ExactSpelling = true)]
3652
internal static extern int PrjWritePlaceholderInfo(
53+
#endif
3754
IntPtr namespaceVirtualizationContext,
3855
string destinationFileName,
3956
ref PRJ_PLACEHOLDER_INFO placeholderInfo,
4057
uint length);
4158

59+
#if NET7_0_OR_GREATER
60+
[LibraryImport(ProjFSLib, StringMarshalling = StringMarshalling.Utf16)]
61+
internal static partial int PrjWritePlaceholderInfo2(
62+
#else
4263
[DllImport(ProjFSLib, CharSet = CharSet.Unicode, ExactSpelling = true)]
4364
internal static extern int PrjWritePlaceholderInfo2(
65+
#endif
4466
IntPtr namespaceVirtualizationContext,
4567
string destinationFileName,
4668
ref PRJ_PLACEHOLDER_INFO placeholderInfo,
4769
uint placeholderInfoSize,
4870
ref PRJ_EXTENDED_INFO extendedInfo);
4971

72+
#if NET7_0_OR_GREATER
73+
[LibraryImport(ProjFSLib, EntryPoint = "PrjWritePlaceholderInfo2")]
74+
internal static partial int PrjWritePlaceholderInfo2Raw(
75+
#else
5076
[DllImport(ProjFSLib, CharSet = CharSet.Unicode, ExactSpelling = true, EntryPoint = "PrjWritePlaceholderInfo2")]
5177
internal static extern int PrjWritePlaceholderInfo2Raw(
78+
#endif
5279
IntPtr namespaceVirtualizationContext,
5380
IntPtr destinationFileName,
5481
IntPtr placeholderInfo,
5582
uint placeholderInfoSize,
5683
IntPtr extendedInfo);
5784

85+
#if NET7_0_OR_GREATER
86+
[LibraryImport(ProjFSLib, StringMarshalling = StringMarshalling.Utf16)]
87+
internal static partial int PrjUpdateFileIfNeeded(
88+
#else
5889
[DllImport(ProjFSLib, CharSet = CharSet.Unicode, ExactSpelling = true)]
5990
internal static extern int PrjUpdateFileIfNeeded(
91+
#endif
6092
IntPtr namespaceVirtualizationContext,
6193
string destinationFileName,
6294
ref PRJ_PLACEHOLDER_INFO placeholderInfo,
6395
uint length,
6496
uint updateFlags,
6597
out uint failureReason);
6698

99+
#if NET7_0_OR_GREATER
100+
[LibraryImport(ProjFSLib, StringMarshalling = StringMarshalling.Utf16)]
101+
internal static partial int PrjDeleteFile(
102+
#else
67103
[DllImport(ProjFSLib, CharSet = CharSet.Unicode, ExactSpelling = true)]
68104
internal static extern int PrjDeleteFile(
105+
#endif
69106
IntPtr namespaceVirtualizationContext,
70107
string destinationFileName,
71108
uint updateFlags,
72109
out uint failureReason);
73110

111+
#if NET7_0_OR_GREATER
112+
[LibraryImport(ProjFSLib, StringMarshalling = StringMarshalling.Utf16)]
113+
internal static partial int PrjMarkDirectoryAsPlaceholder(
114+
#else
74115
[DllImport(ProjFSLib, CharSet = CharSet.Unicode, ExactSpelling = true)]
75116
internal static extern int PrjMarkDirectoryAsPlaceholder(
117+
#endif
76118
string rootPathName,
77119
string targetPathName,
78120
ref PRJ_PLACEHOLDER_VERSION_INFO versionInfo,
79121
ref Guid virtualizationInstanceID);
80122

81123
// Overload for MarkDirectoryAsVirtualizationRoot (versionInfo = null)
124+
#if NET7_0_OR_GREATER
125+
[LibraryImport(ProjFSLib, StringMarshalling = StringMarshalling.Utf16, EntryPoint = "PrjMarkDirectoryAsPlaceholder")]
126+
internal static partial int PrjMarkDirectoryAsVirtualizationRoot(
127+
string rootPathName,
128+
string? targetPathName,
129+
#else
82130
[DllImport(ProjFSLib, CharSet = CharSet.Unicode, ExactSpelling = true, EntryPoint = "PrjMarkDirectoryAsPlaceholder")]
83131
internal static extern int PrjMarkDirectoryAsVirtualizationRoot(
84132
string rootPathName,
85133
[MarshalAs(UnmanagedType.LPWStr)] string targetPathName,
134+
#endif
86135
IntPtr versionInfo,
87136
ref Guid virtualizationInstanceID);
88137

89138
// ============================
90139
// File data streaming
91140
// ============================
92141

142+
#if NET7_0_OR_GREATER
143+
[LibraryImport(ProjFSLib)]
144+
internal static partial int PrjWriteFileData(
145+
#else
93146
[DllImport(ProjFSLib, ExactSpelling = true)]
94147
internal static extern int PrjWriteFileData(
148+
#endif
95149
IntPtr namespaceVirtualizationContext,
96150
ref Guid dataStreamId,
97151
IntPtr buffer,
98152
ulong byteOffset,
99153
uint length);
100154

155+
#if NET7_0_OR_GREATER
156+
[LibraryImport(ProjFSLib)]
157+
internal static partial IntPtr PrjAllocateAlignedBuffer(
158+
#else
101159
[DllImport(ProjFSLib, ExactSpelling = true)]
102160
internal static extern IntPtr PrjAllocateAlignedBuffer(
161+
#endif
103162
IntPtr namespaceVirtualizationContext,
104163
UIntPtr size);
105164

165+
#if NET7_0_OR_GREATER
166+
[LibraryImport(ProjFSLib)]
167+
internal static partial void PrjFreeAlignedBuffer(IntPtr buffer);
168+
#else
106169
[DllImport(ProjFSLib, ExactSpelling = true)]
107170
internal static extern void PrjFreeAlignedBuffer(IntPtr buffer);
171+
#endif
108172

109173
// ============================
110174
// Command completion
111175
// ============================
112176

177+
#if NET7_0_OR_GREATER
178+
[LibraryImport(ProjFSLib)]
179+
internal static partial int PrjCompleteCommand(
180+
#else
113181
[DllImport(ProjFSLib, ExactSpelling = true)]
114182
internal static extern int PrjCompleteCommand(
183+
#endif
115184
IntPtr namespaceVirtualizationContext,
116185
int commandId,
117186
int completionResult,
118187
IntPtr extendedParameters);
119188

189+
#if NET7_0_OR_GREATER
190+
[LibraryImport(ProjFSLib, EntryPoint = "PrjCompleteCommand")]
191+
internal static partial int PrjCompleteCommandWithNotification(
192+
#else
120193
[DllImport(ProjFSLib, ExactSpelling = true, EntryPoint = "PrjCompleteCommand")]
121194
internal static extern int PrjCompleteCommandWithNotification(
195+
#endif
122196
IntPtr namespaceVirtualizationContext,
123197
int commandId,
124198
int completionResult,
@@ -128,30 +202,50 @@ internal static extern int PrjCompleteCommandWithNotification(
128202
// Cache management
129203
// ============================
130204

205+
#if NET7_0_OR_GREATER
206+
[LibraryImport(ProjFSLib)]
207+
internal static partial int PrjClearNegativePathCache(
208+
#else
131209
[DllImport(ProjFSLib, ExactSpelling = true)]
132210
internal static extern int PrjClearNegativePathCache(
211+
#endif
133212
IntPtr namespaceVirtualizationContext,
134213
out uint totalEntryNumber);
135214

136215
// ============================
137216
// Directory enumeration
138217
// ============================
139218

219+
#if NET7_0_OR_GREATER
220+
[LibraryImport(ProjFSLib, StringMarshalling = StringMarshalling.Utf16)]
221+
internal static partial int PrjFillDirEntryBuffer(
222+
#else
140223
[DllImport(ProjFSLib, CharSet = CharSet.Unicode, ExactSpelling = true)]
141224
internal static extern int PrjFillDirEntryBuffer(
225+
#endif
142226
string fileName,
143227
ref PRJ_FILE_BASIC_INFO fileBasicInfo,
144228
IntPtr dirEntryBufferHandle);
145229

230+
#if NET7_0_OR_GREATER
231+
[LibraryImport(ProjFSLib, StringMarshalling = StringMarshalling.Utf16)]
232+
internal static partial int PrjFillDirEntryBuffer2(
233+
#else
146234
[DllImport(ProjFSLib, CharSet = CharSet.Unicode, ExactSpelling = true)]
147235
internal static extern int PrjFillDirEntryBuffer2(
236+
#endif
148237
IntPtr dirEntryBufferHandle,
149238
string fileName,
150239
ref PRJ_FILE_BASIC_INFO fileBasicInfo,
151240
ref PRJ_EXTENDED_INFO extendedInfo);
152241

242+
#if NET7_0_OR_GREATER
243+
[LibraryImport(ProjFSLib, StringMarshalling = StringMarshalling.Utf16, EntryPoint = "PrjFillDirEntryBuffer2")]
244+
internal static partial int PrjFillDirEntryBuffer2NoExtInfo(
245+
#else
153246
[DllImport(ProjFSLib, CharSet = CharSet.Unicode, ExactSpelling = true, EntryPoint = "PrjFillDirEntryBuffer2")]
154247
internal static extern int PrjFillDirEntryBuffer2NoExtInfo(
248+
#endif
155249
IntPtr dirEntryBufferHandle,
156250
string fileName,
157251
ref PRJ_FILE_BASIC_INFO fileBasicInfo,
@@ -161,30 +255,57 @@ internal static extern int PrjFillDirEntryBuffer2NoExtInfo(
161255
// Filename utilities
162256
// ============================
163257

258+
#if NET7_0_OR_GREATER
259+
[LibraryImport(ProjFSLib, StringMarshalling = StringMarshalling.Utf16)]
260+
[return: MarshalAs(UnmanagedType.U1)]
261+
internal static partial bool PrjDoesNameContainWildCards(string fileName);
262+
#else
164263
[DllImport(ProjFSLib, CharSet = CharSet.Unicode, ExactSpelling = true)]
165264
[return: MarshalAs(UnmanagedType.U1)]
166265
internal static extern bool PrjDoesNameContainWildCards(string fileName);
266+
#endif
167267

268+
#if NET7_0_OR_GREATER
269+
[LibraryImport(ProjFSLib, StringMarshalling = StringMarshalling.Utf16)]
270+
[return: MarshalAs(UnmanagedType.U1)]
271+
internal static partial bool PrjFileNameMatch(string fileNameToCheck, string pattern);
272+
#else
168273
[DllImport(ProjFSLib, CharSet = CharSet.Unicode, ExactSpelling = true)]
169274
[return: MarshalAs(UnmanagedType.U1)]
170275
internal static extern bool PrjFileNameMatch(string fileNameToCheck, string pattern);
276+
#endif
171277

278+
#if NET7_0_OR_GREATER
279+
[LibraryImport(ProjFSLib, StringMarshalling = StringMarshalling.Utf16)]
280+
internal static partial int PrjFileNameCompare(string fileName1, string fileName2);
281+
#else
172282
[DllImport(ProjFSLib, CharSet = CharSet.Unicode, ExactSpelling = true)]
173283
internal static extern int PrjFileNameCompare(string fileName1, string fileName2);
284+
#endif
174285

175286
// ============================
176287
// File state query
177288
// ============================
178289

290+
#if NET7_0_OR_GREATER
291+
[LibraryImport(ProjFSLib, StringMarshalling = StringMarshalling.Utf16)]
292+
internal static partial int PrjGetOnDiskFileState(string destinationFileName, out uint fileState);
293+
#else
179294
[DllImport(ProjFSLib, CharSet = CharSet.Unicode, ExactSpelling = true)]
180295
internal static extern int PrjGetOnDiskFileState(string destinationFileName, out uint fileState);
296+
#endif
181297

182298
// ============================
183299
// Virtualization instance info
184300
// ============================
185301

302+
#if NET7_0_OR_GREATER
303+
[LibraryImport(ProjFSLib)]
304+
internal static partial int PrjGetVirtualizationInstanceInfo(
305+
#else
186306
[DllImport(ProjFSLib, ExactSpelling = true)]
187307
internal static extern int PrjGetVirtualizationInstanceInfo(
308+
#endif
188309
IntPtr namespaceVirtualizationContext,
189310
ref PRJ_VIRTUALIZATION_INSTANCE_INFO virtualizationInstanceInfo);
190311

0 commit comments

Comments
 (0)