Feeds:
Записи
Комментарии

Archive for Апрель 2013

Вопрос был задан на форуме OsZone.Net в теме «PowerShell — Закрытие всех окон приложений кроме активного« . Был предложен вариант с ярлыком, но возникла проблема, при нажатии hotkey  — фокус приложения переключался на другое приложение.

Что нам потребуется:

Основная проблема – это работа с hotkey. Идея работы позаимствована у Hans Passant’a — How to prevent my C# winforms application from stealing focus when I set the visible properly to true?

Схема скрипта:

  • Функция RegisterHotKey —  определяет комбинацию «горячая» клавиша для текущего потока

RegisterHotKey(this.Handle, MYKEYID, MOD_CONTROL + MOD_SHIFT, Keys.U);

  • this.Handle  — Идентификатор окна нашей формы,которое принимает сообщение WM_HOTKEY
  • MYKEYID — Определяет идентификатор комбинации
  • MOD_CONTROL + MOD_SHIFT — Определяет клавиши, которые должны быть нажаты в комбинации с клавишей, заданной параметром vk, чтобы генерировать сообщение WM_HOTKEY. Параметр modifiers может быть комбинацией следующих значений:
    • MOD_ALT — Любая клавиша ALT должна удерживаться нажатой.
    • MOD_CONTROL — Любая клавиша CTRL должна удерживаться нажатой.
    • MOD_SHIFT — Любая клавиша SHIFT должна удерживаться нажатой.
  • Keys.U — Определяет код виртуальной клавиши комбинации «горячая» клавиша.

В данном примере комбинация будет CTRL+Shift + U

  • Функция  UnregisterHotKey — освобождает комбинацию «горячая» клавиша, предварительно зарегистрированную вызывающим потоком

UnregisterHotKey(this.Handle, MYKEYID);

  • this.Handle  — Идентификатор окна нашей формы,которое принимает сообщение WM_HOTKEY
  • MYKEYID — Определяет идентификатор комбинации

Вызывается при закрытии формы

  • Для обработки сообщений операционной системы в нашей форме, потребуется переопределить метод WndProc.
  • if (m.Msg == WM_HOTKEY && m.WParam.ToInt32() == MYKEYID) { – Производим проверку на получение сочетания CTRL+Shift +
  • Вызов скрипта PowerShell —  How to run PowerShell scripts from C#
  • Import-Module -Name Wasp\r\nSelect-Window | Where-Object { -not $_.IsActive} | Remove-Window
    • Import-Module -Name Wasp – Импортирует модуль WASP (не обязательно для PowerShell V3, но с учетом того,что переменная $PSModuleAutoloadingPreference не None)
    • Select-Window – Получаем список окон
    • Where-Object { -not $_.IsActive} – Отфильтровываем все кроме активного
    • Remove-Window – Закрываем окна
  • Function OnLoad –  Определяем свойства для запуска формы в скрытом режиме
  • Function OnClick – При нажатии на кнопку меню Exit – закрываем форму
  • Создаем значок в трее и определяем меню Exit
  • Запуск формы
$ActiveWindow = @'
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Management.Automation;
using System.Management.Automation.Runspaces;

namespace WindowsApplication1 {
public partial class Form1 : Form {
private const int MYKEYID = 0;
public Form1() {
RegisterHotKey(this.Handle, MYKEYID, MOD_CONTROL + MOD_SHIFT, Keys.U);
this.FormClosing += Form1_FormClosing;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
UnregisterHotKey(this.Handle, MYKEYID);
}

protected override void SetVisibleCore(bool value)
{
base.SetVisibleCore(false);
}

protected override void WndProc(ref Message m) {
if (m.Msg == WM_HOTKEY && m.WParam.ToInt32() == MYKEYID) {
// create Powershell runspace
Runspace runspace = RunspaceFactory.CreateRunspace();

// open it
runspace.Open();

// create a pipeline and feed it the script text
string scriptText = "Import-Module -Name Wasp\r\nSelect-Window | Where-Object { -not $_.IsActive} | Remove-Window";
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(scriptText);

// execute the script
pipeline.Invoke();

// close the runspace
runspace.Close();
}
base.WndProc(ref m);
}

// P/Invoke declarations
private const int WM_HOTKEY = 0x312;
private const int MOD_ALT = 1;
private const int MOD_CONTROL = 2;
private const int MOD_SHIFT = 4;
[DllImport("user32.dll")]
private static extern int RegisterHotKey(IntPtr hWnd, int id, int modifier, Keys vk);
[DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
}
}
'@

Function OnLoad {
$form.Visible = $false
$form.ShowInTaskbar = $false
}

Function OnClick {
$trayIcon.Visible = $False
$form.close()
}

Add-Type -TypeDefinition $ActiveWindow -ReferencedAssemblies System.Windows.Forms
Add-Type -AssemblyName System.Drawing

$trayIcon = New-Object System.Windows.Forms.NotifyIcon
$trayMenu = New-Object System.Windows.Forms.ContextMenu
$menuExit = New-Object System.Windows.Forms.MenuItem
$form = New-Object WindowsApplication1.Form1

$trayIcon.Icon = [System.Drawing.SystemIcons]::Information
$trayIcon.ContextMenu = $trayMenu

$menuExit.Text = "Exit"
$menuExit.Add_Click({OnClick})

$trayMenu.MenuItems.AddRange(@($menuExit))

$form.Add_Load({OnLoad})

$trayIcon.Visible = $true
[Windows.Forms.Application]::Run($form)

Запуск скрипта:

Powershell –WindowStyle Hidden –File «C:\Script\Close-InactiveWindow.ps1»

Выход:

Реклама

Read Full Post »