private async void FtpConnect_Click(object sender, RoutedEventArgs e) { var dialog = new FtpDialog(); dialog.ShowDialog(); if (dialog.Address == "") { return; } var client = new Ftp(); IPHostEntry host; try { host = await Dns.GetHostEntryAsync(dialog.Address); } catch (SocketException) { MessageBox.Show("Invalid address."); return; } client.ReceiveTimeout = TimeSpan.FromSeconds(5); client.SendTimeout = TimeSpan.FromSeconds(5); try { await Task.Run(() => client.Connect(host.AddressList[0], 21, false)); } catch (FtpException) { MessageBox.Show("FTP Server didn't respond."); return; } try { if (dialog.Password != "" && dialog.Login != "") { await Task.Run(() => client.Login(dialog.Login, dialog.Password)); } else { await Task.Run(() => client.LoginAnonymous()); } } catch (FtpResponseException) { MessageBox.Show("Invalid login or password."); return; } var root = new FtpFolder(new MyPath("/"), client); var disk = new Disk(root, Repo, new FtpFileManager(root, client)) { Header = dialog.Address }; DiskTabs.Items.Add(disk); }
private async Task <IFolder> _GetWorkflowFolder(Workflow workflow, FolderType type, bool suppressLogging = false) { IFolder folder; string typeName = Enum.GetName(typeof(FolderType), type); if (type == FolderType.Archive) { IFolder sourceFolder = await _GetWorkflowFolder(workflow, FolderType.Source, true); folder = await sourceFolder.CreateOrGetFolder($"{_ArchiveFolderName}_{workflow.Id}"); } else if (type == FolderType.Failed) { IFolder sourceFolder = await _GetWorkflowFolder(workflow, FolderType.Source, true); folder = await sourceFolder.CreateOrGetFolder($"{_FailedFolderName}_{workflow.Id}"); } else if (type == FolderType.Staging) { IFolder sourceFolder = await _GetWorkflowFolder(workflow, FolderType.Source, true); folder = await sourceFolder.CreateOrGetFolder($"{_ProcessingFolderName}_{workflow.Id}"); } else if ((type == FolderType.Source && workflow.Direction == WorkflowDirection.Inbound) || (type == FolderType.Destination && workflow.Direction == WorkflowDirection.Outbound)) { Server server = workflow.Server; FtpClient ftpClient = new FtpClient(server.Host, server.Port, server.Username, server.Password); if (_log.IsEnabled(LogLevel.Trace)) { _log.LogTrace("Using {FtpUsername} / {FtpPassword} to connect to {FtpHost}:{FtpPort}.", server.Username, server.Password, server.Host, server.Port); } else { _log.LogDebug("Using {FtpUsername} to connect to {FtpHost}:{FtpPort}. Enable trace-level logging to see password.", server.Username, server.Host, server.Port); } folder = new FtpFolder(ftpClient, PathUtil.CombineFragments(server.Path, workflow.RemotePath)); } else { folder = new LocalFolder(workflow.LocalPath); } if (!suppressLogging) { _log.LogDebug(string.Concat(typeName, " Folder: {", typeName, "folderName}"), folder.FullName); } return(folder); }
private void SetReadOnly(FtpFolder folder, String userName) { folder.UserRead = true; folder.UserWrite = false; folder.WorldRead = false; folder.WorldWrite = false; folder.GroupRead = false; folder.GroupWrite = false; folder.OwningUser = userName; }
/// <summary> /// 上传文件 /// </summary> /// <param name="ftpAddress"></param> /// <param name="remoteFilename"></param> /// <param name="localFilename"></param> /// <param name="resumeOperation"></param> public bool UploadFile(string ftpAddress, string localFilename, string remoteFilename, bool resumeOperation) { FtpSiteData siteData = ParseFtpAddress(ftpAddress); if (siteData == null) { throw new ArgumentException("Invalid ftp address format!"); } using (FtpConnection connection = new FtpConnection(siteData.Host, siteData.Port, siteData.UserName, siteData.Password)) { SetConnection(connection); AbstractFolder remoteFolder = new FtpFolder(connection); AbstractFile remoteFile = remoteFolder.GetFile(remoteFilename); AbstractFile localFile = new DiskFile(localFilename); if (!resumeOperation || !remoteFile.Exists || remoteFile.Size > localFile.Size) { localFile.CopyTo(remoteFile, true); } else if (remoteFile.Size == localFile.Size) { return(true); } else if (remoteFile.Size < localFile.Size) { byte[] buf = new byte[1024]; int cnt = -1; using (System.IO.Stream remoteStream = remoteFile.OpenWrite(false)) { using (System.IO.Stream localStream = localFile.OpenRead()) { localStream.Seek(remoteFile.Size, System.IO.SeekOrigin.Begin); // can't seek. OpenWrite如果不overwrite自动append //remoteStream.Seek(0, System.IO.SeekOrigin.End); do { cnt = localStream.Read(buf, 0, buf.Length); remoteStream.Write(buf, 0, cnt); } while (cnt == buf.Length); } } } return(true); } //FtpClient client = LoginFtp(ftpAddress); //client.SendFile(localFilename, remoteFilename); }
private void FillFtpDirectoryTree(FtpFolder argFtpInfo) { TreeNode rootNode = new TreeNode(argFtpInfo.Name) { Tag = argFtpInfo, ImageKey = "folder", SelectedImageKey = "folder_open" }; GetFtpDirectories(rootNode, 0); // First clear nodes trvFtpFolders.Nodes.Clear(); // Add the new nodes trvFtpFolders.Nodes.Add(rootNode); }
private async Task DeleteFtpFolderAsync(FtpFolder argFolder) { // Delete all the files in the folder foreach (FtpFile file in argFolder.Files) { await _ftp.DeleteRemoteFile(UrlHelper.Combine(argFolder.FullPath, file.Name)); } // Delete all the sub folders foreach (FtpFolder folder in argFolder.Folders) { if (folder.Name != "..." && folder.Name != ".." && folder.Name != ".") { await DeleteFtpFolderAsync(folder); } } // Delete the folder await _ftp.DeleteRemoteFolder(argFolder.FullPath); }
private async Task DownloadFtpFolderAsync(FtpFolder argFolder, String argLocalRoot) { // Make all the necessary local folders String localDestFolder = Path.Combine(argLocalRoot, argFolder.Name); if (!Directory.Exists(localDestFolder)) { Directory.CreateDirectory(localDestFolder); } List <Job> jobs = new List <gFtpGUI.Job>(); foreach (FtpFile file in argFolder.Files.OrderBy(f => f.Name)) { Job j = new gFtpGUI.Job { AriaPath = txtAria.Text, FtpPath = argFolder.FullPath, FtpFilename = file.Name, LocalPath = localDestFolder, LocalFilename = file.Name, Size = new FileSize(file.Size), Ftp = _ftp }; jobs.Add(j); Application.DoEvents(); } await _FrmQueue.AddJobsAsync(jobs); foreach (FtpFolder folder in argFolder.Folders) { if (folder.Name != "..." && folder.Name != ".." && folder.Name != ".") { await DownloadFtpFolderAsync(folder, localDestFolder); } } }
private async void btnConnect_Click(object sender, EventArgs e) { try { ClearFtpFolder(); grpFtpServer.Enabled = false; grpFtpServer.Cursor = Cursors.WaitCursor; grpFtpFiles.Enabled = false; grpFtpFiles.Cursor = Cursors.WaitCursor; _ftp = new gFTP(txtFtpServer.Text, txtUsername.Text, txtPassword.Text); FtpFolder f = await _ftp.GetFtpFolderDetailsAsync("", 0); FillFtpDirectoryTree(f); grpFtpServer.Enabled = true; grpFtpServer.Cursor = Cursors.Default; grpFtpFiles.Enabled = true; grpFtpFiles.Cursor = Cursors.Default; } catch (Exception ex) { Debug.WriteLine(ex); grpFtpServer.Cursor = Cursors.Default; grpFtpFiles.Cursor = Cursors.Default; MessageBox.Show(ex.Message, "An error has occured!", MessageBoxButtons.OK, MessageBoxIcon.Error); grpFtpServer.Enabled = true; grpFtpFiles.Enabled = true; } }
public void UploadOrders() { try { Xceed.Ftp.Licenser.LicenseKey = "FTN42-K40Z3-DXCGS-PYGA"; //Xceed.FileSystem.Licenser.LicenseKey = ""; if (!UploadWork) { try { UploadWork = true; SqlConnection db_connection = new SqlConnection(prop.Connection_string); db_connection.Open(); file.WriteLine(DateTime.Now.ToString("g", ci) + " [+] Выбираем заказы на экспорт"); file.Flush(); SqlCommand db_command = new SqlCommand("SELECT [number], [auto_export], [id_place] FROM [order] WHERE [auto_export] > 0;", db_connection); SqlDataAdapter db_adapter = new SqlDataAdapter(db_command); DataTable tbl = new DataTable(); db_adapter.Fill(tbl); foreach (DataRow rw in tbl.Rows) { try { file.WriteLine(DateTime.Now.ToString("g", ci) + " [+] Подготавливаем к выгрузке заказ " + rw["number"].ToString().Trim()); file.Flush(); PSA.Lib.Util.ExportOrder.autoExport((int)rw["auto_export"], rw["number"].ToString().Trim()); db_command = new SqlCommand("SELECT [server], [path], [username], [password] FROM [place] WHERE [id_place] = " + rw["id_place"], db_connection); db_adapter = new SqlDataAdapter(db_command); DataTable ptbl = new DataTable(); db_adapter.Fill(ptbl); if (ptbl.Rows.Count > 0) { DataRow place = ptbl.Rows[0]; file.WriteLine(DateTime.Now.ToString("g", ci) + " [+] Выгружаем заказ " + rw["number"].ToString().Trim() + " на " + place["server"].ToString().Trim() + " в " + place["path"].ToString().Trim()); file.Flush(); using (FtpConnection connection = new FtpConnection( place["server"].ToString().Trim(), place["username"].ToString().Trim(), place["password"].ToString().Trim())) { connection.Encoding = Encoding.GetEncoding(1251); file.WriteLine("from: " + prop.Dir_export + "\\auto_export\\" + rw["number"].ToString().Trim() + "\\"); file.Flush(); DiskFolder source = new DiskFolder(prop.Dir_export + "\\auto_export\\" + rw["number"].ToString().Trim() + "\\"); string ftp_to = place["path"].ToString().Trim() + rw["number"].ToString().Trim() + "/"; if (ftp_to.Substring(0, 1) == "/") ftp_to = ftp_to.Substring(1); file.WriteLine("to: " + ftp_to); file.Flush(); try { FtpFolder _ftp_to = new FtpFolder(connection, ftp_to); _ftp_to.Delete(); } catch { } FtpFolder destination = new FtpFolder(connection, ftp_to); StreamWriter _tmp = new StreamWriter(prop.Dir_export + "\\auto_export\\" + rw["number"].ToString().Trim() + "\\.lock"); _tmp.Write("\n"); _tmp.Close(); db_command = new SqlCommand("UPDATE [order] SET [status_export] = 'Началась выгрузка', [status_export_date] = getdate() WHERE [number] = '" + rw["number"].ToString().Trim() + "'", db_connection); db_command.ExecuteNonQuery(); source.CopyFilesTo(destination, true, true); FtpFile _lock = new FtpFile(connection, ftp_to + ".lock"); _lock.Delete(); db_command = new SqlCommand("UPDATE [order] SET [auto_export] = -1, [status_export] = 'Отправлен', [status] = '500000', [status_export_date] = getdate() WHERE [number] = '" + rw["number"].ToString().Trim() + "'", db_connection); db_command.ExecuteNonQuery(); file.WriteLine(DateTime.Now.ToString("g", ci) + " [+] Выгружен заказ " + rw["number"].ToString().Trim()); file.Flush(); Directory.Delete(prop.Dir_export + "\\auto_export\\" + rw["number"].ToString().Trim() + "\\", true); } } } catch (Exception ex) { db_command = new SqlCommand("UPDATE [order] SET [status_export] = '" + ex.Message + "', [status_export_date] = getdate() WHERE [number] = '" + rw["number"].ToString().Trim() + "'", db_connection); db_command.ExecuteNonQuery(); file.WriteLine(DateTime.Now.ToString("g", ci) + " [!] Ошибка выгрузки заказа " + ex.Message + "\n" + ex.Source + "\n" + ex.StackTrace); file.Flush(); } } } catch (Exception ex) { file.WriteLine(DateTime.Now.ToString("g", ci) + " [!] Ошибка выгрузки заказов " + ex.Message + "\n" + ex.Source + "\n" + ex.StackTrace); file.Flush(); } finally { UploadWork = false; } } } catch (Exception ex) { file.WriteLine(DateTime.Now.ToString("g", ci) + " [!] Глобальная ошибка по время отправления " + ex.Message); file.Flush(); } }
private void btnStart_Click(object sender, EventArgs e) { btnStart.Enabled = false; try { Xceed.Ftp.Licenser.LicenseKey = "FTN42-K40Z3-DXCGS-PYGA"; data.Columns.Clear(); data.Rows.Clear(); data.Columns.Add("name", "Точка"); data.Columns.Add("rezult", "Результат"); data.Columns[0].Width = 200; data.Columns[1].Width = 350; cn = new SqlConnection(setting.Connection_string); cn.Open(); cmd = new SqlCommand("SELECT * FROM [place];", cn); DataTable tbl = new DataTable(); SqlDataAdapter da = new SqlDataAdapter(cmd); da.Fill(tbl); pb.Minimum = 0; pb.Maximum = tbl.Rows.Count; pb.Value = 0; foreach (DataRow r in tbl.Rows) { try { using (FtpConnection connection = new FtpConnection( r["server"].ToString().Trim(), r["username"].ToString().Trim(), r["password"].ToString().Trim())) { connection.Timeout = 10; string tmp = Guid.NewGuid().ToString(); StreamWriter w = new StreamWriter(System.IO.Path.GetTempPath() + tmp); w.Write(tmp); w.Close(); connection.Encoding = Encoding.GetEncoding(1251); DiskFile source = new DiskFile(System.IO.Path.GetTempPath() + tmp); string ftp_to = r["path"].ToString().Trim(); if (ftp_to.Substring(0, 1) == "/") ftp_to = ftp_to.Substring(1); FtpFolder destination = new FtpFolder(connection, ftp_to); source.CopyTo(destination, true); Thread.Sleep(2000); FtpFile remote = new FtpFile(connection, ftp_to + tmp); remote.Delete(); } data.Rows.Add(new string[] { r["name"].ToString().Trim(), "ok" }); } catch (Exception ex) { data.Rows.Add(new string[] { r["name"].ToString().Trim(), "ошибка: " + ex.Message }); } finally { pb.Value++; Application.DoEvents(); } } } catch { } finally { btnStart.Enabled = true; MessageBox.Show("ok"); } }
private void button6_Click(object sender, EventArgs e) { try { Xceed.Ftp.Licenser.LicenseKey = "FTN42-K40Z3-DXCGS-PYGA"; using (FtpConnection connection = new FtpConnection( ftpAddress.Text, ftpUser.Text, ftpPassword.Text)) { connection.Encoding = Encoding.GetEncoding(1251); DiskFolder source = new DiskFolder(ftpSource.Text); FtpFolder destination = new FtpFolder(connection, ftpDestanation.Text); source.CopyFilesTo(destination, true, true); } MessageBox.Show("ok"); } catch (Exception ex) { MessageBox.Show(ex.Message + "\n" + ex.Source + "\n" + ex.StackTrace); } }
private async void btnDownload_Click(object sender, EventArgs e) { try { if (grdFtpFiles.SelectedIndex == -1) { throw new Exception("No Ftp File selected!"); } if (String.IsNullOrWhiteSpace(txtLocalPath.Text)) { throw new Exception("No local path was selected!"); } if (String.IsNullOrWhiteSpace(txtAria.Text)) { throw new Exception("No Aria2 path was provided!"); } grpFtpFiles.Enabled = false; grpFtpServer.Enabled = false; grpFtpFiles.Cursor = Cursors.WaitCursor; grpFtpServer.Cursor = Cursors.WaitCursor; Application.DoEvents(); var selectedFtpItems = grdFtpFiles.SelectedItems.Cast <FileItem>().OrderBy(f => f.Name); foreach (FileItem f in selectedFtpItems) { if (f.Type != "Directory") { Job j = new gFtpGUI.Job { AriaPath = txtAria.Text, FtpPath = txtFtpPath.Text, FtpFilename = f.Name, LocalPath = txtLocalPath.Text, LocalFilename = f.Name, Size = f.Size, Ftp = _ftp }; await _FrmQueue.AddJobAsync(j); } else { // First we have to get all the Folders and Directories are inside FtpFolder fd = await _ftp.GetFtpFolderDetailsAsync(UrlHelper.Combine(txtFtpPath.Text, f.Name), Int32.MaxValue); await DownloadFtpFolderAsync(fd, txtLocalPath.Text); } } grpFtpFiles.Enabled = true; grpFtpServer.Enabled = true; grpFtpFiles.Cursor = Cursors.Default; grpFtpServer.Cursor = Cursors.Default; } catch (Exception ex) { Debug.WriteLine(ex); grpFtpFiles.Cursor = Cursors.Default; grpFtpServer.Cursor = Cursors.Default; MessageBox.Show(ex.Message, "An error has occured!", MessageBoxButtons.OK, MessageBoxIcon.Error); grpFtpFiles.Enabled = true; grpFtpServer.Enabled = true; } }
private async void btnDeleteRemoteFile_Click(object sender, EventArgs e) { try { if (grdFtpFiles.SelectedIndex == -1) { throw new Exception("No Ftp File selected!"); } // Ask for confirmation from user if (MessageBox.Show( "Are you sure you want to delete remote files?", "Are you sure?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) { return; } grpFtpFiles.Enabled = false; grpFtpServer.Enabled = false; btnDeleteRemoteFile.Enabled = false; grpFtpFiles.Cursor = Cursors.WaitCursor; grpFtpServer.Cursor = Cursors.WaitCursor; Application.DoEvents(); foreach (FileItem f in grdFtpFiles.SelectedItems) { if (f.Type != "Directory") { await _ftp.DeleteRemoteFile(UrlHelper.Combine(txtFtpPath.Text, f.Name)); } else { // First we have to get all the Folders and Directories are inside FtpFolder fd = await _ftp.GetFtpFolderDetailsAsync(UrlHelper.Combine(txtFtpPath.Text, f.Name), Int32.MaxValue); await DeleteFtpFolderAsync(fd); } } // Refresh the ftp grid TaskCompletionSource <int> t = new TaskCompletionSource <int>(); btnRefreshFtpPath_Click(t, null); await t.Task; grpFtpFiles.Cursor = Cursors.Default; grpFtpServer.Cursor = Cursors.Default; MessageBox.Show($"The remote file(s) was deleted successfully!", "Success!", MessageBoxButtons.OK, MessageBoxIcon.Information); grpFtpFiles.Enabled = true; grpFtpServer.Enabled = true; btnDeleteRemoteFile.Enabled = true; } catch (Exception ex) { Debug.WriteLine(ex); grpFtpFiles.Cursor = Cursors.Default; grpFtpServer.Cursor = Cursors.Default; MessageBox.Show(ex.Message, "An error has occured!", MessageBoxButtons.OK, MessageBoxIcon.Error); grpFtpFiles.Enabled = true; grpFtpServer.Enabled = true; btnDeleteRemoteFile.Enabled = true; } }
private async void trvFtpFolders_AfterSelect(object sender, TreeViewEventArgs e) { try { grpFtpFiles.Enabled = false; grpFtpFiles.Cursor = Cursors.WaitCursor; // Read the Sub Directories of the selected node and update the Folder Tree View TreeNode selNode = e.Node; selNode.Tag = await _ftp.GetFtpFolderDetailsAsync((selNode.Tag as FtpFolder).FullPath, 0); FtpFolder selDirInfo = selNode.Tag as FtpFolder; txtFtpPath.Text = selDirInfo.FullPath; GetFtpDirectories(selNode, 0); // Read the contents and add them to the ListView // First clear the list view contents grdFtpFiles.DataSource = null; List <FileItem> items = new List <FileItem>(); // First add the Up Directory only if there is a parent node if (selNode.Parent != null) { FileItem itemUp = new FileItem { Type = "Directory", Name = "...", Icon = Properties.Resources.folder1.ToBitmap(), Size = null }; items.Add(itemUp); } IList <FtpFolder> localDirs = null; try { localDirs = selDirInfo.Folders; } catch (Exception ex) { Debug.WriteLine(ex); } if (localDirs != null) { foreach (FtpFolder dir in localDirs) { FileItem item = new FileItem { Type = "Directory", Name = dir.Name, Icon = Properties.Resources.folder1.ToBitmap(), Date = dir.Date, Size = null }; items.Add(item); } } IList <FtpFile> localFiles = null; try { localFiles = selDirInfo.Files; } catch (Exception ex) { Debug.WriteLine(ex); } if (localFiles != null) { foreach (FtpFile file in localFiles) { FileItem item = new FileItem { Type = file.Extension(), Name = file.Name, Icon = IconReader.GetFileIcon(file.Extension(), IconReader.IconSize.Small, false).ToBitmap(), Date = file.Date, Size = new gFtpGUI.FileSize(file.Size) }; items.Add(item); } } grdFtpFiles.DataSource = items; grpFtpFiles.Enabled = true; grpFtpFiles.PerformLayout(); grpFtpFiles.Cursor = Cursors.Default; } catch (Exception ex) { Debug.WriteLine(ex); grpFtpFiles.Cursor = Cursors.Default; MessageBox.Show(ex.Message, "An error has occured!", MessageBoxButtons.OK, MessageBoxIcon.Error); grpFtpFiles.Enabled = true; } }
private async void btnRefreshFtpPath_Click(object sender, EventArgs e) { TaskCompletionSource <int> taskCompletionSource = null; if (sender is TaskCompletionSource <int> t) { taskCompletionSource = t; } try { if (trvFtpFolders.SelectedNode == null) { taskCompletionSource?.SetResult(1); return; } grpFtpFiles.Enabled = false; grpFtpFiles.Cursor = Cursors.WaitCursor; // Read the Sub Directories of the selected node and update the Folder Tree View TreeNode selNode = trvFtpFolders.SelectedNode; selNode.Tag = await _ftp.GetFtpFolderDetailsAsync((selNode.Tag as FtpFolder).FullPath, 0); FtpFolder selDirInfo = selNode.Tag as FtpFolder; txtFtpPath.Text = selDirInfo.FullPath; GetFtpDirectories(selNode, 0); // Read the contents and add them to the ListView // Keep the sorted column and order DataGridViewColumn sortColumn = grdFtpFiles.SortedColumn; SortOrder sortOrder = grdFtpFiles.SortOrder; int oldVerticalOffset = grdFtpFiles.FirstDisplayedScrollingRowIndex; int oldSelectedIndex = grdFtpFiles.SelectedIndex; // First clear the list view contents grdFtpFiles.DataSource = null; List <FileItem> items = new List <FileItem>(); // First add the Up Directory only if there is a parent node if (selNode.Parent != null) { FileItem itemUp = new FileItem { Type = "Directory", Name = "...", Icon = Properties.Resources.folder1.ToBitmap(), Size = null }; items.Add(itemUp); } IList <FtpFolder> localDirs = null; try { localDirs = selDirInfo.Folders; } catch (Exception ex) { Debug.WriteLine(ex); } if (localDirs != null) { foreach (FtpFolder dir in localDirs) { FileItem item = new FileItem { Type = "Directory", Name = dir.Name, Icon = Properties.Resources.folder1.ToBitmap(), Date = dir.Date, Size = null }; items.Add(item); } } IList <FtpFile> localFiles = null; try { localFiles = selDirInfo.Files; } catch (Exception ex) { Debug.WriteLine(ex); } if (localFiles != null) { foreach (FtpFile file in localFiles) { FileItem item = new FileItem { Type = file.Extension(), Name = file.Name, Icon = IconReader.GetFileIcon(file.Extension(), IconReader.IconSize.Small, false).ToBitmap(), Date = file.Date, Size = new gFtpGUI.FileSize(file.Size) }; items.Add(item); } } grdFtpFiles.DataSource = items; // Set the sortedColumn and order again if (sortColumn != null) { // Find the new DataGridViewColumn DataGridViewColumn newSortColumn = grdFtpFiles.Columns.Cast <DataGridViewColumn>().FirstOrDefault(c => c.Name == sortColumn.Name); if (newSortColumn != null) { if (sortOrder == SortOrder.Ascending) { grdFtpFiles.Sort(newSortColumn, ListSortDirection.Ascending); } else if (sortOrder == SortOrder.Descending) { grdFtpFiles.Sort(newSortColumn, ListSortDirection.Descending); } } } // Check if Vertical Offset is now valid if (oldVerticalOffset > grdFtpFiles.Rows.Count - 1) { oldVerticalOffset = grdFtpFiles.Rows.Count - 1; } grdFtpFiles.FirstDisplayedScrollingRowIndex = oldVerticalOffset; // Check if selected index is now valid if (oldSelectedIndex > grdFtpFiles.Rows.Count - 1) { oldSelectedIndex = grdFtpFiles.Rows.Count - 1; } grdFtpFiles.SetSelectedRowByIndex(oldSelectedIndex, false); grpFtpFiles.Enabled = true; grdFtpFiles.PerformLayout(); grpFtpFiles.Cursor = Cursors.Default; taskCompletionSource?.SetResult(1); } catch (Exception ex) { Debug.WriteLine(ex); grpFtpFiles.Cursor = Cursors.Default; MessageBox.Show(ex.Message, "An error has occured!", MessageBoxButtons.OK, MessageBoxIcon.Error); grpFtpFiles.Enabled = true; taskCompletionSource?.SetResult(1); } }