Skip to content

Commit 183402d

Browse files
committed
5.0.15216.0-Beta
1 parent 5e2c6d1 commit 183402d

27 files changed

+475
-131
lines changed

Common/Common.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@
1010
<Platforms>AnyCPU;x64</Platforms>
1111
</PropertyGroup>
1212
<ItemGroup>
13-
<PackageReference Include="ITHit.FileSystem" Version="5.0.14943.0-Beta" />
13+
<PackageReference Include="ITHit.FileSystem" Version="5.0.15216.0-Beta" />
1414
</ItemGroup>
1515
</Project>

README.md

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,50 @@
1-
��
1+
2+
<h1>User-mode File System Examples for Windows and macOS in .NET/C#</h1>
3+
<div class="description"></div>
4+
<ul class="list">
5+
<li>
6+
<a class="link-header" href="https://github.com/ITHit/UserFileSystemSamples/tree/master/Windows/VirtualFileSystem">
7+
<h2>Virtual File System Sample in .NET, C#</h2>
8+
</a>
9+
10+
<a href="https://github.com/ITHit/UserFileSystemSamples/tree/master/Windows/VirtualFileSystem">
11+
<p>
12+
This sample implements a virtual file system with synchronization support, on-demand loading,&nbsp;selective offline files support, upload and download progress, and error reporting. It synchronizes files and folders both from remote storage to the user f <span>...</span>
13+
</p>
14+
</a>
15+
</li>
16+
<li>
17+
<a class="link-header" href="https://github.com/ITHit/UserFileSystemSamples/tree/master/macOS">
18+
<h2>Virtual File System Sample for Mac in .NET, C#</h2>
19+
</a>
20+
21+
<a href="https://github.com/ITHit/UserFileSystemSamples/tree/master/macOS">
22+
<p>
23+
This sample implements a virtual file system for Mac with synchronization support and folders on-demand listing.&nbsp;It synchronizes files and folders both from remote storage to the user file system and from the user file system to remote storage. This <span>...</span>
24+
</p>
25+
</a>
26+
</li>
27+
<li>
28+
<a class="link-header" href="https://github.com/ITHit/UserFileSystemSamples/tree/master/Windows/VirtualDrive/">
29+
<h2>Virtual Drive Sample in .NET, C#</h2>
30+
</a>
31+
32+
<a href="https://github.com/ITHit/UserFileSystemSamples/tree/master/Windows/VirtualDrive/">
33+
<p>
34+
This is a virtual drive implementation with thumbnail support, Microsoft Office and AutoCAD documents editing support, and automatic Microsoft Office/AutoCAD documents locking. It also demonstrates custom column support in Windows File Manager.&nbsp;To si <span>...</span>
35+
</p>
36+
</a>
37+
</li>
38+
<li>
39+
<a class="link-header" href="https://github.com/ITHit/UserFileSystemSamples/tree/master/Windows/WebDAVDrive/">
40+
<h2>WebDAV Drive Sample in .NET, C#</h2>
41+
</a>
42+
43+
<a href="https://github.com/ITHit/UserFileSystemSamples/tree/master/Windows/WebDAVDrive/">
44+
<p>
45+
This sample implements a virtual file system that displays documents from a WebDAV server. You can edit documents, upload and download documents as well as manage folders structure using Windows File Manager. This sample provides automatic documents <span>...</span>
46+
</p>
47+
</a>
48+
</li>
49+
</ul>
50+

Windows/Common/Core/Common.Windows.Core.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
<PackageReference Include="Microsoft.Windows.SDK.Contracts" Version="10.0.19041.1" />
2121
</ItemGroup>
2222
<ItemGroup>
23-
<PackageReference Include="ITHit.FileSystem.Windows" Version="5.0.14943.0-Beta" />
23+
<PackageReference Include="ITHit.FileSystem.Windows" Version="5.0.15216.0-Beta" />
2424
<ProjectReference Include="..\..\..\Common\Common.csproj" />
2525
</ItemGroup>
2626
</Project>

Windows/Common/Core/FsPath.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public static string GetAttString(string path)
103103
{
104104
try
105105
{
106-
return File.GetAttributes(path).ToString();
106+
return Convert.ToString((int)File.GetAttributes(path), 2);
107107
}
108108
catch
109109
{

Windows/Common/Core/LogFormatter.cs

Lines changed: 83 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public class LogFormatter
2727
/// <summary>
2828
/// Indicates if more debugging and performance information should be logged.
2929
/// </summary>
30-
public bool DebugLoggingEnabled
30+
public bool DebugLoggingEnabled
3131
{
3232
get { return debugLoggingEnabled; }
3333
set
@@ -38,20 +38,26 @@ public bool DebugLoggingEnabled
3838
}
3939
}
4040

41-
public bool debugLoggingEnabled = false;
41+
private bool debugLoggingEnabled = false;
4242

4343
private readonly ILog log;
4444

4545
private readonly string appId;
4646

47+
private readonly string remoteStorageRootPath;
48+
49+
private const int sourcePathWidth = 60;
50+
private const int remoteStorageIdWidth = 20;
51+
4752
/// <summary>
4853
/// Creates instance of this class.
4954
/// </summary>
5055
/// <param name="log">Log4net logger.</param>
51-
public LogFormatter(ILog log, string appId)
56+
public LogFormatter(ILog log, string appId, string remoteStorageRootPath)
5257
{
5358
this.log = log;
5459
this.appId = appId;
60+
this.remoteStorageRootPath = remoteStorageRootPath;
5561
LogFilePath = ConfigureLogger();
5662
}
5763

@@ -84,19 +90,45 @@ public void PrintEnvironmentDescription()
8490
log.Info($"\n{"AppID:",-15} {appId}");
8591
log.Info($"\n{"Engine version:",-15} {typeof(IEngine).Assembly.GetName().Version}");
8692
log.Info($"\n{"OS version:",-15} {RuntimeInformation.OSDescription}");
87-
log.Info($"\n{"Env version:",-15} {RuntimeInformation.FrameworkDescription} {IntPtr.Size * 8}bit.");
93+
log.Info($"\n{".NET version:",-15} {RuntimeInformation.FrameworkDescription} {IntPtr.Size * 8}bit.");
8894
//log.Info($"\n{"Is UWP:",-15} {PackageRegistrar.IsRunningAsUwp()}");
89-
log.Info($"\n{"Admin mode:",-15} {new System.Security.Principal.WindowsPrincipal(System.Security.Principal.WindowsIdentity.GetCurrent()).IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator)}");
95+
log.Info($"\n{"Admin mode:",-15} {new System.Security.Principal.WindowsPrincipal(System.Security.Principal.WindowsIdentity.GetCurrent()).IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator)}");
96+
}
97+
98+
/// <summary>
99+
/// Print Engine config, settings, console commands, logging headers.
100+
/// </summary>
101+
/// <param name="engine">Engine instance.</param>
102+
/// <param name="remoteStorageRootPath">Remote storage root path.</param>
103+
public async Task PrintEngineStartInfoAsync(EngineWindows engine)
104+
{
105+
await PrintEngineEnvironmentDescriptionAsync(engine);
106+
107+
// Log console commands.
108+
PrintHelp();
109+
110+
// Log logging columns headers.
111+
PrintHeader();
112+
}
113+
114+
public async Task PrintEngineEnvironmentDescriptionAsync(EngineWindows engine)
115+
{
116+
log.Info($"\n{"FS root:",-15} {engine.Path}");
117+
log.Info($"\n{"RS root:",-15} {remoteStorageRootPath}");
118+
log.Info($"\n{"AutoLock:",-15} {engine.AutoLock}");
119+
120+
// Log indexing state. Sync root must be indexed.
121+
await PrintIndexingStateAsync(engine.Path);
90122
}
91123

92124
/// <summary>
93125
/// Prints indexing state.
94126
/// </summary>
95127
/// <param name="path">File system path.</param>
96-
public async Task PrintIndexingStateAsync(string path)
128+
private async Task PrintIndexingStateAsync(string path)
97129
{
98130
StorageFolder userFileSystemRootFolder = await StorageFolder.GetFolderFromPathAsync(path);
99-
log.Info($"\nIndexed state: {(await userFileSystemRootFolder.GetIndexedStateAsync())}");
131+
log.Info($"\n{"Indexed state:",-15} {await userFileSystemRootFolder.GetIndexedStateAsync()}");
100132
}
101133

102134
/// <summary>
@@ -108,7 +140,7 @@ public void PrintHelp()
108140
log.Info("\nPress Spacebar to exit without unregistering (simulate reboot).");
109141
log.Info("\nPress 'p' to unregister sparse package.");
110142
log.Info("\nPress 'e' to start/stop the Engine and all sync services.");
111-
log.Info("\nPress 's' to start/stop full synchronization service.");
143+
log.Info("\nPress 's' to start/stop synchronization service.");
112144
log.Info("\nPress 'm' to start/stop remote storage monitor.");
113145
log.Info("\nPress 'd' to enable/disable debug and performance logging.");
114146
log.Info($"\nPress 'l' to open log file. ({LogFilePath})");
@@ -118,17 +150,17 @@ public void PrintHelp()
118150

119151
public void LogError(IEngine sender, EngineErrorEventArgs e)
120152
{
121-
WriteLog(e, log4net.Core.Level.Error);
153+
WriteLog(sender, e, log4net.Core.Level.Error);
122154
}
123155

124156
public void LogMessage(IEngine sender, EngineMessageEventArgs e)
125157
{
126-
WriteLog(e, log4net.Core.Level.Info);
158+
WriteLog(sender, e, log4net.Core.Level.Info);
127159
}
128160

129161
public void LogDebug(IEngine sender, EngineMessageEventArgs e)
130162
{
131-
WriteLog(e, log4net.Core.Level.Debug);
163+
WriteLog(sender, e, log4net.Core.Level.Debug);
132164
}
133165

134166
/// <summary>
@@ -137,23 +169,36 @@ public void LogDebug(IEngine sender, EngineMessageEventArgs e)
137169
/// <param name="log">log4net</param>
138170
/// <param name="e">Message or error description.</param>
139171
/// <param name="level">Log level.</param>
140-
private void WriteLog(EngineMessageEventArgs e, log4net.Core.Level level)
172+
private void WriteLog(IEngine sender, EngineMessageEventArgs e, log4net.Core.Level level)
141173
{
142174
string att = FsPath.Exists(e.SourcePath) ? FsPath.GetAttString(e.SourcePath) : null;
143175
string process = null;
144176
byte? priorityHint = null;
145-
ulong? clientFileId = null;
177+
string fileId = null;
146178
string size = null;
147179

148180
if (e.OperationContext != null)
149181
{
150182
process = System.IO.Path.GetFileName(e.OperationContext.ProcessInfo?.ImagePath);
151183
priorityHint = e.OperationContext.PriorityHint;
152-
clientFileId = (e.OperationContext as IWindowsOperationContext).FileId;
184+
fileId = (e.OperationContext as IWindowsOperationContext).FileId.ToString();
153185
size = FsPath.FormatBytes((e.OperationContext as IWindowsOperationContext).FileSize);
154186
}
155187

156-
string message = Format(DateTimeOffset.Now.ToString("hh:mm:ss.fff"), process, priorityHint?.ToString(), e.ComponentName, e.Message, e.SourcePath, att, e.TargetPath);
188+
string sourcePath = e.SourcePath?.FitString(sourcePathWidth, 6);
189+
string targetPath = e.TargetPath?.FitString(sourcePathWidth, 6);
190+
191+
// Trim sync root and remote storage root to reduce ammount of logging and improve logs readability
192+
//if (sender != null)
193+
//{
194+
//sourcePath = sourcePath?.Replace((sender as EngineWindows).Path, "<FS root>");
195+
//sourcePath = sourcePath?.Replace(remoteStorageRootPath, "<RS root>");
196+
197+
//targetPath = targetPath?.Replace((sender as EngineWindows).Path, "<FS root>");
198+
//targetPath = targetPath?.Replace(remoteStorageRootPath, "<RS root>");
199+
//}
200+
201+
string message = Format(DateTimeOffset.Now.ToString("hh:mm:ss.fff"), process, priorityHint?.ToString(), fileId, "", e.ComponentName, e.Message, sourcePath, att, targetPath);
157202

158203
if (level == log4net.Core.Level.Error)
159204
{
@@ -172,18 +217,36 @@ private void WriteLog(EngineMessageEventArgs e, log4net.Core.Level level)
172217

173218
}
174219

175-
private static string Format(string date, string process, string priorityHint, string componentName, string message, string sourcePath, string attributes, string targetPath)
220+
private static string Format(string date, string process, string priorityHint, string fileId, string remoteStorageId, string componentName, string message, string sourcePath, string attributes, string targetPath)
176221
{
177-
return $"{Environment.NewLine}|{date, -12}| {process,-25}| {priorityHint,-5}| {componentName,-26}| {message,-45}| {sourcePath,-80}| {attributes, -22}| {targetPath}";
222+
// {fileId,-18} | {remoteStorageId,-remoteStorageIdWidth}
223+
return $"{Environment.NewLine}|{date, -12}| {process,-25}| {priorityHint,-5}| {componentName,-26}| {message,-45}| {sourcePath,-sourcePathWidth} | {attributes, 23 } | {targetPath}";
178224
}
179225

180226
/// <summary>
181227
/// Prints logging data headers.
182228
/// </summary>
183-
public void PrintHeader()
229+
private void PrintHeader()
230+
{
231+
log.Info(Format("Time", "Process Name", "Prty", "FS ID", "RS ID", "Component", "Message", "Source Path", "Attributes", "Target Path"));
232+
log.Info(Format("----", "------------", "----", "_____", "_____", "---------", "-------", "-----------", "----------", "-----------"));
233+
}
234+
}
235+
236+
static class StringExtensions
237+
{
238+
private const string replacement = "...";
239+
internal static string FitString(this string str, int maxLength, int startReplace)
184240
{
185-
log.Info(Format("Time", "Process Name", "Prty", "Component", "Operation", "Source Path", "Attributes", "Target Path"));
186-
log.Info(Format("----", "------------", "----", "---------", "---------", "-----------", "----------", "-----------"));
241+
int length = str.Length;
242+
if (length > maxLength)
243+
{
244+
string start = str.Substring(0, startReplace);
245+
string end = str.Substring(length - (maxLength - (startReplace + replacement.Length)));
246+
return $"{start}{replacement}{end}";
247+
}
248+
return str;
187249
}
188250
}
251+
189252
}

Windows/Common/VirtualDrive/Common.Windows.VirtualDrive.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<Compile Remove="ServerToClientSync.cs" />
1818
</ItemGroup>
1919
<ItemGroup>
20-
<PackageReference Include="ITHit.FileSystem.Windows" Version="5.0.14943.0-Beta" />
20+
<PackageReference Include="ITHit.FileSystem.Windows" Version="5.0.15216.0-Beta" />
2121
<ProjectReference Include="..\..\..\Common\Common.csproj" />
2222
<ProjectReference Include="..\Core\Common.Windows.Core.csproj" />
2323
</ItemGroup>

Windows/Common/VirtualDrive/MenuCommandLock.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public class MenuCommandLock : IMenuCommand
3131
public MenuCommandLock(EngineWindows engine, ILogger logger)
3232
{
3333
this.engine = engine;
34-
this.logger = logger.CreateLogger("Lock Command");
34+
this.logger = logger.CreateLogger("Lock Menu Command");
3535
}
3636

3737
/// <inheritdoc/>
@@ -73,15 +73,16 @@ public async Task InvokeAsync(IEnumerable<string> filesPath)
7373
{
7474
try
7575
{
76-
IClientNotifications clientNotifications = engine.ClientNotifications(userFileSystemPath);
76+
IClientNotifications clientNotifications = engine.ClientNotifications(userFileSystemPath, logger);
7777
if (isLocked)
7878
await clientNotifications.UnlockAsync();
7979
else
8080
await clientNotifications.LockAsync();
8181
}
8282
catch (Exception ex)
8383
{
84-
logger.LogError("Failed to lock item", userFileSystemPath, null, ex);
84+
string actionName = isLocked ? "Unlock" : "Lock";
85+
logger.LogError($"Failed to {actionName} item", userFileSystemPath, null, ex);
8586
}
8687
}
8788
}
@@ -106,7 +107,7 @@ public async Task<string> GetToolTipAsync(IEnumerable<string> filesPath)
106107
{
107108
try
108109
{
109-
IClientNotifications clientNotifications = engine.ClientNotifications(userFileSystemPath);
110+
IClientNotifications clientNotifications = engine.ClientNotifications(userFileSystemPath, logger);
110111
LockMode lockMode = await clientNotifications.GetLockModeAsync(cancellationToken);
111112

112113
bool isLocked = lockMode != LockMode.None;

Windows/Common/VirtualDrive/VirtualEngineBase.cs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
using System;
22
using System.IO;
3+
using System.Threading;
34
using System.Threading.Tasks;
4-
using log4net;
55

6-
using ITHit.FileSystem;
76
using ITHit.FileSystem.Windows;
8-
using ITHit.FileSystem.Samples.Common.Windows;
9-
using System.Collections.Generic;
10-
using System.Threading;
117

128

139
namespace ITHit.FileSystem.Samples.Common.Windows
@@ -61,6 +57,7 @@ public VirtualEngineBase(
6157
Error += logFormatter.LogError;
6258
Message += logFormatter.LogMessage;
6359
Debug += logFormatter.LogDebug;
60+
SyncService.StateChanged += SyncService_StateChanged;
6461

6562
//RemoteStorageMonitor = new RemoteStorageMonitor(remoteStorageRootPath, this, log4net);
6663
}
@@ -91,11 +88,11 @@ public override async Task<bool> FilterAsync(OperationType operationType, string
9188
return FilterHelper.AvoidSync(userFileSystemPath);
9289
}
9390
}
94-
catch(FileNotFoundException ex)
91+
catch(FileNotFoundException)
9592
{
9693
// Typically the file is not found in case of some temporary file that is being deleted.
9794
// We do not want to continue processing this file, and we do not want any exceptions in the log as this is a normal behaviour.
98-
LogMessage(ex.Message, userFileSystemPath, userFileSystemNewPath, operationContext);
95+
LogDebug($"{nameof(IEngine)}.{nameof(FilterAsync)}(): Item not found", userFileSystemPath, userFileSystemNewPath, operationContext);
9996
return true;
10097
}
10198
}
@@ -114,7 +111,7 @@ public override async Task StopAsync()
114111
}
115112

116113
/// <summary>
117-
/// Show status change.
114+
/// Fired on Engine status change.
118115
/// </summary>
119116
/// <param name="engine">Engine</param>
120117
/// <param name="e">Contains new and old Engine state.</param>
@@ -123,6 +120,19 @@ private void Engine_StateChanged(Engine engine, EngineWindows.StateChangeEventAr
123120
engine.LogMessage($"{e.NewState}");
124121
}
125122

123+
/// <summary>
124+
/// Fired on sync service status change.
125+
/// </summary>
126+
/// <param name="sender">Sync service.</param>
127+
/// <param name="e">Contains new and old sync service state.</param>
128+
private void SyncService_StateChanged(SyncService sender, SynchEventArgs e)
129+
{
130+
if (e.NewState == SynchronizationState.Enabled || e.NewState == SynchronizationState.Disabled)
131+
{
132+
SyncService.Logger.LogMessage($"{e.NewState}");
133+
}
134+
}
135+
126136

127137
private bool disposedValue;
128138

0 commit comments

Comments
 (0)