예제 #1
0
        public void MountNetworkDrive(Guid cloudId, string mountPoint)
        {
            if (mountPoint?.Length != 3 || !mountPoint.EndsWith(@":\", StringComparison.OrdinalIgnoreCase))
            {
                throw new ArgumentException("Mount Point is invalid.");
            }

            if (Globals.Volumes.TryGetValue(cloudId, out var thread) && thread != null)
            {
                UnmountNetworkDrive(cloudId);
            }

            var cloud = Globals.CloudService.PersonalClouds.First(x => new Guid(x.Id) == cloudId);

            var dokanThread = new AsyncContextThread();

            dokanThread.Factory.Run(() => {
                try
                {
                    var disk = new DokanFileSystemAdapter(new PersonalCloudRootFileSystem(cloud, Globals.Loggers.CreateLogger <PersonalCloudRootFileSystem>()));
                    disk.Mount(mountPoint, DokanOptions.EnableNotificationAPI, 5, new DokanyLogger());
                }
                catch (Exception exception)
                {
                    Globals.Loggers.CreateLogger <CloudManagerService>().LogError(exception, "Mount failed.");
                    Globals.Database.SaveSetting(WindowsUserSettings.EnableVolumeMounting, "0");

                    Task.Run(async() => {
                        await Globals.NotificationCenter.InvokeAsync(x => x.OnVolumeIOError(mountPoint, exception))
                        .ConfigureAwait(false);
                        await Task.Delay(TimeSpan.FromSeconds(5)).ConfigureAwait(false);
                        Globals.Volumes.TryRemove(cloudId, out _);
                        dokanThread.Dispose();
                    });
                }
            });

            Globals.Database.SaveSetting(WindowsUserSettings.EnableVolumeMounting, "1");
            Globals.Database.SaveMountPoint(cloudId, mountPoint);
            Globals.Volumes[cloudId] = dokanThread;
        }
예제 #2
0
        public bool Start(HostControl hostControl)
        {
            try
            {
                Logger.LogInformation("Windows service started.");
                HostControl = hostControl;

                Initialize();

                Runners = new CancellationTokenSource();

                /*
                 * var ipcServiceCollection = new ServiceCollection()
                 *  .AddSingleton<CloudManagerService>()
                 *  .AddSingleton<StorageService>()
                 *  .AddIpc(builder => {
                 *      builder.AddNamedPipe()
                 *             .AddService<ICloudManager>(services => services.GetRequiredService<CloudManagerService>())
                 *             .AddService<IFileSystemController>(services => services.GetRequiredService<CloudManagerService>())
                 *             .AddService<IPersistentStorage>(services => services.GetRequiredService<StorageService>());
                 *  });
                 * _ = new IpcServiceHostBuilder(ipcServiceCollection.BuildServiceProvider())
                 *  .AddNamedPipeEndpoint<ICloudManager>("Cloud Manager", Pipes.CloudAdmin, true)
                 *  .AddNamedPipeEndpoint<IFileSystemController>("Dokan Controller", Pipes.DiskMounter, true)
                 *  .AddNamedPipeEndpoint<IPersistentStorage>("Storage", Pipes.UserSettings, true)
                 *  .Build().RunAsync(Runners.Token);
                 */

                Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder()
                .ConfigureServices(services => {
                    services.AddSingleton <ICloudManager, CloudManagerService>();
                })
                .ConfigureIpcHost(builder => {
                    builder.AddNamedPipeEndpoint <ICloudManager>(Pipes.CloudAdmin);
                })
                .ConfigureLogging(builder => {
                    builder.SetMinimumLevel(LogLevel.Information);
                })
                .Build().RunAsync();

                var services = new ServiceCollection().AddNamedPipeIpcClient <ICloudEventHandler>(NotificationClient, Pipes.NotificationCenter)
                               .BuildServiceProvider();

                Globals.NotificationCenter = services.GetRequiredService <IIpcClientFactory <ICloudEventHandler> >()
                                             .CreateClient(NotificationClient);

                #region Restore last-known state of File Sharing

                if (Globals.Database.CheckSetting(UserSettings.EnableSharing, "1"))
                {
                    var sharedPath = Globals.Database.LoadSetting(UserSettings.SharingRoot);
                    if (string.IsNullOrEmpty(sharedPath) || !Directory.Exists(sharedPath))
                    {
                        Globals.Database.Delete <KeyValueModel>(UserSettings.SharingRoot);
                        Globals.Database.SaveSetting(UserSettings.EnableSharing, "0");
                        sharedPath = null;
                    }

                    Globals.SetupFS(sharedPath);
                }

                #endregion Restore last-known state of File Sharing

                var resourcesPath = Path.Combine(Globals.ConfigurationPath, "Static");
                Directory.CreateDirectory(resourcesPath);
                Globals.CloudService          = new PCLocalService(Globals.CloudConfig, Globals.Loggers, Globals.CloudFileSystem, resourcesPath);
                Globals.CloudService.OnError += (o, e) => {
                    if (e.ErrorCode == ErrorCode.NeedUpdate)
                    {
                        Globals.NotificationCenter.InvokeAsync(x => x.ShowAlert("New Version Available",
                                                                                "Upgrade Personal Cloud to connect to some devices in your network."));
                    }
                };

                if (!Globals.Database.CheckSetting(UserSettings.LastInstalledVersion, Globals.Version))
                {
                    Globals.CloudService.InstallApps().Wait();
                }

                Globals.CloudService.StartService();
                Globals.NotificationCenter.InvokeAsync(x => x.OnServiceStarted());

                #region Restore last-known state of Network Drives

                if (Globals.Database.CheckSetting(WindowsUserSettings.EnableVolumeMounting, "1"))
                {
                    foreach (var cloud in Globals.CloudService.PersonalClouds)
                    {
                        if (cloud == null)
                        {
                            continue;
                        }
                        var cloudId    = new Guid(cloud.Id);
                        var mountPoint = Globals.Database.GetMountPoint(cloudId);

                        var dokanThread = new AsyncContextThread();
                        dokanThread.Factory.Run(() => {
                            try
                            {
                                var disk = new DokanFileSystemAdapter(new PersonalCloudRootFileSystem(cloud, Globals.Loggers.CreateLogger <PersonalCloudRootFileSystem>()));
                                disk.Mount(mountPoint, DokanOptions.EnableNotificationAPI, 5, new NullLogger());
                            }
                            catch (Exception exception)
                            {
                                Logger.LogError(exception, "OnVolumeIOError exception");
                                Globals.NotificationCenter.InvokeAsync(x => x.OnVolumeIOError(mountPoint, exception));
                            }
                        });

                        Globals.Volumes[cloudId] = dokanThread;
                    }
                }

                #endregion

                return(true);
            }
            catch (Exception e)
            {
                Logger.LogError(e, "Exception in PersonalCloudWindowsService:Start");
                throw;
            }
        }