Skip to content

Commit

Permalink
2.5.1.0 - Fixed issues with the SFTP client and failed screenshot upl…
Browse files Browse the repository at this point in the history
…oads to an SFTP server. A null reference exception error would be thrown during a series of attempts in uploading screenshots that previously failed to upload causing the user to exit the application and start the application again (thereby voiding the failed upload process). It was also discovered that, when screenshots that had previously failed to upload, would upload successfully later (after establishing a successful connection with the SFTP server) the screenshots would be uploaded to the incorrect location. They would be uploaded based on the Folder path and the Macro path instead of simply the Macro path (as they usually do upon successful upload). Now screenshots that previously failed to upload will be uploaded based on the Macro path to keep it consistent with how sucessfully uploaded screenshots are handled.
  • Loading branch information
gavinkendall committed Sep 1, 2022
1 parent 865978f commit d36e04a
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 53 deletions.
6 changes: 3 additions & 3 deletions AutoScreenCaptureSetup/AutoScreenCaptureSetup.vdproj
Original file line number Diff line number Diff line change
Expand Up @@ -259,15 +259,15 @@
{
"Name" = "8:Microsoft Visual Studio"
"ProductName" = "8:Auto Screen Capture"
"ProductCode" = "8:{23F9442C-D935-4974-B060-2AE627EFD750}"
"PackageCode" = "8:{AC9F2877-9900-4F45-A3B3-2826555A7597}"
"ProductCode" = "8:{1BA6261F-F580-404D-873D-A2BB82E6D83D}"
"PackageCode" = "8:{C456F1EE-5A83-4F4F-B98F-BE49590A7F28}"
"UpgradeCode" = "8:{6B29B7BC-0101-4495-B28C-26B6D3CDCC02}"
"AspNetVersion" = "8:4.0.30319.0"
"RestartWWWService" = "11:FALSE"
"RemovePreviousVersions" = "11:TRUE"
"DetectNewerInstalledVersion" = "11:TRUE"
"InstallAllUsers" = "11:TRUE"
"ProductVersion" = "8:2.5.09"
"ProductVersion" = "8:2.5.10"
"Manufacturer" = "8:Gavin Kendall"
"ARPHELPTELEPHONE" = "8:"
"ARPHELPLINK" = "8:https://sourceforge.net/p/autoscreen/tickets/"
Expand Down
4 changes: 2 additions & 2 deletions Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.5.0.9")]
[assembly: AssemblyFileVersion("2.5.0.9")]
[assembly: AssemblyVersion("2.5.1.0")]
[assembly: AssemblyFileVersion("2.5.1.0")]
[assembly: NeutralResourcesLanguageAttribute("en-CA")]
2 changes: 1 addition & 1 deletion app.manifest
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<assemblyIdentity
type="win32"
name="GavinKendall.AutoScreenCapture"
version="2.5.0.9"/>
version="2.5.1.0"/>
<asmv3:application>
<asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
<dpiAware>True/PM</dpiAware>
Expand Down
2 changes: 1 addition & 1 deletion autoscreen.conf
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
# The version of Auto Screen Capture that this configuration file is intended for.
# Be careful if you change the version number and don't provide the correct definitions for the specific version
# as some settings will only work with certain versions of the application. Versioning of the configuration file starts with Auto Screen Capture 2.5.0.0 ("Limoncello").
Version=2.5.0.9
Version=2.5.1.0

# Starting with version 2.5.0.0 the entire configuration file defines all the default application and user settings
# that were previously hard-coded within the application itself. Now you have the ability to define all of the default settings in a single file!
Expand Down
1 change: 1 addition & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
Auto Screen Capture by Gavin Kendall

2.5.1.0 Fixed issues with the SFTP client and failed screenshot uploads to an SFTP server. A null reference exception error would be thrown during a series of attempts in uploading screenshots that previously failed to upload causing the user to exit the application and start the application again (thereby voiding the failed upload process). It was also discovered that, when screenshots that had previously failed to upload, would upload successfully later (after establishing a successful connection with the SFTP server) the screenshots would be uploaded to the incorrect location. They would be uploaded based on the Folder path and the Macro path instead of simply the Macro path (as they usually do upon successful upload). Now screenshots that previously failed to upload will be uploaded based on the Macro path to keep it consistent with how sucessfully uploaded screenshots are handled.
2.5.0.9 Fixed bug if you opened the application without having Dashboard as your selected tab view on startup.
2.5.0.8 Fixed issue with SFTP settings when FileTransferIsLinuxServer setting was not available in sftp.xml due to an upgrade from an old version of the application. Added Preview, Start Screen Capture, and Stop Screen Capture buttons to Dashboard. Dynamic Regex Validator and Encryptor/Decryptor tool windows no longer "float"; they now behave like normal non-floating windows. Fixed startup issue when upgrading from an old version of the application and using the wrong version of the config file.
2.5.0.7 Fixed modules panel open state so it no longer affects width of tabs view if modules panel's state is open during LoadSettings.
Expand Down
72 changes: 34 additions & 38 deletions interface/main/FormMain-Screenshots.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ namespace AutoScreenCapture
{
public partial class FormMain : Form
{
// A dictionary of failed uploads containing filepaths and hosts.
private Dictionary<string, string> _failedUploads = new Dictionary<string, string>();
// A dictionary of failed uploads containing screenshots and hosts.
private Dictionary<Screenshot, string> _failedUploads = new Dictionary<Screenshot, string>();

/// <summary>
/// Saves screenshot references every five minutes (300000 milliseconds).
Expand Down Expand Up @@ -1118,12 +1118,12 @@ private bool FileTransferScreenshot(Screenshot screenshot)

if (Convert.ToBoolean(_config.Settings.User.GetByKey("SFTPKeepFailedUploads").Value))
{
// Add the screenshot filepath and host to a dictionary of failed uploads so we'll attempt to upload the screenshot for that host later.
if (!_failedUploads.ContainsKey(screenshot.FilePath))
// Add the screenshot and host to a dictionary of failed uploads so we'll attempt to upload the screenshot for that host later.
if (!_failedUploads.ContainsKey(screenshot))
{
_log.WriteDebugMessage($"Screenshot ({screenshot.FilePath}) has been added to the dictionary of failed uploads because a connection to the file server could not be established at this time so an attempt to retry the upload will occur in the next capture cycle");
_log.WriteDebugMessage($"Screenshot ({screenshot.MacroPath}) has been added to the dictionary of failed uploads because a connection to the file server could not be established at this time so an attempt to retry the upload will occur in the next capture cycle");

_failedUploads.Add(screenshot.FilePath, host);
_failedUploads.Add(screenshot, host);
}
}

Expand All @@ -1135,23 +1135,23 @@ private bool FileTransferScreenshot(Screenshot screenshot)
if (_sftpClient.IsConnected)
{
// This is necessary since we are going to be removing entries from the _failedUploads dictionary while enumerating the collection
// so instead of modifying the collection that we're enumerating it's better to simply enumerate over a copy of the filepaths.
string[] pathsOfFailedUploads = new string[_failedUploads.Count];
_failedUploads.Keys.CopyTo(pathsOfFailedUploads, 0);
// so instead of modifying the collection that we're enumerating it's better to simply enumerate over a copy of the screenshots.
Screenshot[] screenshotsThatFailedToUpload = new Screenshot[_failedUploads.Count];
_failedUploads.Keys.CopyTo(screenshotsThatFailedToUpload, 0);

foreach (string path in pathsOfFailedUploads)
foreach (Screenshot screenshotThatFailedToUpload in screenshotsThatFailedToUpload)
{
if (_failedUploads.ContainsKey(path))
if (_failedUploads.ContainsKey(screenshotThatFailedToUpload))
{
if (_failedUploads.TryGetValue(path, out string hostAssociatedWithPath))
if (_failedUploads.TryGetValue(screenshotThatFailedToUpload, out string hostAssociatedWithPath))
{
_log.WriteDebugMessage($"Screenshot ({path}) was found in dictionary of failed uploads");
_log.WriteDebugMessage($"Screenshot ({screenshotThatFailedToUpload.MacroPath}) was found in dictionary of failed uploads");

// Make sure that the host associated with the path is equal to the host we're currently handling
// Make sure that the host associated with the screenshot is equal to the host we're currently handling
// so we don't accidentally upload the screenshot to the wrong SFTP server just in case the user changes hosts.
if (hostAssociatedWithPath.Equals(host))
{
if (UploadScreenshot(host, path, path))
if (UploadScreenshot(screenshotThatFailedToUpload, host))
{
_log.WriteDebugMessage($"This screenshot previously failed to upload. It has now been successfully uploaded to {host}");
}
Expand All @@ -1165,7 +1165,7 @@ private bool FileTransferScreenshot(Screenshot screenshot)
}

// Upload the screenshot we're currently handling.
return UploadScreenshot(host, screenshot.FilePath, screenshot.MacroPath);
return UploadScreenshot(screenshot, host);
}

return false;
Expand All @@ -1184,45 +1184,44 @@ private bool FileTransferScreenshot(Screenshot screenshot)
}

/// <summary>
/// Uploads a screenshot image file to the SFTP server given the provided local filepath and macro path of the screenshot.
/// Uploads a screenshot image file to the SFTP server.
/// </summary>
/// <param name="screenshot">The screenshot we want to upload to the SFTP server.</param>
/// <param name="host">The hostname for the SFTP server.</param>
/// <param name="path">The local filepath of the screenshot.</param>
/// <param name="macroPath">The screenshot's macro path (filename pattern) which will be used for the remote directory on the SFTP server.</param>
/// <returns>True if the upload was successful. False if the upload failed.</returns>
private bool UploadScreenshot(string host, string path, string macroPath)
private bool UploadScreenshot(Screenshot screenshot, string host)
{
string destinationFolder = Path.GetDirectoryName(macroPath);
string destinationFilename = Path.GetFileName(macroPath);
string destinationFolder = Path.GetDirectoryName(screenshot.MacroPath);
string destinationFilename = Path.GetFileName(screenshot.MacroPath);

bool isLinuxServer = Convert.ToBoolean(_config.Settings.SFTP.GetByKey("FileTransferIsLinuxServer").Value);

_log.WriteDebugMessage("Attempting to upload screenshot to file server");
_log.WriteDebugMessage("Source (Local) Path: " + path);
_log.WriteDebugMessage("Source (Local) Path: " + screenshot.FilePath);
_log.WriteDebugMessage("Destination (Remote) Folder Path: " + destinationFolder);
_log.WriteDebugMessage("Destination (Remote) Filename: " + destinationFilename);
_log.WriteDebugMessage("Is Linux Server: " + isLinuxServer.ToString());

if (_sftpClient.UploadFile(path, destinationFolder, destinationFilename, isLinuxServer))
if (_sftpClient.UploadFile(screenshot.FilePath, destinationFolder, destinationFilename, isLinuxServer))
{
_log.WriteDebugMessage("Successfully uploaded screenshot");

if (Convert.ToBoolean(_config.Settings.User.GetByKey("SFTPDeleteLocalFileAfterSuccessfulUpload").Value))
{
if (_fileSystem.FileExists(path))
if (_fileSystem.FileExists(screenshot.FilePath))
{
_fileSystem.DeleteFile(path);
_fileSystem.DeleteFile(screenshot.FilePath);

_log.WriteDebugMessage($"Screenshot ({path}) deleted locally because of successful upload to file server");
_log.WriteDebugMessage($"Screenshot ({screenshot.FilePath}) deleted locally because of successful upload to file server");
}
}

// Remove the path from the dictionary of failed uploads if we were successful in uploading the file to the SFTP server.
if (_failedUploads.ContainsKey(path))
// Remove the screenshot from the dictionary of screenshots that failed to upload if we were successful in uploading the screenshot to the SFTP server.
if (_failedUploads.ContainsKey(screenshot))
{
_log.WriteDebugMessage($"Screenshot ({path}) has been removed from the dictionary of failed uploads because the upload was successful");
_log.WriteDebugMessage($"Screenshot ({screenshot.MacroPath}) has been removed from the dictionary of failed uploads because the upload was successful");

_failedUploads.Remove(path);
_failedUploads.Remove(screenshot);
}
}
else
Expand All @@ -1231,18 +1230,15 @@ private bool UploadScreenshot(string host, string path, string macroPath)

if (Convert.ToBoolean(_config.Settings.User.GetByKey("SFTPKeepFailedUploads").Value))
{
// Add the screenshot filepath and host to a dictionary of failed uploads so we'll attempt to upload the screenshot later.
if (!_failedUploads.ContainsKey(path))
// Add the screenshot and host to a dictionary of screenshots that failed tp upload so we'll attempt to upload the screenshot later.
if (!_failedUploads.ContainsKey(screenshot))
{
_log.WriteDebugMessage($"Screenshot ({path}) has been added to the dictionary of failed uploads because the upload failed at this time so an attempt to retry the upload will occur in the next capture cycle");
_log.WriteDebugMessage($"Screenshot ({screenshot.MacroPath}) has been added to the dictionary of failed uploads because the upload failed at this time so an attempt to retry the upload will occur in the next capture cycle");

_failedUploads.Add(path, host);
_failedUploads.Add(screenshot, host);
}
}

// We can't simply say that the SFTP client is now disconnected so we just need to nullify the SFTP client.
_sftpClient = null;

return false;
}

Expand Down
16 changes: 8 additions & 8 deletions modules/screenshots/ScreenshotCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public class ScreenshotCollection
/// </summary>
/// <param name="screenshotsToDelete">A list of screenshots to delete.</param>
/// <param name="failedUploads">A dictionary of failed uploads.</param>
private void DeleteScreenshots(List<Screenshot> screenshotsToDelete, Dictionary<string, string> failedUploads)
private void DeleteScreenshots(List<Screenshot> screenshotsToDelete, Dictionary<Screenshot, string> failedUploads)
{
lock (_screenshotList)
{
Expand All @@ -115,11 +115,11 @@ private void DeleteScreenshots(List<Screenshot> screenshotsToDelete, Dictionary<
_slideList.Remove(screenshot.Slide);
_slideNameList.Remove(screenshot.Slide.Name);

// Do not delete the screenshot if the path exists in the dictionary of failed uploads.
string[] filePathsOfFailedUploads = new string[failedUploads.Count];
failedUploads.Keys.CopyTo(filePathsOfFailedUploads, 0);
// Do not delete the screenshot if it exists in the dictionary of failed uploads.
Screenshot[] screenshotsThatFailedToUpload = new Screenshot[failedUploads.Count];
failedUploads.Keys.CopyTo(screenshotsThatFailedToUpload, 0);

if (filePathsOfFailedUploads.Contains(screenshot.FilePath))
if (screenshotsThatFailedToUpload.Contains(screenshot))
{
continue;
}
Expand Down Expand Up @@ -1433,7 +1433,7 @@ public void SaveToXmlFile(Config config)
/// <param name="macroParser">The macro tag parser to use.</param>
/// <param name="macroTagCollection">A collectino of macro tags.</param>
/// <param name="failedUploads">A dictionary of failed uploads.</param>
public void DeleteScreenshotsByDays(int days, string folder, MacroParser macroParser, MacroTagCollection macroTagCollection, Dictionary<string, string> failedUploads)
public void DeleteScreenshotsByDays(int days, string folder, MacroParser macroParser, MacroTagCollection macroTagCollection, Dictionary<Screenshot, string> failedUploads)
{
try
{
Expand Down Expand Up @@ -1503,7 +1503,7 @@ public void DeleteScreenshotsByDays(int days, string folder, MacroParser macroPa
/// </summary>
/// <param name="cycleCount">The cycle count to use when considering when to delete screenshots.</param>
/// <param name="failedUploads">A dictionary of failed uploads.</param>
public void DeleteScreenshotsByCycleCount(int cycleCount, Dictionary<string, string> failedUploads)
public void DeleteScreenshotsByCycleCount(int cycleCount, Dictionary<Screenshot, string> failedUploads)
{
try
{
Expand Down Expand Up @@ -1566,7 +1566,7 @@ public void DeleteScreenshotsByCycleCount(int cycleCount, Dictionary<string, str
/// Deletes screenshots from the oldest screen capture cycle. You can use this for a rolling delete given the correctly configured setup.
/// </summary>
/// <param name="failedUploads">A dictionary of failed uploads.</param>
public void DeleteScreenshotsFromOldestCaptureCycle(Dictionary<string, string> failedUploads)
public void DeleteScreenshotsFromOldestCaptureCycle(Dictionary<Screenshot, string> failedUploads)
{
try
{
Expand Down
1 change: 1 addition & 0 deletions settings/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ public void Initialize(FileSystem fileSystem)
_versionCollection.Add(new Version(CODENAME_LIMONCELLO, "2.5.0.6"));
_versionCollection.Add(new Version(CODENAME_LIMONCELLO, "2.5.0.7"));
_versionCollection.Add(new Version(CODENAME_LIMONCELLO, "2.5.0.8"));
_versionCollection.Add(new Version(CODENAME_LIMONCELLO, "2.5.0.9"));

Application = new SettingCollection()
{
Expand Down

0 comments on commit d36e04a

Please sign in to comment.