/// <summary> /// Saves the captured bitmap image as a screenshot to an image file. /// </summary> /// <param name="path">The filepath of the image file to write to.</param> /// <param name="format">The format of the image file.</param> /// <param name="component">The component of the screenshot to be saved. This could be the active window or a screen.</param> /// <param name="screenshotType">The type of screenshot to save. This could be the active window, a region, or a screen.</param> /// <param name="jpegQuality">The JPEG quality setting for JPEG images being saved.</param> /// <param name="viewId">The unique identifier to identify a particular region or screen.</param> /// <param name="bitmap">The bitmap image to write to the image file.</param> /// <param name="label">The current label being used at the time of capture which we will apply to the screenshot object.</param> /// <param name="windowTitle">The title of the window being captured.</param> /// <param name="processName">The process name of the application being captured.</param> /// <param name="screenshotCollection">A collection of screenshot objects.</param> /// <returns>A boolean to determine if we successfully saved the screenshot.</returns> public bool SaveScreenshot(string path, ImageFormat format, int component, ScreenshotType screenshotType, int jpegQuality, Guid viewId, Bitmap bitmap, string label, string windowTitle, string processName, ScreenshotCollection screenshotCollection) { try { int filepathLengthLimit = Convert.ToInt32(Settings.Application.GetByKey("FilepathLengthLimit", DefaultSettings.FilepathLengthLimit).Value); bool optimizeScreenCapture = Convert.ToBoolean(Settings.Application.GetByKey("OptimizeScreenCapture", DefaultSettings.OptimizeScreenCapture).Value); if (!string.IsNullOrEmpty(path)) { if (path.Length > filepathLengthLimit) { Log.WriteMessage($"File path length exceeds the configured length of {filepathLengthLimit} characters so value was truncated. Correct the value for the FilepathLengthLimit application setting to prevent truncation"); path = path.Substring(0, filepathLengthLimit); } Log.WriteMessage("Attempting to write image to file at path \"" + path + "\""); // This is a normal path used in Windows (such as "C:\screenshots\"). if (!path.StartsWith(FileSystem.PathDelimiter)) { if (FileSystem.DriveReady(path)) { int lowDiskSpacePercentageThreshold = Convert.ToInt32(Settings.Application.GetByKey("LowDiskPercentageThreshold", DefaultSettings.LowDiskPercentageThreshold).Value); double freeDiskSpacePercentage = FileSystem.FreeDiskSpacePercentage(path); Log.WriteDebugMessage("Percentage of free disk space on drive for \"" + path + "\" is " + (int)freeDiskSpacePercentage + "% and low disk percentage threshold is set to " + lowDiskSpacePercentageThreshold + "%"); if (freeDiskSpacePercentage > lowDiskSpacePercentageThreshold) { string dirName = FileSystem.GetDirectoryName(path); if (!string.IsNullOrEmpty(dirName)) { if (!FileSystem.DirectoryExists(dirName)) { FileSystem.CreateDirectory(dirName); Log.WriteDebugMessage("Directory \"" + dirName + "\" did not exist so it was created"); } Screenshot lastScreenshotOfThisView = screenshotCollection.GetLastScreenshotOfView(viewId); Screenshot newScreenshotOfThisView = new Screenshot(windowTitle, DateTimeScreenshotsTaken) { ViewId = viewId, Path = path, Format = format, Component = component, ScreenshotType = screenshotType, ProcessName = processName + ".exe", Label = label }; if (optimizeScreenCapture) { newScreenshotOfThisView.Hash = GetMD5Hash(bitmap, format); if (lastScreenshotOfThisView == null || string.IsNullOrEmpty(lastScreenshotOfThisView.Hash) || !lastScreenshotOfThisView.Hash.Equals(newScreenshotOfThisView.Hash)) { screenshotCollection.Add(newScreenshotOfThisView); SaveToFile(path, format, jpegQuality, bitmap); } } else { screenshotCollection.Add(newScreenshotOfThisView); SaveToFile(path, format, jpegQuality, bitmap); } } } else { // There is not enough disk space on the drive so log an error message and change the system tray icon's colour to yellow. Log.WriteErrorMessage($"Unable to save screenshot due to lack of available disk space on drive for {path} (at " + freeDiskSpacePercentage + "%) which is lower than the LowDiskPercentageThreshold setting that is currently set to " + lowDiskSpacePercentageThreshold + "%"); bool stopOnLowDiskError = Convert.ToBoolean(Settings.Application.GetByKey("StopOnLowDiskError", DefaultSettings.StopOnLowDiskError).Value); if (stopOnLowDiskError) { Log.WriteErrorMessage("Running screen capture session has stopped because application setting StopOnLowDiskError was set to True when the available disk space on any drive was lower than the value of LowDiskPercentageThreshold"); ApplicationError = true; return(false); } ApplicationWarning = true; } } else { // Drive isn't ready so log an error message. Log.WriteErrorMessage($"Unable to save screenshot for \"{path}\" because the drive is not found or not ready"); } } else { // This is UNC network share path (such as "\\SERVER\screenshots\"). string dirName = FileSystem.GetDirectoryName(path); if (!string.IsNullOrEmpty(dirName)) { try { if (!FileSystem.DirectoryExists(dirName)) { FileSystem.CreateDirectory(dirName); Log.WriteDebugMessage("Directory \"" + dirName + "\" did not exist so it was created"); } Screenshot lastScreenshotOfThisView = screenshotCollection.GetLastScreenshotOfView(viewId); Screenshot newScreenshotOfThisView = new Screenshot(windowTitle, DateTimeScreenshotsTaken) { ViewId = viewId, Path = path, Format = format, Component = component, ScreenshotType = screenshotType, ProcessName = processName + ".exe", Label = label }; if (optimizeScreenCapture) { newScreenshotOfThisView.Hash = GetMD5Hash(bitmap, format); if (lastScreenshotOfThisView == null || string.IsNullOrEmpty(lastScreenshotOfThisView.Hash) || !lastScreenshotOfThisView.Hash.Equals(newScreenshotOfThisView.Hash)) { screenshotCollection.Add(newScreenshotOfThisView); SaveToFile(path, format, jpegQuality, bitmap); } } else { screenshotCollection.Add(newScreenshotOfThisView); SaveToFile(path, format, jpegQuality, bitmap); } } catch (Exception) { // We don't want to stop the screen capture session at this point because there may be other components that // can write to their given paths. If this is a misconfigured path for a particular component then just log an error. Log.WriteErrorMessage($"Cannot write to \"{path}\" because the user may not have the appropriate permissions to access the path"); } } } } return(true); } catch (System.IO.PathTooLongException ex) { Log.WriteErrorMessage($"The path is too long. I see the path is \"{path}\" but the length exceeds what Windows can handle so the file could not be saved. There is probably an exception error from Windows explaining why"); Log.WriteExceptionMessage("ScreenCapture::SaveScreenshot", ex); // This shouldn't be an error that should stop a screen capture session. return(true); } catch (Exception ex) { Log.WriteExceptionMessage("ScreenCapture::SaveScreenshot", ex); return(false); } }
/// <summary> /// Saves the captured bitmap image as a screenshot to an image file. /// </summary> /// <param name="jpegQuality">The JPEG quality setting for JPEG images being saved.</param> /// <param name="screenshot">The screenshot to save.</param> /// <param name="screenshotCollection">A collection of screenshot objects.</param> /// <returns>A boolean to determine if we successfully saved the screenshot.</returns> public bool SaveScreenshot(int jpegQuality, Screenshot screenshot, ScreenshotCollection screenshotCollection) { try { int filepathLengthLimit = Convert.ToInt32(Settings.Application.GetByKey("FilepathLengthLimit", DefaultSettings.FilepathLengthLimit).Value); if (!string.IsNullOrEmpty(screenshot.Path)) { if (screenshot.Path.Length > filepathLengthLimit) { Log.WriteMessage($"File path length exceeds the configured length of {filepathLengthLimit} characters so value was truncated. Correct the value for the FilepathLengthLimit application setting to prevent truncation"); screenshot.Path = screenshot.Path.Substring(0, filepathLengthLimit); } Log.WriteMessage("Attempting to write image to file at path \"" + screenshot.Path + "\""); // This is a normal path used in Windows (such as "C:\screenshots\"). if (!screenshot.Path.StartsWith(FileSystem.PathDelimiter)) { if (FileSystem.DriveReady(screenshot.Path)) { int lowDiskSpacePercentageThreshold = Convert.ToInt32(Settings.Application.GetByKey("LowDiskPercentageThreshold", DefaultSettings.LowDiskPercentageThreshold).Value); double freeDiskSpacePercentage = FileSystem.FreeDiskSpacePercentage(screenshot.Path); Log.WriteDebugMessage("Percentage of free disk space on drive for \"" + screenshot.Path + "\" is " + (int)freeDiskSpacePercentage + "% and low disk percentage threshold is set to " + lowDiskSpacePercentageThreshold + "%"); if (freeDiskSpacePercentage > lowDiskSpacePercentageThreshold) { AddScreenshotAndSaveToFile(jpegQuality, screenshot, screenshotCollection); } else { // There is not enough disk space on the drive so log an error message and change the system tray icon's colour to yellow. Log.WriteErrorMessage($"Unable to save screenshot due to lack of available disk space on drive for {screenshot.Path} (at " + freeDiskSpacePercentage + "%) which is lower than the LowDiskPercentageThreshold setting that is currently set to " + lowDiskSpacePercentageThreshold + "%"); bool stopOnLowDiskError = Convert.ToBoolean(Settings.Application.GetByKey("StopOnLowDiskError", DefaultSettings.StopOnLowDiskError).Value); if (stopOnLowDiskError) { Log.WriteErrorMessage("Running screen capture session has stopped because application setting StopOnLowDiskError was set to True when the available disk space on any drive was lower than the value of LowDiskPercentageThreshold"); ApplicationError = true; return(false); } ApplicationWarning = true; } } else { // Drive isn't ready so log an error message. Log.WriteErrorMessage($"Unable to save screenshot for \"{screenshot.Path}\" because the drive is not found or not ready"); } } else { // This is a UNC network share path (such as "\\SERVER\screenshots\"). AddScreenshotAndSaveToFile(jpegQuality, screenshot, screenshotCollection); } } return(true); } catch (System.IO.PathTooLongException ex) { Log.WriteErrorMessage($"The path is too long. I see the path is \"{screenshot.Path}\" but the length exceeds what Windows can handle so the file could not be saved. There is probably an exception error from Windows explaining why"); Log.WriteExceptionMessage("ScreenCapture::SaveScreenshot", ex); // This shouldn't be an error that should stop a screen capture session. return(true); } catch (Exception ex) { Log.WriteExceptionMessage("ScreenCapture::SaveScreenshot", ex); return(false); } }
/// <summary> /// Saves the captured bitmap image as a screenshot to an image file. /// </summary> /// <param name="path">The filepath of the image file to write to.</param> /// <param name="format">The format of the image file.</param> /// <param name="component">The component of the screenshot to be saved. This could be the active window or a screen.</param> /// <param name="screenshotType">The type of screenshot to save. This could be the active window, a region, or a screen.</param> /// <param name="jpegQuality">The JPEG quality setting for JPEG images being saved.</param> /// <param name="viewId">The unique identifier to identify a particular region or screen.</param> /// <param name="bitmap">The bitmap image to write to the image file.</param> /// <param name="label">The current label being used at the time of capture which we will apply to the screenshot object.</param> /// <param name="windowTitle">The title of the window being captured.</param> /// <param name="processName">The process name of the application being captured.</param> /// <param name="screenshotCollection">A collection of screenshot objects.</param> /// <returns>A boolean to determine if we successfully saved the screenshot.</returns> public bool SaveScreenshot(string path, ImageFormat format, int component, ScreenshotType screenshotType, int jpegQuality, Guid viewId, Bitmap bitmap, string label, string windowTitle, string processName, ScreenshotCollection screenshotCollection) { try { if (!string.IsNullOrEmpty(path) && path.Length >= MAX_WINDOWS_PATH_LENGTH) { // We just want to log a normal message and not stop the screen capture session because we want to continue // for other components that are using paths which are still valid. Log.WriteMessage($"No path available at \"{path}\" or path length exceeds {MAX_WINDOWS_PATH_LENGTH} characters"); } if (!string.IsNullOrEmpty(path) && path.Length < MAX_WINDOWS_PATH_LENGTH) { Log.WriteDebugMessage("Attempting to write image to file at path \"" + path + "\""); // This is a normal path used in Windows (such as "C:\screenshots\"). if (!path.StartsWith(FileSystem.PathDelimiter)) { if (FileSystem.DriveReady(path)) { int lowDiskSpacePercentageThreshold = Convert.ToInt32(Settings.Application.GetByKey("LowDiskPercentageThreshold", defaultValue: 1).Value); double freeDiskSpacePercentage = FileSystem.FreeDiskSpacePercentage(path); Log.WriteDebugMessage("Percentage of free disk space on drive for \"" + path + "\" is " + (int)freeDiskSpacePercentage + "% and low disk percentage threshold is set to " + lowDiskSpacePercentageThreshold + "%"); if (freeDiskSpacePercentage > lowDiskSpacePercentageThreshold) { string dirName = FileSystem.GetDirectoryName(path); if (!string.IsNullOrEmpty(dirName)) { if (!FileSystem.DirectoryExists(dirName)) { FileSystem.CreateDirectory(dirName); Log.WriteDebugMessage("Directory \"" + dirName + "\" did not exist so it was created"); } Screenshot screenshot = new Screenshot(DateTimeScreenshotsTaken, path, format, component, screenshotType, windowTitle, processName, viewId, label); screenshotCollection.Add(screenshot); SaveToFile(path, format, jpegQuality, bitmap); } } else { // There is not enough disk space on the drive so stop the current running screen capture session and log an error message. Log.WriteErrorMessage($"Unable to save screenshot due to lack of available disk space on drive for {path} (at " + freeDiskSpacePercentage + "%) which is lower than the LowDiskPercentageThreshold setting that is currently set to " + lowDiskSpacePercentageThreshold + "% so screen capture session is being stopped"); return(false); } } else { // Drive isn't ready so log an error message. Log.WriteErrorMessage($"Unable to save screenshot for \"{path}\" because the drive is not found or not ready"); } } else { // This is UNC network share path (such as "\\SERVER\screenshots\"). string dirName = FileSystem.GetDirectoryName(path); if (!string.IsNullOrEmpty(dirName)) { try { if (!FileSystem.DirectoryExists(dirName)) { FileSystem.CreateDirectory(dirName); Log.WriteDebugMessage("Directory \"" + dirName + "\" did not exist so it was created"); } screenshotCollection.Add(new Screenshot(DateTimeScreenshotsTaken, path, format, component, screenshotType, windowTitle, processName, viewId, label)); SaveToFile(path, format, jpegQuality, bitmap); } catch (Exception) { // We don't want to stop the screen capture session at this point because there may be other components that // can write to their given paths. If this is a misconfigured path for a particular component then just log an error. Log.WriteErrorMessage($"Cannot write to \"{path}\" because the user may not have the appropriate permissions to access the path"); } } } } return(true); } catch (Exception ex) { Log.WriteExceptionMessage("ScreenCapture::SaveScreenshot", ex); return(false); } }
/// <summary> /// Saves the captured bitmap image as a screenshot to an image file. /// </summary> /// <param name="security">The security class.</param> /// <param name="jpegQuality">The JPEG quality setting for JPEG images being saved.</param> /// <param name="screenshot">The screenshot to save.</param> /// <param name="screenshotCollection">A collection of screenshot objects.</param> /// <returns>A boolean to determine if we successfully saved the screenshot.</returns> public int SaveScreenshot(Security security, int jpegQuality, Screenshot screenshot, ScreenshotCollection screenshotCollection) { int returnFlag = 0; try { int filepathLengthLimit = Convert.ToInt32(_config.Settings.Application.GetByKey("FilepathLengthLimit", _config.Settings.DefaultSettings.FilepathLengthLimit).Value); if (!string.IsNullOrEmpty(screenshot.FilePath)) { if (screenshot.FilePath.Length > filepathLengthLimit) { _log.WriteMessage($"File path length exceeds the configured length of {filepathLengthLimit} characters so value was truncated. Correct the value for the FilepathLengthLimit application setting to prevent truncation"); screenshot.FilePath = screenshot.FilePath.Substring(0, filepathLengthLimit); } // This is a normal path used in Windows (such as "C:\screenshots\"). if (!screenshot.FilePath.StartsWith(_fileSystem.PathDelimiter)) { if (_fileSystem.DriveReady(screenshot.FilePath)) { // The low disk mode we want to use (either check by percentage (0) or check the number of available bytes (1)). int lowDiskMode = Convert.ToInt32(_config.Settings.Application.GetByKey("LowDiskMode", _config.Settings.DefaultSettings.LowDiskMode).Value); // Low disk space threshold by percentage. int lowDiskPercentageThreshold = Convert.ToInt32(_config.Settings.Application.GetByKey("LowDiskPercentageThreshold", _config.Settings.DefaultSettings.LowDiskPercentageThreshold).Value); double freeDiskSpacePercentage = _fileSystem.FreeDiskSpacePercentage(screenshot.FilePath); // Low disk space threshold in bytes. long lowDiskBytesThreshold = Convert.ToInt64(_config.Settings.Application.GetByKey("LowDiskBytesThreshold", _config.Settings.DefaultSettings.LowDiskBytesThreshold).Value); long freeDiskSpaceBytes = _fileSystem.FreeDiskSpace(screenshot.FilePath); _log.WriteDebugMessage("Percentage of free disk space on drive for \"" + screenshot.FilePath + "\" is " + (int)freeDiskSpacePercentage + "% and low disk percentage threshold is set to " + lowDiskPercentageThreshold + "%"); _log.WriteDebugMessage("Bytes of free disk space on drive for \"" + screenshot.FilePath + "\" is " + freeDiskSpaceBytes + " and low disk bytes threshold is set to " + lowDiskBytesThreshold); // Check low disk space by percentage. if (lowDiskMode == 0) { if (freeDiskSpacePercentage < lowDiskPercentageThreshold) { return(NotEnoughDiskSpace(screenshot, returnFlag, freeDiskSpacePercentage, lowDiskPercentageThreshold, freeDiskSpaceBytes, lowDiskBytesThreshold)); } } // Check low disk space in bytes. if (lowDiskMode == 1) { if (freeDiskSpaceBytes < lowDiskBytesThreshold) { return(NotEnoughDiskSpace(screenshot, returnFlag, freeDiskSpacePercentage, lowDiskPercentageThreshold, freeDiskSpaceBytes, lowDiskBytesThreshold)); } } return(SaveToFile(security, jpegQuality, screenshot, screenshotCollection)); } else { // Drive isn't ready so log an error message. _log.WriteErrorMessage($"Unable to save screenshot for \"{screenshot.FilePath}\" because the drive is not found or not ready"); return(returnFlag | (int)ScreenSavingErrorLevels.DriveNotReady); } } else { // This is a UNC network share path (such as "\\SERVER\screenshots\"). return(SaveToFile(security, jpegQuality, screenshot, screenshotCollection)); } } return(returnFlag & (int)ScreenSavingErrorLevels.None); } catch (PathTooLongException ex) { _log.WriteErrorMessage($"The path is too long. I see the path is \"{screenshot.FilePath}\" but the length exceeds what Windows can handle so the file could not be saved. There is probably an exception error from Windows explaining why"); _log.WriteExceptionMessage("ScreenCapture::SaveScreenshot", ex); // This shouldn't be an error that should stop a screen capture session. return(returnFlag | (int)ScreenSavingErrorLevels.PathLengthExceeded); } catch (Exception ex) { _log.WriteExceptionMessage("ScreenCapture::SaveScreenshot", ex); return(returnFlag | (int)ScreenSavingErrorLevels.ExceptionCaught); } }