线程.FTP.SFTP.打包
Windows就是多线程模式.
每一个解决方案就是一个进程.
一个进程下拥有多个线程.
单核的处理器不存在多线程.
是CPU在每一个线程上切换处理.
在人反应不过来的情况下完成同步的效果.
比如左手画圆右手画方.
聪明的人会利用时间差完成.
System.Threading.Thread[] threads = new System.Threading.Thread[2]; for (int i = 0; i <= 1; i++) { System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(p.GGG)); threads[i].Start(); } private void GGG()//证明线程利用时间差做出类似同步的案例 { for (int i = 0; i < 100; i++) { int f = 10; GGG1(f); } } private void GGG1(int f) { //lock (Glock)//lock最好放在方法的最上面,没有死锁就会出现复数 //{ if (A1 >= f) { Console.WriteLine(Thread.CurrentThread.Name); Console.WriteLine(A1 + "|" + f); A1 = A1 - f; Console.WriteLine(A1); } // } } int A1 = 1000;
简单点.将单例模式注释解开.可以得到A1的值大于0if判断生效
如果将单例模式注释掉.可以得到A1值小于0 if 无效
如果运行到a1=1 f =1时
第一个线程进入if判断.通过.但是没有相减.CPU切换到第二个线程.进入if判断.然后通过
结果a1运行了-1-1
所以if判断无效.证明.
在单核CPU上不存在同步的多线程.
多线程是利用时间差完成对资源的分配.
线程利用时间差完成类似同步效果
现在的CPU可以处理几十个进程.上百个线程.
就像一个人不启动线程就只有一只手.但是他感觉像有一千只手
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace ConsoleApplication1 { class MyThread { WaitHandle[] wssssss = new WaitHandle[] { }; Thread t = null; //如果为 true则将初始状态设置为终止 //如果为 false,则将初始状态设置为非终止。 ManualResetEvent manualEvent = new ManualResetEvent(false);//true没有信号运行,false有信号不运行 private void Run() { Console.WriteLine(this.manualEvent.WaitOne());//等待信号 ,收到信号返回true,没有永不返回 //+int|TimeSpan等待指定时间并运行, Console.WriteLine("这里是 {0}", Thread.CurrentThread.ManagedThreadId);//如果有多个线程,这里就自动循环打印 Thread.Sleep(500); } public void Start() { this.manualEvent.Set();//启动没有信号 Console.WriteLine("已启动"); } public void Stop() { this.manualEvent.Reset();//阻止有信号 Console.WriteLine("已阻止"); } public MyThread() { for (int i = 0; i <=5; i++) { t = new Thread(this.Run); t.Start(); } } public void w() { for (int i = 0; i <= 5; i++) { t = new Thread(this.Run); t.Start(); } } static void Main(string[] args) { MyThread myt = new MyThread(); //myt.w(); string str1 = Console.ReadLine(); if (str1.ToLower().Trim() == "stop") { myt.Stop(); } if (str1.ToLower().Trim() == "start") { myt.Start(); } Console.Read(); } } }
以上是多线程通信.
ManualResetEvent 就是信号灯.在线程中通信.
true没有信号运行,false有信号不运行
using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Net; using System.Globalization; namespace ConsoleApplication1 { public class FtpWeb { string ftpServerIP; string ftpRemotePath; string ftpUserID; string ftpPassword; string ftpURI; /// <summary> /// 连接FTP /// </summary> /// <param name="FtpServerIP">FTP连接地址</param> /// <param name="FtpRemotePath">指定FTP连接成功后的当前目录, 如果不指定即默认为根目录</param> /// <param name="FtpUserID">用户名</param> /// <param name="FtpPassword">密码</param> public FtpWeb(string FtpServerIP, string FtpRemotePath, string FtpUserID, string FtpPassword) { ftpServerIP = FtpServerIP; ftpRemotePath = FtpRemotePath; ftpUserID = FtpUserID; ftpPassword = FtpPassword; ftpURI = "ftp://" + ftpServerIP + "/" + ftpRemotePath + "/"; } /// <summary> /// 上传 /// </summary> /// <param name="filename"></param> public void Upload(string filename) { FileInfo fileInf = new FileInfo(filename); string uri = ftpURI + fileInf.Name; FtpWebRequest reqFTP; reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); reqFTP.KeepAlive = false; reqFTP.Method = WebRequestMethods.Ftp.UploadFile; reqFTP.UseBinary = true; reqFTP.ContentLength = fileInf.Length; int buffLength = 2048; byte[] buff = new byte[buffLength]; int contentLen; FileStream fs = fileInf.OpenRead(); try { Stream strm = reqFTP.GetRequestStream(); contentLen = fs.Read(buff, 0, buffLength); while (contentLen != 0) { strm.Write(buff, 0, contentLen); contentLen = fs.Read(buff, 0, buffLength); } strm.Close(); fs.Close(); } catch (Exception ex) { Insert_Standard_ErrorLog.Insert("FtpWeb", "Upload Error --> " + ex.Message); } } /// <summary> /// 下载 /// </summary> /// <param name="filePath"></param> /// <param name="fileName"></param> public void Download(string filePath, string fileName) { FtpWebRequest reqFTP; try { FileStream outputStream = new FileStream(filePath + "\\" + fileName, FileMode.Create); reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI + fileName)); reqFTP.Method = WebRequestMethods.Ftp.DownloadFile; reqFTP.UseBinary = true; reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse(); Stream ftpStream = response.GetResponseStream(); long cl = response.ContentLength; int bufferSize = 2048; int readCount; byte[] buffer = new byte[bufferSize]; readCount = ftpStream.Read(buffer, 0, bufferSize); while (readCount > 0) { outputStream.Write(buffer, 0, readCount); readCount = ftpStream.Read(buffer, 0, bufferSize); } ftpStream.Close(); outputStream.Close(); response.Close(); } catch (Exception ex) { Insert_Standard_ErrorLog.Insert("FtpWeb", "Download Error --> " + ex.Message); } } /// <summary> /// 删除文件 /// </summary> /// <param name="fileName"></param> public void Delete(string fileName) { try { string uri = ftpURI + fileName; FtpWebRequest reqFTP; reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); reqFTP.KeepAlive = false; reqFTP.Method = WebRequestMethods.Ftp.DeleteFile; string result = String.Empty; FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse(); long size = response.ContentLength; Stream datastream = response.GetResponseStream(); StreamReader sr = new StreamReader(datastream); result = sr.ReadToEnd(); sr.Close(); datastream.Close(); response.Close(); } catch (Exception ex) { Insert_Standard_ErrorLog.Insert("FtpWeb", "Delete Error --> " + ex.Message + " 文件名:" + fileName); } } /// <summary> /// 删除文件夹 /// </summary> /// <param name="folderName"></param> public void RemoveDirectory(string folderName) { try { string uri = ftpURI + folderName; FtpWebRequest reqFTP; reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri)); reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); reqFTP.KeepAlive = false; reqFTP.Method = WebRequestMethods.Ftp.RemoveDirectory; string result = String.Empty; FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse(); long size = response.ContentLength; Stream datastream = response.GetResponseStream(); StreamReader sr = new StreamReader(datastream); result = sr.ReadToEnd(); sr.Close(); datastream.Close(); response.Close(); } catch (Exception ex) { Insert_Standard_ErrorLog.Insert("FtpWeb", "Delete Error --> " + ex.Message + " 文件名:" + folderName); } } /// <summary> /// 获取当前目录下明细(包含文件和文件夹) /// </summary> /// <returns></returns> public string[] GetFilesDetailList() { string[] downloadFiles; try { StringBuilder result = new StringBuilder(); FtpWebRequest ftp; ftp = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI)); ftp.Credentials = new NetworkCredential(ftpUserID, ftpPassword); ftp.Method = WebRequestMethods.Ftp.ListDirectoryDetails; WebResponse response = ftp.GetResponse(); StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default); //while (reader.Read() > 0) //{ //} string line = reader.ReadLine(); //line = reader.ReadLine(); //line = reader.ReadLine(); while (line != null) { result.Append(line); result.Append("\n"); line = reader.ReadLine(); } result.Remove(result.ToString().LastIndexOf("\n"), 1); reader.Close(); response.Close(); return result.ToString().Split('\n'); } catch (Exception ex) { downloadFiles = null; Insert_Standard_ErrorLog.Insert("FtpWeb", "GetFilesDetailList Error --> " + ex.Message); return downloadFiles; } } /// <summary> /// 获取当前目录下文件列表(仅文件) /// </summary> /// <returns></returns> public string[] GetFileList(string mask) { string[] downloadFiles; StringBuilder result = new StringBuilder(); FtpWebRequest reqFTP; try { reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI)); reqFTP.UseBinary = true; reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); reqFTP.Method = WebRequestMethods.Ftp.ListDirectory; WebResponse response = reqFTP.GetResponse(); StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.Default); string line = reader.ReadLine(); while (line != null) { if (mask.Trim() != string.Empty && mask.Trim() != "*.*") { string mask_ = mask.Substring(0, mask.IndexOf("*")); if (line.Substring(0, mask_.Length) == mask_) { result.Append(line); result.Append("\n"); } } else { result.Append(line); result.Append("\n"); } line = reader.ReadLine(); } result.Remove(result.ToString().LastIndexOf('\n'), 1); reader.Close(); response.Close(); return result.ToString().Split('\n'); } catch (Exception ex) { downloadFiles = null; if (ex.Message.Trim() != "远程服务器返回错误: (550) 文件不可用(例如,未找到文件,无法访问文件)。") { Insert_Standard_ErrorLog.Insert("FtpWeb", "GetFileList Error --> " + ex.Message.ToString()); } return downloadFiles; } } /// <summary> /// 获取当前目录下所有的文件夹列表(仅文件夹) /// </summary> /// <returns></returns> public string[] GetDirectoryList() { string[] drectory = GetFilesDetailList(); string m = string.Empty; foreach (string str in drectory) { int dirPos = str.IndexOf("<DIR>"); if (dirPos > 0) { /*判断 Windows 风格*/ m += str.Substring(dirPos + 5).Trim() + "\n"; } else if (str.Trim().Substring(0, 1).ToUpper() == "D") { /*判断 Unix 风格*/ string dir = str.Substring(54).Trim(); if (dir != "." && dir != "..") { m += dir + "\n"; } } } char[] n = new char[] { '\n' }; return m.Split(n); } /// <summary> /// 判断当前目录下指定的子目录是否存在 /// </summary> /// <param name="RemoteDirectoryName">指定的目录名</param> public bool DirectoryExist(string RemoteDirectoryName) { string[] dirList = GetDirectoryList(); foreach (string str in dirList) { if (str.Trim() == RemoteDirectoryName.Trim()) { return true; } } return false; } /// <summary> /// 判断当前目录下指定的文件是否存在 /// </summary> /// <param name="RemoteFileName">远程文件名</param> public bool FileExist(string RemoteFileName) { string[] fileList = GetFileList("*.*"); foreach (string str in fileList) { if (str.Trim() == RemoteFileName.Trim()) { return true; } } return false; } /// <summary> /// 创建文件夹 /// </summary> /// <param name="dirName"></param> public void MakeDir(string dirName) { FtpWebRequest reqFTP; try { // dirName = name of the directory to create. reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI + dirName)); reqFTP.Method = WebRequestMethods.Ftp.MakeDirectory; reqFTP.UseBinary = true; reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse(); Stream ftpStream = response.GetResponseStream(); ftpStream.Close(); response.Close(); } catch (Exception ex) { Insert_Standard_ErrorLog.Insert("FtpWeb", "MakeDir Error --> " + ex.Message); } } /// <summary> /// 获取指定文件大小 /// </summary> /// <param name="filename"></param> /// <returns></returns> public long GetFileSize(string filename) { FtpWebRequest reqFTP; long fileSize = 0; try { reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI + filename)); reqFTP.Method = WebRequestMethods.Ftp.GetFileSize; reqFTP.UseBinary = true; reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse(); Stream ftpStream = response.GetResponseStream(); fileSize = response.ContentLength; ftpStream.Close(); response.Close(); } catch (Exception ex) { Insert_Standard_ErrorLog.Insert("FtpWeb", "GetFileSize Error --> " + ex.Message); } return fileSize; } /// <summary> /// 改名 /// </summary> /// <param name="currentFilename"></param> /// <param name="newFilename"></param> public void ReName(string currentFilename, string newFilename) { FtpWebRequest reqFTP; try { reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(ftpURI + currentFilename)); reqFTP.Method = WebRequestMethods.Ftp.Rename; reqFTP.RenameTo = newFilename; reqFTP.UseBinary = true; reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse(); Stream ftpStream = response.GetResponseStream(); ftpStream.Close(); response.Close(); } catch (Exception ex) { Insert_Standard_ErrorLog.Insert("FtpWeb", "ReName Error --> " + ex.Message); } } /// <summary> /// 移动文件 /// </summary> /// <param name="currentFilename"></param> /// <param name="newFilename"></param> public void MovieFile(string currentFilename, string newDirectory) { ReName(currentFilename, newDirectory); } /// <summary> /// 切换当前目录 /// </summary> /// <param name="DirectoryName"></param> /// <param name="IsRoot">true 绝对路径 false 相对路径</param> public void GotoDirectory(string DirectoryName, bool IsRoot) { if (IsRoot) { ftpRemotePath = DirectoryName; } else { ftpRemotePath += DirectoryName + "/"; } ftpURI = "ftp://" + ftpServerIP + "/" + ftpRemotePath + "/"; } /// <summary> /// 删除订单目录 /// </summary> /// <param name="ftpServerIP">FTP 主机地址</param> /// <param name="folderToDelete">FTP 用户名</param> /// <param name="ftpUserID">FTP 用户名</param> /// <param name="ftpPassword">FTP 密码</param> public static void DeleteOrderDirectory(string ftpServerIP, string folderToDelete, string ftpUserID, string ftpPassword) { try { if (!string.IsNullOrEmpty(ftpServerIP) && !string.IsNullOrEmpty(folderToDelete) && !string.IsNullOrEmpty(ftpUserID) && !string.IsNullOrEmpty(ftpPassword)) { FtpWeb fw = new FtpWeb(ftpServerIP, folderToDelete, ftpUserID, ftpPassword); //进入订单目录 fw.GotoDirectory(folderToDelete, true); //获取规格目录 string[] folders = fw.GetDirectoryList(); foreach (string folder in folders) { if (!string.IsNullOrEmpty(folder) || folder != "") { //进入订单目录 string subFolder = folderToDelete + "/" + folder; fw.GotoDirectory(subFolder, true); //获取文件列表 string[] files = fw.GetFileList("*.*"); if (files != null) { //删除文件 foreach (string file in files) { fw.Delete(file); } } //删除冲印规格文件夹 fw.GotoDirectory(folderToDelete, true); fw.RemoveDirectory(folder); } } //删除订单文件夹 string parentFolder = folderToDelete.Remove(folderToDelete.LastIndexOf('/')); string orderFolder = folderToDelete.Substring(folderToDelete.LastIndexOf('/') + 1); fw.GotoDirectory(parentFolder, true); fw.RemoveDirectory(orderFolder); } else { throw new Exception("FTP 及路径不能为空!"); } } catch (Exception ex) { throw new Exception("删除订单时发生错误,错误信息为:" + ex.Message); } } } public class Insert_Standard_ErrorLog { public static void Insert(string x, string y) { } } }
以上就是FTP的操作类.
// FtpWeb URL = new FtpWeb("FTP地址", "指定目录", "账号", "密码 ");
//上传到指定目录
// URL.Upload("D:\\install\\dorado\\docs\\javadoc\\constant-values.html");
//下载指定目录的文件到指定位置
//URL.Download("sc", "S.TXT");
核心就三个对象.ftprequest .ftprespon . 和FileStream .Stream 基本上类似的对象底层都是这三个.请求.接受.数据流
using System; using System.Collections; using System.Windows.Forms; using Tamir.SharpSsh.jsch; /* * ITransferProtocol.cs * * Copyright (c) 2006 Tamir Gal, http://www.tamirgal.com, All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the distribution. * * 3. The names of the authors may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR * *OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * **/ namespace sharpSshTest { public class SFTPHelper { private Session m_session; private Channel m_channel; private ChannelSftp m_sftp; /// <summary> /// 连接SFTP /// </summary> /// <param name="host">sftp地址</param> /// <param name="user">用户名</param> /// <param name="pwd">密码</param> public SFTPHelper(string host, string user, string pwd) { string[] arr = host.Split(':'); string ip = arr[0]; int port = 22; if (arr.Length > 1) port = Int32.Parse(arr[1]); JSch jsch = new JSch(); m_session = jsch.getSession(user, ip, port); MyUserInfo ui = new MyUserInfo(); ui.setPassword(pwd); m_session.setUserInfo(ui); } /// <summary> /// 判断SFTP连接状态 /// </summary> public bool Connected { get { return m_session.isConnected(); } } /// <summary> /// 连接SFTP /// </summary> /// <returns></returns> public bool Connect() { try { if (!Connected) { m_session.connect(); m_channel = m_session.openChannel("sftp"); m_channel.connect(); m_sftp = (ChannelSftp)m_channel; } return true; } catch { return false; } } /// <summary> /// 断开SFTP /// </summary> public void Disconnect() { if (Connected) { m_channel.disconnect(); m_session.disconnect(); } } /// <summary> /// SFTP上传文件 /// </summary> /// <param name="remotePath">服务器路径</param> /// <param name="localPath">本地路径</param> /// <returns></returns> public bool Put(string remotePath, string localPath) { try { Tamir.SharpSsh.java.String src = new Tamir.SharpSsh.java.String(localPath); Tamir.SharpSsh.java.String dst = new Tamir.SharpSsh.java.String(remotePath); m_sftp.put(src, dst); return true; } catch(Exception e) { var a = e.Message; return false; } } /// <summary> /// SFTP下载文件 /// </summary> /// <param name="remotePath">服务器路径</param> /// <param name="localPath">本地路径</param> /// <returns>是否下载成功</returns> public bool Get(string remotePath, string localPath) { try { Tamir.SharpSsh.java.String src = new Tamir.SharpSsh.java.String(remotePath); Tamir.SharpSsh.java.String dst = new Tamir.SharpSsh.java.String(localPath); m_sftp.get(src, dst); return true; } catch { return false; } } /// <summary> /// SFTP删除文件 /// </summary> /// <param name="remoteFile">服务器文件</param> /// <returns>是否成功</returns> public bool Delete(string remoteFile) { try { m_sftp.rm(remoteFile); return true; } catch(Exception e) { MessageBox.Show(e.Message); return false; } } /// <summary> /// 获取SFTP文件列表 /// </summary> /// <param name="remotePath">服务器路径</param> /// <param name="fileType">文件类型</param> /// <returns>文件名列表</returns> public ArrayList GetFileList(string remotePath, string fileType) { try { Tamir.SharpSsh.java.util.Vector vvv = m_sftp.ls(remotePath); ArrayList objList = new ArrayList(); foreach (Tamir.SharpSsh.jsch.ChannelSftp.LsEntry qqq in vvv) { string sss = qqq.getFilename(); if (sss.Length > (fileType.Length + 1) && fileType == sss.Substring(sss.Length - fileType.Length)) { objList.Add(sss); } else { continue; } } return objList; } catch { return null; } } /// <summary> /// 登录验证信息 /// </summary> public class MyUserInfo : UserInfo { private string passwd; public String getPassword() { return passwd; } public void setPassword(String passwd) { this.passwd = passwd; } public String getPassphrase() { return null; } public bool promptPassphrase(String message) { return true; } public bool promptPassword(String message) { return true; } public bool promptYesNo(String message) { return true; } public void showMessage(String message) { } } } /// <summary> /// Summary description for sharpSshTest. /// </summary> public class sharpSshTest { const int JSCH_SHELL = 1; const int JSCH_AES = 2; const int JSCH_PUBKEY = 3; const int JSCH_SFTP = 4; const int JSCH_KEYEGEN = 5; const int JSCH_KNOWN_HOSTS = 6; const int JSCH_CHANGE_PASS = 7; const int JSCH_PORT_FWD_L = 8; const int JSCH_PORT_FWD_R = 9; const int JSCH_STREAM_FWD = 10; const int JSCH_STREAM_SUBSYSTEM = 11; const int JSCH_VIA_HTTP = 12; const int SHARP_SHELL = 13; const int SHARP_EXPECT = 14; const int SHARP_EXEC = 15; const int SHARP_TRANSFER = 16; const int EXIT = 17; public static void Main() { //SFTPHelper sftp = new SFTPHelper("网址", "账号", "密码"); ////注意文件的路径 string remote = "/data/file/clients/relase for Win7 or above.zip"; string local = "D://relase for Win7 or above.zip"; SFTPHelper _helper = new SFTPHelper("网址", "账号", "密码"); if (!_helper.Connected) { _helper.Connect(); _helper.Get(remote, local);//下载 _helper.Put("/data/file/clients/", @"D:\test.zip");//上传 var a= _helper.GetFileList("/data/file/clients","zip");//读取 var b= _helper.Delete("/data/file/clients/test.zip");//删除 } _helper.Disconnect(); Console.WriteLine("OK"); Console.ReadLine(); } public static string[] GetArgs(string[] args) { for(int i=0; i<args.Length; i++) { Console.Write("Enter {0}: ", args[i]); args[i] = Console.ReadLine(); } return args; } static void PrintVersoin() { try { System.Reflection.Assembly asm = System.Reflection.Assembly.GetAssembly(typeof(Tamir.SharpSsh.SshBase)); Console.WriteLine("SharpSSH-"+asm.GetName().Version); } catch { Console.WriteLine("sharpSsh v1.0"); } } } }
以上就是SFTP
InstallShield貌似在VS15版本上无法安装打包
Smart Install Maker就可以满足
在文件中加入Release编译的dll.后选择绿色的按钮完成安装包的制作
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)