<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          如何隱藏運(yùn)行 winform 程序?

          共 7610字,需瀏覽 16分鐘

           ·

          2020-08-01 06:39

          群里有個(gè)同學(xué)問了問題 如何隱藏運(yùn)行 winform 程序?,提起了我的興趣,玩玩唄?那就玩玩吧!

          第一版

          將一個(gè) winform 程序隱藏執(zhí)行,隱藏執(zhí)行的方式有很多種,第一個(gè) demo 就用最簡單的方式,實(shí)現(xiàn)隱藏執(zhí)行。

          demo 執(zhí)行時(shí),不會顯示任何窗體,但是過10秒,會彈出對話框證明程序在運(yùn)行。

          1. 按照常規(guī)思路,在窗體初始化完成之后,調(diào)整窗體參數(shù)。
          public?partial?class?Form1?:?Form
          {
          ????public?Form1()
          ????{
          ????????InitializeComponent();

          ????????//不要顯示在任務(wù)欄
          ????????this.ShowInTaskbar?=?false;
          ????????//隱藏窗體
          ????????this.Visible?=?false;
          ????????//窗體寬度調(diào)整為0
          ????????this.Width?=?0;
          ????????//窗體高度調(diào)整為0
          ????????this.Height?=?0;
          ????????//窗體最左邊設(shè)置成-10000,保證在屏幕外邊
          ????????this.Left?=?-10000;
          ????????//窗體最頂部設(shè)置成-10000,保證在屏幕外邊
          ????????this.Top?=?-10000;
          ????}
          }
          1. Form1_Load 方法里新啟動(dòng)一個(gè)線程,彈出對話框試試。
          private?void?Form1_Load(object?sender,?EventArgs?e)
          {
          ????new?Thread(new?ThreadStart(()?=>
          ????{
          ????????Thread.Sleep(10?*?1000);
          ????????MessageBox.Show("我在后臺執(zhí)行喲...");
          ????})).Start();
          }

          運(yùn)行起來發(fā)現(xiàn)還是有顯示,而且左邊和頂邊的位置沒有設(shè)置成功。如圖:

          1. 還有一個(gè) opacity,窗體透明度的屬性,設(shè)置成0。如下:
          this.Opacity?=?0;
          1. 現(xiàn)在就好了,看不見窗體,達(dá)到了隱藏的目的,簡單粗暴,但是還湊合實(shí)用。

          不足之處:窗體雖然是隱藏了,但只是調(diào)整了透明度(心里有點(diǎn)不爽,明明它是存在的,肉眼看不見而已)。

          第二版

          經(jīng)過第一個(gè) demo,我們簡單的實(shí)現(xiàn)了一個(gè)隱藏運(yùn)行的應(yīng)用程序,那么還有什么方式能隱藏執(zhí)行呢?

          細(xì)心的同學(xué)發(fā)現(xiàn),這里在 Program.cs 文件 Main 方法中運(yùn)行了一個(gè) new Form1(),那么有什么辦法能不執(zhí)行這一句,應(yīng)用程序還能運(yùn)行呢?

          我們把這一句注釋掉,看到 Application 類提供了一個(gè) Run 方法,不帶任何參數(shù)。我們試著刪掉沒用的 Form1 這個(gè)窗體,把代碼改成下面這樣執(zhí)行一下試試。

          Application.EnableVisualStyles();
          Application.SetCompatibleTextRenderingDefault(false);
          //Application.Run(new?Form1());
          Application.Run();

          prefect!程序照常可以運(yùn)行,任務(wù)管理器中可以看到 HiddenApp2.exe 這個(gè)進(jìn)程,也不用費(fèi)心隱藏窗體,何樂不為?

          PS: 某些想法不良的同學(xué),可能想到了隱藏起來干點(diǎn)壞事,記住:法網(wǎng)恢恢、疏而不漏!

          再來改造一下,讓他實(shí)現(xiàn)上面的功能,10秒后彈出一個(gè)對話框,證明程序確實(shí)在運(yùn)行。

          Application.EnableVisualStyles();
          Application.SetCompatibleTextRenderingDefault(false);
          //Application.Run(new?Form1());
          new?Thread(new?ThreadStart(()?=>
          {
          ????Thread.Sleep(10?*?1000);
          ????MessageBox.Show("我在后臺執(zhí)行喲...");
          })).Start();
          Application.Run();

          代碼很簡單,就是啟動(dòng)一個(gè)線程延遲10秒后彈窗,有的同學(xué)可能要問了,為啥 new Thread 不放在 Application.Run() 方法之后?因?yàn)?Application.Run() 會使應(yīng)用程序主進(jìn)程阻塞執(zhí)行,所以后面的代碼不會執(zhí)行。

          擴(kuò)展

          這一節(jié)里,我們使用第二步里使用的方法來干一點(diǎn)壞事(PS:我喜歡),做一個(gè) 剪切板尾巴

          最終效果:他會在你復(fù)制的文本后面綴上設(shè)置好的文字,然后放進(jìn)剪切板。

          迅雷的監(jiān)視剪切板,就是監(jiān)視了剪切板中是否有 Html 格式的文本,從中間解析 URL,實(shí)現(xiàn)下載。

          winform 使用 Clipboard 這個(gè)密封類實(shí)現(xiàn)剪切板的一些基本用法,來看下定義:

          namespace?System.Windows.Forms
          {
          ????public?sealed?class?Clipboard
          ????{
          ????????public?static?void?Clear();
          ????????public?static?bool?ContainsAudio();
          ????????public?static?bool?ContainsData(string?format);
          ????????public?static?bool?ContainsFileDropList();
          ????????public?static?bool?ContainsImage();
          ????????public?static?bool?ContainsText(TextDataFormat?format);
          ????????public?static?bool?ContainsText();
          ????????public?static?Stream?GetAudioStream();
          ????????public?static?object?GetData(string?format);
          ????????public?static?IDataObject?GetDataObject();
          ????????public?static?StringCollection?GetFileDropList();
          ????????public?static?Image?GetImage();
          ????????public?static?string?GetText();
          ????????public?static?string?GetText(TextDataFormat?format);
          ????????public?static?void?SetAudio(Stream?audioStream);
          ????????public?static?void?SetAudio(byte[]?audioBytes);
          ????????public?static?void?SetData(string?format,?object?data);
          ????????public?static?void?SetDataObject(object?data);
          ????????public?static?void?SetDataObject(object?data,?bool?copy,?int?retryTimes,?int?retryDelay);
          ????????public?static?void?SetDataObject(object?data,?bool?copy);
          ????????public?static?void?SetFileDropList(StringCollection?filePaths);
          ????????public?static?void?SetImage(Image?image);
          ????????public?static?void?SetText(string?text);
          ????????public?static?void?SetText(string?text,?TextDataFormat?format);
          ????}
          }

          這一節(jié)主要是使用 public static string GetText(); 這個(gè)方法,來盜取用戶剪切的內(nèi)容,并在其后邊追加一個(gè)尾巴來惡搞一下。

          原理:使用后臺線程,定時(shí)的把剪切板內(nèi)容復(fù)制下來,然后追加一些文字,再寫回剪切板。廢話不多說,直接上核心代碼:

          var?text?=?Clipboard.GetText();
          //不要問我為啥不用?String.IsNullOrEmpty(),因?yàn)槲矣玫?.Net?Framework?3.5
          if?(text?!=?null?&&?text.Length?>?0)
          {
          ????if?(!text.EndsWith(TAIL))
          ????{
          ????????Clipboard.SetText(text?+?TAIL);
          ????????Debug.WriteLine($"[{DateTime.Now.ToString("yyyy-MM-dd?HH:mm:ss")}]?successful?catch?text【{text}】changed?to【{Clipboard.GetText()}】");
          ????}
          }

          代碼很短,但是很惡搞。

          有趣的問題,看下面的代碼:

          private?static?void?MemoryBomb()
          {
          ????Clipboard.SetDataObject(new?MemoryStream(new?byte[1024000000?*?2L]));
          ????var?data?=?Clipboard.GetDataObject()?.GetData(typeof(MemoryStream));
          ????var?thread?=?new?Thread(new?ThreadStart(()?=>
          ????{
          ????????Thread.Sleep(3000);
          ????????//1
          ????????data?=?null;
          ????????GC.Collect();
          ????????Clipboard.SetDataObject(new?MemoryStream(new?byte[0]));
          ????????data?=?Clipboard.GetDataObject()?.GetData(typeof(MemoryStream));
          ????????//2
          ????????data?=?null;
          ????????GC.Collect();
          ????}));
          ????thread.SetApartmentState(ApartmentState.STA);
          ????thread.Start();
          }

          看到剪切板 Clipboard.SetDataObject 方法可以接受一個(gè) object 參數(shù),我好奇的弄了一個(gè)很大的 byte[] 放了進(jìn)去,結(jié)果發(fā)現(xiàn)在 GetData() 方法調(diào)用后內(nèi)存劇增(完全算得上內(nèi)存炸彈),大小是2倍的 byte[] 大小字節(jié),我又重啟一個(gè)線程來,再次調(diào)用 SetDataObject() 方法設(shè)置剪切板內(nèi)容,發(fā)現(xiàn)內(nèi)存不會釋放。

          加了第一個(gè) GC.Collect(); 之后,內(nèi)存會降一半,我猜想 data 變量被釋放,但是剪切板內(nèi)容沒釋放,2倍大小的字節(jié)應(yīng)該是 data 變量占用 2G,剪切板占用 2G。如圖:

          剛啟動(dòng)
          GC.Collect();

          緊接著執(zhí)行完畢這段代碼之后:

          data?=?null;
          GC.Collect();
          Clipboard.SetDataObject(new?MemoryStream(new?byte[0]));
          data?=?Clipboard.GetDataObject()?.GetData(typeof(MemoryStream));

          有趣的是占用的2G內(nèi)存,不會釋放。為什么上面的 GetData 會使內(nèi)存劇增,而這一句不會使內(nèi)存變小呢?如圖:

          2G

          緊接著執(zhí)行第二個(gè) GC.Collect(); 執(zhí)行之后,內(nèi)存會被回收,但是還是比最初的大了一些,沒有完全釋放。如圖:

          奇思妙想:可以用 Clipboard 申請一些內(nèi)存,然后在內(nèi)存中執(zhí)行一些代碼,會不會對系統(tǒng)造成威脅?有能力的大牛可以嘗試一下。

          完整代碼:

          using?System;
          using?System.Collections.Generic;
          using?System.Diagnostics;
          using?System.IO;
          using?System.Linq;
          using?System.Threading;
          using?System.Windows.Forms;

          namespace?HiddenApp3
          {
          ????static?class?Program
          ????{
          ????????///?
          ????????///?應(yīng)用程序的主入口點(diǎn)。
          ????????///?

          ????????[STAThread]
          ????????static?void?Main()
          ????????{
          ????????????Application.EnableVisualStyles();
          ????????????Application.SetCompatibleTextRenderingDefault(false);
          ????????????//MemoryBomb();
          ????????????RunClipboardTail();
          ????????????Application.Run();
          ????????}

          ????????private?static?void?MemoryBomb()
          ????????{
          ????????????Clipboard.SetDataObject(new?MemoryStream(new?byte[1024000000?*?2L]));
          ????????????var?data?=?Clipboard.GetDataObject()?.GetData(typeof(MemoryStream));

          ????????????var?thread?=?new?Thread(new?ThreadStart(()?=>
          ????????????{
          ????????????????Thread.Sleep(3000);
          ????????????????//1
          ????????????????data?=?null;
          ????????????????GC.Collect();
          ????????????????Clipboard.SetDataObject(new?MemoryStream(new?byte[1]));
          ????????????????data?=?Clipboard.GetDataObject()?.GetData(typeof(MemoryStream));
          ????????????????//2
          ????????????????data?=?null;
          ????????????????GC.Collect();
          ????????????}));
          ????????????thread.SetApartmentState(ApartmentState.STA);
          ????????????thread.Start();
          ????????}

          ????????private?const?string?TAIL?=?"你需要關(guān)注《開發(fā)者精選資訊》公眾號";
          ????????private?static?void?RunClipboardTail()
          ????????{
          ????????????var?thread?=?new?Thread(new?ThreadStart(()?=>
          ????????????{
          ????????????????while?(true)
          ????????????????{
          ????????????????????try
          ????????????????????{
          ????????????????????????var?text?=?Clipboard.GetText();
          ????????????????????????if?(text?!=?null?&&?text.Length?>?0)
          ????????????????????????{
          ????????????????????????????if?(!text.EndsWith(TAIL))
          ????????????????????????????{
          ????????????????????????????????Clipboard.SetText(text?+?TAIL);
          ????????????????????????????????Debug.WriteLine($"[{DateTime.Now.ToString("yyyy-MM-dd?HH:mm:ss")}]?successful?catch?text【{text}】changed?to【{Clipboard.GetText()}】");
          ????????????????????????????}
          ????????????????????????}
          ????????????????????}
          ????????????????????catch?{?}
          ????????????????????Thread.Sleep(10000);
          ????????????????}
          ????????????}))
          ????????????{
          ????????????????IsBackground?=?true
          ????????????};
          ????????????thread.SetApartmentState(ApartmentState.STA);
          ????????????thread.Start();
          ????????}
          ????}
          }

          github:

          https://github.com/mrhuo/HiddenAppDemo


          推薦閱讀:

          開發(fā)者精選資訊
          ?每日為您推薦開發(fā)精選資訊


          長按二維碼
          關(guān)注 「開發(fā)者精選資訊」 公眾號

          好文章,我在看 ???

          瀏覽 27
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久美女主播视频 | 精品久久国产 | 日韩无码视频一区二区三区 | 啊啊啊国产 | 欧美成人黄色电影网站 |