zoukankan      html  css  js  c++  java
  • 多进程监控自动关机工具升级远程关闭多台server——C# works with PowerShell

    之前给单位做过一个多进程监控的自动关机工具,详见那篇blog

    这次领导又加了需求,说要等进程监控结束后,不止需要关闭主控端server,还需要关闭其他servers。于是就用到了我上篇文章所介绍的知识——通过PowerShell来远程管理计算机。

    由于PowerShell和C#都是基于.NET的,所以也不需要胶水把这两种语言粘合到一起。可以充分的利用两者各自的优点,结合到一起!(PowerShell在远程管理server这方面是很擅长的。)

    于是我修改了之前的工具UI界面,多出了两个textbox,分别用来选择server配置文件(需要关闭的除主控端的server的相关信息都记录在该配置文件中)和PowerShell脚本文件(主要负责远程方面的操作):

    server配置文件格式如下,一行对应一台server,每一行中的server ip、用户名、密码用空格隔开:

    选用的PowerShell脚本文件代码如下:

    function ShutDownRemoteComputers
    {
        param($ip,$user,$pwd)
        #winrm s winrm/config/client '@{TrustedHosts=10.1.23.60"}'
        $sen = "'@{TrustedHosts=`""+$ip+"`"}'"
        winrm s winrm/config/client $sen
        $pw = convertto-securestring -AsPlainText -Force -String $pwd
        $cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $user,$pw
        $session = New-PSSession $ip -Credential $cred
        icm $session {shutdown -s -t 0}
    }

    Winform程序在主控端结束进程检查后,会先关闭server配置文件中的servers,然后关闭主控端server(本机)。

    代码如下(粉色部分为新加的和远程相关的主要内容):

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Diagnostics;
    using System.Text.RegularExpressions;
    using System.IO;
    using System.Management.Automation;
    using System.Management.Automation.Runspaces;
    
    namespace AutoShutDown2
    {
        public partial class MainForm : Form
        {
            public MainForm()
            {
                InitializeComponent();
            }
    
            private void chooseFileButton_Click(object sender, EventArgs e)
            {
                OpenFileDialog fileName = new OpenFileDialog();
                fileName.Filter = "文本文件|*.*|C#文件|*.cs|所有文件|*.*";
                if (fileName.ShowDialog() == DialogResult.OK)
                {
                    filePath.Text = fileName.FileName;
                }
            }
    
            private void filePath_Click(object sender, EventArgs e)
            {
                filePath.Text = "";
            }
    
            private void startButton_Click(object sender, EventArgs e)
            {
                if (filePath.Text.ToString().Substring(filePath.Text.Length - 3, 3) == "txt")
                {
                    if (Regex.IsMatch(duration.Text, "^([0-9]{1,})$"))
                    {
                        if (int.Parse(duration.Text) >= 30)
                        {
                            if (serverFilePath.Text == "")
                            {
                                MessageBox.Show("You should choose a server configuration file first.");
                            }
                            else
                            {
                                MessageBox.Show("PCAS will check with a duration of " + duration.Text + "s.");
                                this.Hide();
                                //Check the processes with the duration.
                                DurationStart();
                            }
                        }
                        else 
                        {
                            MessageBox.Show("The integer number should be greater than 30 seconds.");
                        }
                    }
                    else
                    {
                        MessageBox.Show("You can only type in an integer for duration.");
                        duration.Text = "";
                    }
                }
                else 
                {
                    MessageBox.Show("You can only choose a txt to be a configuration file.");
                    filePath.Text = "";
                }
            }
    
            private void DurationStart()
            {
                //Check the process's status with the duration.
                System.Timers.Timer tmr = new System.Timers.Timer(int.Parse(duration.Text)*1000);
                tmr.Elapsed += new System.Timers.ElapsedEventHandler(CheckProcess);
                tmr.AutoReset = true;
                tmr.Enabled = true;
            }
    
            private void CheckProcess(object source, System.Timers.ElapsedEventArgs e)
            {
                //Check the processes's status in the config file.
                using (FileStream fs = new FileStream(filePath.Text, FileMode.Open))
                {
                    using (StreamReader sr = new StreamReader(fs))
                    {
                        string line;
                        int numOfTheProcesses = 0;
                        while ((line = sr.ReadLine()) != null)
                        {
                            var processes = System.Diagnostics.Process.GetProcesses();
                            foreach (var process in processes)
                            {
                                if (process.ProcessName == line)
                                {
                                    //Find the objective process.
                                    //MessageBox.Show(line);
                                    numOfTheProcesses++;
                                }
                            }
                        }
                        if (numOfTheProcesses == 0)
                        {
                            //No such process, shut down the computer.
                            //MessageBox.Show("The computer is ready to be shut down.");
                            //Shut down the computer
                            ShutDown();
                        }
                        sr.Close();
                    }
                    fs.Close();
                }
            }
    
            private void ShutDown()
            {
                //Shut down the other computers.
                ShutDownOthers(serverFilePath.Text, scriptPathText.Text);
                //Shut down this computer.
                System.Diagnostics.Process myProcess = new System.Diagnostics.Process();
                myProcess.StartInfo.FileName = "cmd.exe";
                myProcess.StartInfo.UseShellExecute = false;
                myProcess.StartInfo.RedirectStandardInput = true;
                myProcess.StartInfo.RedirectStandardOutput = true;
                myProcess.StartInfo.RedirectStandardError = true;
                myProcess.StartInfo.CreateNoWindow = true;
                myProcess.Start();
                Thread.Sleep(3000);
                myProcess.StandardInput.WriteLine("shutdown -s -t 0"); 
                //MessageBox.Show("Shut down self.");
            }
    
            private void ShutDownOthers(string serverFilePath,string scriptPath)
            {
                //Read servers from the server file and shut down the servers.
                //Read the servers.
                string filePath = serverFilePath;
                using (FileStream fs1 = new FileStream(filePath, FileMode.Open))
                {
                    try
                    {
                        using (StreamReader sr1 = new StreamReader(fs1))
                        {
                            string line;
                            try
                            {
                                while ((line = sr1.ReadLine()) != null)
                                {
                                    var elements = line.Split();
                                    string ip = elements[0].ToString();
                                    string user = elements[1].ToString();
                                    string pwd = elements[2].ToString();
                                    //Shut down the server checked from the line.
                                    //Open the PowerShell.
                                    using (Runspace runspace = RunspaceFactory.CreateRunspace())
                                    {
                                        //MessageBox.Show("Run PowerShell.");
                                        string script = File.ReadAllText(scriptPath);
                                        runspace.Open();
                                        PowerShell ps = PowerShell.Create();
                                        ps.Runspace = runspace;
                                        ps.AddScript(script);
                                        ps.Invoke();
                                        ps.AddCommand("ShutDownRemoteComputers").AddParameter("ip", ip).AddParameter("user", user).AddParameter("pwd", pwd);
                                        ps.Invoke();
                                        //MessageBox.Show("Shut down others");
                                    }
                                }
                            }
                            finally
                            {
                                sr1.Close();
                            }
                        }
                    }
                    finally
                    {
                        fs1.Close();
                    }
                }       
            }
    
            private void chooseServerFileButton_Click(object sender, EventArgs e)
            {
                OpenFileDialog fileName = new OpenFileDialog();
                fileName.Filter = "文本文件|*.*|C#文件|*.cs|所有文件|*.*";
                if (fileName.ShowDialog() == DialogResult.OK)
                {
                    serverFilePath.Text = fileName.FileName;
                }
            }
    
            private void serverFilePath_Click(object sender, EventArgs e)
            {
                serverFilePath.Text = "";
            }
    
            private void scriptPathText_Click(object sender, EventArgs e)
            {
                scriptPathText.Text = "";
            }
    
            private void chooseScriptButton_Click(object sender, EventArgs e)
            {
                OpenFileDialog fileName = new OpenFileDialog();
                fileName.Filter = "文本文件|*.*|C#文件|*.cs|所有文件|*.*";
                if (fileName.ShowDialog() == DialogResult.OK)
                {
                    scriptPathText.Text = fileName.FileName;
                }
            }
        }
    }

    至于远程所需要在主控端和被控端所做的准备工作,一语概括就是在主控端和被控端都Enable-PSRemoting(全选A),然后互相配置Winrm信任就ok了(这两步都是在PowerShell中进行的,详见通过PowerShell来远程管理计算机这篇blog)。

    //Open the PowerShell.
    using (Runspace runspace = RunspaceFactory.CreateRunspace())
    {
         //MessageBox.Show("Run PowerShell.");
         string script = File.ReadAllText(scriptPath);
         runspace.Open();
         PowerShell ps = PowerShell.Create();
         ps.Runspace = runspace;
         ps.AddScript(script);
         ps.Invoke();
         ps.AddCommand("ShutDownRemoteComputers")
            .AddParameter("ip", ip)
            .AddParameter("user", user)
            .AddParameter("pwd", pwd);
         ps.Invoke();
    }

    上面这段代码就是在C#中调用PowerShell脚本的关键。想要在C#中引用PowerShell需要事先add reference:

    找到这个reference最快捷的方式就是在PowerShell中输入[psobject].Assembly.Location

    然后在代码里using相应的命名空间就可以了:

    亲测通过后获得了相关部门领导赠送的可爱多一个。

  • 相关阅读:
    element-ui Checkbox 实现单选
    鼠标移到到div上,div放大
    linux下hue的安装与部署
    window10搭建pyspark(超级详细)
    Spark的checkpoint源码讲解
    Phoneix(一)简介及常用命令
    Phoneix(四)hbase导入数据同时与phoenix实现映射同步
    Phoneix(三)HBase集成Phoenix创建二级索引
    Hive数据导入Hbase
    Spark Streaming 与Filnk对比分析
  • 原文地址:https://www.cnblogs.com/LanTianYou/p/4727496.html
Copyright © 2011-2022 走看看