瀏覽代碼

添加项目文件。

zhaowei 5 年之前
父節點
當前提交
c2b0a3ad24
共有 17 個文件被更改,包括 3577 次插入0 次删除
  1. 69 0
      AutoStartTask.cs
  2. 173 0
      MainForm.Designer.cs
  3. 420 0
      MainForm.cs
  4. 2415 0
      MainForm.resx
  5. 76 0
      Program.cs
  6. 36 0
      Properties/AssemblyInfo.cs
  7. 63 0
      Properties/Resources.Designer.cs
  8. 117 0
      Properties/Resources.resx
  9. 26 0
      Properties/Settings.Designer.cs
  10. 7 0
      Properties/Settings.settings
  11. 137 0
      SIASUN.TwinCatLogger.csproj
  12. 25 0
      SIASUN.TwinCatLogger.sln
  13. 二進制
      Thumbs.db
  14. 二進制
      TwinCAT.Ads.dll
  15. 13 0
      app.config
  16. 二進制
      logger.ico
  17. 二進制
      reddot.png

+ 69 - 0
AutoStartTask.cs

@@ -0,0 +1,69 @@
+using System;
+using System.Windows.Forms;
+using TaskScheduler;
+
+namespace SIASUN.TwinCatLogger
+{
+    static class AutoStartTask
+    {
+        // 创建开机登陆后启动的计划任务
+        static public void CreateLogonTask(bool autoStart)
+        {
+            //取得程序路径
+            string startup = Application.ExecutablePath;
+            //程序名称
+            string appname = Application.ProductName;
+            try
+            {
+                //新建任务
+                TaskSchedulerClass scheduler = new TaskSchedulerClass();
+                //连接
+                scheduler.Connect(null, null, null, null);
+                //获取创建任务的目录
+                ITaskFolder folder = scheduler.GetFolder("\\");
+                // 查找现有任务
+                IRegisteredTaskCollection tasks_exists = folder.GetTasks(1);
+                for (int i = 1; i <= tasks_exists.Count; i++)
+                {
+                    IRegisteredTask taski = tasks_exists[i];
+                    ITaskDefinition taskdef = taski.Definition;
+                    if (taski.Name == appname)
+                    //if (taskdef.Actions[1].Type == _TASK_ACTION_TYPE.TASK_ACTION_EXEC)
+                    //    if (((IExecAction)taskdef.Actions[1]).Path != appname)
+                    {
+                        folder.DeleteTask(appname, 0);
+                        break;
+                    }
+                }
+                // 是否开机自动启动
+                if (!autoStart) return;
+
+                //设置参数
+                ITaskDefinition task = scheduler.NewTask(0);
+                task.RegistrationInfo.Author = Application.CompanyName; //创建者
+                task.RegistrationInfo.Description = Application.ProductName; //描述
+                ILogonTrigger tt = (ILogonTrigger)task.Triggers.Create(_TASK_TRIGGER_TYPE2.TASK_TRIGGER_LOGON);
+                tt.Delay = "PT20S";
+                //task.Triggers.Create(_TASK_TRIGGER_TYPE2.TASK_TRIGGER_LOGON); //设置触发机制(此处是 登陆后)
+                IExecAction action = (IExecAction)task.Actions.Create(_TASK_ACTION_TYPE.TASK_ACTION_EXEC); //设置动作(此处为运行exe程序)
+                action.Path = startup;//设置文件目录
+                action.WorkingDirectory = Application.StartupPath;
+                task.Settings.ExecutionTimeLimit = "PT0S"; //运行任务时间超时停止任务吗? PTOS 不开启超时
+                task.Settings.DisallowStartIfOnBatteries = false;//只有在交流电源下才执行
+                task.Settings.RunOnlyIfIdle = false;//仅当计算机空闲下才执行
+
+                IRegisteredTask regTask =
+                    folder.RegisterTaskDefinition(appname, task,//此处需要设置任务的名称(name)
+                    (int)_TASK_CREATION.TASK_CREATE, null, //user
+                    null, // password
+                    _TASK_LOGON_TYPE.TASK_LOGON_INTERACTIVE_TOKEN,
+                    "");
+                //IRunningTask runTask = regTask.Run(null);
+            }
+            catch (Exception exp)
+            {
+                MessageBox.Show(exp.Message.ToString(), "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
+            }
+        }
+    }
+}

+ 173 - 0
MainForm.Designer.cs

@@ -0,0 +1,173 @@
+namespace SIASUN.TwinCatLogger
+{
+    partial class MainForm
+    {
+        /// <summary>
+        /// 必需的设计器变量。
+        /// </summary>
+        private System.ComponentModel.IContainer components = null;
+
+        /// <summary>
+        /// 清理所有正在使用的资源。
+        /// </summary>
+        /// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing && (components != null))
+            {
+                components.Dispose();
+            }
+            base.Dispose(disposing);
+        }
+
+        #region Windows 窗体设计器生成的代码
+
+        /// <summary>
+        /// 设计器支持所需的方法 - 不要修改
+        /// 使用代码编辑器修改此方法的内容。
+        /// </summary>
+        private void InitializeComponent()
+        {
+            this.components = new System.ComponentModel.Container();
+            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
+            this.notifyIcon1 = new System.Windows.Forms.NotifyIcon(this.components);
+            this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
+            this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.HideToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.OpenToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.timer1 = new System.Windows.Forms.Timer(this.components);
+            this.button1 = new System.Windows.Forms.Button();
+            this.lableTime = new System.Windows.Forms.Label();
+            this.timer2 = new System.Windows.Forms.Timer(this.components);
+            this.textNotice = new System.Windows.Forms.TextBox();
+            this.contextMenuStrip1.SuspendLayout();
+            this.SuspendLayout();
+            // 
+            // notifyIcon1
+            // 
+            this.notifyIcon1.ContextMenuStrip = this.contextMenuStrip1;
+            this.notifyIcon1.Icon = ((System.Drawing.Icon)(resources.GetObject("notifyIcon1.Icon")));
+            this.notifyIcon1.Text = "TwinCatLogger";
+            this.notifyIcon1.Visible = true;
+            this.notifyIcon1.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.notifyIcon1_MouseDoubleClick);
+            // 
+            // contextMenuStrip1
+            // 
+            this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.exitToolStripMenuItem,
+            this.HideToolStripMenuItem,
+            this.OpenToolStripMenuItem});
+            this.contextMenuStrip1.Name = "exitMenuItem";
+            this.contextMenuStrip1.Size = new System.Drawing.Size(101, 70);
+            // 
+            // exitToolStripMenuItem
+            // 
+            this.exitToolStripMenuItem.Name = "exitToolStripMenuItem";
+            this.exitToolStripMenuItem.Size = new System.Drawing.Size(100, 22);
+            this.exitToolStripMenuItem.Text = "退出";
+            this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click);
+            // 
+            // HideToolStripMenuItem
+            // 
+            this.HideToolStripMenuItem.Name = "HideToolStripMenuItem";
+            this.HideToolStripMenuItem.Size = new System.Drawing.Size(100, 22);
+            this.HideToolStripMenuItem.Text = "隐藏";
+            this.HideToolStripMenuItem.Click += new System.EventHandler(this.HideToolStripMenuItem_Click);
+            // 
+            // OpenToolStripMenuItem
+            // 
+            this.OpenToolStripMenuItem.Name = "OpenToolStripMenuItem";
+            this.OpenToolStripMenuItem.Size = new System.Drawing.Size(100, 22);
+            this.OpenToolStripMenuItem.Text = "打开";
+            this.OpenToolStripMenuItem.Click += new System.EventHandler(this.OpenToolStripMenuItem_Click);
+            // 
+            // timer1
+            // 
+            this.timer1.Interval = 1000;
+            this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
+            // 
+            // button1
+            // 
+            this.button1.Enabled = false;
+            this.button1.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
+            this.button1.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.button1.Image = ((System.Drawing.Image)(resources.GetObject("button1.Image")));
+            this.button1.Location = new System.Drawing.Point(0, 0);
+            this.button1.Name = "button1";
+            this.button1.Size = new System.Drawing.Size(130, 30);
+            this.button1.TabIndex = 1;
+            this.button1.Text = "开始记录";
+            this.button1.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+            this.button1.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
+            this.button1.UseVisualStyleBackColor = true;
+            this.button1.Click += new System.EventHandler(this.button1_Click);
+            // 
+            // lableTime
+            // 
+            this.lableTime.BackColor = System.Drawing.Color.Black;
+            this.lableTime.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.lableTime.ForeColor = System.Drawing.Color.White;
+            this.lableTime.Location = new System.Drawing.Point(130, 0);
+            this.lableTime.Name = "lableTime";
+            this.lableTime.Size = new System.Drawing.Size(120, 30);
+            this.lableTime.TabIndex = 2;
+            this.lableTime.Text = "00:00:00";
+            this.lableTime.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+            // 
+            // timer2
+            // 
+            this.timer2.Interval = 1000;
+            this.timer2.Tick += new System.EventHandler(this.timer2_Tick);
+            // 
+            // textNotice
+            // 
+            this.textNotice.BackColor = System.Drawing.SystemColors.GradientInactiveCaption;
+            this.textNotice.Cursor = System.Windows.Forms.Cursors.Default;
+            this.textNotice.Font = new System.Drawing.Font("微软雅黑", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+            this.textNotice.Location = new System.Drawing.Point(250, 1);
+            this.textNotice.Name = "textNotice";
+            this.textNotice.ReadOnly = true;
+            this.textNotice.Size = new System.Drawing.Size(534, 29);
+            this.textNotice.TabIndex = 3;
+            this.textNotice.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+            // 
+            // MainForm
+            // 
+            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+            this.BackColor = System.Drawing.SystemColors.GradientInactiveCaption;
+            this.ClientSize = new System.Drawing.Size(784, 30);
+            this.Controls.Add(this.textNotice);
+            this.Controls.Add(this.lableTime);
+            this.Controls.Add(this.button1);
+            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
+            this.MaximizeBox = false;
+            this.Name = "MainForm";
+            this.ShowInTaskbar = false;
+            this.Text = "TwinCatLogger";
+            this.TopMost = true;
+            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing);
+            this.Load += new System.EventHandler(this.MainForm_Load);
+            this.SizeChanged += new System.EventHandler(this.MainForm_SizeChanged);
+            this.contextMenuStrip1.ResumeLayout(false);
+            this.ResumeLayout(false);
+            this.PerformLayout();
+
+        }
+
+        #endregion
+
+        private System.Windows.Forms.NotifyIcon notifyIcon1;
+        private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
+        private System.Windows.Forms.ToolStripMenuItem exitToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem HideToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem OpenToolStripMenuItem;
+        private System.Windows.Forms.Timer timer1;
+        private System.Windows.Forms.Button button1;
+        private System.Windows.Forms.Label lableTime;
+        private System.Windows.Forms.Timer timer2;
+        private System.Windows.Forms.TextBox textNotice;
+    }
+}
+

+ 420 - 0
MainForm.cs

@@ -0,0 +1,420 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Drawing;
+using System.IO;
+using System.Text;
+using System.Windows.Forms;
+using TwinCAT.Ads;
+
+namespace SIASUN.TwinCatLogger
+{
+    public partial class MainForm : Form
+    {
+        public MainForm()
+        {
+            InitializeComponent();
+            this.ShowInTaskbar = true;
+            this.WindowState = FormWindowState.Normal;
+        }
+
+        public string GetConfiguration(string key)
+        {
+            try
+            {
+                string value = System.Configuration.ConfigurationManager.AppSettings[key];
+                if (!string.IsNullOrEmpty(value))
+                    return value;
+            }
+            catch (Exception ce)
+            {
+            }
+            return "";
+        }
+
+        private void MainForm_Load(object sender, EventArgs e)
+        {
+            this.Visible = false;
+            this.notifyIcon1.Visible = true;
+            //this.skinEngine1.SkinFile = "EmeraldColor1.ssk"; //皮肤文件.ssk
+            runInDebug = GetConfiguration("测试模式").ToLower() == "true";
+            //try
+            //{
+            //    AutoStartTask.CreateLogonTask(!runInDebug);
+            //}
+            //catch (Exception ex)
+            //{
+            //    textNotice.Text = "创建开机自动启动任务失败:" + ex.Message;
+            //}
+            小数位数 = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["小数位数"]);
+            单文件行数 = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["单文件行数"]);
+            //LogonStart.CreateLogonTask(!runInDebug);
+            timer1.Interval = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["刷新时间"]);
+            if (LoadPointList())
+                timer2.Enabled = true;
+        }
+
+        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
+        {
+            //e.Cancel = true; // 取消关闭窗体
+            //HideToolStripMenuItem_Click(sender, e);
+            if (MessageBox.Show("是否确认退出程序?", "退出", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK)
+            {
+                e.Cancel = false;
+            }
+            else
+            {
+                e.Cancel = true;
+            }
+        }
+
+        private void MainForm_SizeChanged(object sender, EventArgs e)
+        {
+            if (WindowState == FormWindowState.Minimized)
+            {
+                HideToolStripMenuItem_Click(sender, e);
+            }
+        }
+
+        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
+        {
+            if (e.Button == MouseButtons.Left)
+            {
+                OpenToolStripMenuItem_Click(sender, e);
+            }
+        }
+
+        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            exitToolStripMenuItem.Enabled = false;
+            this.Close();
+            exitToolStripMenuItem.Enabled = true;
+        }
+
+        private void HideToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            this.Hide();
+        }
+
+        private void OpenToolStripMenuItem_Click(object sender, EventArgs e)
+        {
+            this.ShowInTaskbar = true;
+            this.Show();
+            this.WindowState = FormWindowState.Normal;
+            this.Activate();
+        }
+
+        #region 数据
+        bool runInDebug = false;
+        int 小数位数 = 0;
+        int 单文件行数 = 0;
+        int 当前行数 = 0;
+
+        struct PlcPoint
+        {
+            public string name;
+            public string address;
+            public Type type;
+        }
+        List<PlcPoint> pointList = new List<PlcPoint>();
+        List<int> handleList = new List<int>();
+
+        private TcAdsClient adsClient = new TcAdsClient();
+        private string[] plcAdress = ConfigurationManager.AppSettings["PLC地址"].Split(':');
+        private int startSignal = 0;
+        private bool isRecording = false;
+        private bool isManuel = false;
+        private long stopWatch = 0;
+
+        private string filePrefix = "Log_";
+        private string filePath = "";
+        private StreamWriter fileWriter = null;
+        #endregion
+
+        private Type GetTypeByName(string typename)
+        {
+            if (typename.ToUpper() == "BOOL")
+                return typeof(bool);
+            if (typename.ToUpper() == "BYTE")
+                return typeof(Byte);
+            if (typename.ToUpper() == "WORD")
+                return typeof(UInt16);
+            if (typename.ToUpper() == "DWORD")
+                return typeof(UInt32);
+            if (typename.ToUpper() == "INT")
+                return typeof(Int16);
+            if (typename.ToUpper() == "DINT")
+                return typeof(Int32);
+            if (typename.ToUpper() == "REAL")
+                return typeof(float);
+            if (typename.ToUpper() == "LREAL")
+                return typeof(Double);
+            return typeof(bool);
+        }
+
+        private bool LoadPointList()
+        {
+            string filePath = GetConfiguration("点表文件");
+            pointList.Clear();
+            try
+            {
+                string line;
+                string[] arrItem;
+                PlcPoint plcPoint = new PlcPoint() { name = "", address = "", type = null };
+                // 创建一个 StreamReader 的实例来读取文件 ,using 语句也能关闭 StreamReader
+                using (System.IO.StreamReader sr = new System.IO.StreamReader(filePath, Encoding.GetEncoding("GB2312")))
+                {
+                    // 从文件读取并显示行,直到文件的末尾 
+                    while ((line = sr.ReadLine()) != null)
+                    {
+                        arrItem = line.Split(',');
+                        if (arrItem.Length != 3)
+                            continue;
+                        plcPoint.name = arrItem[0];
+                        if (!runInDebug || plcPoint.type == null)
+                        {
+                            plcPoint.address = arrItem[1];
+                            plcPoint.type = GetTypeByName(arrItem[2]);
+                        }                        
+                        pointList.Add(plcPoint);
+                        textNotice.Text = "已从" + filePath + "读取" + pointList.Count.ToString() + "条数据定义";
+                    }
+                }
+                return true;
+            }
+            catch (Exception ex)
+            {
+                textNotice.Text = "读取数据点表文件(" + filePath + ")发生错误:" + ex.Message;
+                return false;
+            }
+        }
+
+        private void timer2_Tick(object sender, EventArgs e)
+        {
+            if (!adsClient.IsConnected || startSignal == 0)
+            {
+                BeginConnect();
+            }
+            else if (isRecording)
+            {
+                stopWatch++;
+                if (this.InvokeRequired)
+                    this.BeginInvoke((Action)delegate
+                    {
+                        lableTime.Text = string.Format("{0:D2}:{1:D2}:{2:D2}", stopWatch / 3600, stopWatch / 60, stopWatch % 60);
+                    });
+                else
+                    lableTime.Text = string.Format("{0:D2}:{1:D2}:{2:D2}", stopWatch / 3600, stopWatch / 60, stopWatch % 60);
+            }
+            else
+            {
+                if (lableTime.Text == "")
+                    lableTime.Text = "00:00:00";
+                else
+                    lableTime.Text = "";
+            }
+        }
+
+        private void timer1_Tick(object sender, EventArgs e)
+        {
+            try
+            {
+                if (adsClient.IsConnected)
+                {
+                    if (isManuel)
+                    {
+                        ReadAllValues();
+                        return;
+                    }
+                    bool isStart = (bool)adsClient.ReadAny(startSignal, typeof(bool));
+                    if (!isRecording)
+                    {
+                        if (isStart)
+                            StartRecording();
+                    }
+                    else
+                    {
+                        if (!isStart)
+                            StopRecording();
+                        else
+                            ReadAllValues();
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                textNotice.Text = "数据读取定时器发生错误:" + ex.Message;
+            }
+        }
+
+        public int getHandle(string varName)
+        {
+            try
+            {
+                int handle = adsClient.CreateVariableHandle(varName);
+                return handle;
+            }
+            catch (Exception ex)
+            {
+                textNotice.Text = "获取PLC变量(" + varName + ")发生错误:" + ex.Message;
+                return 0;
+            }
+        }
+
+        private void BeginConnect()
+        {
+            try
+            {
+                adsClient.Connect(plcAdress[0], Convert.ToInt32(plcAdress[1]));
+                startSignal = getHandle(System.Configuration.ConfigurationManager.AppSettings["启动信号"]);
+                if (startSignal == 0)
+                    return;
+                for (int i = 0; i < pointList.Count; i++)
+                {
+                    handleList.Add(getHandle(pointList[i].address));
+                }
+                button1.Enabled = true;
+                timer1.Enabled = true;
+            }
+            catch (Exception ex)
+            {
+                textNotice.Text = "连接PLC发生发生错误:" + ex.Message;
+                timer1.Enabled = false;
+                button1.Enabled = false;
+            }
+        }
+
+        private void StartRecording()
+        {
+            if (!CreateLogFile())
+                return;
+            isRecording = true;
+            stopWatch = 0;
+            button1.Text = "正在记录";
+            textNotice.Text = "已创建记录文件:" + filePath;
+        }
+
+        private void StopRecording()
+        {
+            fileWriter.Flush();
+            fileWriter.Close();
+            isRecording = false;
+            button1.Text = "开始记录";
+            textNotice.Text = "已保存到记录文件:" + filePath;
+        }
+
+        private bool CreateLogFile()
+        {
+            filePath = filePrefix + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".csv";
+            当前行数 = 0;
+            try
+            {
+                fileWriter = new StreamWriter(filePath, false, Encoding.GetEncoding("GB2312"));
+                fileWriter.Write("时间");
+                for (int i = 0; i < pointList.Count; i++)
+                {
+                    fileWriter.Write("," + pointList[i].name);
+                }
+                fileWriter.WriteLine();
+                fileWriter.Flush();
+                return true;
+            }
+            catch (Exception ex)
+            {
+                textNotice.Text = "创建记录文件(" + filePath + ")发生错误:" + ex.Message;
+                timer1.Enabled = false;
+                button1.Enabled = false;
+                timer2.Enabled = false;
+                return false;
+            }
+        }
+
+        public delegate void AsyncEventHandler();
+
+        private string getValue(int index)
+        {
+            try
+            {
+                if (handleList[index] == 0)
+                    return "";
+                string value = adsClient.ReadAny(handleList[index], pointList[index].type).ToString();
+                return value;
+            }
+            catch (Exception ex)
+            {
+                textNotice.Text = "读取PLC变量(" + pointList[index].name + ")值时发生错误:" + ex.Message;
+                return "";
+            }
+        }
+
+        private void BeginReadAllValues()
+        {
+            AsyncEventHandler asy = new AsyncEventHandler(AsyncReadAllValues);
+            IAsyncResult result = asy.BeginInvoke(null, asy);
+        }
+
+        private void AsyncReadAllValues()
+        {
+            StringBuilder line = new StringBuilder();
+            line.Append(DateTime.Now.ToString("HH:mm:ss:fff"));
+            for (int i = 0; i < handleList.Count; i++)
+            {
+                string value = getValue(i);
+                int p = value.IndexOf('.');
+                if (p > 0)
+                    line.Append("," + value.Substring(0, p + 1 + 小数位数));
+                else
+                    line.Append("," + value);
+            }
+            fileWriter.WriteLine(line);
+            当前行数++;
+            if (单文件行数 > 0 && 当前行数 >= 单文件行数)
+            {
+                fileWriter.Flush();
+                fileWriter.Close();
+                CreateLogFile();
+            }
+        }
+
+        private void ReadAllValues()
+        {
+            BeginReadAllValues();
+            //string time = DateTime.Now.ToString("HH:mm:ss.fff");
+            //fileWriter.Write(time);
+            //for (int i = 0; i < handleList.Count; i++)
+            //{
+            //    string value = adsClient.ReadAny(handleList[i], pointList[i].type).ToString();
+            //    fileWriter.Write("," + value);
+            //}
+            //fileWriter.WriteLine();
+            //fileWriter.Flush();
+        }
+
+        private void button1_Click(object sender, EventArgs e)
+        {
+            if (isRecording)
+            {
+                StopRecording();
+                isManuel = true;
+                timer1.Enabled = false;
+                timer2.Enabled = false;
+                button1.Text = "已停止";
+            }
+            else
+            {
+                if (isManuel)
+                {
+                    isManuel = false;
+                    timer1.Enabled = true;
+                    timer2.Enabled = true;
+                    button1.Text = "开始记录";
+                }
+                else
+                {
+                    isManuel = true;
+                    StartRecording();
+                }
+            }
+        }
+    }
+}

File diff suppressed because it is too large
+ 2415 - 0
MainForm.resx


+ 76 - 0
Program.cs

@@ -0,0 +1,76 @@
+using System;
+using System.Windows.Forms;
+using System.Diagnostics;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+namespace SIASUN.TwinCatLogger
+{
+    static class Program
+    {
+        /// <summary>
+        /// 应用程序的主入口点。
+        /// </summary>
+        [STAThread]
+        static void Main()
+        {
+            //Get the running instance.   
+            Process instance = RunningInstance();
+            if (instance == null)
+            {
+                System.IO.Directory.SetCurrentDirectory(Application.StartupPath);
+                Application.EnableVisualStyles();
+                Application.SetCompatibleTextRenderingDefault(false);
+                Application.Run(new MainForm());
+            }
+            else
+            {
+                //There is another instance of this process.   
+                HandleRunningInstance(instance);
+            }
+        }
+
+        #region 单实例运行
+        public static Process RunningInstance()
+        {
+            Process current = Process.GetCurrentProcess();
+            Process[] processes = Process.GetProcessesByName(current.ProcessName);
+            //Loop through the running processes in with the same name
+            foreach (Process process in processes)
+            {
+                //Ignore the   current   process   
+                if (process.Id != current.Id)
+                {
+                    //Make sure that the process is running from the exe file.
+                    if (Assembly.GetExecutingAssembly().Location.Replace("/", "//") == current.MainModule.FileName)
+                    {
+                        //Return the other process instance.
+                        return process;
+                    }
+                }
+            }
+            //No other instance was found, return null. 
+            return null;
+        }
+        public static void HandleRunningInstance(Process instance)
+        {
+            //Make sure the window is not minimized or maximized
+            ShowWindowAsync(instance.MainWindowHandle, SW_NORMAL);
+            //Set the real intance to foreground window
+            SetForegroundWindow(instance.MainWindowHandle);
+        }
+        [DllImport("User32.dll")]
+        private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
+        [DllImport("User32.dll")]
+        private static extern bool SetForegroundWindow(IntPtr hWnd);
+        private const int SW_HIDE = 0;
+        private const int SW_NORMAL = 1;
+        private const int SW_MAXIMIZE = 3;
+        private const int SW_SHOWNOACTIVATE = 4;
+        private const int SW_SHOW = 5;
+        private const int SW_MINIMIZE = 6;
+        private const int SW_RESTORE = 9;
+        private const int SW_SHOWDEFAULT = 10;
+        #endregion
+    }
+}

+ 36 - 0
Properties/AssemblyInfo.cs

@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// 有关程序集的常规信息通过以下
+// 特性集控制。更改这些特性值可修改
+// 与程序集关联的信息。
+[assembly: AssemblyTitle("Twincat日志记录工具")]
+[assembly: AssemblyDescription("Twincat日志记录工具")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("SIASUN")]
+[assembly: AssemblyProduct("SIASUN.TwinCatLogger")]
+[assembly: AssemblyCopyright("Copyright ©  2019")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 将 ComVisible 设置为 false 使此程序集中的类型
+// 对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型,
+// 则将该类型上的 ComVisible 特性设置为 true。
+[assembly: ComVisible(false)]
+
+// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
+[assembly: Guid("e53dd096-beaf-4013-8b6d-65afc8fd407e")]
+
+// 程序集的版本信息由下面四个值组成:
+//
+//      主版本
+//      次版本 
+//      内部版本号
+//      修订号
+//
+// 可以指定所有这些值,也可以使用“内部版本号”和“修订号”的默认值,
+// 方法是按如下所示使用“*”:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

+ 63 - 0
Properties/Resources.Designer.cs

@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     此代码由工具生成。
+//     运行时版本:4.0.30319.42000
+//
+//     对此文件的更改可能会导致不正确的行为,并且如果
+//     重新生成代码,这些更改将会丢失。
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace SIASUN.TwinCatLogger.Properties {
+    using System;
+    
+    
+    /// <summary>
+    ///   一个强类型的资源类,用于查找本地化的字符串等。
+    /// </summary>
+    // 此类是由 StronglyTypedResourceBuilder
+    // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
+    // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
+    // (以 /str 作为命令选项),或重新生成 VS 项目。
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Resources {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Resources() {
+        }
+        
+        /// <summary>
+        ///   返回此类使用的缓存的 ResourceManager 实例。
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SIASUN.TwinCatLogger.Properties.Resources", typeof(Resources).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   使用此强类型资源类,为所有资源查找
+        ///   重写当前线程的 CurrentUICulture 属性。
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+    }
+}

+ 117 - 0
Properties/Resources.resx

@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+</root>

+ 26 - 0
Properties/Settings.Designer.cs

@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     此代码由工具生成。
+//     运行时版本:4.0.30319.42000
+//
+//     对此文件的更改可能会导致不正确的行为,并且如果
+//     重新生成代码,这些更改将会丢失。
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace SIASUN.TwinCatLogger.Properties {
+    
+    
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")]
+    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+        
+        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+        
+        public static Settings Default {
+            get {
+                return defaultInstance;
+            }
+        }
+    }
+}

+ 7 - 0
Properties/Settings.settings

@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
+  <Profiles>
+    <Profile Name="(Default)" />
+  </Profiles>
+  <Settings />
+</SettingsFile>

+ 137 - 0
SIASUN.TwinCatLogger.csproj

@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">x86</Platform>
+    <ProductVersion>8.0.30703</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{210F67CF-D0E5-42EE-98E8-AD47C8D3893A}</ProjectGuid>
+    <OutputType>WinExe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>SIASUN.TwinCatLogger</RootNamespace>
+    <AssemblyName>SIASUN.TwinCatLogger</AssemblyName>
+    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <TargetFrameworkProfile>
+    </TargetFrameworkProfile>
+    <FileAlignment>512</FileAlignment>
+    <PublishUrl>publish\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>0</ApplicationRevision>
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
+    <PlatformTarget>x86</PlatformTarget>
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
+    <PlatformTarget>x86</PlatformTarget>
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup>
+    <ApplicationIcon>logger.ico</ApplicationIcon>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.configuration" />
+    <Reference Include="System.Core" />
+    <Reference Include="System.Web.Extensions" />
+    <Reference Include="System.Web.Services" />
+    <Reference Include="System.Xml.Linq" />
+    <Reference Include="System.Data.DataSetExtensions" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Deployment" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+    <Reference Include="System.Xml" />
+    <Reference Include="TwinCAT.Ads">
+      <HintPath>.\TwinCAT.Ads.dll</HintPath>
+    </Reference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="AutoStartTask.cs" />
+    <Compile Include="MainForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="MainForm.Designer.cs">
+      <DependentUpon>MainForm.cs</DependentUpon>
+    </Compile>
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+    <EmbeddedResource Include="MainForm.resx">
+      <DependentUpon>MainForm.cs</DependentUpon>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+    <Compile Include="Properties\Resources.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Resources.resx</DependentUpon>
+      <DesignTime>True</DesignTime>
+    </Compile>
+    <None Include="app.config">
+      <SubType>Designer</SubType>
+    </None>
+    <None Include="Properties\Settings.settings">
+      <Generator>SettingsSingleFileGenerator</Generator>
+      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+    </None>
+    <Compile Include="Properties\Settings.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DependentUpon>Settings.settings</DependentUpon>
+      <DesignTimeSharedInput>True</DesignTimeSharedInput>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <COMReference Include="TaskScheduler">
+      <Guid>{E34CB9F1-C7F7-424C-BE29-027DCC09363A}</Guid>
+      <VersionMajor>1</VersionMajor>
+      <VersionMinor>0</VersionMinor>
+      <Lcid>0</Lcid>
+      <WrapperTool>tlbimp</WrapperTool>
+      <Isolated>False</Isolated>
+      <EmbedInteropTypes>False</EmbedInteropTypes>
+    </COMReference>
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1</ProductName>
+      <Install>true</Install>
+    </BootstrapperPackage>
+  </ItemGroup>
+  <ItemGroup>
+    <Content Include="logger.ico" />
+  </ItemGroup>
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>

+ 25 - 0
SIASUN.TwinCatLogger.sln

@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.27703.2000
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SIASUN.TwinCatLogger", "SIASUN.TwinCatLogger.csproj", "{210F67CF-D0E5-42EE-98E8-AD47C8D3893A}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|x86 = Debug|x86
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{210F67CF-D0E5-42EE-98E8-AD47C8D3893A}.Debug|x86.ActiveCfg = Debug|x86
+		{210F67CF-D0E5-42EE-98E8-AD47C8D3893A}.Debug|x86.Build.0 = Debug|x86
+		{210F67CF-D0E5-42EE-98E8-AD47C8D3893A}.Release|x86.ActiveCfg = Release|x86
+		{210F67CF-D0E5-42EE-98E8-AD47C8D3893A}.Release|x86.Build.0 = Release|x86
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {A577A785-77EB-4856-B024-3497D298E5C7}
+	EndGlobalSection
+EndGlobal

二進制
Thumbs.db


二進制
TwinCAT.Ads.dll


+ 13 - 0
app.config

@@ -0,0 +1,13 @@
+<?xml version="1.0"?>
+<configuration>
+  <appSettings>
+    <add key="点表文件" value="log日志地址表20190710.csv"/>
+    <add key="PLC地址" value="192.168.253.128.1.1:801"/>
+    <add key="启动信号" value="MAIN.axis01_abs_enable"/>
+    <add key="刷新时间" value="100"/>
+    <add key="小数位数" value="3"/>
+    <add key="单文件行数" value="10000"/>
+    <add key="测试模式" value="false"/>
+  </appSettings>
+  <startup><supportedRuntime version="v2.0.50727"/></startup>
+</configuration>

二進制
logger.ico


二進制
reddot.png