Сценарий к статье Павла Чубарова автоматизирующий удаление устаревших драйверов из папки C:\windows\system32\DriverStore\FileRepository.

При установке драйверов старые версии сохраняются в системе, данный скрипт удаляет все дубликаты кроме драйвера имеющего самую последнюю дату

Может кому пригодится.

Сценарий получает список драйверов в системе выполняя команду:

dism /online /get-drivers

Затем идет парсинг текстового вывода, на выходе получаются нормальные объекты с которыми можно работать.

После выбираются дубликаты и сортируются по дате. Самый последний драйвер из списка исключается

Для каждого файла в списке вызывается консольная утилита pnputil с параметром удаления драйвера, если какойто драйвер не удалится добавьте еще ключ -f.

для того чтобы создать контрольную точку на всякий случай выполните в консоли повершелла из под админа команду Checkpoint-Computer -Description «Driversdelete». Чтобы проверить создалась ли точка восстановления выполните командлет Get-ComputerRestorePoint
код скрипта тут
Содержимое спойлера

<#
    2016.09.01
    перечисляет драйвера в системе
    находит дубликаты в хранилище и удаляет их
    если вам нужно только посмотреть драйвера закомментируйте 135 строку
    если драйвер нужно удалить принудительно используйте pnputil.exe -f -d
#>

#[Console]::OutputEncoding = [System.Text.Encoding]::GetEncoding("cp866")

#расскомментируйте если вам нужно создать точку восстановления
#Checkpoint-Computer -Description "Driversdelete"

# получаем список драйверов
$temp = dism /online /get-drivers
$Lines = $temp | select -Skip 10

$Operation = "ItIsName"
$Drivers = @()

foreach ( $Line in $Lines ) {

    $temp1 = $Line
    $text = $($temp1.Split( ':' ))[1]

    switch ($Operation) {

        'ItIsName' { $Name = $text
                     $Operation = 'ItIsFileName'
                     break
                   }

        'ItIsFileName' { $FileName = $text.Trim()
                         $Operation = 'ItIsVhod'
                         break
                       }

        'ItIsVhod' { $Vhod = $text.Trim()
                     $Operation = 'ItIsClassName'
                     break
                   }

        'ItIsClassName' { $ClassName = $text.Trim()
                          $Operation = 'ItIsVendor'
                          break
                        }

        'ItIsVendor' { $Vendor = $text.Trim()
                       $Operation = 'ItIsDate'
                       break
                     }

        'ItIsDate' { # переводим дату в европейский стандарт, чтобы сортировать
                     $tmp = $text.split( '.' )
                     $text = "$($tmp[2]).$($tmp[1]).$($tmp[0].Trim())"
                     $Date = $text
                     $Operation = 'ItIsVersion'
                     break
                   }

        'ItIsVersion' { $Version = $text.Trim()
                        $Operation = 'ItIsNull'

                        $params = [ordered]@{ 'FileName' = $FileName
                                              'Vendor' = $Vendor
                                              'Date' = $Date
                                              'Name' = $Name
                                              'ClassName' = $ClassName
                                              'Version' = $Version
                                              'Vhod' = $Vhod
                                            }
    
                        $obj = New-Object -TypeName PSObject -Property $params
                        $Drivers += $obj

                        break
                      }

         'ItIsNull' { $Operation = 'ItIsName'
                      break
                     }

    }
}

Write-Host "все драйверы" -ForegroundColor Yellow
Write-Host "-------------------" -ForegroundColor Yellow
$Drivers | sort Filename | ft



Write-Host "несколько версий драйверов" -ForegroundColor Yellow
Write-Host "-------------------" -ForegroundColor Yellow

$last = ''
$NotUnique = @()

foreach ( $Dr in $($Drivers | sort Filename) ) {
    
    if ($Dr.FileName -eq $last  ) {  $NotUnique += $Dr  }
    $last = $Dr.FileName
}

$NotUnique | sort FileName | ft



Write-Host "устаревшие версии драйверов" -ForegroundColor Yellow
Write-Host "-------------------" -ForegroundColor Yellow
$list = $NotUnique | select -ExpandProperty FileName -Unique

$ToDel = @()
foreach ( $Dr in $list ) {
    Write-Host "найден дубликат" -ForegroundColor Yellow
    $sel = $Drivers | where { $_.FileName -eq $Dr } | sort date -Descending | select -Skip 1
    $sel | ft

    $ToDel += $sel
}

Write-Host "драйвера на удаление" -ForegroundColor Green
Write-Host "-------------------" -ForegroundColor Green
Write-Host "будте осторожны, любые автоматические действия опасны" -ForegroundColor Green

$ToDel | ft



# удаляем драйвера
foreach ( $item in $ToDel ) {
    $Name = $($item.Name).Trim()

    Write-Host " " -ForegroundColor Green
    Write-Host "удаляем $Name" -ForegroundColor Green
    Write-Host "pnputil.exe -d $Name" -ForegroundColor Green
    Invoke-Expression -Command "pnputil.exe -d $Name"
}


Спасибо за внимание!
Поделиться с друзьями
-->

Комментарии (74)


  1. AzureSeraphim
    09.01.2017 15:02

    Помню то же столкнулся с подобной проблемой. Винда сохранила драйвер для принтера, а в самом драйвере появилась ошибка. Он начал печатать пакеты один пакет одна страница. Беда в том что при простом удалении, винда восстанавливала драйвер и не давала переустановить. В итоге ползли в эту папку и удаляли с помощью рук все её драйверы. Тока потом она дала шанс установить новенький и чистенький драйвер.
    Как говорится век живи, век учись. Сохраню страничку вдруг пригодится.


  1. dartraiden
    09.01.2017 15:12

    Благодарю, давно искал что-то консольное, что можно запускать автоматически по расписанию.
    До этого пользовался тоже хабраразработкой — pyWinClobber


  1. tsklab
    09.01.2017 16:57

    Начнём с ошибки:

    Cистема DISM
    Версия: 10.0.14393.0
    Версия образа: 10.0.14393.0
    /Get-Drivers [/Format:<формат_вывода>] [/all]
      Выводит сведения о драйверах в образе.  Чтобы определить вывод результата
      в виде списка или таблицы, используйте параметр /Format.  Если
      параметр /Format не задан, результат форматируется как список.  По
      умолчанию выводятся только готовые драйверы. Чтобы вывести все драйверы
      образа, используйте параметр /all.
        Примеры:
          DISM.exe /Image:C:\test\offline /Get-Drivers
          DISM.exe /Image:C:\test\offline /Get-Drivers /all
          DISM.exe /Image:C:\test\offline /Get-Drivers /Format:Table
    

    Вы же понимаете что обновляются не только драйвера oem*.inf.


    1. pak-nikolai
      09.01.2017 17:01

      это скрипт на статью, механизм описанный в статье автоматизирован


  1. Mishania
    09.01.2017 17:01

    Как полный ноль в скриптах хочу спросить. Я правильно понял, выделяем всё и запускаем в PS?


    1. pak-nikolai
      09.01.2017 17:05

      сохраните его в файл с расширением ps1 и запустите от админа.
      если скажет что сценарии в данной системе запускать нельзя то запустите его так

      powershell -executionpolicy bypass -file "путь до скрипта"
      


  1. Sterpa
    09.01.2017 17:18
    -2

    Скрипт в Win10 64 не работает. Просто выдает текст:

    все драйверы
    — несколько версий драйверов
    — устаревшие версии драйверов
    — драйвера на удаление
    — будте осторожны, любые автоматические действия опасны


    От админа скрипты запустить низя, нет такой опции. Можно сказать «Yes» на предупреждение о запуске нелогичного сценария, и только один раз, потом уже не спрашивает.


    1. Sterpa
      09.01.2017 17:30

      В самой среде PS действительно не запускает, пишет выполнение сценариев отключено.
      Но то же самое выдает по команде powershell -executionpolicy bypass -file, просто текст без цифр, т.е. скрипт не выполняется, список драйверов он из системы не получает и далее, соответственно, не парсит.


    1. commanderxo
      09.01.2017 18:29

      У меня работает под Win10 64, пользователь — локальный админ.

      1. Нажать на клавиатуре кнопку Windows
      2. Печатаем ISE. Список программ сокращается до Windows PowerShell ISE
      3. Правая кнопка мыши на оставшейся программе -> «Run as administrator»
      4. Копипастим скрипт
      5. Нажимаем зелёную кнопку Run


      У меня нашло 4 дубликата.


    1. Light_Metal
      09.01.2017 18:36
      +1

      От админа скрипты запустить низя, нет такой опции.

      У самой консоли PowerShell есть эта опция (проверил на Win7, Win10 под рукой сейчас нет).
      Так что сперва сам PS, и потом в нём уже скрипт.


      1. mayorovp
        10.01.2017 09:05

        На самом деле это "опция" не PS, а UAC. Любая программа может быть запущена либо от админа, либо от ограниченного пользователя (кроме тех у которых в манифесте прописано что они из-под ограниченного пользователя не запускаются).


    1. rbt2008
      10.01.2017 18:22
      -2

      Такая же ерунда (Windows 10, x64). Из Powershell ISE отработало ок.


    1. n01d
      10.01.2017 18:37
      -1

      Кошмар какой. Если берётесь за PowerShell и не знаете, как запускать скрипты из-под админа, лучше не беритесь вовсе. Можно много бед наворотить.
      Мне это напоминает историю, когда сотрудник обратился в поддержку с просьбой выполнить скрипт с админскими правами в духе «вот я тут скрипт обалденный нашёл — он всё супер круто делает, но мне прав не хватает». А инженер взял и выполнил, не проверив толком, что за скрипт. В итоге BSOD -> перезаливка. Что был за скрипт и что конкретно поломал даже уже и разбираться не стали.

      Это я всё к тому, что если вы не знаете PowerShell — НИ В КОЕМ СЛУЧАЕ НЕ ЗАПУСКАЙТЕ СКРИПТЫ PowerShell ОТ ИМЕНИ АДМИНИСТРАТОРА! Тем более, если не знаете как.

      На всякий случай научу — авось своих шишек набьёте:
      Первый вариант: В открывшейся консоли пишете путь к скрипту и жмакаете ENTER.
      Второй вариант (если первый говорит, что запуск скриптов запрещён политикой): Нажимаете сочетание клавиш Win + X, там выбираете пункт . В открывшейся консоли пишете

      powershell -executionpolicy bypass -file "X:\тут\мой\скрипт.ps1"


      P.S. простите за английскую винду. Привычка-с...


      1. Sterpa
        10.01.2017 18:42
        -1

        Капитан очевидность, у вас залет. Почитайте посты ниже, вы не поняли суть проблемы.
        Но мы уже вроде разобрались, кэп.


        1. n01d
          10.01.2017 18:46

          От админа скрипты запустить низя, нет такой опции.
          Вся суть проблемы в одном предложении. Это вы не понимаете суть вашей проблемы ;)
          Проблема в том, что процитированная фраза могла исходить только от технически неграмотного, либо совершенно не знакомого с PowerShell человека.

          Ваш К.О.


          1. Sterpa
            10.01.2017 19:06
            -1

            Действительно, первый раз вчера открыл PS. На Делфи ни разу не похоже, но интересно.
            Так вот, прелесть законченного решения состоит в том, что законченный скрипт.ps1 запускается по правой клавише мыши «Выполнить в PowerShell», чистит машину и не спрашивает о безопасности, админских правах и не портит аппетит всякими «Если не это, то попробуйте вот так, но все очень индивидуально на каждой машине».
            Для меня проблема ФрендлиЮзерИнтерфейса решается оберткой powershell -executionpolicy bypass -file скрипт.ps1 в чиститьдиск.bat
            Но остается необходимость запускать его опять от имени администратора — это не комильфо.

            Вот суть моей проблемы. В остальном же совершал акт дефекации на вашу парадигму относительно моей профессиональной компетенции.


            1. pak-nikolai
              10.01.2017 19:42

              Для меня проблема ФрендлиЮзерИнтерфейса решается оберткой powershell -executionpolicy bypass -file скрипт.ps1 в чиститьдиск.bat

              слуш ну хитееер, додумался ведь — засунул команду вызова скрипта в батник и запустил батник от админа чтобы он запустил пошик от админа и потом сам запустил скрипт ))))


              1. Sterpa
                10.01.2017 22:00
                -1

                Это не всё еще)) Проблема окончательно разрешилась созданием ярлыка для батника и в его доп.настройках установкой «запуск от админа».
                Вот теперь всё — простой двойной клик лкм ))))… но в дистрибутиве три файла
                Завтра упакую все в один экзешник.)


                1. mayorovp
                  10.01.2017 22:19

                  "В один экзешник" достаточно положить всего один файл. Сам скрипт.


                  Параметры для powershell и сам экзешник передать сможет. И запуск от админа в его манифесте прописать можно.


                  Кстати, если делать его на C# — то можно и вовсе обойтись без распаковки и запуска дочернего процесса.


                  Но вы, конечно же, упаковывайте три файла. Два скрипта на разных языках и ярлык. И все это — для того чтобы запустить один раз и забыть на пять лет.


                  1. pak-nikolai
                    10.01.2017 22:49
                    +1

                    да пусть пишет. Поближе познакомится с пошиком, тулзы погуглит, уровень знания по любому вырастет.

                    Я в свое время тоже написал очередной psexec чтобы запускать файлы без показа окошек, из принципа хотел разобраться как это делать, ну и что, по итогу подсел на пошик, перестал сомневаться в его преимуществах перед bat и vba файлами, перестал пытаться запихать скрипты в exe и даже стал писать кой какие статейки


                    1. Sterpa
                      10.01.2017 23:37

                      Да нет, пошик я посмотрел, применять мне его особо негде, хотя было забавно.
                      Экзешник забирайте, уверен, пригодится всем, кто хотел просто почистить дрова, без приключений, политики безопасности UAC и прочих бубнов.
                      Версия 32х разрядная, без создания контрольной точки (очень долго создает уж).
                      Запустится у всех, у кого сам скрипт не выдавал ошибок и нет проблем с версией PS.
                      Ну а тем, кто не дошел таки до запуска, не победили UAC, и не в силах далее внимать солнцеликим гуру — бог в помощь! Юзайте на здоровье, полезный продукт готов к употреблению)))

                      ЗЫ если антивирь ругнется, пошлите на))
                      ЗЫЗЫ автору скрипта респект, хотя ты и сноб))


            1. mayorovp
              10.01.2017 21:52
              -2

              Видите ли в чем дело. У вас — винда со включенным UAC. На ней любые действия по администрированию компьютера требуют запуска хоть какой-нибудь программы с правами, сюрприз, админа!


              Если вы не умеете запускать программы из-под админа — это ваша проблема. Не скрипта.


            1. n01d
              11.01.2017 16:16

              Если вдруг возникнет желание вернуться к PowerShell и чтобы сразу «от админа» советую глянуть в сторону вот этого замечательного скрипта по преобразованию *.ps1 в *.exe.
              По функционалу прилично порезан (в смысле, что не все возможности PS поддерживает), но в целом очень даже рабочий инструмент.

              Помимо вашей проблемы позволяет также обойти и другую: запрет на запуск скриптов через GPO. Т.к. выполняется в итоге не скрипт, а его «скомпилированный» (в каком-то смысле) вариант.

              Правда, есть и минус: иногда при использовании некоторых «приёмов» PS на готовый exe срабатывает эвристика антивирусов (того же каспера, в моём случае).


              1. Sterpa
                11.01.2017 17:21
                -1

                Полагаю, последний минус решается какой-нибудь упаковкой со смещением. На 99.99% полученный exe не будет содержать явно выраженных типовых jmp-пов для эврестического анализа, а вот явное выполнение сценария уже будет скрыто.


  1. AAT666
    09.01.2017 18:36

    Но то же самое выдает по команде powershell -executionpolicy bypass -file, просто текст без цифр

    Попробуйте запустить cmd от имени администратора. У меня win10 x64 — все чудесно работает.
    Вставил такую строку в скрипт (чтобы показать свою ОС и разрядность):

    Write-Host (Get-WmiObject -Class Win32_OperatingSystem).Caption (Get-WmiObject -Class Win32_OperatingSystem).OSArchitecture


    Вот результат:

    PS C:\WINDOWS\system32> D:\PowerShell\RemoveDr.ps1
    Майкрософт Windows 10 Pro (Registered Trademark) 64-разрядная
    все драйверы
    -------------------

    FileName Vendor Date Name ClassName Version Vhod
    -------- ------ ---- ---- --------- ------- ----
    bcmwlhigh6.inf ASUS 2013.02.28 oem27.inf Net 6.30.145.30 ЌҐв
    bcmwlhigh63.inf NETGEAR,Inc. 2013.04.03 oem44.inf Net 6.30.145.30 ЌҐв
    benq gw2260.inf BenQ 2012.08.15 oem40.inf Monitor 2.0.0.0 ЌҐв


    … ну и т.д.


    1. Sterpa
      10.01.2017 03:47
      -3

      и для Light_Metal, нет, друзья…
      не влияет никак запуск PowerShell от имени администратора, выдает тоже самое о невозможности запускать сценарии, хотя я админ и других админов нет:

      PS C:\WINDOWS\system32> C:\2OldDrvClear.ps1
      Невозможно загрузить файл C:\2OldDrvClear.ps1, так как выполнение сценариев отключено в этой системе. Для получения дополнит
      ельных сведений см. about_Execution_Policies по адресу http://go.microsoft.com/fwlink/?LinkID=135170.
          + CategoryInfo          : Ошибка безопасности: (:) [], ParentContainsErrorRecordException
          + FullyQualifiedErrorId : UnauthorizedAccess
      
      PS C:\WINDOWS\system32> 
      


      1. AAT666
        10.01.2017 05:14
        +1

        В описании ошибки дан ответ — «так как выполнение сценариев отключено в этой системе.» Можно сходить по ссылке, приведенной в ошибке и почитать про политики выполнения скриптов Powershell — очень толково все расписано. Если коротко, то PoSh мало того, что Вы администратор — ему еще надо четко указать, что Вы разрешаете делать со скриптами и в каком контексте.

        Удачи!


    1. Sterpa
      10.01.2017 03:55

      Запустилось только из под CMD запущенного от имени администратора. Нашел 8 дубликатов.
      Почему из под админского PowerShell сценарий не выполняется, не понимаю…


      1. pak-nikolai
        10.01.2017 09:42
        +1

        запустите powershell ISE, откройте в ней и запустите из нее нажав F5
        из консоли не запускает скорее всего из за безопасности — чтобы избежать запуска вирусных скриптов posh имеет защиту в виде политики посмотреть ее можно выполнив команду get-executionpolicy если вернет Restricted то значит выполнение скриптов запрещено. чтобы разрешить выполнение скриптов нужно выполнить команду set-executionpolicy unrestricted

        блин, кажется нужно по модели безопасности пошика статью написать…
        кароче это сделано чтобы не было штук как в VBA когда можно запустить что угодно, или подменить широко применяемый exe файл, например мы имеет доступ в папку где лежит word.exe мы берем пишем VBA файл и ложим тудаже, и из него после отработки запускаем word.exe который перед этим переименовали в word1.exe и таким образом мы можем атаковать админа когда он запустит ворд если мы на терминальном сервере, не говоря о том что можно играть на порядке поиска файлов, и на изменении тела самих скриптов. Таким образом система безопасности должна не давать по умолчанию запускать что попало. если вы попробуете на свежеустановленной системе открыть ps1 файл у вас откроется вообще блокнот, ну и т.д. есть хорошая статья на 2 страницы по безопасности, наверное пришло время ее перевести


        1. mayorovp
          10.01.2017 10:09

          Почему скрипт нельзя запустить двойным кликом по нему — совершенно понятно.


          Но каким боком к защите от случайного запуска относится запрет ввода в консоли powershell -file ...?


          1. pak-nikolai
            10.01.2017 10:33

            дополните указанием полтики исполнения и заработает


  1. shumaher86
    09.01.2017 22:42

    скрипт только на 10-ке работать должен? на 7-ке кучу ошибок красным цветом выводит…


    1. pak-nikolai
      10.01.2017 10:24

      должен работать, напишите в личку что показывает


  1. vorphalack
    10.01.2017 04:05

    DISM /online /get-drivers
    =========
    Obtaining list of 3rd party drivers from the driver store…

    Driver packages listing:

    (No drivers found in the image matching the criteria)
    =========

    7x64 ultimate, если запустить с /all в нагрузку, находит с десяток драйверов непойми откуда и всё. или у меня какой-то сервис пришиблен за ненадобностью, или не все винды одинаково полезны…


    1. pak-nikolai
      10.01.2017 05:50

      не получилось воспроизвести такую же ошибку, у меня есть тестовая машина win7 x64 на ней работает

      какая версия dism`а?


      1. vorphalack
        10.01.2017 11:07

        Deployment Image Servicing and Management tool
        Version: 6.1.7600.16385


  1. Erleke
    10.01.2017 05:46

    Через Windows PowerShell ISE сработало.
    Спасибо!


  1. n00b1k
    10.01.2017 05:46

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


    1. pak-nikolai
      10.01.2017 05:59

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

      можно предварительно скопировать содержимое папки C:\windows\system32\DriverStore\FileRepository куданибудь, и после этого играть со скриптом

      в данном случае целью ставилось посмотреть какие версии драйверов хранятся в системе и автоматизировать процедуру удаления старых. т.к. при нажимании 122 раза вверх — поменять цифры — ввод можно допустить ошибку

      может быть можно скопировать папку в которой лежит inf файл со своим барахлишком и после этого делать деинсталяцию, это я не проверял


  1. Compiller
    10.01.2017 05:46

    for /l %%i in (0,1,256) do pnputil -d oem%%i.inf
    просто удаление ненужных сторонних драйверов


    1. pak-nikolai
      10.01.2017 06:03

      а рабочие драйвера при таком способе он просто не удалит?


      1. RogueShy
        10.01.2017 10:31

        Не удалит. pnputil выдаст вот это на используемые драйвера (на Win7):

        Не удалось удалить пакет драйвера: С помощью указанного INF-файла сейчас было установлено одно или несколько устройств.


  1. alkoro
    10.01.2017 11:09

    Падает на Win7x64sp1, многочисленные одинаковые ошибки, в цикле:

    Посмотреть
    Невозможно найти тип [ordered]: убедитесь в том, что сборка, содержащая этот тип, загружена.
    C:\TEMP\deldrivers.ps1:61 знак:44
    +                         $params = [ordered] <<<< @{ 'FileName' = $FileName
        + CategoryInfo          : InvalidOperation: (ordered:String) [], RuntimeException
    New-Object : Не удается проверить аргумент для параметра "Property". Аргумент пустой или имеет значение NULL. Укажите не пустой аргумент, не имеющий значение NULL, после чего повторите выполнение команды.
    C:\TEMP\deldrivers.ps1:70 знак:71
    +                         $obj = New-Object -TypeName PSObject -Property <<<<  $params
        + CategoryInfo          : InvalidData: (:) [New-Object], ParameterBindingValidationException
        + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.NewObjectCommand
    


    1. pak-nikolai
      10.01.2017 11:12

      ошибка из за того что у вас пошик старый, скорее всего 2й

      удалите [ordered] должно быть так и заработает

                              $params = @{ 'FileName' = $FileName
                                                    'Vendor' = $Vendor
                                                    'Date' = $Date
                                                    'Name' = $Name
                                                    'ClassName' = $ClassName
                                                    'Version' = $Version
                                                    'Vhod' = $Vhod
                                                  }
      


      покажите если не сложно версию пошика сделать для этого введите в порвешелле $psversiontable

      если захотите обновить пошик то скачайте WMF5.1 или хотя бы WMF4


    1. pak-nikolai
      10.01.2017 11:23

      и удалите trim должно быть вот так

              'ItIsName' { $Name = $text
                           $Operation = 'ItIsFileName'
                           break
                         }
      

      это особенность старого пошика, в нем не хватает некоторых конструкций, в данном случае для работы скрипта они не существенны


      1. alkoro
        10.01.2017 12:08

        Да, вторая версия
        Name Value
        — — CLRVersion 2.0.50727.5420
        BuildVersion 6.1.7601.17514
        PSVersion 2.0
        WSManStackVersion 2.0
        PSCompatibleVersions {1.0, 2.0}
        SerializationVersion 1.1.0.1
        PSRemotingProtocolVersion 2.1


        1. pak-nikolai
          10.01.2017 12:47
          +1

          плюсы перевешивают минусы на самом деле.
          это мой недочет что я не прогнал скрипт на 7ке, хотя когда писал я знал что ордеред был введен начиная с 3го пошика.
          но я написал его так чтобы это не повлияло на его работу (не убило ничего) а вставил эти конструкции из за привычки писать код таким стилем.

          кстати код VBA куда более опасен, хотя если сделать делит папки windows ничего конечно не спасет


          1. mnaoumov
            10.01.2017 18:40
            +2

            Напишите в начале скрипта


            #requires -version 3.0

            и будьте спокойны, он просто не запустится на младших версиях


        1. n01d
          10.01.2017 17:32

          ЕМНИП, WMF5.1 ставится только поверх 3-ей или 4й версии.
          В принципе, в скрипте нет ничего особенного. 3й версии уже с головой хватит.


          1. alkoro
            10.01.2017 18:11

            Я уже пробовал. Даже WMF 5.0 установилась поверх 4-й, установил SHA-2 Security Update, что было в требованиях, но нет, 5.1 Preview не хочет устанавливаться.


            1. n01d
              10.01.2017 18:15

              Почитайте: https://msdn.microsoft.com/en-us/powershell/wmf/5.1/install-configure
              Там немножко подробнее о том, что нужно поставить. Прям со ссылками.

              У меня на 10ку встало без проблем (что неудивительно тащемто).

              Неизвестно, что может удалитьсяупасть из-за несоответствия версии.
              Кстати, практически ничего. В 99% случаев скрипт просто споткнётся на неподдерживаемом методе.
              А вообще да — это немного раздражает. Приходится постоянно писать скрипты на PS5, а потом их отлаживать и заставлять работать на PS2.


              1. pak-nikolai
                10.01.2017 18:39

                эт из за исторического развития пошика так произошло, когда балмер принял решение что главное это девелоперы начали резко пилить пошик, это видно прям по версиям, фактически первым полноценным стал powershell 3 но в 7 винду успели зарелизить только версию 2. мне приходится при установке 2008 или 7ки всегда делать установку WMF4 чтобы получить SkipLast, создание объектов без добавление методов и командлеты, и то при установке на 2008R2 нет оснасток например из модуля storage и модулей работы с AD что сильно ограничивает функционал, нужно юзать WMI
                в первом пошике вообще 128 командлетов всего, в 5.1 более 1500, но весь функционал вы получите только сделав ап самой винды
                по мне так 5.0 и 5.1 самые нормальные версии из за функций по работе с сервисами, этого действительно не хватает, нормальная поддержка PSEdit — редактирование на удаленных машинах, в 5.1 встроен psreadline ну и т.д.
                Минимальной является WMF4 в нем уже все есть особенно биндинг и нормальный дебаг (можно нормально парсить ошибки, не до конца перебирает списки объектов что ускоряет работу в разы), работа с сетью

                встречал баг только на терминальном сервере когда после установки WMF4 перестал работать мап принтеров либо глючил с чем связано не знаю
                в exchange приходится тестить с пристрастием скрипты сильно от версии различаются, но это ерунда, по сравнению с той мощью которую можно достигнуть за счет автоматики


              1. alkoro
                10.01.2017 22:21

                Если вы заметили, я эту же ссылку и приводил, и да, я конечно читал про требования. Все компоненты (EMF4, SHA2 Update, .NET 4.6.1, WinRM Dependency — WinRM был запущен) есть, а результата нет.


                1. pak-nikolai
                  10.01.2017 22:43

                  у меня тоже есть такой баг на одной машине в инфраструктуре, win 8.1 пош 5 поставился а 5.1 нет. глубоко не копал но подтверждаю, баг такой имеется


                  1. alkoro
                    11.01.2017 07:32

                    Добавлю ещё: пришёл домой и установил на домашний комп сразу 5.1 поверх 2.0 (sha2+dot net уже были). Получается, то, что в ссылке, ещё и не совсем верно.


                1. n01d
                  11.01.2017 16:19

                  Не заметил, простите.


  1. LevOrdabesov
    10.01.2017 11:12

    Полезный скрипт, прямо вчера о нём думал, собирался писать. Спасибо!

    Есть нюансы: например, 1С версии 7.7 на Win 7 x32 с локальным ключом безопасности работает, только если в системе присутствует старый драйвер HASP из комплекта поставки самой 1С 7.7. При этом основным (отображаемым в диспетчере устройств как установленный для устройства) может быть и другой драйвер HASP.
    Подозреваю, что нюанс не единичный. Так что имеет смысл добавить в начало скрипта создание точки восстановления.


    1. pak-nikolai
      10.01.2017 11:20

      дополнил сценарий одной закомментированной строкой создания контрольной точки

      # чтобы создать контрольную точку
      Checkpoint-Computer -Description "Driversdelete"
      # чтобы просмотреть контрольные точки
      Get-ComputerRestorePoint 
      


  1. n01d
    10.01.2017 14:05

    Уберите, пожалуйста, код скрипта в спойлер.
    И вопрос на засыпку: почему такой странный парсер со свитчами..? Почему выбран именно такой вариант?


    1. pak-nikolai
      10.01.2017 14:37

      убрал в спойлер

      прост стиль мой такой

      • во первых в нем описан точный порядок переключений,
      • во вторых его можно дополнить
      • в третьих можно дописать default и тогда автомат не сможет принять никаких состояний кроме описанных, т.е. мы получим точный автомат, не дописал только из за того что тогда надо дописывать проверку на содержимое и потому что и так получилось очень robust даже с ошибками отрабатывает нормально
      • Четвертой причиной является то что в разных системах может быть написано на русском а может на английском, или еще каком языке. Поэтому парсить по сравнению содержимого до двоеточия опасно
      • Пятое — потому что в автомате реализуемом через switch я могу дополнять в последующем действия не загромождая код и без страха сломать нижестоящий код, хоть конструкция и пространсвенно большая, она очень понятная и детерминируемая штоли,
      • Шестое — если я буду рефакторить то я скопирую конструкцию и выкину только входные строки каждого блока, при этом сохранив логику внутри такого блока, этот автомат мал чтобы это увидеть, но логика такова, именно поэтому я использую присвоение переменной вначале и потом работу с этой переменной внутри каждого блока

      например: как можно было заметить вывод даты утилитой DISM происходит в последовательности DD.MM.YYYY а мне нужно отсортировать по дате драйвера и выбрать самый новый, я мог бы парсить строку в дату и потом делать сравнение, вместо этого я при парсинге переворачиваю строку в европейский формат — YYYY.MM.DD и тогда при строковой сортировке у меня будет правильный порядок дат. Так вот парсинг этот я дописывал после создания блока, и труда это не составило и если бы мне понадобилось обрабатывать имена файлов то я бы это делал внутри подблока конструкции switch, плюс я могу быстро дополнить состояния автомата если нужно, а если нужно то просто перенаправить алгоритм по другому пути просто заменой состояние на которое будет переключаться в следующей итерации (это нужно если ваш автомат отрабатывает у многих пользователей через время, и чтобы ничего не сломать, приходится делать такие переключения в другие промежуточные состояния).

      Есть еще скрытый смысл — при компиляции подобных конструкций в ассемблере получается очень короткий переход — сравнение по таблице и прыжок, а при других конструкциях код запутаннее и больше. Наверное это привычка оттуда…

      Сорри, многабукф


  1. n01d
    10.01.2017 15:20
    +1

    парсить по сравнению содержимого до двоеточия опасно
    в разных системах может быть написано на русском а может на английском, или еще каком языке
    Можно добавить к команде /format:table и парсить таблицу, в качестве Headers используем заголовок получившейся таблицы, который можно предварительно распарсить по разделителю.

    вывод даты утилитой DISM происходит в последовательности DD.MM.YYYY а мне нужно отсортировать по дате драйвера
    Вы не поверите, но PoSH объектно-ориентирован. Конвертируем богомерзкий объект класса «String» в православный объект класса «DateTime» через [DateTime]::Parse($Date). И этот объект уже будет сортироваться как надо — PoSH знает, как правильно сортировать дату.

    Впрочем, ваша фраза про ассемблер всё объясняет… :) Я к программированию пришёл недавно и пошло оно уже после увлечения PoSH (его стало не хватать), так что у меня мозг слишком сильно испорчен ООП. На низкоуровневые языки смотреть не могу Т__Т

    Попробовал сваять свой парсер без привязки к локали.
    Получилось нечто такое:
    # Получаем данные от Dism
    $data = & dism /online /get-drivers /format:table | select -Skip 12 # Первые 12 строк - стандартный мусор
    
    # Получаем заголовок таблицы и разбиваем на составные
    $Headers = @( ($data | select -First 1).ToString().Split('|') | %{$_.Trim() <# обрезаем лишние пробелы #>} )
    
    # оформляем в хэш-таблицу
    $HashTable = $data | select -Skip 2 | 
        ConvertFrom-Csv -Delimiter '|' -Header $Headers | 
            select @{n='FileName';e={$_."$($Headers[1])"}},
                   @{n='Class';e={$_."$($Headers[3])"}},
                   @{n='Vendor';e={$_."$($Headers[4])"}},
                   @{n='Date';e={[datetime]::Parse($_."$($Headers[5])")}},
                   @{n='Version';e={$_."$($Headers[6])"}}
    


    1. pak-nikolai
      10.01.2017 15:39

      ваш способ православнее и в русле идеологии пошика

      скорее всего на меня влияет «материнский язык»

      P/S/ кстати последний объект выпал как пустой, из за двух пустых строк в конце. автомат такое бы не пропустил. нужна одна проверка или принудительно удалить последний объект


      1. n01d
        10.01.2017 16:03

        Упс, промахнулся мимо ответа, получилась новая ветка...

        ваш способ православнее и в русле идеологии пошика
        И, надеюсь, нагляднее. Ваш парсер нужно вдумчиво разбирать, чтобы понять, что происходит. Ну мне пришлось, по крайней мере %)

        кстати последний объект выпал как пустой, из за двух пустых строк в конце. автомат такое бы не пропустил. нужна одна проверка или принудительно удалить последний объект
        И правда. Упустил этот момент. Всё из-за последних строк в конце вывода:
        
        The operation completed successfully.
        
        
        (это 3 строки, 2 пустые)
        Ну, никто не мешает, действительно, проверять на IsNullOrEmpty.


    1. mayorovp
      10.01.2017 16:21

      Делать PSObject в таких случаях — обязательно. Потому что Hashtable — это последовательность, а последовательность последовательностей в PoSh выводится ужасно. Работать с ней еще можно, а вот в отладке разобраться что там да как — уже тяжело :)


      1. n01d
        10.01.2017 16:54

        Ну это уже вкусовщина. Сам я тоже предпочитаю PSObject, да. Он крайне удобен как для работы с ним, так и для последующей выгрузки в CSV/XLSX.

        Кстати, тов. pak-nikolai (чтоб 2 коммента не писать), можно ещё и версию распарсить на объект класса Version и сортировать дрова даже хоть по версии.


  1. vskv
    10.01.2017 15:35

    Для драйверов есть DISM.
    А есть что-то для установленных обновлений, точнее той свалки, что скапливается в %systemroot%\Installer?


    1. MortumSK
      10.01.2017 18:08

      С некоторыми устаревшими хвостами обновлений может помочь cleanmgr.


    1. dartraiden
      13.01.2017 20:11

      С помощью Dism++ можно почистить \Installer\$PatchCache$\ (и вообще, много чего почистить: устаревшие и замененные компоненты WinSxS, устаревшие драйверы).


      1. vorphalack
        16.01.2017 23:19

        уххх. 5.5Г на одной машинке и 20 (видимо от неудавшейся попытки апгрейда до 10) на другой, обе с семеркой… интересно где эта утилита была раньше…


  1. CTpaHHoe
    10.01.2017 21:58

    спасибо, сработало.
    win7 x64 prof. была проблема с ordered — решилось обновлением PS


    1. pak-nikolai
      10.01.2017 22:03

      ordered можно выкинуть вообще, это команда чтобы не перемешивались свойства при создании объекта а создавались именно в этой последовательности. она в принципе на работу никак не влияет

      удалил ordered из скрипта чтобы не смущать людей


  1. Sterpa
    10.01.2017 23:42
    -1

    Бояре, скрипт скомпилирован в exe, брать здесь, архив 7z.
    Версия 32х разрядная, без создания контрольной точки (очень долго создает уж).
    Запустится у всех, у кого сам скрипт не выдавал ошибок и нет проблем с версией PS. Запустится сам от админа, без бубнов.
    Юзайте на здоровье, полезный продукт готов к употреблению, автору скрипта респект)))

    ЗЫ если антивирь ругнется, пошлите на))


  1. fifonik
    11.01.2017 11:20
    +2

    1. pak-nikolai
      11.01.2017 12:08

      GUI для pnputil когда надо убить старый драйвер NVIDIA засевший в системе. Спасибо что поделились