/// <summary> /// Returns the volume serial of the drive where this path resides or empty if no serial is found. /// </summary> /// <param name="self"></param> /// <returns></returns> public static string GetDriveVolumeSerial(this FileSystemInfo self) { DriveInfo driveInfo = self.GetDriveInfo(); string serial = (driveInfo != null) ? driveInfo.GetVolumeSerial() : string.Empty; return(serial); }
/// <summary> /// Gets a value indicating if the FileSystemInfo object is currently available /// </summary> /// <param name="fsInfo"></param> /// <param name="serial">if a serial is specified the return value is more reliable.</param> /// <returns></returns> public static bool IsAvailable(FileSystemInfo fsInfo, string recordedSerial) { // Get Drive Information DriveInfo driveInfo = GetDriveInfo(fsInfo); // Refresh the object information (important) fsInfo.Refresh(); // Check if the file exists bool fileExists = fsInfo.Exists; // Do we have a logical volume? if (driveInfo != null && fileExists) { string currentSerial = driveInfo.GetVolumeSerial(); // if we have both the recorded and the current serial we can do this very exact // by checking if the serials match if (!String.IsNullOrEmpty(recordedSerial) && !String.IsNullOrEmpty(currentSerial)) { // return the exact check result return(currentSerial == recordedSerial); } } // return the simple check result return(fileExists); }
/// <summary> /// Gets the disk serial of the drive were the path is located. /// </summary> /// <param name="path"></param> /// <returns></returns> public static string GetVolumeSerial(string path) { DriveInfo driveInfo = GetDriveInfo(path); if (driveInfo != null && driveInfo.IsReady) { return(driveInfo.GetVolumeSerial()); } else { return(string.Empty); } }
public List <DBLocalMedia> GetLocalMedia(bool returnOnlyNew) { logger.Debug("Scanning: {0}", Directory.FullName); // default values string volume = string.Empty; string label = string.Empty; string serial = string.Empty; string format = string.Empty; // validate the import path if (!_replaced && this.IsAvailable) { if (!this.IsUnc) { // Logical volume (can be a mapped network share) int retry = 0; while (serial == string.Empty) { // Grab information for this logical volume DriveInfo driveInfo = Directory.GetDriveInfo(); if (driveInfo != null && driveInfo.IsReady) { // get the volume properties volume = driveInfo.GetDriveLetter(); label = driveInfo.VolumeLabel; serial = driveInfo.GetVolumeSerial(); format = driveInfo.DriveFormat; logger.Debug("Drive='{0}', Label='{1}', Serial='{2}', Format='{3}'", volume, label, serial, format); } // check if the serial is empty // logical volumes SHOULD have a serial number or something went wrong // Currently the only exception is when a NDFS filesystem is detected to cover the special case of network paths mounted by 3rd party programs // todo: to prevent more exceptions in the future we should keep an eye out for these special cases and come up with a better solution if (serial == string.Empty && format != "NDFS") { // If we tried 3 times already then we should report a failure if (retry == 3) { logger.Error("Canceled scan for '{0}': Could not get required volume information.", Directory.FullName); return(null); } // up the retry count and wait for 1 second retry++; Thread.Sleep(1000); logger.Debug("Retrying: {1} ({0})", Directory.FullName, retry); } } } // todo: for UNC paths we could consider using the host part of the UNC path as the MediaLabel (ex. '//SomeHost/../..' => 'SomeHost') } else { if (this.IsRemovable) { if (this.IsUnc) { // network share logger.Info("Skipping scan for '{0}': the share is offline.", Directory.FullName); } else if (this.IsOpticalDrive) { // optical drive logger.Info("Skipping scan for '{0}': the drive is empty.", Directory.FullName); } else { // all other removable paths logger.Info("Skipping scan for '{0}': the volume is disconnected.", Directory.FullName); } } else { logger.Error("Scan for '{0}' was cancelled because the import path is not available.", Directory.FullName); } // returning nothing return(null); } // Grab the list of files and validate them List <DBLocalMedia> rtn = new List <DBLocalMedia>(); try { List <FileInfo> fileList = null; // When the option to ignore interactive content is enabled (applies to optical drives that are internally managed) // we first check for known video formats (DVD, Bluray etc..) before we are going to scan for all files on the disc. if (MovingPicturesCore.Settings.IgnoreInteractiveContentOnVideoDisc && IsOpticalDrive && InternallyManaged) { string videoPath = VideoUtility.GetVideoPath(Directory.FullName); if (VideoUtility.IsVideoDisc(videoPath)) { // if we found one we can safely asume by standards that this will be the // only valid video file on the disc so we create the filelist and add only this file fileList = new List <FileInfo>(); fileList.Add(new FileInfo(videoPath)); } } // if the fileList is null it means that we didn't find an 'exclusive' video file above // and we are going to scan the whole tree if (fileList == null) { fileList = VideoUtility.GetVideoFilesRecursive(Directory); } // go through the video file list DriveType type = GetDriveType(); foreach (FileInfo videoFile in fileList) { // Create or get a localmedia object from the video file path DBLocalMedia newFile = DBLocalMedia.Get(videoFile.FullName, serial); // The file is in the database if (newFile.ID != null) { // for optical paths + DVD we have to check the actual DiscId // todo: add bluray disc id support if (IsOpticalDrive) { if ((newFile.IsDVD) && !newFile.IsAvailable) { string discId = newFile.VideoFormat.GetIdentifier(newFile.FullPath); // Create/get a DBLocalMedia object using the the DiscID newFile = DBLocalMedia.GetDisc(videoFile.FullName, discId); } } // If the file is still in the database continue if we only want new files if (newFile.ID != null && returnOnlyNew) { continue; } } else if (!IsOpticalDrive && !IsUnc) { // Verify the new file, if we find a similar file it could be that the serial has changed List <DBLocalMedia> otherFiles = DBLocalMedia.GetAll(newFile.FullPath); if (otherFiles.Count == 1) { DBLocalMedia otherFile = otherFiles[0]; if (type != DriveType.Unknown && type != DriveType.CDRom && type != DriveType.NoRootDirectory) { bool fileAvailable = otherFile.IsAvailable; if ((String.IsNullOrEmpty(otherFile.VolumeSerial) && fileAvailable) || (!fileAvailable && File.Exists(otherFile.FullPath))) { // the disk serial was updated for this file otherFile.VolumeSerial = serial; otherFile.MediaLabel = label; otherFile.Commit(); logger.Info("Disk information updated for '{0}'", otherFile.FullPath); continue; } } } } // NEW FILE // Add additional file information newFile.ImportPath = this; newFile.VolumeSerial = serial; newFile.MediaLabel = label; // add the localmedia object to our return list logger.Debug("New File: {0}", videoFile.Name); rtn.Add(newFile); } } catch (Exception e) { if (e.GetType() == typeof(ThreadAbortException)) { throw e; } if (logger.IsDebugEnabled) { // In debug mode we log the geeky version logger.DebugException("Error scanning '" + Directory.FullName + "'", e); } else { // In all other modes we do it more friendlier logger.Error("Error scanning '{0}': {1}", Directory.FullName, e.Message); } } return(rtn); }
private static void WatchDisks() { while (true) { lock (syncRoot) { if (driveStates == null) { driveStates = new Dictionary <string, bool>(); } foreach (string currDrive in watchedDrives) { try { // check if the drive is available bool isAvailable; DriveInfo driveInfo = DriveInfoHelper.GetDriveInfo(currDrive); if (driveInfo == null) { isAvailable = false; } else { isAvailable = driveInfo.IsReady; } // if the previous drive state is not stored, store it and continue if (!driveStates.ContainsKey(currDrive)) { driveStates[currDrive] = isAvailable; continue; } // if a change has occured if (driveStates[currDrive] != isAvailable) { // update our state driveStates[currDrive] = isAvailable; // notify any listeners if (isAvailable) { if (driveInfo.DriveType != DriveType.Network) { logger.Info("Volume Inserted: " + currDrive); } else { logger.Info("Volume Online: " + currDrive); } if (OnVolumeInserted != null) { OnVolumeInserted(currDrive, driveInfo.GetVolumeSerial()); } } else { // if a mapped network share gets disconnected it can either show Network or NoRootDirectory if (driveInfo.DriveType != DriveType.Network && driveInfo.DriveType != DriveType.NoRootDirectory) { logger.Info("Volume Removed: " + currDrive); } else { logger.Info("Volume Offline: " + currDrive); } if (OnVolumeRemoved != null) { OnVolumeRemoved(currDrive, null); } } } } catch (Exception e) { if (e is ThreadAbortException) { throw e; } logger.ErrorException("Unexpected error in Disk Watcher thread!", e); } } } Thread.Sleep(5000); } }