我想把新的windows10包装起来
ProjFS
C#中的功能。第一步,
as outlined on MSDN
,工作正常:我设置一个目录作为虚拟化根目录,然后注册投影提供程序,包括其回调,如下所示:
static void Main(string[] args)
{
// Create and mark clean directory as virtualization root.
const string directory = @"C:\test_projfs"; // Warning: Deleted to get clean directory.
if (Directory.Exists(directory))
Directory.Delete(directory);
Directory.CreateDirectory(directory);
Guid guid = Guid.NewGuid();
Marshal.ThrowExceptionForHR(PrjMarkDirectoryAsPlaceholder(directory, null, IntPtr.Zero,
ref guid));
// Set up the callback table for the projection provider.
PrjCallbacks callbackTable = new PrjCallbacks
{
StartDirectoryEnumerationCallback = StartDirectoryEnumerationCallback,
EndDirectoryEnumerationCallback = EndDirectoryEnumerationCallback,
GetDirectoryEnumerationCallback = GetDirectoryEnumerationCallback,
GetPlaceholderInfoCallback = GetPlaceholderInfoCallback,
GetFileDataCallback = GetFileDataCallback
};
// Start the projection provider.
IntPtr instanceHandle = IntPtr.Zero;
Marshal.ThrowExceptionForHR(PrjStartVirtualizing(directory, ref callbackTable,
IntPtr.Zero, IntPtr.Zero, ref instanceHandle));
// Keep a test console application running.
Console.ReadLine();
}
// Managed callbacks, simply returning S_OK for now.
static int StartDirectoryEnumerationCallback(ref PrjCallbackData callbackData, ref Guid enumerationId)
{
return 0;
}
static int EndDirectoryEnumerationCallback(ref PrjCallbackData callbackData, ref Guid enumerationId) => 0;
static int GetDirectoryEnumerationCallback(ref PrjCallbackData callbackData, ref Guid enumerationId, string searchExpression, IntPtr dirEntryBufferHandle) => 0;
static int GetPlaceholderInfoCallback(ref PrjCallbackData callbackData) => 0;
static int GetFileDataCallback(ref PrjCallbackData callbackData, ulong byteOffset, uint length) => 0;
本机声明如下所示(很抱歉,这个代码块可以滚动-基本的东西已经很多了):
// Methods to mark directory as virtualization root, and start the projection provider.
[DllImport("ProjectedFSLib.dll", CharSet = CharSet.Unicode)]
static extern int PrjMarkDirectoryAsPlaceholder(string rootPathName,
string targetPathName, IntPtr versionInfo, ref Guid virtualizationInstanceID);
[DllImport("ProjectedFSLib.dll", CharSet = CharSet.Unicode)]
static extern int PrjStartVirtualizing(string virtualizationRootPath,
ref PrjCallbacks callbacks, IntPtr instanceContext, IntPtr options,
ref IntPtr namespaceVirtualizationContext);
// Structure configuring the projection provider callbacks.
[StructLayout(LayoutKind.Sequential)]
struct PrjCallbacks
{
public PrjStartDirectoryEnumerationCb StartDirectoryEnumerationCallback;
public PrjEndDirectoryEnumerationCb EndDirectoryEnumerationCallback;
public PrjGetDirectoryEnumerationCb GetDirectoryEnumerationCallback;
public PrjGetPlaceholderInfoCb GetPlaceholderInfoCallback;
public PrjGetFileDataCb GetFileDataCallback;
public PrjQueryFileNameCb QueryFileNameCallback;
public PrjNotificationCb NotificationCallback;
public PrjCancelCommandCb CancelCommandCallback;
}
// Callback signatures.
delegate int PrjStartDirectoryEnumerationCb(ref PrjCallbackData callbackData, ref Guid enumerationId);
delegate int PrjEndDirectoryEnumerationCb(ref PrjCallbackData callbackData, ref Guid enumerationId);
delegate int PrjGetDirectoryEnumerationCb(ref PrjCallbackData callbackData, ref Guid enumerationId, string searchExpression, IntPtr dirEntryBufferHandle);
delegate int PrjGetPlaceholderInfoCb(ref PrjCallbackData callbackData);
delegate int PrjGetFileDataCb(ref PrjCallbackData callbackData, ulong byteOffset, uint length);
delegate int PrjQueryFileNameCb(ref PrjCallbackData callbackData);
delegate int PrjNotificationCb(ref PrjCallbackData callbackData, bool isDirectory, int notification, string destinationFileName, IntPtr operationParameters);
delegate int PrjCancelCommandCb(ref PrjCallbackData callbackData);
// Callback data passed to each of the callbacks above.
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct PrjCallbackData
{
public uint Size;
public uint Flags;
public IntPtr NamespaceVirtualizationContext;
public int CommandId;
public Guid FileId;
public Guid DataStreamId;
public string FilePathName;
public IntPtr VersionInfo;
public uint TriggeringProcessId;
public string TriggeringProcessImageFileName;
public IntPtr InstanceContext;
}
PRJ_START_DIRECTORY_ENUMERATION_CB
回拨(
PrjStartDirectoryEnumerationCb
开始枚举我的目录。它将指针传递给
PRJ_CALLBACK_DATA
PrjCallbackData
在我的代码中)。
现在,虽然我显然很好地将结构接收到了托管回调中,但所有值直到最后一个成员都有意义
InstanceContext
S_OK
).
static int StartDirectoryEnumerationCallback(ref PrjCallbackData callbackData, ref Guid enumerationId)
{
return 0; // Crashes here or when stepping out of this method.
}
我试图找出错误所在,但由于调试立即停止,没有任何异常(我没有过滤掉任何异常),我没有走多远。我意识到当我把回调改为默默地接受
IntPtr
而不是
ref PrjCallbackData
,应用程序不会崩溃。
static int StartDirectoryEnumerationCallback(IntPtr callbackData, ref Guid enumerationId)
{
return 0; // No crash executing this with IntPtr passed in.
}
delegate int PrjStartDirectoryEnumerationCb(IntPtr callbackData, ref Guid enumerationId);
从逻辑上讲,如果没有我可以访问的重要信息,这不会让我走远。
我是不是漏了一步?这样简单的结构映射是不是不可能直接映射?
如果感兴趣,事件查看器条目如下所示。我使用.NETFramework 4.6在一个新型的C#项目文件中运行应用程序(它应该解释“dotnet.exe”可执行文件名)。如果需要其他信息,我很乐意提供。
Faulting application name: dotnet.exe, version: 2.1.26919.1, time stamp: 0x5ba1bb46
Faulting module name: ntdll.dll, version: 10.0.17763.1, time stamp: 0xa369e897
Exception code: 0xc0000374
Fault offset: 0x00000000000fb349
Faulting process id: 0xfa8
Faulting application start time: 0x01d46d623aee076d
Faulting application path: C:\Program Files\dotnet\dotnet.exe
Faulting module path: C:\WINDOWS\SYSTEM32\ntdll.dll
Report Id: adcfba5c-dfd4-428d-8eb5-81aceada1983
Faulting package full name:
Faulting package-relative application ID:
请注意,如果要尝试上面的示例代码,则必须在windows1809中安装投影的文件系统功能,并将其编译为x64(x86/AnyCPU配置没有本机库)。