В организации изменились правила транслитерации имён пользователей при создании почтовых ящиков email. И захотелось сделать какой-нибудь простенький инструмент на Powershell для автоматической транслитерации имён, чтобы не ломать голову каждый раз вспоминая правила сопоставления символов при необходимости создания нового мылбокса. За основу был взята PS-функция транслитерации Ильи Сазонова (с учётом правки правил преобразования для нужд нашей организации) и добавлен код для поддержки простой диалоговой формы.
Сам скрипт:
[void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") function TranslitRU2LAT{ param([string]$inString) $Translit = @{ [char]'а' = "a";[char]'А' = "A"; [char]'б' = "b";[char]'Б' = "B"; [char]'в' = "v";[char]'В' = "V"; [char]'г' = "g";[char]'Г' = "G"; [char]'д' = "d";[char]'Д' = "D"; [char]'е' = "e";[char]'Е' = "E"; [char]'ё' = "ye";[char]'Ё' = "Ye"; [char]'ж' = "zh";[char]'Ж' = "Zh"; [char]'з' = "z";[char]'З' = "Z"; [char]'и' = "i";[char]'И' = "I"; [char]'й' = "y";[char]'Й' = "Y"; [char]'к' = "k";[char]'К' = "K"; [char]'л' = "l";[char]'Л' = "L"; [char]'м' = "m";[char]'М' = "M"; [char]'н' = "n";[char]'Н' = "N"; [char]'о' = "o";[char]'О' = "O"; [char]'п' = "p";[char]'П' = "P"; [char]'р' = "r";[char]'Р' = "R"; [char]'с' = "s";[char]'С' = "S"; [char]'т' = "t";[char]'Т' = "T"; [char]'у' = "u";[char]'У' = "U"; [char]'ф' = "f";[char]'Ф' = "F"; [char]'х' = "kh";[char]'Х' = "Kh"; [char]'ц' = "ts";[char]'Ц' = "Ts"; [char]'ч' = "ch";[char]'Ч' = "Ch"; [char]'ш' = "sh";[char]'Ш' = "Sh"; [char]'щ' = "sch";[char]'Щ' = "Sch"; [char]'ъ' = "";[char]'Ъ' = ""; [char]'ы' = "y";[char]'Ы' = "Y"; [char]'ь' = "";[char]'Ь' = ""; [char]'э' = "e";[char]'Э' = "E"; [char]'ю' = "yu";[char]'Ю' = "Yu"; [char]'я' = "ya";[char]'Я' = "Ya" } $outChars = "" $Result.Text = "" $inString = $InputName.Text +"."+ $InputSName.Text foreach ($c in $inChars = $inString.ToCharArray()) { if ($Translit[$c] -cne $Null ) {$outChars += $Translit[$c]} else {$outChars += $c} } $Result.Text = $outChars } # # function SplitFName{ $inStr = $InputFName.Text -split " " $InputSName.Text = $inStr[0] $InputName.Text = $inStr[1] $InputInitName.Text = $inStr[2] TranslitRU2LAT } # function SetToClipboard{ param($cltext) if($cltext){ [Windows.Forms.Clipboard]::SetText($cltext); $Form.close() } } # # Форма GUI # $labFName = New-Object windows.Forms.Label $labFName.text = "Фамилия Имя Отчество полностью:" $labFName.left = "8" $labFName.top = "10" $labFName.Width = "300" $labSName = New-Object windows.Forms.Label $labSName.text = "Фамилия:" $labSName.left = "8" $labSName.top = "65" $labSName.Width = "80" $labName = New-Object windows.Forms.Label $labName.text = "Имя:" $labName.left = "113" $labName.top = "65" $labName.Width = "80" $labInitName = New-Object windows.Forms.Label $labInitName.text = "Отчество:" $labInitName.left = "218" $labInitName.top = "65" $labInitName.Width = "80" $InputFName = New-Object windows.Forms.TextBox $InputFName.Left ="10" $InputFName.Top = "34" $InputFName.Width = "310" $InputFName.add_TextChanged($Function:SplitFName) $InputSName = New-Object windows.Forms.TextBox $InputSName.Left ="10" $InputSName.Top = "88" $InputName = New-Object windows.Forms.TextBox $InputName.Left ="115" $InputName.Top = "88" $InputInitName = New-Object windows.Forms.TextBox $InputInitName.Left ="220" $InputInitName.Top = "88" $button1 = New-Object Windows.Forms.Button $button1.Text="Транслитерация : Загранпаспорт (1997—2010)" $button1.Left ="10" $button1.Top = "120" $button1.Width = "310" $button1.add_click($Function:TranslitRU2LAT) $Result = New-Object windows.Forms.TextBox $Result.Left= "10" $Result.Top="154" $Result.Width = "200" $Result.Height = "200" $Result.ReadOnly = "true" $Result.Text = "" $button2 = New-Object Windows.Forms.Button $button2.Text = "В буфер обмена" $button2.Left ="212" $button2.Top = "153" $button2.Width = "108" $button2.Height = "22" $button2.add_click({SetToClipboard $Result.Text}) $Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($PSHOME + "\powershell.exe") $Form = New-Object Windows.Forms.Form $Form.Height = 220 $Form.Width = 350 $Form.Text = "Транслит ФИО для Email" $Form.Icon = $Icon $Form.AutoSize = $True $Form.AutoSizeMode = "GrowOnly" #$Form.StartPosition = "CenterScreen" $Form.controls.add($labFName) $Form.controls.add($labName) $Form.controls.add($labInitName) $Form.controls.add($labSName) $Form.controls.add($inputFName) $Form.controls.add($inputSName) $Form.controls.add($inputName) $Form.controls.add($inputInitName) $Form.controls.add($button1) $Form.controls.add($button2) $Form.controls.add($Result) $Form.Add_Shown({$Form.Activate()}) $Form.ShowDialog()
Однако при запуске скрипта из под обычного пользователя возможно будут появляться всевозможные предупреждения безопасности, типа того, что скрипт не подписан и т.п. Можно конечно изменять настройки безопасности PS, а можно пойти по другому пути – скомпилировать скрипт в исполняемое .net приложение. Для этого можно использовать разные инструменты, например можно использовать утилиту PowerGUI Script Editor (меню Tools > Compile Script)
При компиляции скрипта мы можем указать имя результирующего исполняемого файла, выбрать версию .Net Framework (3.5/4.0), выбрать иконку и запретить открытие консольного окна Powershell при запуске…
В результате компиляции мы получим два файла – сам исполняемый *.exe файл и его вспомогательный конфигурационный файл *.config
Если компилируемый скрипт может принимать входящие параметры, то судя по заметке Дмитрия Сотникова, скомпилированный исполняемый файл можно использовать в режиме передачи аргументов, например:
Generated.exe -Arguments -MyParam2 "Value2" -MyParam1 "Value1"
Возможность конечно интересная, но сам я такой режим запуска не проверял. Неприятным моментом использования исполняемых файлов скомпилированных с помощью PowerGUI мне показался долгий запуск таких файлов. Поэтому было решено попробовать воспользоваться другим вариантом - скриптом PS2EXE
Если мы скачаем с Codeplex текущую версию скрипта v0.4.0.0 (03/09/2013), то при попытке использовать его с PowerShell 4, узнаем о том, что максимально поддерживаемая версия – 3. На свой страх и риск можем добавить поддержку PS4 внеся небольшую правку в ps2exe.ps1
Меняем фрагмент кода проверки версии…
$psversion = 0 if($PSVersionTable.PSVersion.Major - 3) { $psversion = 3 write-host "You are using PowerShell 3.0." }
на что-нибудь типа…
$psversion = 0 if($PSVersionTable.PSVersion.Major -ge 3) { $psversion = 3 write-host "You are using PowerShell 3.0. or newer" }
Попробуем выполнить компиляцию нашего исходного PS-скрипта (в консоли Powershell):
C:\Tools\PS2EXE-v0.4.0.0\ps2exe.ps1 -inputFile "C:\Tools\Scripts\TranslitRU2EN.ps1" -outputFile "C:\Tools\Scripts\TranslitRU2EN.exe" -sta -noconsole
Обратите внимание на то, что при компиляции используется ключ –sta (однопоточный режим - single thread apartment), так как в приведённом выше скрипте есть необходимость работы с буфером обмена Windows, а это имеет свои особенности. В результате такой компиляции также получается 2 файла (*.exe и *.config) и теперь наш скрипт полностью выглядит как самостоятельная утилита.
Позже был найден ещё один вариант компиляции с помощью скрипта Make-PS1ExeWrapper, но до его испытания руки не добрались, так как меня вполне устроил результат работы скрипта PS2EXE
Спасибо, Алексей за интересные и полезные примеры использования Powershell в качестве exe варианта.
Для трансляции использую в QIP комбинацию клавиш CTRL+T.
Пользуюсь PuntoSwitcher для транслитерации, а за PowerShellGUI спасибо)
Нечто подобное у меня делается vbs скриптом,очень удобно для создания учеток в домене.
Нашёл онлайн ресурс, на котором можно слепить форму с нужными контролами, для которой генерируется код:
http://www.poshgui.com
Всё что остается, добавить код логики работы контролов.
Что-то не так с Верхним регистром - в логине все маленькие буквы. пробовал добавить .ToUpper() - не помогло. подскажите как поправить
В каком ещё логине ? "Свистелка" вполне рабочая. Пользуюсь ей до сих пор :)
Огромное спасибо, написал скрипт резервного копирования в облако, но в нём были открытым текстом учётные данные - теперь они спрятаны от любопытных глаз. Защита от перехвата данных в данном конкретном случае не понадобится :)
А как можно сделать несколько вариантов транслитерации для символов ? Например символ "и", встречается сочетание "ьи" или "ъи" то переводится в "yi", в остальных случаях в "i". Голову себе ломаю сижу, а сообразить не получается.
"А как можно сделать "...переписать скрипт, расширив его логику.