2017-04-19 129 views
0

應用程序A(例如:AutoCAD,Word,...)運行時,它將在運行時調用DLL X來執行任務→打開表單登錄如何在其他應用程序中關閉1個應用程序的表單?

應用程序B(例如:Photoshop,Excel .. 。)當運行時,它會在運行時調用DLL Y執行任務→我想關閉上面的登錄表單可以這樣做嗎?

這可能嗎?

Image description

+1

cad,excel等是非常糟糕的例子。 –

+0

@LeiYang他們和任何人一樣好,這不是一個好主意,因爲你將不得不惹上ROT。 Oosutsuke你應該谷歌ROT和實現東西在計時器 – EpicKip

+0

@雷洋:我**只是想**的例子(CAD,單詞,...)很容易想象。因爲我不知道如何,我希望有人提出想法。 EpicKip:謝謝。我會谷歌ROT! – Oosutsuke

回答

0

這是一個小示例,展示瞭如何在另一個進程中關閉窗口。創建一個新的Windows窗體項目,將它添加兩種形式,並在第一個添加兩個按鈕,並把這些代碼在Form1中:

public partial class Form1 : Form 
{ 
    delegate bool EnumWindowsProc(IntPtr Hwnd, IntPtr lParam); 

    [DllImport("user32", SetLastError = true)] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    private extern static bool EnumThreadWindows(int threadId, EnumWindowsProc callback, IntPtr lParam); 

    [DllImport("user32", SetLastError = true)] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam); 

    [DllImport("user32", SetLastError = true, CharSet = CharSet.Auto)] 
    private extern static int GetWindowText(IntPtr hWnd, StringBuilder text, int maxCount); 

    [DllImport("user32.dll", CharSet = CharSet.Auto)] 
    static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam); 

    private const int WM_CLOSE = 0x10; 

    public Form1() 
    { 
     InitializeComponent(); 
     button1.Click += button1_Click; 
     button2.Click += button2_Click; 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     var frm = new Form2(); 
     frm.Show(this); 
    } 

    private void button2_Click(object sender, EventArgs e) 
    { 
     Process[] processes = Process.GetProcessesByName("FindWindowSample"); 

     foreach (Process p in processes) 
     { 
      var handle = FindWindowInProcess(p, x => x == "Form2"); 

      if (handle != IntPtr.Zero) 
      { 
       SendMessage(handle, WM_CLOSE, IntPtr.Zero, IntPtr.Zero); 
      } 
     } 
    } 

    public static IntPtr FindWindowInProcess(Process process, Func<string, bool> compareTitle) 
    { 
     IntPtr windowHandle = IntPtr.Zero; 

     foreach (ProcessThread t in process.Threads) 
     { 
      windowHandle = FindWindowInThread(t.Id, compareTitle); 
      if (windowHandle != IntPtr.Zero) 
      { 
       break; 
      } 
     } 

     return windowHandle; 
    } 

    private static IntPtr FindWindowInThread(int threadId, Func<string, bool> compareTitle) 
    { 
     IntPtr windowHandle = IntPtr.Zero; 
     EnumThreadWindows(threadId, (hWnd, lParam) => 
     { 
      StringBuilder text = new StringBuilder(200); 
      GetWindowText(hWnd, text, 200); 
      if (compareTitle(text.ToString())) 
      { 
       windowHandle = hWnd; 
       return false; 
      } 
      return true; 
     }, IntPtr.Zero); 

     return windowHandle; 
    } 
} 

編譯並運行應用程序的兩個實例。在第一次單擊Button1以顯示Form2。在第二個實例上點擊Button2從第一個實例關閉Form2。

+1

這是一件美妙的事情。它運行良好。非常感謝您的努力! +1 – Oosutsuke

+0

因此代碼爲:open word/cad ...並顯示登錄表單? –

+0

@雷洋:我只是想給例子**讓讀者輕鬆想象我的想法。 – Oosutsuke

0

以及如果只是關閉正在運行的proccess最簡單的方法很可能是像類似

using System.Diagnostics; 
var autocad = Process.GetProcesses().FirstOrDefault(w=>w.ProcessName == "AutoCAD"); 
autocad.Close(); 

打開你大概可以循環proccesses爲所需的名稱。它不是非常冒險,但它會完成工作,如果它剛剛打開和關閉你的後面

+0

我想關閉在AutoCAD中被打開的形式,但AutoCAD中沒有關閉(不退出) – Oosutsuke

+0

所以you're試圖關閉被通過AutoCAD中打開,但只有對話而不是整個的AutoCAD proccess? – subkonstrukt

+0

是的,它是真實的一種形式。 – Oosutsuke

0

你可以用一個(只是一個例子)無窗口控制檯應用程序來檢查新進程。我有一個例子:

  1. 做一個控制檯應用程序和登錄表單

  2. 使控制檯應用程序Windows應用程序像這樣的一個新項目:

enter image description here
新聞屬性 enter image description here 選擇Windows應用程序

請在檢查過程中的控制檯應用程序定時器:

public static bool IsOpen = false; 

static void Main(string[] args) 
{ 
    Timer t = new Timer(TimerCallback, null, 0, 1200); 
    while (true) 
    { 
     //keep it running 
    } 
} 

private static void TimerCallback(Object o) 
{ 
    if (!IsOpen && Process.GetProcesses().Select(r => r.ProcessName).Contains("EXCEL")) 
    { 
     //Excel is running, show the form 
     Form1 loginForm = new Form1(); 
     loginForm.ShowDialog(); 
     //Stop it from spawning a million forms by setting bool 
     IsOpen = true; 
    } 
} 

關閉表單時,應用程序可以關閉此計時器內部放太多的邏輯,用同樣的方式。

要打開控制檯窗口形式,但是你需要將引用添加到控制檯應用程序:

enter image description here

如果你想進程名稱:
只需使用一種形式,補充一點:

foreach (var proc in Process.GetProcesses()) 
{ 
    MessageBox.Show(proc.ProcessName); 
} 

這將顯示當前正在運行的所有進程的名稱。

+0

所以登錄表單是在一個單獨的過程? –

+0

@LeiYang它不是從excel本身,所以是的。 – EpicKip

+0

@LeiYang不知道你爲什麼想要這樣做,但...像這樣,你可以 – EpicKip

相關問題