示例#1
0
        /// <inheritdoc/>
        public async Task <byte[]> CreateFileAsync(IFileMetadata fileMetadata, Stream content = null)
        {
            Logger.LogMessage($"{nameof(IFolder)}.{nameof(CreateFileAsync)}()", Path.Combine(UserFileSystemPath, fileMetadata.Name));

            FileInfo remoteStorageItem = new FileInfo(Path.Combine(RemoteStoragePath, fileMetadata.Name));

            // Upload remote storage file content.
            await using (FileStream remoteStorageStream = remoteStorageItem.Open(FileMode.CreateNew, FileAccess.Write, FileShare.Delete))
            {
                if (content != null)
                {
                    await content.CopyToAsync(remoteStorageStream);

                    remoteStorageStream.SetLength(content.Length);
                }
            }

            // Update remote storage file metadata.
            remoteStorageItem.Attributes        = fileMetadata.Attributes;
            remoteStorageItem.CreationTimeUtc   = fileMetadata.CreationTime.UtcDateTime;
            remoteStorageItem.LastWriteTimeUtc  = fileMetadata.LastWriteTime.UtcDateTime;
            remoteStorageItem.LastAccessTimeUtc = fileMetadata.LastAccessTime.UtcDateTime;
            remoteStorageItem.LastWriteTimeUtc  = fileMetadata.LastWriteTime.UtcDateTime;

            // Return remote storage item ID. It will be passed later into IEngine.GetFileSystemItemAsync() method.
            return(WindowsFileSystemItem.GetItemIdByPath(remoteStorageItem.FullName));
        }
示例#2
0
        /// <summary>
        /// Gets a user file system item info from the remote storage data.
        /// </summary>
        /// <param name="remoteStorageItem">Remote storage item info.</param>
        /// <returns>User file system item info.</returns>
        public static IFileSystemItemMetadata GetUserFileSysteItemMetadata(FileSystemInfo remoteStorageItem)
        {
            IFileSystemItemMetadata userFileSystemItem;

            if (remoteStorageItem is FileInfo)
            {
                userFileSystemItem = new FileMetadata();
                ((FileMetadata)userFileSystemItem).Length = ((FileInfo)remoteStorageItem).Length;
            }
            else
            {
                userFileSystemItem = new FolderMetadata();
            }

            // Store you item ID here. It will be passed to IEngine.GetFileSystemItemAsync() during every operation.
            // Note that the file is deleted during MS Office transactional save and iten ID will be deleted with it.
            // See Virtual Drive sample for MS Office documents editing.
            userFileSystemItem.ItemId = WindowsFileSystemItem.GetItemIdByPath(remoteStorageItem.FullName);

            userFileSystemItem.Name           = remoteStorageItem.Name;
            userFileSystemItem.Attributes     = remoteStorageItem.Attributes;
            userFileSystemItem.CreationTime   = remoteStorageItem.CreationTime;
            userFileSystemItem.LastWriteTime  = remoteStorageItem.LastWriteTime;
            userFileSystemItem.LastAccessTime = remoteStorageItem.LastAccessTime;
            userFileSystemItem.ChangeTime     = remoteStorageItem.LastWriteTime;

            return(userFileSystemItem);
        }
 /// <summary>
 /// Deletes a file or folder placeholder in user file system.
 /// </summary>
 /// <remarks>This method failes if the file or folder in user file system is modified (not in sync with the remote storage).</remarks>
 public async Task DeleteAsync()
 {
     // Windows does not provide a function to delete a placeholder file only if it is not modified.
     // Here we check that the file is not modified in user file system, using GetInSync() call.
     // To avoid the file modification between GetInSync() call and Delete() call in this method we
     // open it without FileShare.Write flag.
     using (WindowsFileSystemItem userFileSystemWinItem = WindowsFileSystemItem.Open(userFileSystemPath, (FileAccess)0, FileMode.Open, FileShare.Read | FileShare.Delete))
     {
         if (PlaceholderItem.GetInSync(userFileSystemWinItem.SafeHandle))
         {
             if (FsPath.IsFile(userFileSystemPath))
             {
                 File.Delete(userFileSystemPath);
             }
             else
             {
                 Directory.Delete(userFileSystemPath, true);
             }
         }
         else
         {
             throw new IOException("File not in-sync.");
         }
     }
 }
        ///<inheritdoc>
        public async Task MoveToAsync(string userFileSystemNewPath, byte[] newParentItemId, IOperationContext operationContext, IConfirmationResultContext resultContext)
        {
            string userFileSystemOldPath = this.UserFileSystemPath;

            Logger.LogMessage($"{nameof(IFileSystemItem)}.{nameof(MoveToAsync)}()", userFileSystemOldPath, userFileSystemNewPath);

            string remoteStorageOldPath       = RemoteStoragePath;
            string remoteStorageNewParentPath = WindowsFileSystemItem.GetPathByItemId(newParentItemId);
            string remoteStorageNewPath       = Path.Combine(remoteStorageNewParentPath, Path.GetFileName(userFileSystemNewPath));

            FileSystemInfo remoteStorageOldItem = FsPath.GetFileSystemItem(remoteStorageOldPath);

            if (remoteStorageOldItem != null)
            {
                if (remoteStorageOldItem is FileInfo)
                {
                    (remoteStorageOldItem as FileInfo).MoveTo(remoteStorageNewPath, true);
                }
                else
                {
                    (remoteStorageOldItem as DirectoryInfo).MoveTo(remoteStorageNewPath);
                }
                Logger.LogMessage("Moved item in remote storage succesefully", userFileSystemOldPath, userFileSystemNewPath);
            }
        }
示例#5
0
        /// <summary>
        /// Creates or updates file in the remote storage.
        /// </summary>
        /// <param name="remoteStoragePath">Path of the file to be created or updated in the remote storage.</param>
        /// <param name="newInfo">New information about the file, such as modification date, attributes, custom data, etc.</param>
        /// <param name="mode">Specifies if a new file should be created or existing file should be updated.</param>
        /// <param name="newContentStream">New file content or null if the file content is not modified.</param>
        /// <param name="eTagOld">The ETag to be sent to the remote storage as part of the update request to make sure the content is not overwritten.</param>
        /// <param name="lockInfo">Information about the lock. Null if the item is not locked.</param>
        /// <returns>The new ETag returned from the remote storage.</returns>
        protected async Task <string> CreateOrUpdateFileAsync(
            string remoteStoragePath, IFileMetadata newInfo, FileMode mode, Stream newContentStream = null, string eTagOld = null, ServerLockInfo lockInfo = null)
        {
            FileInfo remoteStorageItem = new FileInfo(remoteStoragePath);

            try
            {
                Program.VirtualDrive.RemoteStorageMonitor.Enabled = false; // Disable RemoteStorageMonitor to avoid circular calls.

                // If another thread is trying to sync the same file, this call will fail in other threads.
                // In your implementation you must lock your remote storage file, or block it for reading and writing by other means.
                await using (FileStream remoteStorageStream = remoteStorageItem.Open(mode, FileAccess.Write, FileShare.None))
                {
                    string userFileSystemPath = Mapping.ReverseMapPath(remoteStoragePath);
                    if (mode == FileMode.Open)
                    {
                        // Verify that the item in the remote storage is not modified since it was downloaded to the user file system.
                        // In your real-life application you will send the ETag to the server as part of the update request.
                        FileSystemItemMetadataExt itemInfo = Mapping.GetUserFileSysteItemMetadata(remoteStorageItem);
                        if (!(await VirtualDrive.GetETagManager(userFileSystemPath).ETagEqualsAsync(itemInfo)))
                        {
                            throw new ConflictException(Modified.Server, "Item is modified in the remote storage, ETags not equal.");
                        }
                    }

                    // Update ETag/LastWriteTime in user file system, so the synchronyzation or remote storage monitor would not start the new update.
                    // This is only required to avoid circular updates because of the simplicity of this sample.
                    // In your real-life application you will receive a new ETag from the server in the update response
                    // and return it from this method.
                    string eTagNew = newInfo.LastWriteTime.ToUniversalTime().ToString("o");
                    await VirtualDrive.GetETagManager(userFileSystemPath).SetETagAsync(eTagNew);

                    // Update remote storage file content.
                    if (newContentStream != null)
                    {
                        await newContentStream.CopyToAsync(remoteStorageStream);

                        remoteStorageStream.SetLength(newContentStream.Length);
                    }

                    // Update remote storage file basic info.
                    WindowsFileSystemItem.SetFileInformation(
                        remoteStorageStream.SafeFileHandle,
                        newInfo.Attributes,
                        newInfo.CreationTime,
                        newInfo.LastWriteTime,
                        newInfo.LastAccessTime,
                        newInfo.LastWriteTime);

                    return(eTagNew);
                }
            }
            finally
            {
                Program.VirtualDrive.RemoteStorageMonitor.Enabled = true;
            }
        }
示例#6
0
        /// <summary>
        /// Recursively restores OriginalPath and the 'locked' icon.
        /// </summary>
        /// <param name="userFileSystemNewPath">Path in the user file system to start recursive processing.</param>
        private async Task MoveToCompletionRecursiveAsync(string userFileSystemNewPath)
        {
            if (FsPath.IsFolder(userFileSystemNewPath))
            {
                if (!new DirectoryInfo(userFileSystemNewPath).Attributes.HasFlag(System.IO.FileAttributes.Offline))
                {
                    //LogMessage("Folder offline, skipping:", userFileSystemFolderPath);

                    IEnumerable <string> userFileSystemChildren = Directory.EnumerateFileSystemEntries(userFileSystemNewPath, "*");

                    foreach (string userFileSystemChildPath in userFileSystemChildren)
                    {
                        try
                        {
                            await MoveToCompletionRecursiveAsync(userFileSystemChildPath);
                        }
                        catch (Exception ex)
                        {
                            logger.LogError("Failed to complete move", userFileSystemChildPath, null, ex);
                        }
                    }
                }
            }

            if (FsPath.Exists(userFileSystemNewPath) &&         // This check is just to avoid extra error in the log.
                !FsPath.IsRecycleBin(userFileSystemNewPath) &&  // When a file with content is deleted, it is moved to a Recycle Bin.
                !FsPath.AvoidAutoLock(userFileSystemNewPath))   // No need to update temp MS Office docs.
            {
                // Open file to prevent reads and changes between GetFileDataSizeInfo() call and SetInSync() call.
                using (WindowsFileSystemItem userFileSystemWinItem = WindowsFileSystemItem.OpenReadAttributes(userFileSystemNewPath, FileMode.Open, FileShare.None))
                {
                    // If a file with content is deleted it is moved to a recycle bin and converted
                    // to a regular file, so placeholder features are not available on it, checking if a file is a placeholder.
                    if (/*updateTargetOnSuccess &&*/ PlaceholderItem.IsPlaceholder(userFileSystemNewPath))
                    {
                        PlaceholderItem placeholderNew = PlaceholderItem.GetItem(userFileSystemNewPath);

                        await virtualDrive.GetUserFileSystemRawItem(userFileSystemNewPath, logger).ClearStateAsync();

                        // Update OriginalPath if the item is not new.
                        // Required for pptx and xlsx files Save As operation.
                        if (!placeholderNew.IsNew(virtualDrive))
                        {
                            // Update OriginalPath, so the item does not appear as moved.
                            logger.LogMessage("Setting Original Path", userFileSystemNewPath);
                            placeholderNew.SetOriginalPath(userFileSystemNewPath);
                        }

                        // Restore the 'locked' icon.
                        ServerLockInfo existingLock = await virtualDrive.LockManager(userFileSystemNewPath, logger).GetLockInfoAsync();

                        await virtualDrive.GetUserFileSystemRawItem(userFileSystemNewPath, logger).SetLockInfoAsync(existingLock);
                    }
                }
            }
        }
        private async Task CreateOrUpdateFileAsync(string userFileSystemPath, bool create)
        {
            try
            {
                Program.RemoteStorageMonitorInstance.Enabled = false; // Disable RemoteStorageMonitor to avoid circular calls.

                FileInfo userFileSystemFile = new FileInfo(userFileSystemPath);
                FileInfo remoteStorageFile  = new FileInfo(remoteStoragePath);

                FileMode fileMode = create ? FileMode.CreateNew : FileMode.Open;


                await using (FileStream userFileSystemStream = userFileSystemFile.Open(FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    // If another thread is trying to sync the same file, this call will fail in other threads.
                    // In your implemntation you must lock your remote storage file, or block it for reading and writing by other means.
                    await using (FileStream remoteStorageStream = remoteStorageFile.Open(fileMode, FileAccess.Write, FileShare.None))
                    {
                        userFileSystemFile.Refresh(); // Ensures LastWriteTimeUtc is in sync with file content after Open() was called.

                        // Update ETag/LastWriteTime in user file system, so the synchronyzation or remote storage monitor would not start the new update.
                        byte[] customData = BitConverter.GetBytes(userFileSystemFile.LastWriteTime.ToBinary());
                        PlaceholderItem.SetCustomData(userFileSystemStream.SafeFileHandle, customData);

                        // Update remote storage file content.
                        await userFileSystemStream.CopyToAsync(remoteStorageStream);

                        remoteStorageStream.SetLength(userFileSystemStream.Length);

                        // Update remote storage file basic info.
                        WindowsFileSystemItem.SetFileInformation(remoteStorageStream.SafeFileHandle,
                                                                 userFileSystemFile.Attributes & (FileAttributes) ~FileAttributesExt.Pinned, // Remove Pinned flag.
                                                                 userFileSystemFile.CreationTimeUtc,
                                                                 userFileSystemFile.LastWriteTimeUtc,
                                                                 userFileSystemFile.LastAccessTimeUtc,
                                                                 userFileSystemFile.LastWriteTimeUtc);

                        // If you are using ETags, here you will also send to the remote storage a new file ETag.

                        PlaceholderItem.SetInSync(userFileSystemStream.SafeFileHandle, true);
                    }
                }
            }
            finally
            {
                Program.RemoteStorageMonitorInstance.Enabled = true;
            }
        }
示例#8
0
        //$>

        /// <summary>
        /// Deletes a file or folder placeholder in user file system.
        /// </summary>
        /// <remarks>
        /// This method throws <see cref="ConflictException"/> if the file or folder or any file or folder
        /// in the folder hierarchy being deleted in user file system is modified (not in sync with the remote storage).
        /// </remarks>
        /// <returns>True if the file was deleted. False - otherwise.</returns>
        public async Task <bool> DeleteAsync()
        {
            // Cloud Filter API does not provide a function to delete a placeholder file only if it is not modified.
            // Here we check that the file is not modified in user file system, using GetInSync() call.
            // To avoid the file modification between GetInSync() call and Delete() call we
            // open it without FileShare.Write flag.
            try
            {
                // Because of the on-demand population the file or folder placeholder may not exist in the user file system.
                if (FsPath.Exists(userFileSystemPath))
                {
                    using (WindowsFileSystemItem userFileSystemWinItem = WindowsFileSystemItem.Open(userFileSystemPath, (FileAccess)0, FileMode.Open, FileShare.Read | FileShare.Delete))
                    {
                        if (PlaceholderItem.GetInSync(userFileSystemWinItem.SafeHandle))
                        {
                            if (FsPath.IsFile(userFileSystemPath))
                            {
                                File.Delete(userFileSystemPath);
                            }
                            else
                            {
                                Directory.Delete(userFileSystemPath, true);
                            }

                            // Delete ETag
                            ETag.DeleteETag(userFileSystemPath);

                            return(true);
                        }
                        else
                        {
                            throw new ConflictException(Modified.Client, "The item is not in-sync with the cloud.");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                await SetDownloadErrorStateAsync(ex);

                // Rethrow the exception preserving stack trace of the original exception.
                System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(ex).Throw();
            }

            return(false);
        }
示例#9
0
        /// <inheritdoc/>
        public async Task <byte[]> CreateFolderAsync(IFolderMetadata folderMetadata)
        {
            Logger.LogMessage($"{nameof(IFolder)}.{nameof(CreateFolderAsync)}()", Path.Combine(UserFileSystemPath, folderMetadata.Name));

            DirectoryInfo remoteStorageItem = new DirectoryInfo(Path.Combine(RemoteStoragePath, folderMetadata.Name));

            remoteStorageItem.Create();

            // Update remote storage folder metadata.
            remoteStorageItem.Attributes        = folderMetadata.Attributes;
            remoteStorageItem.CreationTimeUtc   = folderMetadata.CreationTime.UtcDateTime;
            remoteStorageItem.LastWriteTimeUtc  = folderMetadata.LastWriteTime.UtcDateTime;
            remoteStorageItem.LastAccessTimeUtc = folderMetadata.LastAccessTime.UtcDateTime;
            remoteStorageItem.LastWriteTimeUtc  = folderMetadata.LastWriteTime.UtcDateTime;

            // Return remote storage item ID. It will be passed later into IEngine.GetFileSystemItemAsync() method.
            return(WindowsFileSystemItem.GetItemIdByPath(remoteStorageItem.FullName));
        }
        /// <summary>
        /// Creates instance of this class.
        /// </summary>
        /// <param name="userFileSystemPath">File or folder path in the user file system.</param>
        /// <param name="itemId">Remote storage item ID.</param>
        /// <param name="logger">Logger.</param>
        public VirtualFileSystemItem(string userFileSystemPath, byte[] itemId, ILogger logger)
        {
            if (string.IsNullOrEmpty(userFileSystemPath))
            {
                throw new ArgumentNullException(nameof(userFileSystemPath));
            }
            ItemId = itemId ?? throw new ArgumentNullException(nameof(itemId));
            Logger = logger ?? throw new ArgumentNullException(nameof(logger));

            UserFileSystemPath = userFileSystemPath;

            try
            {
                RemoteStoragePath = WindowsFileSystemItem.GetPathByItemId(ItemId);
            }
            catch (ArgumentException)
            {
                // When a file is deleted, the IFile.CloseAsync() is called for the deleted file.
            }
        }
        internal async Task MoveToAsync(string userFileSystemNewPath, IConfirmationResultContext resultContext = null)
        {
            string userFileSystemOldPath = userFileSystemPath;

            try
            {
                bool?  inSync = null;
                bool   updateTargetOnSuccess = false;
                string eTag = null;
                try
                {
                    if (!FsPath.IsRecycleBin(userFileSystemNewPath) && // When a file is deleted, it is moved to a Recycle Bin.
                        !FsPath.AvoidSync(userFileSystemOldPath) && !FsPath.AvoidSync(userFileSystemNewPath))
                    {
                        logger.LogMessage("Moving item in remote storage", userFileSystemOldPath, userFileSystemNewPath);

                        // Read In-Sync state before move and set after move
                        if (FsPath.Exists(userFileSystemOldPath))
                        {
                            inSync = PlaceholderItem.GetItem(userFileSystemOldPath).GetInSync();
                        }

                        eTag = await ETag.GetETagAsync(userFileSystemOldPath);

                        ETag.DeleteETag(userFileSystemOldPath);

                        IUserFileSystemItem userFileSystemItemOld = await virtualDrive.GetItemAsync <IUserFileSystemItem>(userFileSystemOldPath);

                        await userFileSystemItemOld.MoveToAsync(userFileSystemNewPath);

                        updateTargetOnSuccess = true;
                        logger.LogMessage("Moved succesefully in remote storage", userFileSystemOldPath, userFileSystemNewPath);
                    }
                }
                finally
                {
                    if (resultContext != null)
                    {
                        resultContext.ReturnConfirmationResult();
                    }

                    // This check is just to avoid extra error in the log.
                    if (FsPath.Exists(userFileSystemNewPath))
                    {
                        // Open file to preven reads and changes between GetFileDataSizeInfo() call and SetInSync() call.
                        using (WindowsFileSystemItem userFileSystemWinItem = WindowsFileSystemItem.OpenReadAttributes(userFileSystemNewPath, FileMode.Open, FileShare.None))
                        {
                            if ((eTag != null) && PlaceholderItem.IsPlaceholder(userFileSystemNewPath))
                            {
                                await ETag.SetETagAsync(userFileSystemNewPath, eTag);
                            }

                            // If a file with content is deleted it is moved to a recycle bin and converted
                            // to a regular file, so placeholder features are not available on it, checking if a file is a placeholder.
                            if (updateTargetOnSuccess && PlaceholderItem.IsPlaceholder(userFileSystemNewPath))
                            {
                                PlaceholderItem placeholderNew = PlaceholderItem.GetItem(userFileSystemNewPath);

                                // Update OriginalPath, so the item does not appear as moved.
                                placeholderNew.SetOriginalPath(userFileSystemNewPath);

                                if (inSync != null)
                                {
                                    placeholderNew.SetInSync(inSync.Value);
                                }
                                else if ((placeholderNew is PlaceholderFile) && ((PlaceholderFile)placeholderNew).GetFileDataSizeInfo().ModifiedDataSize == 0)
                                {
                                    placeholderNew.SetInSync(true);
                                }
                                await new UserFileSystemRawItem(userFileSystemNewPath).ClearStateAsync();
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                string userFileSystemPath = FsPath.Exists(userFileSystemNewPath) ? userFileSystemNewPath : userFileSystemOldPath;
                await new UserFileSystemRawItem(userFileSystemPath).SetUploadErrorStateAsync(ex);

                // Rethrow the exception preserving stack trace of the original exception.
                System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(ex).Throw();
            }
        }
        /// <summary>
        /// Creates or updates the item in the remote storage.
        /// </summary>
        /// <param name="mode">
        /// Indicates if the file should created or updated.
        /// Supported modes are <see cref="FileMode.CreateNew"/> and <see cref="FileMode.Open"/>
        /// </param>
        /// <param name="lockInfo">Information about the lock. Pass null if the item is not locked.</param>
        private async Task CreateOrUpdateAsync(FileMode mode, ServerLockInfo lockInfo = null)
        {
            if ((mode != FileMode.CreateNew) && (mode != FileMode.Open))
            {
                throw new ArgumentOutOfRangeException("mode", $"Must be {FileMode.CreateNew} or {FileMode.Open}");
            }

            FileSystemInfo userFileSystemItem = FsPath.GetFileSystemItem(userFileSystemPath);

            using (WindowsFileSystemItem userFileSystemWinItem = WindowsFileSystemItem.OpenReadAttributes(userFileSystemPath, FileMode.Open, FileShare.Read))
            //await using (FileStream userFileSystemStream = userFileSystemFile.Open(FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                // Create the new file/folder in the remote storage only if the file/folder in the user file system was not moved.
                // If the file is moved in user file system, move must first be syched to remote storage.
                if ((mode == FileMode.CreateNew) && PlaceholderItem.GetItem(userFileSystemPath).IsMoved())
                {
                    string originalPath = PlaceholderItem.GetItem(userFileSystemPath).GetOriginalPath();
                    throw new ConflictException(Modified.Client, $"The item was moved. Original path: {originalPath}");
                }

                // Ensures LastWriteTimeUtc is in sync with file content after Open() was called.
                userFileSystemItem.Refresh();

                IFileSystemItemBasicInfo info = GetBasicInfo(userFileSystemItem);

                // Update remote storage file.
                FileStream userFileSystemStream = null;
                try
                {
                    string eTag = null;
                    if (FsPath.IsFile(userFileSystemPath))
                    {
                        // File is marked as not in-sync when updated OR moved.
                        // Opening a file for reading triggers hydration, make sure to open only if content is modified.
                        if (PlaceholderFile.GetFileDataSizeInfo(userFileSystemWinItem.SafeHandle).ModifiedDataSize > 0)
                        {
                            //userFileSystemStream = new FileStream(userFileSystemWinItem.SafeHandle, FileAccess.Read);
                            userFileSystemStream = ((FileInfo)userFileSystemItem).Open(FileMode.Open, FileAccess.Read, FileShare.Read);
                        }
                        if (mode == FileMode.CreateNew)
                        {
                            string      userFileSystemParentPath = Path.GetDirectoryName(userFileSystemPath);
                            IUserFolder userFolder = await virtualDrive.GetItemAsync <IUserFolder>(userFileSystemParentPath);

                            eTag = await userFolder.CreateFileAsync((IFileBasicInfo)info, userFileSystemStream);
                        }
                        else
                        {
                            IUserFile userFile = await virtualDrive.GetItemAsync <IUserFile>(userFileSystemPath);

                            eTag = await userFile.UpdateAsync((IFileBasicInfo)info, userFileSystemStream, lockInfo);
                        }
                    }
                    else
                    {
                        if (mode == FileMode.CreateNew)
                        {
                            string      userFileSystemParentPath = Path.GetDirectoryName(userFileSystemPath);
                            IUserFolder userFolder = await virtualDrive.GetItemAsync <IUserFolder>(userFileSystemParentPath);

                            eTag = await userFolder.CreateFolderAsync((IFolderBasicInfo)info);
                        }
                        else
                        {
                            IUserFolder userFolder = await virtualDrive.GetItemAsync <IUserFolder>(userFileSystemPath);

                            eTag = await userFolder.UpdateAsync((IFolderBasicInfo)info, lockInfo);
                        }
                    }
                    await ETag.SetETagAsync(userFileSystemPath, eTag);

                    if (mode == FileMode.CreateNew)
                    {
                        PlaceholderItem.GetItem(userFileSystemPath).SetOriginalPath(userFileSystemPath);
                    }
                }
                finally
                {
                    if (userFileSystemStream != null)
                    {
                        userFileSystemStream.Close();
                    }
                }

                PlaceholderItem.SetInSync(userFileSystemWinItem.SafeHandle, true);
            }
        }
示例#13
0
        static async Task Main(string[] args)
        {
            // Load Settings.
            IConfiguration configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json", false, true).Build();

            Settings = configuration.ReadSettings();

            // Load Log4Net for net configuration.
            var logRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());

            XmlConfigurator.Configure(logRepository, new FileInfo(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "log4net.config")));

            // Enable UTF8 for Console Window
            Console.OutputEncoding = System.Text.Encoding.UTF8;

            log.Info($"\n{System.Diagnostics.Process.GetCurrentProcess().ProcessName} {Settings.AppID}");
            log.Info("\nPress 'Q' to unregister file system, delete all files/folders and exit (simulate uninstall with full cleanup).");
            log.Info("\nPress 'q' to unregister file system and exit (simulate uninstall).");
            log.Info("\nPress any other key to exit without unregistering (simulate reboot).");
            log.Info("\n----------------------\n");

            // Typically you will register sync root during your application installation.
            // Here we register it during first program start for the sake of the development convenience.
            if (!await Registrar.IsRegisteredAsync(Settings.UserFileSystemRootPath))
            {
                log.Info($"\nRegistering {Settings.UserFileSystemRootPath} sync root.");
                Directory.CreateDirectory(Settings.UserFileSystemRootPath);

                await Registrar.RegisterAsync(SyncRootId, Settings.UserFileSystemRootPath, Settings.ProductName,
                                              Path.Combine(Settings.IconsFolderPath, "Drive.ico"));


                // Set root item ID. It will be passed to IEngine.GetFileSystemItemAsync() method
                // as itemId parameter when a root folder is requested.
                byte[] itemId = WindowsFileSystemItem.GetItemIdByPath(Settings.RemoteStorageRootPath);
                PlaceholderFolder.GetItem(Settings.UserFileSystemRootPath).SetItemId(itemId);
            }
            else
            {
                log.Info($"\n{Settings.UserFileSystemRootPath} sync root already registered.");
            }

            // Log indexed state.
            StorageFolder userFileSystemRootFolder = await StorageFolder.GetFolderFromPathAsync(Settings.UserFileSystemRootPath);

            log.Info($"\nIndexed state: {(await userFileSystemRootFolder.GetIndexedStateAsync())}\n");

            ConsoleKeyInfo exitKey;

            try
            {
                Engine = new VirtualEngine(Settings.UserFileSystemLicense, Settings.UserFileSystemRootPath, Settings.RemoteStorageRootPath, log);

                // Start processing OS file system calls.
                await Engine.StartAsync();

#if DEBUG
                // Opens Windows File Manager with user file system folder and remote storage folder.
                ShowTestEnvironment();
#endif
                // Keep this application running until user input.
                exitKey = Console.ReadKey();
            }
            finally
            {
                Engine.Dispose();
            }

            if (exitKey.KeyChar == 'q')
            {
                // Unregister during programm uninstall.
                await Registrar.UnregisterAsync(SyncRootId);

                log.Info($"\n\nUnregistering {Settings.UserFileSystemRootPath} sync root.");
                log.Info("\nAll empty file and folder placeholders are deleted. Hydrated placeholders are converted to regular files / folders.\n");
            }
            else if (exitKey.KeyChar == 'Q')
            {
                log.Info($"\n\nUnregistering {Settings.UserFileSystemRootPath} sync root.");
                log.Info("\nAll files and folders placeholders are deleted.\n");

                // Unregister during programm uninstall and delete all files/folder.
                await Registrar.UnregisterAsync(SyncRootId);

                try
                {
                    Directory.Delete(Settings.UserFileSystemRootPath, true);
                }
                catch (Exception ex)
                {
                    log.Error($"\n{ex}");
                }
            }
            else
            {
                log.Info("\n\nAll downloaded file / folder placeholders remain in file system. Restart the application to continue managing files.\n");
            }
        }