Post a reply

Options
Add an Attachment

If you do not want to add an Attachment to your Post, please leave the Fields blank.

(maximum 10 MB; please compress large files; only common media, archive, text and programming file formats are allowed)

Options

Topic review

solutionsville

Anytime.
martin

Re: DebugLogLevel Enable/Disable

Thanks for sharing your code.
solutionsville

DebugLogLevel Enable/Disable

Looks like the forum logged me out when I posted this topic.
Guest

DebugLogLevel Enable/Disable

Martin, I wanted a way to enable or disable the DebugLogging & SessionLogging programatically in my app that i built.

On my main form, I added a ToolStripMenu item called Debug and made it Checked type. I then added a bool to the Class file that handles the WinSCP session items, it sets the log paths, and the DebugLogLevel.

Forwarded for info and for use if anyone else is looking for how to do it. Maybe something to add to an example in the documentation section?




using System;

using System.Collections.Concurrent;
using System.Data.SqlClient;
using System.IO;
using System.Threading;
using WinSCP;

namespace CnaFirmware
{
    public enum UpdateState
    {
        Idle,               // black
        Working,            // black
        Uploading,

        // complete:
        CompleteNoError,    // green

        // errors:
        Aborted,
        CompleteWithError   // red
    };

    public class UploadTask
    {
        ConcurrentQueue<string> ConsoleQueue;
        public string cna_ip;
        string fingerprint;
        readonly string ImageFileName;
        public string CnaVersion;
        readonly string TargetVersion;
        public string CurrentFileName;
        public double CurrentFileProgress;
        private static string _lastFileName;
        bool abort = false;
        Session session;
        Thread TaskThread;
        readonly string LogFileName;
        public string UpdatedFirmwareVersion;
        public bool WarningShown;

        // this string is for the user checking status during the update from the UI:
        public string status;

        // this status determines the color of the item in the list box
        public UpdateState state;

        // these allow the main form to track progress and repaint the item when done
        public bool UpdateSuccess;
        public bool JobComplete;
        public bool NeedUiUpdate;
        public bool Verbose;
        // Set WinSCP DebugLogLevel Boolean
        public bool debug;

        // need states so the checkedlistbox knows what color to paint this.

        // this class will push firmware to one CNA.
        // inputs:  IP address of CNA
        //          Fingerprint string
        //          image file (*.run) to upload
        //          queue for sending messages back to main (UI) thread

        // status:  idle
        //          transfering
        //          load (remote script)
        //          complete

        // logging: only log start, errors, or success to the UI. everything goes to the log file for this cna.

        // update 20180618:  fingerprint is no longer required: WinSCP will scan for fingerprint, then upload firmware.


        public UploadTask(string cnaip,
                          string fprint,
                          ConcurrentQueue<string> q,
                          string filename)
        {
            // DebugLogLevel=0 by default
            debug = false;
            cna_ip = cnaip;
            WarningShown = false;
            UpdateSuccess = false;
            fingerprint = fprint;
            ConsoleQueue = q;
            ImageFileName = filename;
            LogFileName = string.Format("{0}\\{1}.log", Globals.LogPath + @"\CNAip\", cna_ip);

            // for checking file transfer progress:
            CurrentFileName = string.Empty;
            CurrentFileProgress = 0;
            status = "idle";
            state = UpdateState.Idle;
            JobComplete = false;
            NeedUiUpdate = false;
            UpdatedFirmwareVersion = "";

            // firmware version of target CNA
            CnaVersion = "";

            // new firmware version to be uploaded
            TargetVersion = ExtractCnaVersion(filename);
        }

        // This is to extract the version of the Firmware file
        string ExtractCnaVersion(string filename)
        {
            // ...CNA15xxvX_X_X.run   10,16
            string v = "0.0.0";
            string f = Path.GetFileName(filename);
            int posv = f.IndexOf("v");
            int posr = f.IndexOf(".run");
            posv++;
            try
            {
                v = f.Substring(posv, posr - posv);
            }
            catch (Exception) { }
            return v.Replace("_", ".");
        }
        void _PostStatus(string s)
        {
            // set status string to what's going on.
            ConsoleQueue.Enqueue(string.Format("!{0}: {1}", cna_ip, s));
        }

        void NewState(UpdateState s)
        {
            state = s;
            NeedUiUpdate = true;
        }

        public void SetCnaVersion(byte[] data)
        {
            // Set Expected CNA version
            if (data[0] < 2) return;
            string v = string.Format("{0}.{1}.{2}", data[1], data[2], data[3]);
            Log("SetCnaVersion:" + v);
            CnaVersion = v;
        }

        public void Start()
        {
            // Start the Thread
            TaskThread = new Thread(() => TaskThreadCode());
            TaskThread.Start();
        }
        void Logui(string s)
        {
            // send to UI
            ConsoleQueue.Enqueue(string.Format("{0}: {1}", cna_ip, s));
            // and file it
            Log(s);
        }
        void Log(string s)
        {
            Directory.CreateDirectory(Globals.LogPath + @"\CNAip");
            File.AppendAllText(LogFileName, string.Format("{0} {1}: {2}{3}", DateTime.Now.ToString("yyyyMMdd.HHmmss.fff"), cna_ip, s, Environment.NewLine));
        }

        // Upload Status and progress
        public string GetStatus()
        {
            string s = "";
            if (status == "uploading binary")
            {
                s = string.Format("{0}: uploading binary ({1:P0})", cna_ip, CurrentFileProgress);
            }
            else
            {
                s = status;
                s = string.Format("{0}: {1}", cna_ip, status);
            }
            return s;
        }

        public void TaskThreadCode()
        {
            Logui("Starting update");
            NewState(UpdateState.Working);
            try
            {
                // first get the CNA SSH fingerprint
                SessionOptions sessionOptions = new SessionOptions
                {
                    Protocol = Protocol.Scp,
                    HostName = cna_ip
                };

                sessionOptions.AddRawSettings("KEX", "ecdh,dh-gex-sha1,dh-group14-sha1,dh-group1-sha1,rsa,WARN");
                //Session session;
                using (session = new Session())
                {
                    fingerprint = session.ScanFingerprint(sessionOptions, "MD5");
                    Log($"Fingerprint: {fingerprint}");
                }

                // Set up session options for firmware transfer
                // The same configuration is used on all devices
                sessionOptions = new SessionOptions
                {
                    Protocol = Protocol.Scp,
                    HostName = cna_ip,
                    UserName = "root",
                    Password = "root",
                    SshHostKeyFingerprint = fingerprint
                };
                // This is the same for all connections
                sessionOptions.AddRawSettings("AuthGSSAPI", "1");
                sessionOptions.AddRawSettings("Cipher", "aes,blowfish,3des,chacha20,WARN,arcfour,des");
                sessionOptions.AddRawSettings("KEX", "ecdh,dh-gex-sha1,dh-group14-sha1,dh-group1-sha1,rsa,WARN");

                status = "uploading binary";

                using (session = new Session())
                {
                    try
                    {
                        fingerprint = session.ScanFingerprint(sessionOptions, "MD5");
                        Log($"Fingerprint: {fingerprint}");
                        // Will continuously report progress of transfer
                        Directory.CreateDirectory(Globals.LogPath + @"\Debug");
                        // If MenuItem is checked then DebugLogLevel = 2, else Default of 0.
                        // also sets the DebugLogPath and SessionLogPath values.
                        if (debug == true)
                        {
                            session.DebugLogLevel = 2;
                            session.DebugLogPath = Globals.LogPath + @"\Debug\WSCPDebug.log";
                            session.SessionLogPath = Globals.LogPath + @"\Debug\WSCPSession.log";
                        }

                        else
                        {
                            session.DebugLogLevel = 0;
                            session.DebugLogPath = null;
                            session.SessionLogPath = null;
                        }

                        session.FileTransferProgress += SessionFileTransferProgress;
                        session.OutputDataReceived += SessionOutputDataReceived;
                        // session.DisableVersionCheck = true;
                        // Connect
                        Log("Opening session");
                        session.Open(sessionOptions);
                        // Upload files
                        TransferOptions transferOptions = new TransferOptions()
                        {
                            TransferMode = TransferMode.Binary
                        };
                        // Transfer Results
                        TransferOperationResult transferResult;
                        transferResult = session.PutFiles(ImageFileName, "/var/tmp/*", false, transferOptions);
                    }
                    catch (Exception ex)
                    {
                        Logui("WinSCP: " + ex.Message);
                        ConsoleQueue.Enqueue("@" + ex.Message);
                        status = "WinSCP Error";
                        NewState(UpdateState.CompleteWithError);
                        JobComplete = true;
                        _PostStatus("Failed");
                        // terminate thread
                        return;