Как стать автором
Обновить

Powershell настоящий язык программирования. Скрипт оптимизации рутины в техподдержке

Время на прочтение17 мин
Количество просмотров17K
Всего голосов 9: ↑8 и ↓1+9
Комментарии68

Комментарии 68

Powershell — настоящий язык программирования, и он обладает потрясающим свойством — стоит только хоть чуть-чуть задуматься о происхождении магических заклинаний с SO, как тебя в полный рост макают в .net. Вместо того, чтобы думать про админские задачи, обнаруживаешь себя в мире волшебных уродливых классов, интерфейсов и монстросити, которая на тебя смотрит со дна .net.


При том, что есть много админских инструментов, которые уводят в недра языка программирования (тот же питон), только .net с C# обладает настолько ярко выраженной ненавистью к красивому и простому.

Э-э-э, а что такого уродливого в классах .NET?

То же, что и в java.


class ReadFromFile
{
    static void Main()
    {
        string text = System.IO.File.ReadAllText(@"C:\Users\Public\TestFolder\WriteText.txt");
        System.Console.WriteLine("Contents of WriteText.txt = {0}", text);
        string[] lines = System.IO.File.ReadAllLines(@"C:\Users\Public\TestFolder\WriteLines2.txt");
        System.Console.WriteLine("Contents of WriteLines2.txt = ");
        foreach (string line in lines)
        {
            Console.WriteLine("\t" + line);
        }
        Console.WriteLine("Press any key to exit.");
        System.Console.ReadKey();
    }
}

(рандомный пример из интернетов).


Я считаю, что оно антигуманно. Сравните с эквивалентом на питоне:


with open("WriteText.txt") as f:
    print(f.read())

with open("WriteText2.txt") as f:
  for line in f.readlines():
     print(line)

Все вот эти class и static void могли быть придуманы только тем, кому насрать на людей, пишущих скрипты.

Так у вас не эквивалент, вот эквивалент на C#

WriteLine(File.ReadAllText("WriteText.txt"));

foreach (var line in File.ReadAllLines("WriteLines2.txt"))
  WriteLine(line);
Все вот эти class и static void могли быть придуманы только тем, кому насрать на людей, пишущих скрипты.
Ну так они и не обязательны. Можно писать без всего этого.

Конечно, можно без этого. Тем паче, что это C#. А сам powershell ещё более ужасающий.


  Begin {
    # If we fail, stop the pipe...
    $ErrorActionPreference = "Stop"
    # Look for the command in PATH
    $cmdinfo = $(Get-Command $cmd)
    if (!$cmdinfo -or !$cmdinfo.Path) {
      throw  [System.IO.FileNotFoundException] "Failed to find $cmd..";
    }
    $fullpath = $cmdinfo.Path
    # Use of System.Diagnostics.Process to launch the command and redirect its STDIN/STDOUT
    $ProcessInfo = New-Object System.Diagnostics.ProcessStartInfo 
    $ProcessInfo.FileName = $fullpath
    $ProcessInfo.RedirectStandardError = $False
    $ProcessInfo.RedirectStandardOutput = $True
    $ProcessInfo.RedirectStandardInput = $True
    $ProcessInfo.UseShellExecute = $False 
    $ProcessInfo.CreateNoWindow = $False;
    if ($cmdpar) {
      $ProcessInfo.Arguments = $cmdpar
    }
    $Process = New-Object System.Diagnostics.Process 
    $Process.StartInfo = $ProcessInfo 
    # Reference to the stream reader and writer for the command's STDOUT / STDIN processing
    $StdInStreamWriter = $null;
    $StdOutStreamReader = $null;
    # Sleep time for polling STDIN. To not slow too much the pipeline processing, 
    # we take 1ms. We have to avoid stressing the CPU with the polling.
    $SleepTime=1;
    # Control of input parameters if any
    if ($bufferedPipe -gt 8000) { $bufferedPipe = 8000; }
    if ($bufferedPipe -lt 0) { $bufferedPipe = 0; }
    # Launch the command 
    $ProcessStarted = $Process.Start()
    if ($ProcessStarted) {
      $StdInStreamWriter = $Process.StandardInput;
      $StdOutStreamReader = $Process.StandardOutput;
      $StdInStreamWriter.AutoFlush = $True;
    } else {
      throw  [System.Exception] "Failed to open $cmd..";
    }
    # We use two FIFO stacks to exchange STDIN and STDOUT stream data between
    # the PowerShell pipeline processing in the 'premise-style' context and the
    # process we have launched for the command. We will feed them in the
    # following two poll subprocesses for STDIN and STDOUT as no async operations
    # are allowed in a 'premise-style' context.
    $StdOutStack = new-object System.Collections.Queue;
    if (!$StdOutStack) {
      throw [System.Exception] "Can't get a stack..."
    }
    $StdInStack = new-object System.Collections.Queue;
    if (!$StdInStack) {
      throw [System.Exception] "Can't get a stack..."
    }
    # We create two poll subprocesses to read from STDOUT and write into STDIN 
    # of the process we have launched for the command. As theses subprocesses  
    # are started from the 'begin' pipeline part of the function, they can then 
    # makes STDOUT read that feed the STDOUT stack and STDIN write from the
    # STDIN stack. Theses operations are not directly doable into the 'process' 
    # pipeline part of the function as it is a 'premise-style' context.
    #
    # STDOUT poll subprocess
    #
    $OutProc = [powershell]::Create().AddScript({
      Param ([parameter(Mandatory=$True)]$args)
      $Process = $args[0]
      $StdOutStreamReader = $args[1]
      $SleepTime = $args[2]
      $cmd = $args[3]
      $StdOutStack = $args[4]
      $debugPipe = $args[5]
      while (!$StdOutStreamReader.EndOfStream) {
        $msgproc = $StdOutStreamReader.ReadLine()
        Write-Output ($cmd+": OUT_S: "+[String]$msgproc)
        try {
          $syncStdOutStack = [System.Collections.Queue]::Synchronized($StdOutStack);
          $syncStdOutStack.Enqueue($msgproc)
        } finally {
          $syncStdOutStack = $null
        }
      }
      if ($debugPipe) { Write-Output ($cmd+": OUT_S terminated.") }
    })
    $tmp = $OutProc.AddParameter("args", @($Process, $StdOutStreamReader, $SleepTime, $cmd, $StdOutStack, $debugPipe))
    $OutJob = $OutProc.BeginInvoke()
    #
    # STDIN poll subprocess
    #
    $InProc = [powershell]::Create().AddScript({
      Param ([parameter(Mandatory=$True)]$args)
      $Process = $args[0]
      $StdInStreamWriter = $args[1]
      $SleepTime = $args[2]
      $cmd = $args[3]
      $StdInStack = $args[4]
      $debugPipe = $args[5]
      $bufferedPipe = $args[6]
   ...

Из рандомного SO ответа про работу с pipe'ом.


Я по своему опыту знаю, то если какой-то инструмент имеет вырвиглазный синтаксис с самого начала, то и вся остальная работа с ним такая же — через ненависть и боль.

Ну что вам на это сказать? Я не знаю, почему ответ был написан так сложно. Может, автор решал какую-то специфичную задачу, требующую указать нестандартные параметры, передаваемые в CreateProcess. Или — чтобы скрипт можно было запустить внутри другого конвейера(pipe) — вложенные конвейеры в Powershell не поддерживаются. А может, он просто не знал как следует Powershell, потому что Powershell не был его основным рабочим языком.
Потому что в Powershell для того, чтобы просто запустить внешнюю команду (исполняемый файл) и перенаправить его стандартный вывод в конвейер (pipe) не нужно делать вообще ничего: достаточно просто набрать имя файла и нажать Enter.
Конвейер в Powershell отличается тем, что по нему передаются не байты, а объекты. Но вывод внешней команды автоматически преобразуется в последовательность объектов Powershell типа String (реализован как тип System.String в .NET). Можно эту последовательность присвоить переменной Powershell: она будет преобразована в массив String, можно — передать на вход другой команды Powershell — например вот эта связка команд отсортирует вывод внешней команды netstat (это — чисто для примера, практического смысла это не имеет):
netstat -n -p TCP | Sort-Object

Можно для дальнейшей обработки сделать разбор строк и преобразовать их в объекты. Например, эта связка команд преобразует все строки выдачи, показывающие соединение, в объект со свойствами LocalIP, LocalPort, RemoteIP, RemotePort, State (и отбросит все строки, не являющиеся соединениями):
netstat -n -p TCP `
 | ?{$_ -match '^\s+(.+?)\s+(.+?):(.+?)\s+(.+?):(.+?)\s+([^\s]+?)\s*$'}`
 | %{New-Object PSObject -Property @{LocalIP=$matches[2];LocalPort=`
 $matches[3]; RemoteIP=$matches[4];RemotePort=$matches[5];State=$matches[6]}}

(пояснение:? — это псевдоним команды Where-Object, % — Foreach-Object, мне так писать сподручнее, но незнающего это может сбить с толку).
Да, регулярка выглядит весьма не наглядно (и мне пришлось потратить минут 15 на ее написание и отладку), но после разбора вывода с ее помощью мы получаем объекты, с которыми дальше работать может быть сильно проще, чем с сырыми строками.
Результат этой последовательности можно присвоить переменной (получится массив объектов) или передать дальше по конвейеру для дальнейшей обработки, в том числе — способом, не слишком просто достижимым стандартными командами обработки строк (например, отбросить все объекты локальных соединений, у которых LocalIP=RemoteIP).
Спасибо, приму на вооружение
вот что меня восхищает в PowerShell, так это обмен не потоком как в архаичных системах, а объектами со всеми их свойствами. Можно и свои свойства и свои объекты динамически заводить.
Может реализация не самая удачная, да и выглядит как обертка над .net, но тем не менее это гигантский шаг вперед со времен дос и юникс
Даже если это и выглядит как плюс это скорее минус. В обычных архаичных системах вам ничто не мешает кидаться json-ом (например). При этом вы на любом этапе можете вклиниться в поток данных сохранить его в файл, или прочитать из файла, или преобразовать, при этом работая с одним потоком данных. Даже можете его посети послать или через UART. А тут куча дополнительных сущностный, причем весьма не тривиальных, которые еще могут и эволюционировать. Но главное это убогий синтаксис, тот же perl, gradle и даже pyton на порядки приятнее. Да лучше php написать чем на ps и работать будет на большем количестве платформ.
Так ведь вам ничто не мешает в современном PS полученный откуда-то JSON прогнать через ConvertFrom-Json и получить на выходе объект соответствующей структуры. Или, наоборот — сконвертировать объект в JSON с помощью ConvertTo-Json (или в один из множества других форматов с помощью команд с глаголом ConvertTo) либо просто перегнать объекты в поток символов банальным вызовом метода ToString().
А насчет ситаксиса… Я вот, к примеру, очень мало знаю perl, и скрипты на нем обычно выглядят для меня «перловой кашей», но я понимаю, что это не дает мне никаких оснований объявлять perl плохим, негодным языком — просто этим инструментом я не владею. Почему в случае с PS не происходит то же самое?
Недостаток «архаичных систем» по сравнению с PS, что в них заметно сложнее манипулировать проходящим по конвейеру потоком символов в случае, если этот поток имеет нетривиальную структуру: ему надо устраивать грамматический разбор перед применением, чтобы структурировать. А по конвейеру PS уже идет структурированный поток объектов, имеющих свойства, к которым можно легко и просто обратиться по их имени, чтобы использовать для фильтрации или обработки.
А эквивалент на Poweshell — он еще проще:
$File = 'имя.файла
Get-Content $File -ReadCount 0
Get-Content $File

Первая команда читает файл целиком в одну строку и кладет ее в конвейер (можно это проверить, передав ее результат в Measure-Object: свойство Count результата будет равно 1), вторая — построчно (в конвейер передаются по одной строки, содержащиеся в файле, проверить можно опять-таки с помощью Measure-Count).
Ну а выдача содержимого конвейера на экран после выполнения команды — это действие Powershell по умолчанию.

Ну давайте меряться.


cat "filename"

Ну, давайте :-):
cat "filename"

У Get-Content есть и такой псевдоним. И псевдоним type (родом из MS DOS) — тоже еcть.
PS С Get-ChildItem/ls/dir ситуация аналогичная.

Ага. Только пользы от него никакой, потому что ни /proc, ни /sys, ни /dev.

Ну, если посмотреть, что показывает Get-PSDrive, то в PS много разных «дисков» в пространстве имен есть, помимо файловой системы: HKLM+HKCU (это реестр), Env, WSMan. А еcли дополнительные компоненты ОС поставить да модули подключить, то может и кое-что дополнительное появиться. Например — AD: (т. е. — каталог Active Directory, DS или LDS). Или «диск» с конфигурацией службы Information Rights Management (это — одно из основных средств задания этой самой конфигурации).
А вообще-то, для полного доступа к конфигурации локальной системы в Windows gwmi (т.е. Get-WmiObject) есть. И Set-WMIInstance.

PS Да, методы администрирования Windows и Linux — они таки отличаются.
PPS На этом соревнование предлагаю считать законченным и, если хотите — признать вас победителем: я на приз в любой дисциплине соревнований типа Windows vs Linux традиционно не претендую. Но, надеюсь, я вас убедил, что Powerhell — он не такой страшный как вам казалось раньше?

Он не страшный. Он уродливый. Я этот поинт с самого начала вёл. Есть языки, которые пишутся с представлением о красоте, а есть языки, в которых "как-то получилось и сойдёт".

«Красота — в глазах смотрящего»((с), AFAIK — перевод с английского фразы О.Уайлда(но это неточно)).
То есть понятие красоты — оно сугубо субъективно.
На этом обсуждение Powershell с вами предлагаю закончить.
Надеюсь, вам никогда не придется администрировать MS Exchange: там Powershell без альтернатив.

Не придётся. Я покинул экосистему windows из-за этой "красоты", в том числе.

Ну я бы отметил, что java и c# и не были изначально скриптовыми языками, чем является python изначально. Да, по моим ощущениям они конечно пытаются и в скриптовые языки войти в последнее время многими упрощениями, но это все равно не то.

Это как сравнивать теплое с мягким, натягивать сову на глобус, ну и другие аналогии придумайте. Очень странно предъявы кидать языкам, которые и не были именно для этого предназначены

Я кидаю предъявы не языку, а человеку, который пытается эту монстросити притащить в администрирование и считает, что так и надо.


ровно так же мы можем обсуждать код для автоматического провиза виртуалок в CI, написанный на boost'е в C++. Неподобающий инструмент, провоцирующий невыносимые условия работы.

А чем Powershell монструозен? Да, считаю, что все, что упрощает мне жизнь в администрировании, имеет право на жизнь. Никого пользоваться не заставляю

Я ж показал чем. Ужасный синтаксис, постоянные отсылки объектную модель .net.

Принял. Но какая альтернатива скриптового администрирования Windows?
Как, например, скриптом создать подключение к VPN не через Powershell?
А от .NET тут только Win.forms, который лишь объединяет несколько скриптов в один с выбором действий через «окошко».

Я последний раз видел винды всерьёз в 2008. В принципе, тот кусок, который мне надо было автоматизировать, мы сделали на winrm, но он оставил примерно такое же ощущение брезгливости и уныния.


Я не знаю ответа "как хорошо и красиво администрировать Windows", и это было одним из ключевых моих мотивов для перехода на Linux. Тогда Ансибла ещё не было. Наверное, сейчас я бы попытался использовать Ансибл.

Если использовать Powershell исключительно как средство доступа к сборкам .NET, то так оно и будет.
Иногда это неизбежно: например, для одновременного доступа к содержимому п/я и к средствам администрирования Exchange нет другого выхода, кроме как использовать Powershell (доступ к администрированию Exchаnge, альтернатив тут нет) и EWS Manged API из .NET (в средствах администрирования Exhange крайне ограничены возможности доступа к содержимому п/я).
Но чаще всего альтернатива есть.

данные для подключению к клиентам с логинами\паролями в облаке гугл? Окей, думаю они в восторге были-бы, если-б узнали.

PS: вообще удивляет, что люди осуществляющую L3 поддержку, не в состоянии автоматизировать свой труд. На данном уровне, руководитель должен решать только административные вопросы.

У нас в конторе даже специально написано каким приложением пользоватся для обмена паролями.

Блин ну не делайте так. Случайно нажмете на не ту ссылку и ваша таблица будет видна всему интернету
А вы не боитесь, что у вас доступы утекут? Начиная с банальной недоработки со стороны Гугла, заканчивая утечкой самой ссылки? Декомпилировать .Net приложение и посмотреть откуда тянутся данные не составит труда, не говоря уже о распространении скрипта в чистом виде
Спасибо, поправил статью, указав, что GD выбран для примера.
Скрипт, естественно, не стоит распространять за пределы собственного использования с оставлением в нем частных данных.
Он предназначен для персонального использования.
С тем же успехом, можно просто передать все имена/пароли/приватные ключи.
Рабочие данные храню не в гугле, а в собственном облаке, но если описывать еще и его, одной статьи не хватит. Впрочем, спасибо за идею, следующая статья будет о быстром разворачивании Nextcloud с ONLYOFFICE
Никто не мешает хранить не в google, а локально, или на своих закрытых ресурсах. Всего-то чутка поправить скрипт.
Данная статья не предназначена для использования as is, а преследует цель показать некоторые приемы работы в powershell
Каждый волен использовать приведенный здесь текст по своему усмотрению.
Вы IMHO зря не написали об этом в статье — что Google Docs в качестве хранилища тут чисто для примера, что из соображений безопасности секретные данные, вроде логинов и паролей, там лучше бы не хранить, ибо можно нарваться.

Писать такое надо, причем — в начале статьи — ибо редкий гуглящий читает нагугленное до конца. У меня был пример — статья в личном блоге про создание кластера DNS в MS Windows.
Статья — наполовину шуточная: отказоустойчивость в системе DNS отлично обеспечивается другими средствами. И шуточная она именно наполовину, ибо вообще-то иллюстрирует, как можно добавить в кластер MS FT произвольный сервис, вместе с его конфигурацией в файловой системе и в реестре (собственно, для этого она и была написана). А сервис DNS был выбран в качестве примера только потому, что немногим ранее на мой любимый админский форум приперся некий оригинал (то ли неадекват, то ли, типа, тонкий тролль), который требовал, просил и умолял, чтобы его научили созданию кластера DNS — притом, что ему сразу объяснили, как надо делать DNS отказоустойчивым штатными методами.
Так вот, несмотря на примечание в конце статьи о шуточном характере выбранного примера, я регулярно наблюдал попытки использовать эту статью в качестве руководства по развертыванию DNS в кластере — пока, наконец, не написал предупреждение крупными буквами в самом начале статьи.

Спасибо, внес правки в статью.

Скриншот работающего приложения с затертыми данными:
Все бы ничего, но если вы тестовый гуглодок предоставляете, то и скриншот можно было бы с него сделать. И выглядело бы прилично. А то показывать скриншоты, с затертыми ластиком данными, это прям неуважение к читателям в наше время. Смотрится очень очень плохо.

Да и код под спойлер спрятать неплохо, было бы :)

Это моя первая статья, возможно, что-то не красиво оформил.

Но, расшифруйте, пожалуйста, причём тут текстовый гуглодок?

Скриншоты работы рабочего скрипта, как-то неправильно было бы светить выводимые там данные

Тестовый гуглодок.
Заполнить его, и на его основе сделать скриншот для статьи. Будет просто и наглядно.

Ластик и фильтры в скриншотах делаются в тех редких случаях, когда нужно скрыть логины/пароли/токены/ипы в скриншотах, которые сделаны обычно в рамках траблшутинга/исследования. Делать это нужно очень точечно и что бы было явно видно, что замазано. Иначе получится как у Вас, вроде и интерфейс программы, но на выходе какая не понятная хрень в которой непонятно как отображаются данные, потому что широкими мазками ластиком белому по белому орудовали.

upd.
Увидел исправленный скриншот, спасибо! Теперь сильно нагляднее :)
ОК, сделал
Хрень какая-то, есть же VBScript и редактор для админов www.vbsedit.com с готовыми шаблонами рутинных действий. Там же были и графические приложения hta.

ps: И работает оно даже на xp.
Вы давно в WSH обычный исполняемый файл запускали и его вывод в скрипт возвращали?
ЕМНИП во врмена XP это было нетривиальной задачей, примерно такой же по сложности, как код с SO от amarao выше.
А что есть какие-то проблемы?
Вот скрипт времён xp
Function TestSpeed(ip)
	Set sh=WScript.CreateObject("WScript.Shell")
	Set res=sh.Exec("iperf -c " & ip & " -P 5")
	out=res.StdOut.ReadAll
	Set re=New RegExp
	re.Pattern="\[SUM\].*\s([0-9\.]+) Mbits/sec"
	re.Global=True
	Set m = re.Execute(out)
	If m.Count>0 Then
		TestSpeed=eval(m(0).Submatches(0))
	Else
		TestSpeed=-1
		MsgBox res.StdErr.ReadAll,48,"Error " & ip
	End If
End Function

ip=InputBox("Specify iperf server address ip or hostname", _
	"Enter server address", _
	"192.168.1.2")
if ip<>"" then
	speed=TestSpeed(ip)
	if speed>=0 then
		MsgBox "Speed = " & speed & " MBits/s",0,"Testing " & ip
	end if 
end if

Помню, что были. Потому что самому приходилось их обходить. Но, возможно, это было в Win2K, в изначальной инкарнации WSH и его объектов. Честно говоря, когда появилось свойство, автоматически отслеживающее StdOut, я не помню, а смотреть сейчас — слишком трудоемко. Мне проще признать вашу правоту в данном вопросе.

Совсем не по теме. Vbscript ну совсем другое.

Как в нем создать и управлять vpn-соединениями? Как передавать параметры в winbox, например?

Не читал, но осуждаю?

Как в нем создать и управлять vpn-соединениями?

rasdial?

Не знаю как в winbox, но в линухе есть expect и там на чистом tcl-е можно общаться с сетевым оборудованием типа цисок вполне комфортно.
Какая разница? Точно так же как в ps можно дергать куски .net, которые дергают WinApi, в vbscript можно было дергать WinApi напрямую. Иногда так даже надежнее. Но согласен, с предыдущими коментариями. PowerShell как морская свинка — ни к свиньям не относится, ни к морю. Для shell переусложнен, для ЯП слишком примитивен, те же python/perl/lua позволяют создавать более продвинутые приложения.
Да что там сложного то?
Довольно красиво.
Например, удалить все снапшоты виртуальных машин старше 5 дней и создать ежедневный снапшот можно всего двумя строчками, причем очень понятными

Get-VMSnapshot -VMName *| Where-Object {$_.CreationTime -lt (Get-Date).AddDays(-5) } | Remove-VMSnapshot

Get-VM * | Checkpoint-VM -SnapshotName "Daily Snapshot $((Get-Date).toshortdatestring())"
Ничего, что вы привели пример специфичного приложения для которого производитель написал командлеты облегчающие работу? С таким же успехомможно написать на C# небольшое приложение приложение удаляющее снапшоты, вызвать его из vbs или cmd и сказать смотрите как просто и коротко.
Опять ничего не понял, причем тут c#? Да, теперь для всего в Windows 10/Server есть командлеты. И этим Powershell очень удобен. Зачем что-то писать на C# и вызывать в cmd, если это уже реализовано и документировано?
Сдается мне, что мы на разных языках говорим
Затем что с shell, прочитав справку, разберется даже не подготовленный человек. А приведенный вами пример, для меня не работающего с ps выглядит не намного понятнее однострочника на perl или python. Т. е. для начала придется прочитать мануалы по Get-VMSnapshot, Get-Date, Remove-VMSnapshot,Checkpoint-VM. Потому и говорю, для shell слишком сложный. Vbscript никто shell не называл, хотя он на порядок проще.
По мне так нет ничего проще набрать
Get-Help Get-Date -online

Или
Get-Help Get-Date -full |more

Раз это это для вас сложно, имеет смысл прекратить никуда не ведущую дискуссию
Не говоря уже о переносимости. Что это за shell код для которого сильно зависит от версии? В приведенном вами примере Get-Date -AsUTC есть в current, но нет в LTS. Get-VMSnapshot так и совсем должен быть установлен и разные в разных версиях windows содержит разный набор параметров. Потому и говорю еще раз. PowerShell не shell, а полноценный скриптовый ЯП со специфичным синтаксисом похожим на shell. Но в этом качестве он уступает многим ЯП например в управлении потоками. Не говоря уже о том, что ни один shell не съедает 61 МБ памяти после пары вызовов Get-Help.
Точно так же как в ps можно дергать куски .net, которые дергают WinApi, в vbscript можно было дергать WinApi напрямую.

Утверждение неверное.
Напрямую скриптовые языки, реализованные на базе ActiveScript — кроме vbscript в стандартной поставке был еще JS(и я предпочитал именно его, ибо с юности не любил Basic), а третьи фирмы реализовали и другие языки, из коих мне помнятся Perl и REXX — умели работать только с COM Automation, т.е. объектами классов COM, реализующими интерфейс IDispatch. Для доступа к дргим классам COM из скриптов требовались обертки: например, из скриптов нельзя было напрямую работать с такими базирующимися на COM API, как OLE DB или MAPI, нужны были дополнительные прослойки (ADO и CDO, соответственно). Что касается .NET, то из скриптов ActiveScript доступны компоненты, которые написаны специально для взаимодействия с COM Automation (подробности я с вашего позволения опущу).
С Win32 API была ровно та же ситуация: для обращения к ним требовались обертки, реализующие IDispatch с методами, отображающимися, на функции Win32 API — как, например, здесь (обертка там сделана на VB)

В Powershell с этим сильно легче: из него доступны объекты очень многих (за «всех» не скажу) классов .NET, а также — все «родные»(Native) API, доступные через Interop: в частости — и объекты COM Automation, и функции Win32 API.

Другое дело, что Powershell как инструмент для создания приложений, в общем-то, не предназначен, он заточен для использования в другой сфере — адмистрировании (в том числе — автоматизации администрирования). Не скажу, что он для этого идеален (например, команды можно было бы сделать и покороче — впрочем, это вполне лечится псевдонимами), но — весьма удобен (лично мне, по крайней мере): это я вам как практик, довольно долго работавший с администрированием AD и MS Exchange говорю, со скриптами на базе ActiveScript (с использованием ADSI и CDOEXM, чем приходилось пользоваться до PS) — не сравнить.
Весьма познавательно. Спасибо

Это подключиться, а как создать? И как прописать для конкретного соединения маршруты?

В скриншоте имя клиента справа вверху Вы, видимо, забыли затереть? А в интернете ищется на раз.
P.S. Сам недавно на PowerShell сделал проверку на вирусы передаваемых файлов и передачу отчета во внешнюю программу. Очень неплохо получилось!
В Вашем случае — отличное решение. Что называется, дешево и сердито! Экономия телодвижений сотрудников при минимальных затратах выливается в существенный прирост эффективности предприятия в целом. ))

Попробуйте переписать GUI на WPF используя XAML, у вас будет два файла — один с кодом, второй с разметкой. На мой взгляд разметка XAML удобнее
<Button Name="ExitButton" Content="Выход" Click="ExitButton_OnClick" TabIndex="15"/>
 

чем WinForm
$buttonВыход.Location = '7, 125'
$buttonВыход.Name = 'buttonВыход'
$buttonВыход.Size = '133, 23'
$buttonВыход.TabIndex = 15
$buttonВыход.Text = 'Выход'
$buttonВыход.UseCompatibleTextRendering = $True
$buttonВыход.UseVisualStyleBackColor = $True
$buttonВыход.add_Click($buttonВыход_Click)

В качестве плюса вы получите относительное позиционирование элементов при разном размере окна и разрешений экрана.
Спасибо. Попробую
В качестве плюса вы получите относительное позиционирование элементов при разном размере окна и разрешений экрана.

Это и на вин-формах без проблем делается...

Плюс WPF гораздо гибче в плане дизайна, насколько я понимаю. Попробовал и то, и другое, остановился на WPF для GUI скриптов на PowerShell.

Я тоже пробовал прикручивать к PS интерфейс, но не нашел простого решения проблемы фриза формы при длительных вычислительных и сетевых операциях, пришлось переписать пару утилит на C# с async/await.
Все-таки, PS, не совсем для этого. Он больше скритовой язык.
Всё таки microsoft уже столько технологий для одного и того же выкатила и не одну довести до нормального состояния не может, постоянно что-то новое рожает.
Этот чудо скриптовый язык из той же оперы.
Не согласен. Я с PS по роду работы имел дела много и именно в области его применимости. И, в целом, вполне этим иснтрументом доволен. Надо только правильно понимать только эту самую область применимости: интерактивные ad hoc мини-программы и небольшие по объему скрипты. В этой области PS по сравнению с JS(в ActiveScript, в частности WSH)+COM Automation (это набор иснтрументов, закрывавший у MS примерно тот же круг задач до PS) — небо и земля по удобству использования.
А вот писать сколь-нибудь сложные программы — с этим на PS сложнее.

PS Прикручивать к PS формы я не пробовал (хотя в WinForms на C# вполне умею).
Во времена господства ActiveScript в администрировании Windows я для таких надобностей (была, к примеру, задача — дать девочкам-операторам простой интерфейс для заполнения нужных атрибутов пользователей в AD, чтобы они в адресной книге видны были, на то время, пока программисты интеграцию с кадровой БД не прикрутят) использовал Delphi: из нее объекты COM Automation тоже вызывались легко и непринужденно, а с тех пор подобных задач мне не встречалось.
PPS Сравнивать администрирование Windows с помощью PS и Unix/Linux с помощью shell и стандартного набора команд не берусь (у меня очень мало опыта второго: несколько лет поддержки пары серверов, настроенных, к тому же, другими людьми — это дает слишком мало матриала для сравнения).
В настоящее время PowerShell, на мой взгляд, закрывает процентов 90 задач администрирования в экосистеме MS. Кроме того, многие другие вендоры выпускают свои модули для PS: VMware, Citrix, Amazon и др. У MS далеко не все продукты получаются удачными, но PS вышел таким, если его рассматривать как инструмент администрирования и автоматизации, для чего он и предназначен.
да, там приходится либо форму в параллельный поток выносить, либо таски. И то и другой вариант неудобны. Тоже самое, только еще неудобнее если грузить XAML (WPF) вместо WinForms. Я попробовал все эти варианты.

Remote desktop manager. Умеет работать с облаками разными, можно натравить кучу пользователей на один файл скажем на сетевой шаре. Ну и кроме рдп много что умеет. В том числе умеет всякие vpn сам поднимать, вроде даже маршруты настраивать. В контексте пары пользователей вполне и freeшной версией пользоваться.

А это как по мне для 3 линии тп... Ну тока чтобы до завтра не умереть...

Хорошая программа. Не спорю.
Задача статьи была показать некие приемы работы в PS, и показать что PS не cmd, умеет не только dir c::)

Да нет, задача у вас стояла другая:
Работая в компании IT-аутсорса в качестве руководителя 3 линии поддержки, задумался, как автоматизировать подключение сотрудников по RDP, через VPN к серверам десятков клиентов.

Я не спорю, PS — крут (может знаете как через PS заполнить Имя запускаемой программы и рабочий каталог для пользователя в терминале (управление — пользователи — среда)). Но решать им подобные задачи, когда есть ворох готового… Хуже наверное только те кто в 2021 году делают java приложения для решения задач на всю страну (((
PS. Без обид. У меня ни каких претензий, я просто высказываю свое мнение.

Какие обиды :)
Задача статьи, я имел ввиду.
А рабочая задача - упростить себе работу.
Remote desktop manager, конечно крут, но слишком тяжел и дорог.
К тому же, у нас штат 1Сников, админов 1 и 3 линий и прочих, кому надо быстро подключиться к RDP через VPN или к Mikrotik клиента.
Плюс, вывод самой необходимой информации о клиенте в окошко (серверы, подсети, вебморды etc).
Вот и написал небольшой мультитул, практически не имея опыта в программировании, на основании таких же статей по PS, а уже потом решил поделиться с сообществом, поскольку мне PS для решения таких задач понравился.
Но в реалии, буду уходить от VPN в сторону SSH-туннелей для админских подключений.

НЛО прилетело и опубликовало эту надпись здесь
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации