I have two devices having separate IP addresses and want to check if any one is connected and if connected download the database from the device and any given time only one device is connected.My query works fine for one device how to check which one is connected. I have updated my code but not sure how is it gone work.
private void button7_Click(object sender, EventArgs e)// 1)first download database to local system.
{
this.Process1();
}
public void Process1()
{
string _ftpURL = #"131.000.00.0"; // fake Host URL or address of the SFTP server
/* how to check for another IP adddress if exists */
string _UserName = "root"; //fake User Name of the SFTP server
string _Password = "3term"; // fake Password of the SFTP server
int _Port = 2222; //Port No of the SFTP server (if any)
string _ftpDirectory = "/home/root/systools/WM/WebMobility.db"; //The directory in SFTP server where the files will be uploaded
string LocalDirectory = "F:\\Explor\\final test"; //Local directory from where the files will be uploaded
try
{
Sftp Connection = new Sftp(_ftpURL, _UserName, _Password);
Connection.Connect(_Port);
Connection.Get(_ftpDirectory, LocalDirectory);
Connection.Close();
}
catch (Exception ex)
{
if (ex is SshConnectionException || ex is SocketException)
{
_ifwInstance.Error(string.Format("Ignoring {0} during listing directory", ex.Message));
}
else
{
string _ftpURL = #"131.111.11.11"; // fake Host URL or address of the SFTP server
/* how to check for another IP adddress if exists */
string _UserName = "root"; //fake User Name of the SFTP server
string _Password = "3term"; // fake Password of the SFTP server
int _Port = 2222; //Port No of the SFTP server (if any)
string _ftpDirectory = "/home/root/systools/WM/WebMobility.db"; //The directory in SFTP server where the files will be uploaded
string LocalDirectory = "F:\\Explor\\final test"; //Local directory from where the files will be uploaded
throw new Exception("Login to SFT FAILED", ex);
}
}
}
updated Code:
string[] _ftpURL = { #"100.100.0.0", #"101.0.0.0" }; //Array of address to SFTP servers
string _UserName = "root"; //fake User Name of the SFTP server
string _Password = "310rp3"; // fake Password of the SFTP server
int _Port = 2222; //Port No of the SFTP server (if any)
string _ftpDirectory = "/home/root/systools/WM/WebMobility.db"; //The directory in SFTP server where the files will be uploaded
string LocalDirectory = "F:\\Explor\\final test"; //Local directory from where the files will be uploaded
bool online = false;
foreach(string furl in _ftpURL)
{
Sftp Connection = new Sftp(furl, _UserName, _Password);
try
{
Connection.Connect(_Port);
online = true;
}
catch
{
online = false;
}
if(online == true)
{
Connection.Get(_ftpDirectory, LocalDirectory);
Connection.Close();
break;
}
}
Add these two methods to some class and call public DownloadSftpFile from your desktop code.
// returns true if the file had downloaded
public static bool DownloadSftpFile(string[] hosts, int port, string username, string password, string remotePathAndFile, string localPath)
{
foreach (var host in hosts)
{
try
{
DownloadSftpFile(host, port, username, password, remotePathAndFile, localPath);
return true;
}
catch(SshConnectionException exception)
{
// log
}
catch(SocketExcpetion exception)
{
// log
}
}
return false;
}
private static void DownloadSftpFile(string host, int port, string username, string password, string remotePathAndFile, string localPath)
{
using (var sftp = new Sftp(host, username, password))
{
sftp.Connect(port);
sftp.Get(remotePathAndFile, localPath);
}
}
Related
The below program written in C# which runs fine in Windows but when it comes to running in Linux ( inside a docker container) it doesn't translate the path properly.
class Program
{
static void Main(string[] args)
{
try {
bool validLogin = ValidateUser("domain", "username", "password" );
if (validLogin)
{
var path = "\\\\10.123.123.123\\folder$\\subfolder";
string fullPath = Path.Combine("\\\\10.123.123.123\\folder$\\subfolder", "file_name1");
string body = "Test File Contents";
if (!Directory.Exists(path))
{
Directory.CreateDirectory((path));
}
File.WriteAllText(fullPath, body);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString() + ex.Message);
}
}
public static bool ValidateUser(string domainName, string username, string password)
{
string userDn = $"{username}#{domainName}";
try
{
using (var connection = new LdapConnection {SecureSocketLayer = false})
{
connection.Connect(domainName, LdapConnection.DefaultPort);
connection.Bind(userDn, password);
if (connection.Bound)
return true;
}
}
catch (LdapException )
{
// Log exception
}
return false;
}
}
What exact path should I use? I have tried all sorts of combinations.
In windows, you have "Local Paths" which start with a letter that refers to a local drive, then you have networked paths, which begin with a double-backslash, followed by some domain/IP, followed by a directory share (all of which can be mapped to another letter, for ease of access)
To access network shares, from Linux, you need to Mount the share to some location of the Linux tree.
You can look at many examples on-line, here is one: Mounting and mapping shares between Windows and Linux with Samba
Also, the resulting Path will look nothing like what you have for Windows, so, you will need to know (somehow) that you are running under which SO, and configure your paths accordingly.
Few suggestions
Check the hosing environment & manipulate paths accordingly.
You can use Path.Combine() to formulate your paths.
An example of this application is below
using System.Runtime.InteropServices;
class Program
{
static void Main(string[] args)
{
try {
bool validLogin = ValidateUser("domain", "username", "password" );
if (validLogin)
{
var path = Path.Combine("\\\\10.123.123.123", "folder$", "subfolder");
string fullPath = Path.Combine(path, "file_name1");
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
path = path.Replace(#"\", #"/");
fullPath = fullPath.Replace(#"\", #"/");
}
string body = "Test File Contents";
if (!Directory.Exists(path))
{
Directory.CreateDirectory((path));
}
File.WriteAllText(fullPath, body);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString() + ex.Message);
}
}
public static bool ValidateUser(string domainName, string username, string password)
{
string userDn = $"{username}#{domainName}";
try
{
using (var connection = new LdapConnection {SecureSocketLayer = false})
{
connection.Connect(domainName, LdapConnection.DefaultPort);
connection.Bind(userDn, password);
if (connection.Bound)
return true;
}
}
catch (LdapException )
{
// Log exception
}
return false;
}
}
in a c# program that i made, i read some values from an INI file,put them in string, in function UPLOAD and i make a database manager for those values to connect the user to a db. Now, i need to read those strings from another function, you see it below. What shall i do ?
public Upload()
{
#region INI PROPERTIES and Variables
INIFile inif = new INIFile(#".\Settings\AppSettings.ini");
//Values for DatabaseManager dbm
//Hosting Server IP
string srv_ip = inif.Read("DatabaseSettings", "IP_adress");
//Database Username
string srv_uname = inif.Read("DatabaseSettings", "Admin_Username");
//Database Password
string srv_pass = inif.Read("DatabaseSettings", "Admin_Password");
//Database Name
string srv_dbname = inif.Read("DatabaseSettings", "Database_Name");
//Values for DatabaseManager dbm
//Fingerprint of Hosting Server IP
string ftp_fingerprint = inif.Read("ProgramSettings", "fingerprint");
//Host
string ftp_host = inif.Read("ProgramSettings", "host");
//Username
string ftp_username = inif.Read("ProgramSettings", "username");
//Password
string ftp_pass = inif.Read("ProgramSettings", "password");
#endregion
InitializeComponent();
DatabaseManager dbm = new DatabaseManager(srv_ip, srv_uname, srv_pass, srv_dbname);
dbm.Init();
}
And the other function. I need from the first to store the variables into the strings that you can see on the second.
private void upload_btn_MouseDown(object sender, MouseButtonEventArgs e)
{
string fingerprint = ftp_fingerprint;
string host = ftp_host;
string username = ftp_username;
string password = ftp_pass;
FtpManager ftpm = new FtpManager(host, username, password, fingerprint, ProgressCallback);
string remoteFolder = "/var/whatever"; // Name of directory to upload
string remoteName; // Name of file to save on server
//some more code
}
Problem solved by making those variables fields. Thank you all for your answers i appreciate each one of you for your time.
The simplest way to go is to make them fields.
private string ftp_fingerprint;
private string ftp_host;
private string ftp_username;
private string ftp_pass;
public Upload()
{
#region INI PROPERTIES and Variables
INIFile inif = new INIFile(#".\Settings\AppSettings.ini");
//Values for DatabaseManager dbm
//Hosting Server IP
string srv_ip = inif.Read("DatabaseSettings", "IP_adress");
//Database Username
string srv_uname = inif.Read("DatabaseSettings", "Admin_Username");
//Database Password
string srv_pass = inif.Read("DatabaseSettings", "Admin_Password");
//Database Name
string srv_dbname = inif.Read("DatabaseSettings", "Database_Name");
//Values for DatabaseManager dbm
//Fingerprint of Hosting Server IP
ftp_fingerprint = inif.Read("ProgramSettings", "fingerprint");
//Host
ftp_host = inif.Read("ProgramSettings", "host");
//Username
ftp_username = inif.Read("ProgramSettings", "username");
//Password
ftp_pass = inif.Read("ProgramSettings", "password");
#endregion
InitializeComponent();
DatabaseManager dbm = new DatabaseManager(srv_ip, srv_uname, srv_pass, srv_dbname);
dbm.Init();
}
private void upload_btn_MouseDown(object sender, MouseButtonEventArgs e)
{
string fingerprint = ftp_fingerprint;
string host = ftp_host;
string username = ftp_username;
string password = ftp_pass;
FtpManager ftpm = new FtpManager(host, username, password, fingerprint, ProgressCallback);
string remoteFolder = "/var/whatever"; // Name of directory to upload
string remoteName; // Name of file to save on server
//some more code
}
This question already has answers here:
SFTP Libraries for .NET [closed]
(8 answers)
Closed 4 years ago.
I'am using .NET 4.5 and I need to connect to an SFTP site and download two files to my local pc. From my reading on the internet there are no in built libraries I can use in .NET.
Are there any reliable 3rd parties that I can use that also have simple examples?
I have the following
username: myusername
password: mypassword
hostname: fts-sftp.myhost.com
protocol: SFTP
Port: 6621
Update
I have the code below however I am getting the following error message on the "sftp.Connect()" line.
An unhandled exception of type 'System.Net.Sockets.SocketException' occurred in System.dll
Additional information: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
Have checked the creditenals that have been supplied to me to make sure I have no typo's.
using Renci.SshNet;
using Renci.SshNet.Common;
using Renci.SshNet.Sftp;
namespace SftpExample2
{
class Program
{
static void Main(string[] args)
{
string host = "fts-sftp.myaddress.com";
string password = "mypassword";
string username = "myusername";
string remoteDirectory = ".";
int port = 6671;
using (SftpClient sftp = new SftpClient(host, port, username, password))
{
sftp.Connect();
var files = sftp.ListDirectory(remoteDirectory);
foreach (var file in files)
Console.WriteLine(file.FullName);
sftp.Disconnect();
};
}
}
}
I generaly use Renci.SshNet
below is an example of download, it should be trivial to change it for download.
I ripped it out of an old project, it might need some tuning to get it to compile/run
static public void UploadFiles(string [] files)
{
string host = " fts-sftp.myhost.com";
string userName = "user";
string password = "pass";
var keyboardAuthMethod = new KeyboardInteractiveAuthenticationMethod(userName);
keyboardAuthMethod.AuthenticationPrompt += delegate(Object senderObject, AuthenticationPromptEventArgs eventArgs)
{
foreach (var prompt in eventArgs.Prompts)
{
if (prompt.Request.Equals("Password: ", StringComparison.InvariantCultureIgnoreCase))
{
prompt.Response = password;
}
}
};
var passwordAuthMethod = new PasswordAuthenticationMethod(userName, password);
var connectInfo = new ConnectionInfo(host, userName, passwordAuthMethod, keyboardAuthMethod);
using (SftpClient serverConnection = new SftpClient(connectInfo))
{
try
{
foreach (var file in files)
{
if (!file.Name.StartsWith("."))
{
string remoteFileName = file.Name;
if (file.LastWriteTime.Date == DateTime.Today)
Console.WriteLine(file.FullName);
File.OpenWrite(localFileName);
string sDir = #"localpath";
Stream file1 = File.OpenRead(remoteDirectory + file.Name);
sftp.DownloadFile(remoteDirectory, file1);
}
serverConnection.Disconnect();
}
catch (Exception e)
{
throw e;
}
}
}
using Tamir.SharpSsh;
public void DownloadSFTP_Files()
{
string _ftpURL = "URLHERE";
string _SftpUserName = "USERNAMEHERE";
string _SftpPassword = "PASSWORDHERE";
int _port = 22;
Sftp oSftp = new Sftp(_ftpURL, _SftpUserName, _SftpPassword);
oSftp.Connect(_port);
string path = "";
// Get List of Files in the SFTP Directory
System.Collections.ArrayList GetFiles_List = oSftp.GetFileList(path);
// Download the Files Form SFTP Server to you Local system
string ServerPath= "SERVERDiRECTORYPATHHERE";
string LocalPath= "LOCALDiRECTORYPATHHERE";
oSftp.Get(ServerPath, LocalPath);
oSftp.Close();
}
Before I start, I've already visited Unknown Error (0x80005000) with LDAPS Connection and changed my code and while it did solve the problem it seems that it has mysteriously come back.
Here's the good stuff:
public static bool Authenticate(string username, string password, string domain)
{
bool authentic = false;
try
{
LdapConnection con = new LdapConnection(
new LdapDirectoryIdentifier(Host, Port));
if (IsSSL)
{
con.SessionOptions.SecureSocketLayer = true;
con.SessionOptions.VerifyServerCertificate = ServerCallback;
}
con.Credential = new NetworkCredential(username, password);
con.AuthType = AuthType.Basic;
con.Bind();
authentic = true;
}
catch (LdapException)
{
return false;
}
catch (DirectoryServicesCOMException)
{ }
return authentic;
}
public static bool IsSSL
{
get
{
return ConnectionString.ToLower().Contains("ldaps");
}
}
public static string ConnectionString
{
get
{
if (string.IsNullOrEmpty(_connectionString))
_connectionString = CompleteConfiguration.GetLDAPConnectionString();
return _connectionString;
}
set { _connectionString = value; }
}
public static int Port
{
get
{
var x = new Uri(ConnectionString);
int port = 0;
if (x.Port != -1)
{
port = x.Port;
}
else
{
port = x.OriginalString.ToLower().Contains("ldaps")
? 636
: 389;
}
return port;
}
}
public static string Host
{
get
{
var x = new Uri(ConnectionString);
return x.Host;
}
}
private static bool ServerCallback(LdapConnection connection, X509Certificate certificate)
{
return true;
}
Here's the bad stuff:
When I attempt to authenticate to the application I get the following error, to be precise this is triggered by the con.Bind() line:
[COMException (0x80005000): Unknown error (0x80005000)]
System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail) +378094
System.DirectoryServices.DirectoryEntry.Bind() +36
System.DirectoryServices.DirectoryEntry.get_NativeObject() +31
Complete.Authentication.GCAuthentication.Authenticate(String username, String password, String domain) in c:\Builds\6\Idealink.Open.Pancanal\Panama Canal\Sources\Idealink.Open\Complete.Authentication\GCAuthentication.cs:27
Complete.Authentication.AuthenticationFactory.ValidateUserLdap(String username, String password, String domain, Boolean isValid, String usernameWithDomain) in c:\Builds\6\Idealink.Open.Pancanal\Panama Canal\Sources\Idealink.Open\Complete.Authentication\AuthenticationFactory.cs:93
It is quite confusing as it seems that some user accounts work and others don't. However when I place the above code in an isolated test environment it does succeed each and every time regardless of which account I use. When I place it back on the Windows 2008 R2 Server with ASP.NET and IIS it fails as stated above. The failures are consistent though - accounts consistently fail or succeed, from that perspective there is no randomness.
The LDAP Server must be accessed using LDAPS and NOT LDAP which is why we cannot use the DirectoryEntry object - the LDAP server is controlled by a client and therefore cannot be reconfigured or altered in any way. We simply want to capture username/password on a web form and then use BIND on the LDAP server to check credentials.
We are using .NET 3.5 and cannot upgrade at this time so I respectfully ask that if your main suggestion and arguments are to upgrade than please hold off on your contribution.
Thanks, hope you can help
Would something like this work for you..?
const string Domain = "ServerAddress:389";
const string constrParts = #"OU=Users,DC=domain,DC=com";
const string Username = #"karell";
PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, Domain, constrParts);
UserPrincipal userPrincipal = UserPrincipal.FindByIdentity(principalContext, username);
Here is a really good site for great references and examples
DirectoryServices DirectoryEntry
for Connection over SSL you could do something like the following
const int ldapInvalidCredentialsError = 0x31;
const string server = "your_domain.com:636";
const string domain = "your_domain.com";
try
{
using (var ldapSSLConn = new LdapConnection(server))
{
var networkCredential = new NetworkCredential(username, password, domain);
ldapSSLConn.SessionOptions.SecureSocketLayer = true;
ldapSSLConn.AuthType = AuthType.Negotiate;
ldapSSLConn.Bind(networkCredential);
}
// If the bind succeeds, the credentials are valid
return true;
}
catch (LdapException ldapEx)
{
// Invalid credentials a specific error code
if (ldapEx.ErrorCode.Equals(ldapInvalidCredentialsError))
{
return false;
}
throw;
}
MSDN list of Invalid LDAP Error Codes
I have a website with an ASP.NET MVC backend running .NET 3.5. On this website, there is a script that sends emails using gmail as the mail service. The script runs and sends mail fine locally on my dev machine, but as soon as I upload it to the live server it fails. The only error message it is giving me at the moment is (since I told it to as you will see further down):
The transport failed to connect to the server.
Here is the code for the mailer script:
using System.Net.Mail;
using System.Web.Mail;
using MailMessage = System.Web.Mail.MailMessage;
namespace MySite.Helpers
{
public class GmailHelper
{
private readonly int _port = 465;
private readonly string _accountName;
private readonly string _password;
public GmailHelper(string accountName, string password)
{
_accountName = accountName;
_password = password;
}
public GmailHelper(string accountName, string password, int port)
{
_accountName = accountName;
_password = password;
_port = port;
}
public void Send(string from, string to, string subject, string body, bool isHtml)
{
Send(from, to, subject, body, isHtml, null);
}
public void Send(string from, string to, string subject, string body, bool isHtml, string[] attachments)
{
var mailMessage = new MailMessage
{
From = from,
To = to,
Subject = subject,
Body = body,
BodyFormat = isHtml ? MailFormat.Html : MailFormat.Text
};
// Add attachments
if (attachments != null)
{
foreach (var t in attachments)
{
mailMessage.Attachments.Add(new Attachment(t));
}
}
// Authenticate
mailMessage.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate", 1);
// Username for gmail - email#domain.com for email for Google Apps
mailMessage.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusername", _accountName);
// Password for gmail account
mailMessage.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendpassword", _password);
// Google says to use 465 or 587. I don't get an answer on 587 and 465 works - YMMV
mailMessage.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpserverport", _port.ToString());
// STARTTLS
mailMessage.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpusessl", true);
// assign outgoing gmail server
SmtpMail.SmtpServer = "smtp.gmail.com";
SmtpMail.Send(mailMessage);
}
}
}
And here is how it is called:
[HttpPost]
public ActionResult Employment(EmploymentModel model, FormCollection collection)
{
if (!ModelState.IsValid)
return View(model);
var results = new EmploymentViewModel();
try
{
results.Position = model.Position;
results.FirstName = model.FirstName;
results.LastName = model.LastName;
results.ContactPhone = model.ContactPhone;
results.OtherPhone = model.OtherPhone;
results.Address = model.Address;
results.Email = model.Email;
results.HsDiploma = model.HsDiploma.ToString();
results.CollegeYears = model.CollegeYears;
results.Skills = model.Skills;
results.Employment = model.Employment;
results.DateSent = DateTime.Now.ToString("MM/dd/yyyy HH:mm:ss");
var gmail = new GmailHelper("noreply#mysite.com", "[*removed*]");
var fromAddress = new MailAddress("noreply#mysite.com", "MySite");
var toAddress = new MailAddress("applications#mysite.com", "MySite Employment");
var subject = string.Format("Employment Application for {0} {1}", model.FirstName, model.LastName);
gmail.Send(fromAddress.Address, toAddress.Address, subject, EmployMailBody(results), false);
}
catch (Exception ex)
{
results.Sent = false;
results.Title = "Oops, our mail drone seems to have malfunctioned!";
results.Message = string.Format("We appologize, {0} {1}, but our email system has encountered an error and your email was not sent.</p>",
results.FirstName, results.LastName);
results.Message += Environment.NewLine + "<p>Please try your request later, or fax your résumé to our Corporate office.";
results.Message += Environment.NewLine + JQueryHelpers.GenerateErrorField(ex.Message);
return View("EmploymentSubmit", results);
}
results.Sent = true;
results.Title = "Thank you for your submission!";
results.Message = string.Format("Thank you for your interest in joining our team, {0} {1}!</p>", results.FirstName, results.LastName);
results.Message += Environment.NewLine + "<p>We have successfully recieved your information and will contact you shortly at the number your have provided.";
return View("EmploymentSubmit", results);
}
I am 99% positive that it was functional before when it was up on the site, but I could be mistaken as it has been a month or so since I have had to update the site.
Are there some additional steps I can take to debug this "better" to track down the underlying issue, or did I botch up my code somewhere accidentally?
Thanks!
EDIT1
So I updated the class to use strictly System.Net.Mail. I successfully sent a message from my dev machine. When I uploaded the site to my server, however, I got a new error message:
Request for the permission of type 'System.Net.Mail.SmtpPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.
This site is hosted through godaddy.com, and some after searching around it seems godaddy only allows relaying through their smtp server. It looks like I'll have to change hosting providers to get this working properly.
Thanks!
EDIT2
The reason I moved to gmail from godaddy is originally when I had this script up the email would take anywhere from 15 to 45 minutes to arrive at the destination box. This could have been the deprecated code I was using before, but either way it is now being dispatched and arriving within seconds, as it should be. Here is my GoDaddy helper class, in case it will help someone:
public class GoDaddyHelperNet
{
private readonly int _port = 25;
private readonly MailAddress _accountName;
private readonly string _password;
private readonly string _host = "relay-hosting.secureserver.net";
public GoDaddyHelperNet(MailAddress accountName, string password)
{
_accountName = accountName;
_password = password;
}
public GoDaddyHelperNet(MailAddress accountName, string password, int port)
{
_accountName = accountName;
_password = password;
_port = port;
}
public GoDaddyHelperNet(MailAddress accountName, string password, int port, string host)
{
_accountName = accountName;
_password = password;
_port = port;
_host = host;
}
public void Send(MailAddress to, string subject, string body, bool isHtml)
{
Send(_accountName, to, subject, body, isHtml);
}
public void Send(MailAddress from, MailAddress to, string subject, string body, bool isHtml)
{
var smtp = new SmtpClient
{
Host = _host,
Port = _port,
EnableSsl = false,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(from.Address, _password),
Timeout = 15000
};
using (var message = new System.Net.Mail.MailMessage(from.Address, to.Address)
{
Subject = subject,
Body = body,
})
smtp.Send(message);
}
}
there is probably a firewall rule or other network device blocking you. verify that you can telnet to the gmail server from your web server and can send an email.
http://www.wikihow.com/Send-Email-Using-Telnet
if you can't you probably have to talk to your network admin. i have email problems like this on about half of my clients web servers.
Gmail has got lots of restrictions on SMTP relay. No more than 100 total recipients per day, IIRC. Limits on recipients per message as well. Limits on message/attachment size. If you exceed the limits or Gmail has decided that you look like a spam artiste, their SMTP server may well refuse the connection for a day or so.