Как же все-таки пользоваться PowerShell?

    Навеяно q&a: Как воспроизвести mp3 из командной строки в Windows 7?

    Немного шокирован предлагаемыми ответами, которые сводятся к 'скачать и установить дополнительное ПО'… и так в системе уже под 20Гб какого то говна чего то полезного, которое зовется операционной системой… извиняюсь, вырвалось.

    Когда то в Windows XP использовал для этой задачи простейшую утилиту mplay, хоть и GUI но планировщиком задач нормально запускается, но в Windows 7 удалили его и даже sndrec32. Запускать монстроуозный wmplayer считаю глупостью, поэтому приходится обращаться к скриптовым языкам.

    Примеры однострочных скриптов на vbs для windows scripting host можно нарыть в интернете, вот простейший пример:
    Set oVoice = CreateObject("SAPI.SpVoice")
    set oSpFileStream = CreateObject("SAPI.SpFileStream")
    oSpFileStream.Open "c:\Windows\Media\tada.wav"
    oVoice.SpeakStream oSpFileStream
    oSpFileStream.Close

    Кстати, это чудо, что код заработал на windows 7, так как по сравнению с windows xp ряд activex объектов исчезло (типа WMPlayerClass) и никто не знает, когда исчезнет или как изменится класс SAPI, да и не дело это, микроскопом гвозди забивать. Поэтому это решение считаю неправильным и не логичным, да и отмирает ActiveX потихоньку, вполне логично убиваемый .NET окружением.

    Попробовал решить задачу новомодным PowerShell (не умею готовить, но специально порылся в документации), у меня волосы дыбом встали от того, как там сочетаются замечательные идеи с ужасной реализацией. Например нет нормальной возможности запустить скрипт из командной строки не создав и не подписав файл (я все понимаю, безопасность превыше всего, как результат вопросы, стоит ли этим пользоваться).

    Вот простейший код:
    $s=new-Object System.Media.SoundPlayer;$s.SoundLocation='C:\Windows\Media\tada.wav';$s.Play();
    Прекрасно работает внутри powershell, если его вставить и выполнить вручную!

    Но вот таким образом:
    powershell -Command $s=new-Object System.Media.SoundPlayer;$s.SoundLocation='C:\Windows\Media\tada.wav';$s.Play();
    Ничего не происходит, потому как каждая команда выполняется в своем контексте (т.е. на каждом шаге $s не определено).

    Попробовал воспользоваться перенаправлением:
    echo $s=new-Object System.Media.SoundPlayer;$s.SoundLocation='C:\Windows\Media\tada.wav';$s.Play(); | powershell -command -
    И был шокирован результатом — был запущен зарегистрированный плеер по умолчанию на wav файл (у меня это оказался winamp). С какой стати?

    А без использования -command -:
    echo $s=new-Object System.Media.SoundPlayer;$s.SoundLocation='C:\Windows\Media\tada.wav';$s.Play(); | powershell
    Происходит простой запуск PowerShell с ожиданием ввода команд.

    Ладно, сдаюсь, пробуем разрешить не подписанные скрипты (запускаем под привилегированным шелом):
    powershell Set-ExecutionPolicy Unrestricted
    Создаем и запускаем файл с вышепредложенным кодом (поместив его в c:\a.ps1):
    powershell c:\a.ps1
    И ничего не получаем! Тишина, и никаких сообщений об ошибке (при не разрешенным запуске не подписанных скриптов получаю соответствующее сообщение).

    Не поможет ли уважаемое хабрасообщество решить эту задачу простым и рассово верным способом? Как я понимаю, последний тест показал, что эпопею с сертификатами не стоит и начинать, так как проблема где то в другом месте.

    UPD от TheBits и Paul: Слона то я и не приметил, скрипт завершает работу не доиграв, а запуск кода из командной строки можно организовать с помощью групировки и символа &:
    powershell -Command "& {$s=new-Object System.Media.SoundPlayer; $s.SoundLocation='C:/Windows/Media/tada.wav'; $s.Play(); Sleep -Seconds 9}"


    UPD2 На основе еще ряда комментариев: Окончательное решение, само собой может быть таким, с учетом автоматического определения длительности файла и исключением переменной $s:
    powershell -Command (new-object Media.SoundPlayer "C:\Windows\Media\notify.wav").playsync();
    Но самое главное, так и не решает первоначальную задачу — System.Media.SoundPlayer не умеет играть mp3 файлы, т.е. нужно что то посложнее ваять, но я и не задумывался целью этого поста ставить решение оригинальной задачи.

    Similar posts

    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 32

      +1
      Запускать надо командой powershell -executionpolicy unrestricted -file a.ps1.
      Самой последней командой поставьте Sleep -Seconds 9, сейчас у Вас скрипт выключается и не успевает воспроизвести файл.
        0
        Видимо загвоздка у автора именно в Sleep, у меня без всяких -executionpolicy вот такой однострочник сработал:
        powershell -Command "& {$s=new-Object System.Media.SoundPlayer; $s.SoundLocation='C:/Windows/Media/tada.wav'; $s.Play(); Sleep -Seconds 9}"

        Аккаунт с привилегиями обычного пользователя, не администратор.
          0
          У меня без -executionpolicy не работает, говорит что не подписан скрипт. У Вас наверное тоже глобальная настройка безопасности изменена на лояльный уровень? Хотя я наверное пользователь-администратор, так как один в системе.
            0
            PS C:\Users\Paul> Get-ExecutionPolicy
            Restricted
              0
              Возможно у -file и -command разные требования к executionpolicy.
            0
            Феерично. Чтобы для проигрывания файла нужно было сначала определить его длительность, а потом дать слип этой длительности — это полный… Извините меня. Неужели никто из разработчиков не подумал о создании хоть какого-то синхронного интерфейса или на крайний случай метода isPlaying(), который можно было бы опрашивать в цикле?
              0
              powershell -Command "& {$s=new-Object System.Media.SoundPlayer; $s.SoundLocation='C:/Windows/Media/tada.wav'; $s.PlaySync()}"
                0
                Вот это другое дело. Спасибо за просвещение и приношу свои извниения разработчикам :)
                  0
                  P.S. Может быть это заодно и к посту прикрепить?
              0
              Дополню ответ. Ключем -executionpolicy устанавливается политика безопасности на один этот запуск. Глобальные настройки безопасности лучше не менять, так что верните обратно: Set-ExecutionPolicy Restricted. :)
                +1
                Если пользоваться Powershell повседневно то лучше всего установить ExecutionPolicy в RemoteSigned, тогда дома можно будет запускать любые скрипты, а на скачаные будет ругаться.
                +1
                Зачем sleep, если есть PlaySync
                К тому же SoundPlayer задачу не решает, так как не умеет проигрывать mp3, а вот WMPlayer.OCX умеет, к тому же его можно использовать не только из PS, но и из WSH (ну или если очень захочется — из C++ и пр..)
                  0
                  Спасибо за подсказку, PlaySync будет даже лучше. Я не посмотрел в документацию, но подозревал что такой метод есть.
                  Интересно, WMPlayer.OCX есть в поставке c Windows E (Европейская без WMP)?
                0
                Только зачем так сложно с явным созданием промежуточного объекта?

                Вот так мне кажется и читается проще и писать меньше

                powershell -Command (new-object Media.SoundPlayer "C:\Windows\Media\notify.wav").play(); Sleep -Second 1;
                  +3
                  >Попробовал решить задачу новомодным PowerShell

                  Как-то язык не поворачивается назвать PS «новомодным», это уже зарекомендовавшее себя средство, навороченное и отлаженное, и как следствие применяющееся повсеместно.
                    0
                    а вот я про него только сегодня узнал
                    +1
                    И вообще если мы просто системный звук хотим проиграть то вот так будет наиболее кошерно

                    powershell -Command ([System.Media.SystemSounds]::Beep).Play();
                      0
                      Поправка, еще проще
                      powershell ([System.Media.SystemSounds]::Beep).Play();
                      –4
                      >в системе уже под 20Гб какого то говна чего то полезного, которое зовется операционной системой…
                      +стопятьсот!

                      И хотя то что cmd перерастает в PowerShell это радует, но тем не менее мир командной строки надо оставить всевозможным Shell'ам *nix'ов…
                        0
                        Кому надо?
                        +1
                        RUNDLL32 amovie.ocx,RunDll /play /close \path\to\wave\file.wav

                        насколько я помню, то в XP это работало без PowerShell и прочего. Сейчас проверить не могу, т.к. уже давно не пользовался Windows. Вообще rundll имеет кучу всяких плюшек.
                          0
                          это всякие dll и прочие ocx имеют кучу плюшек, а rundll лишь умеет их вызывать.
                          0
                          Так mp3-то играет или нет? Или только никому не нужный wav играет?
                            +2
                            Увы, нет.
                            Исключение при вызове «Play» с «0» аргументами: «Файл в папке *** не является волновым файлом.»
                              0
                              А зачем вам mp3? Да еще и из консоли? Если уж очень нужно, то запускайте комбайн WMPlayer, а то консольный интерфейс им подавай! Не напасешься на таких как вы…
                                0
                                «Не напасешься на таких как вы» — на каких?
                                  +1
                                  На которых консольную версию требуют :)

                                  P.S. Я забыл тег irony.
                              +1
                              нет, для этого можно поставить mpg123 :)
                              0
                              denis_q
                                0
                                Вы заголовок этого топика прочитали? «Навеяно q&a: Как воспроизвести mp3 из командной строки в Windows 7?»
                                  0
                                  (new-object Media.SoundPlayer "C:\WINDOWS\Media\notify.wav").play();

                                  На первой же строке в поисковике.

                                  Only users with full accounts can post comments. Log in, please.