Страницы

Поиск по вопросам

Показаны сообщения с ярлыком powershell. Показать все сообщения
Показаны сообщения с ярлыком powershell. Показать все сообщения

суббота, 11 апреля 2020 г.

Resolve-Path не разрешает путь, указанный в переменной

#powershell

                    
В сценарии:
$VHDstorage = "d:\term_profile\"

$Domains = “domain1.local", “domain2.local”, “domain3.local”
$TemplProfilePrefix = "UVHD-"
$TemplProfileSuffix = ".vhdx"
$LifetimeProfile=60

ForEach ($Domain in $Domains) {
    Search-ADAccount -server (get-addomain $Domain).pdcemulator -accountdisabled
| where {$_.lastlogondate -lt (get-date).addmonths(-$LifetimeProfile)} | ForEach-Object
-Process {
        $pathto = $VHDstorage + '*\' + $TemplProfilePrefix + $_.SID.Value + $TemplProfileSuffix
        (Resolve-Path -Path $pathto).path
    }
}

неверно отрабатывает блок:
(Resolve-Path -Path $pathto).path

т.е. не выводится ничего, хотя переменная $pathto содержит строку поиска.
Что интересно, создание переменной в консоли Powershell и последующая передача этой
переменной как параметра в Resolve-Path выдает необходимый результат.
Как решить эту проблему?    


Ответы

Ответ 1



Разобрался. Чтобы вся эта конструкция делала то, что задумано, нужно строку с Resolve-Path изложить в следующей редакции: Resolve-Path -Path $pathto | ForEach-Object -Process { $_.Path } Да и $LifetimeProfile=60 (в месяцах) я взял слишком большим, из-за чего не видел результатов.

воскресенье, 15 марта 2020 г.

Запустить PuTTY через PowerShell

#powershell #putty


Я запустил putty через PowerShell:

&'C:\test\dev.lnk' - это точнее ссылка на дев сервер, открываемая через putty.

В открытом окне мне надо написать путь к скриптам: cd script.

Возможно ли как-то написать этот путь через powershell, а затем и запустить скрипты?

Т.е. как с помощью PowerShell мне писать что-либо в открытом ранее окне?
    


Ответы

Ответ 1



для автоматизации выполнения фиксированного набора команд в unix-подобных операционных системах можете поступить так: впишите все команды в файл с произвольным именем (в именах файлов лучше избегать пробелов и других спец-символов, ограничьтесь латинскими буквами в нижнем регистре, арабскими цифрами, точкой, минусом и знаком подчёркивания) — по одной команде на строку: команда1 команда2 команда3 поместите этот файл в каталог, например, /usr/local/bin/: обычно он перечислен в переменной окружения PATH, поэтому помещённые в него файлы можно запускать откуда угодно по их именам. присвойте файлу бит исполнимости: chmod +x /usr/local/bin/moj.nabor.comand.nomer.raz запускайте этот файл по имени: moj.nabor.komand.nomer.raz оговорка если у вас нет прав для записи в каталог /usr/local/bin/, поместите файл в свой домашний каталог, и сразу после логина запускайте его так: sh moj.nabor.komand.nomer.raz

Ответ 2



Как вариант, можно использовать связку из pscp, чтобы положить скрипты на сервер, затем plink, чтобы выполнить на сервере команду. Но в таком случае мне не очень понятен смысл использования PowerShell - вполне можно обойтись банальным BATCH скриптом. Обе утилиты идут в комплекте с PuTTY. Пример скрипта на PowerShell с использованием pscp и plink: $PuTTYPath = "C:\Program Files (x86)\PuTTY" $User = 'administrator' $Pass = Read-Host 'Password' -AsSecureString | ConvertFrom-SecureString $HostName = 'ubuntu-test' # Кладём скрипт на сервер; обязательно с флагом -Wait, чтобы скрипт дождался загрузки файлов Start-Process -FilePath "$PuTTYPath\pscp.exe" ` -ArgumentList "-pw $Pass D:\Soft\Ubuntu\*.sh $User@$HostName`:/home/administrator" -Wait # Запускаем скрипты (предполагаем, что нам не важен порядок запуска) Start-Process -FilePath "$PuTTYPath\plink.exe" ` -ArgumentList "-ssh -pw $Pass $User@$HostName cd /home/administrator/ && chmod +x *.sh && ./*.sh"

вторник, 25 февраля 2020 г.

Как сохранить вывод любой команды в файл и сразу же увидеть его в терминале?

#bash #shell #powershell


Как после долгого ожидания вывода сохранить то что увидел в файл?
Допустим по команде:
git grep  $(git rev-list --all)

Я понимаю что было бы предусмотрительно наличие > log.txt в конце, хочется сразу
сохранять что увидел?
Все сам разобрался, суть в следующем если допустим набрать просто git log, появится
диалог просмотра со значком :. Этот экран можно двигать вверх вниз там, а вот если
нажать кнопку s то появится диалог ввода имени файла, остается набрать допустим log.txt
и весь вывод будет сохранен в этот файл    


Ответы

Ответ 1



Чтобы увидеть вывод и сохранить его одновременно есть специальная команда tee, пример: command | tee log.txt Иллюстрация: Wikipedia, GFDL.

Ответ 2



Если не для одной команды, а для "сеанса", то я пользуюсь командой script (весь протокол работы будет в файле ./typescript, а вообще, посмотрите man script).

Поиск в истории в сеансе PowerShell

#windows #powershell


В линуксовых терминалах есть поиск по истории, вызываемый нажатием Сtrl+R. Существует
ли аналог в PowerShell?
    


Ответы

Ответ 1



Есть, вызывается тем же самым Сtrl+R Поиск вперед по истории - Сtrl+S У меня 10-ка, не уверен, есть ли этот функционал в более старых версиях. Но его точно можно доставить через Install-Module PSReadline вместе с подстветкой и другими плюшками: The Search for a Better PowerShell Console Experience UP: Install-Module - это сниппет из PsGet: (new-object Net.WebClient).DownloadString("http://psget.net/GetPsGet.ps1") | iex

пятница, 14 февраля 2020 г.

Как запустить powershell в определенной папке

#windows #cmd #powershell


Создал ярлык powershell консоли в Windows 10, хочу чтобы она запускалась от администратора
и в определенной папке. Подскажите как сделать? 

Я пробовал параметр запуска указывать, не работает: 

%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -commnad 'cd F:\'


Также не работает рабочая папка в свойствах ярлыка: 

    


Ответы

Ответ 1



Используйте PowerShell Profiles: Находясь в Powershell дайте команду на создание профиля: New-Item -ItemType file -Path $profile -Force Откройте профиль на редактирование: Ise $profile Впишите в открывшемся редакторе команду перехода в нужный каталог: cd F:\ Закройте консоль Powershell и попробуйте открыть снова. Вуаля - вы в папке f:\! PS Статьи в помощь: Профили в PowerShell All About PowerShell Profiles

Ответ 2



В проводнике Windows перейдите в адресную строку (Alt + D или Ctrl + L). Введите powershell или powershell_ise и нажмите Enter.

Ответ 3



Заходите в папку, зажимаете клавишу shift + правую кнопку мыши и затем в контекстном меню нажимаете Открыть окно команд (или, наверное будет по другому написано - Открыть Powershell).

Ответ 4



Для powershell Core pwsh.exe -wd "c:\your_directory" Для powershell version <=5.1 (встроенная в windows) Команда для реестра или при непосредственном запуске powershell powershell -NoExit -command {Set-Location -Path "c:\your_directory"} Команда для "cmd подобных" ярлыки, запуск через bat файлы и другие варианты powershell -NoExit -Command "& {Set-Location -Path \"c:\\your_directory\"}" или powershell -NoExit -Command "& Set-Location -Path \"c:\\your_directory\"" или powershell -NoExit -Command Set-Location -Path "c:\your_directory" Для ярлыка конкретно "absolute_path\powershell.exe" -NoExit -Command "& {Set-Location -Path \"c:\\your_directory\"}" Запуск от имени администратора, правая клавиша мыши - Запуск от имени администратора. Если хотите чтобы ярлык запускал сразу как от имени администратора, то свойства ярлыка=>дополнительно=>запуск от имени администратора или копайте в сторону команды runas и объединяйте команды.

Ответ 5



Можно, конечно, переписывать, но в первой ссылке первый ответ, которым я воспользовался. Редактирование реестра тоже помогло, пробовал https://stackoverflow.com/questions/183901/how-do-i-start-powershell-from-windows-explorer https://www.iguides.ru/main/os/kak_otkryt_powershell_v_tekushchey_papke/

понедельник, 3 февраля 2020 г.

Как удалить данные до конца строки после запятой?

#linux #windows #powershell #active_directory


Есть текстовый файл:


  "CN=Username Alibabaev,OU=?????? ????????????,OU=???ep. ????????,OU=??? \"????????
??????\",DC=domain,DC=ru"
  
  "CN=SUsername DAlibabaev,OU=?????? ????????????,OU=???ep.
  ????????,OU=??? \"???????? ??????\",DC=domain,DC=ru"
  
  "CN=Supeman Batman,OU=??,OU=22 ????????,DC=domain,DC=ru"
  
  "CN=Sergio Amanol,OU=??,OU=22 ????????,DC=domain,DC=ru"
  
  "CN=username,CN=Users,DC=domain,DC=ru"


Нужно удалить то что идёт после "CN=User Suser,  на всех строках. Как можно это сделать?
    


Ответы

Ответ 1



На PowerShell тоже элементарно: cat filename.txt | %{$_.split(',')[0]} Если нужно получить только имена пользователей без CN=, то так: cat filename.txt | %{$_.split('=,')[1]} cat - это алиас для Get-Content, % - алиас для Foreach-Object (для обработки каждой строки).

Ответ 2



В linux задача решается с помощью awk элеметарно (при условии, что в CN нет символа запятой) cat filename.txt | awk -F, '{ print $1; }' -F, - опция awk задающая разделитель (в данном случае ,, по умолчанию - пробел или группа пробельных символов), потом выводим первое поле. Проблемы возникнут при создании пользователя с именем Василий, Алибабаевич Поскольку powershell совсем не знаю, на виндах бы решил средствами python или perl, благо устанавливаются совсем просто. В целом, проблема запятой в имени тоже решается несложно, если нужно напишу скрипт на perl, там буквально пара-тройка строк будет.

пятница, 31 января 2020 г.

Как объявить, описать и проверить параметры командной строки в Python?

#python #python_3x #powershell #argv


В PowerShell есть замечательная возможность объявления параметров скрипта, их проверки,
и автоматического описания. Записывается так:



[CmdletBinding()]
Param(
    # Имя адаптера, обязательное, явно задавить имя параметра не нужно, определяется
по позиции.
    [Parameter(Mandatory=$True,Position=1)]
    [string]$AdapterName,

    # Целевые адреса в виде адрес/маска, например 192.168.72.0/24
    [Parameter(Mandatory=$True)]
    [string[]]$TargetNets
)


А также с проверкой:

[ValidateSet("Tom","Dick","Jane")]
[String]$Name,

[ValidateRange(21,65)]
[Int]$Age,

[ValidateScript({Test-Path $_ -PathType 'Container'})]
[string]$Path


При ошибке ввода оболочка подскажет что и где и как должно быть. Подробнее тут и
тут. Param также применим к функциям.
Есть ли нечто подобное в Python?
    


Ответы

Ответ 1



Пример кода, который показывает как реализовать оба примера из вопроса, используя argparse: #!/usr/bin/env python3 import argparse import pathlib def valid_dir(path): path = pathlib.Path(path) try: if path.is_dir(): return path except OSError: pass raise argparse.ArgumentTypeError('%s is not a valid directory' % (path,)) parser = argparse.ArgumentParser() parser.add_argument('adapter-name') parser.add_argument('targetnets', nargs='+') parser.add_argument('--name', choices={"Tom", "Dick", "Jane"}) parser.add_argument('--age', type=int, choices=range(21, 65)) parser.add_argument('--path', type=valid_dir) print(parser.parse_args()) См. directory path types with argparse. Пример запуска: $ python3 . lo 10.0.3.0/24 127.0.0.0/8 --name Tom --age 22 --path . Namespace(adapter-name='lo', age=22, name='Tom', path=PosixPath('.'), targetnets=['10.0.3.0/24', '127.0.0.0/8'])

Ответ 2



Существует множество библиотек, которые позволяют описывать/проверять параметры командной строки как часть их работы, например, уже упомянутый модуль argparse из стандартной библиотеки, простой docopt, ориентированный на создание стандартного интерфейса, click, ориентированный на поддержку произвольного CLI интерфейса. Парсер командной строки задаётся в docopt, используя стандартный язык для примеров использования, первый фрагмент транслируется в: Usage: ваша-программа ... Это буквальное описание говорит docopt, что ваша-программа имеет два обязательных параметра и второй параметр это список (одно или более значений), живой пример. Вот полный пример кода c docopt: #!/usr/bin/env python3 """Print adapter ips that belong to given networks. Usage: ваша-программа ... ваша-программа -h | --help | --version Arguments: adapter-name Имя адаптера nets Адреса в виде адрес/маска, например 192.168.72.0/24 """ import ipaddress import docopt # $ pip install docopt import netifaces # $ pip install netifaces def parse_ip(ip_string): """Parse ip string such as '10.0.3.0' returning None on error.""" try: return ipaddress.ip_address(ip_string) except ValueError: return None if __name__ == "__main__": args = docopt.docopt(__doc__, version='ваша-программа 1.0') try: networks = [ipaddress.ip_network(network_spec) for network_spec in args['']] ifaddresses = [netifaces.ifaddresses(args[''])[family] for family in [netifaces.AF_INET, netifaces.AF_INET6]] except ValueError as e: raise docopt.DocoptExit(str(e)) adapter_ips = [parse_ip(ip['addr']) for ips in ifaddresses for ip in ips] # find intersection print(*[ip for ip in filter(None, adapter_ips) for network in networks if ip in network]) Пример запуска: $ ваша-программа lo 10.0.3.0/24 127.0.0.0/8 127.0.0.1 $ ваша-программа lxcbr0 10.0.3.0/24 127.0.0.0/8 10.0.3.1 Спецификация, из которой docopt создаёт парсер для командной строки, приведена в __doc__ (строка наверху модуля). Проверка в сам docopt не входит. Как показывает пример, это не всегда нужно: ipaddress.ip_network(), netifaces.ifaddresses() выбросят ValueError, если неправильные значения указать. По желанию, можно установить разные проверяльщики. Вот пример кода с schema. Второй фрагмент c использованием schema: #!/usr/bin/env python3 """Usage: prog.py [--name= --age= --path=]""" import pathlib import docopt # $ pip install docopt from schema import And, Or, Schema, SchemaError, Use # $ pip install schema def valid_dir(path): try: return path.is_dir() except OSError: return False if __name__ == '__main__': args = docopt.docopt(__doc__) schema = Schema({ '--name': Or(None, "Tom", "Dick", "Jane", error='--name can be only Tom, Dick, or Jane'), '--age': Or(None, And(Use(int), lambda n: 21 <= n < 65), error='--age should be in [21, 65) range'), '--path': Or(None, And(Use(pathlib.Path), valid_dir), error='--path should be a valid folder')}) try: args = schema.validate(args) except SchemaError as e: raise docopt.DocoptExit(str(e)) print(args) Пример: $ python prog.py --path . --age 21 Результат: {'--age': 21, '--name': None, '--path': PosixPath('.')} Пример кода без использования schema: #!/usr/bin/env python3 """Usage: prog.py [--name= --age= --path=]""" import pathlib import docopt # $ pip install docopt if __name__ == '__main__': args = docopt.docopt(__doc__) if (args['--name'] is not None and args['--name'] not in {"Tom", "Dick", "Jane"}): raise docopt.DocoptExit('--name can be only Tom, Dick, or Jane') if args['--age'] is not None: try: args['--age'] = int(args['--age']) if args['--age'] not in range(21, 65): raise ValueError except ValueError: raise docopt.DocoptExit('--age should be in [21, 65) range') if args['--path'] is not None: args['--path'] = pathlib.Path(args['--path']) try: if not args['--path'].is_dir(): raise ValueError except (ValueError, OSError): raise docopt.DocoptExit('--path should be a valid folder') print(args) Результат тот же. В данном простом случае, где код ничего кроме проверки аргументов не делает, ограничения на аргументы простые и сами аргументы являются независимыми, вариант с декларативной проверкой аргументов (со schema) выглядит более предпочтительным по сравнению с явным кодом на Питоне, но аргумент, представленный по ссылке в вопросе, является спорным. Это аргумент людей, которые верят, что отсутствие обязательных статических меток для типов в Питоне (но см. typing), должно приводить к куче if isinstance(arg1, type1): raise ValueError, чтобы скомпенсировать работу компилятора в статических языках. Фактически, много вызовов isinstance() не одобряется в Питоне и обычно можно найти лучше решения в зависимости от конкретной задачи. В обычном коде в любом случае, если вы хотите использовать значения, то вам придётся их преобразовывать к нужному виду и обрабатывать соответствующие ошибки по месту использования, чтобы избежать race, например, директория может быть удалена после проверки, но до использования (LBYL vs. EAFP). Использование инструментов по описанию требований к параметрам либо может быть недостаточно для более сложных случаев или же в лучшем случае такое описание будет эквивалентно Python коду только с менее привычным синтаксисом (если вы можете описать любые требования, то ваш язык описаний Turing complete и у нас уже есть приятный Turing complete язык и он называется Python и почему бы его и не использовать напрямую, чтобы выразить требования).

Ответ 3



Используйте argparse import argparse parser = argparse.ArgumentParser(description='Process some integers.') parser.add_argument("foo", ..., required=True) parser.parse_args() Ответ на английском. P.S. Кто-то отвечал, но удалился...

пятница, 24 января 2020 г.

Кодировка DOCX файлов в Powershell

#кодировка #powershell


Доброго времени! есть куча docx файлов, в которых ищется ФИО, переводится в переменную,
а затем используется для переименования файла. так вот, поиск заканчивается неудачей
т.к. powershell не понимает кодировку docx файлов. с txt-файлами в кодировки UTF-8
все отрабатывает замечательно

$pathtball = "C:\Users\Vasiliy\Desktop\BPM\treb\*"

$readfolders = Get-ChildItem $pathtball
foreach ($pathtbone in $readFolders)
{
    $index = [System.IO.File]::ReadAllText($pathtbone)

    # Индекс начала
    $IndexStart1 = $index.IndexOf("Уважаемый (ая) ")
    # Индекс конца
    $IndexEnd1 = $index.IndexOf("!")
    $indextotal1 = $index.Substring($IndexStart1, $IndexEnd1-$IndexStart1)
    $indextotal2 = $index.Substring($IndexStart2, $IndexEnd2-$IndexStart2)
}


Ошибка следующая


  Исключение при вызове "Substring" с "2" аргументами: "Значение
  StartIndex не может быть меньше нуля. Имя параметра: startIndex"
  C:\Users\Vasiliy\Desktop\BPM\renameallfilesv1.ps1:20 знак:36
  +     $indextotal1 = $index.Substring <<<< ($IndexStart1, $IndexEnd1-$IndexStart1)
      + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
      + FullyQualifiedErrorId : DotNetMethodException

    


Ответы

Ответ 1



Файл .docx - документ, созданный с помощью Microsoft Word 2007 или более новой версии Office. Формат файла основан на Open XML и использует сжатие по алгоритму ZIP для уменьшения размера файла. Через обычный редактор он откроется, но понять, что там написано, вы не сможете. Исходя из выше изложенного изменение кодировки данного текста не поможет. Чтобы прочесть файл docx в powershell, вам необходимо скачать и установить Open-Xml-PowerTools. Использую команду: (Select-OpenXmlString -path $file_name).content Где переменная $file_name является файлом "*.docx", который требуется прочесть. Спасибо insolor, Senior Pomidor, 1d0 за оказанную помощь.

Как сменить браузер поисковика Windows | “Поиск в интернете”?

#windows #windows_10 #powershell


Поисковик Windows, помимо поиска по файлам, предлагает поиск в интернете.


Я хочу сменить браузер, а также иметь batch/powershell скрипт для того, чтобы не
делать это вручную при переустановке Windows 10.

Интересуем меня именно смена браузера, а не смена поисковика, т.к имеются разные
Windows Builds, в которых этот поисковик может быть записан в реестре по-разному, например:
{8C3078A0-9AAB-4371-85D1-656CA8E46EE8}, {89418666-DF74-4CAC-A2BD-B69FB4A0228A}, {8C3078A0-9AAB-4371-85D1-656CA8E46EE8},
что делает громоздким скрипт и создает ложные записи в реестре.

Удаление IE11 и Edge, а также смена браузера по умолчанию, в моем вопросе не помогли.
    


Ответы

Ответ 1



Вот сообщение от Райана Гевина в блоге Windows, дам перевод только того, что касается проблемы: "К сожалению, в связи с тем, что Windows 10 становится всё популярнее, мы увидели, как некоторые программы нарушают правила Windows 10 и перенаправляют вас к поисковым провайдерам, которые не предназначены для работы с Cortana. Результатом является скомпрометированный опыт, который менее надежен и предсказуем. Непрерывность этих типов сценариев завершения задач нарушается, если Cortana не может зависеть от Bing в качестве поставщика поиска и Microsoft Edge в качестве браузера. Единственный способ, которым мы можем с уверенностью предоставить этот персонализированный, комплексный поиск, - это интеграция Cortana, Microsoft Edge и Bing - все это разработано для того, чтобы сделать ОС удобнее для вас. Начиная с сегодняшнего дня, чтобы гарантировать, что мы сможем предоставить интегрированные возможности поиска, разработанные для Windows 10, Microsoft Edge будет единственным браузером, который будет запускаться при поиске из окна Cortana." Это касается не только Кортаны, как голосового поиска, но и обычного текстового поиска. Так что штатными средствами - никак. Но, как всегда, если нельзя, а очень хочется, то можно. Например, отлавливать обращение к Edge с помощью Edge Detector, который будет отправлять запрос вместо Edge в ваш любимый браузер. Для FireFox есть дополнения, позволяющие при этом перенаправлять запросы к Bing в другие поисковые сервисы (ищите по тегу Bing to, например, Bing2Google). Да, это костыли, но с ними жить удобнее. P.S. К сожалению, эти костыли придётся ставить заново после каждого большого обновления Windows 10. Я не задумывался, можно ли устанавливать дополнение в Firefox в авторежиме, но EdgeDetector - думаю, вполне.

четверг, 23 января 2020 г.

PowerShell Бинарный Модуль

#powershell


Я создал бинарный модуль на C# (в виде dll). Он у меня нормально импортируется в
среду  PowerShell, посредством  командлет import-module, а также я его вижу с помощью
командлет get-module и его командлет выполняться здесь, как говорится, всё ОК. Но у
меня стоит задача это бинарный модуль импортировать на удаленную ПЭВМ. Но что бы импортировать
на удаленную ПЭВМ, он должен обладать свойством "импортированным в сеанс", т.е. когда
даю на выполнение командлет  Get-Module -ListAvailable, этот модуль невиден, естественно,
Invoke-command { import-module MyModul } -session New-PSSession -computerName 10.3.0.222
Выдает сообщение:


  Указанный модуль "MyModul" не был загружен, так как ни в одном из
  каталогов модулей не был обнаружен действительный файл модуля.

+ CategoryInfo          : ResourceUnavailable: (MyModul:String) [Import-Module],
FileNotFoundException
+ FullyQualifiedErrorId : Modules_ModuleNotFound,Microsoft.PowerShell.Commands.ImportModuleCommand
+ PSComputerName        : 10.3.0.222



Мой модуль находится в директории C:\Users\Alex_Kot\Documents\WindowsPowerShell\Modules.
Эта директория заданна в переменной среды $env:PSModulePath, т.е. здесь все тоже вроде
как ОК.

PS:
Не могу понять как мне сделать модуль способным импортироваться на удаленную ПЭВМ.
    


Ответы

Ответ 1



Импортируй модуль в объект сессии, вот так: $Session = New-PSSession -Computername 10.3.0.222 -Credential (Get-Credential) Invoke-Command -Session $Session {Import-Module MyModul} Import-PSSession -Session $Session -Module MyModul

вторник, 31 декабря 2019 г.

Парсинг строки при помощи регулярных выражений. Задачка на кавычки и пробелы.

#c_sharp #регулярные_выражения #синтаксический_анализ #powershell


Всю голову сломал себе =) из текстового файла читаются строки. В одной строке может
быть "несколько параметров". Нужно строчку разделить на эти параметры.
Есть несколько условий:


Параметры разделяются пробелами.


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


Никто не запрещает заключать параметры без пробелов в кавычки.


Например нужно следующую строку разбить на три.
D:\test "D:\test\Название папки" "D:\test\test"

На выходе из функции должен получить 3 строки содержащие соответственно:
D:\test
D:\test\Название папки
D:\test\test

Подскажите, как бы мне это сделать? Использование string.split() не подходит в этом
случае, потому решил, что это нужно реализовывать при помощи regexp.match()...
Задача еще усложняется тем, что количество параметров может быть не ограничено. Под
концом строки подразумевается \r\n
Очередной раз благодарю Вас за помощь в моей задаче    


Ответы

Ответ 1



Попробуйте ".+?"|[^ ]+ Только надо будет удалять кавычки у параметров, у которых они есть.

Ответ 2



Вот вам ручной парсер (стащил отсюда): public static string[] SplitArguments(string commandLine) { var parmChars = commandLine.ToCharArray(); var inSingleQuote = false; var inDoubleQuote = false; for (var index = 0; index < parmChars.Length; index++) { if (parmChars[index] == '"' && !inSingleQuote) { inDoubleQuote = !inDoubleQuote; parmChars[index] = '\n'; } if (parmChars[index] == '\'' && !inDoubleQuote) { inSingleQuote = !inSingleQuote; parmChars[index] = '\n'; } if (!inSingleQuote && !inDoubleQuote && parmChars[index] == ' ') parmChars[index] = '\n'; } return (new string(parmChars)).Split(new[] {'\n'}, StringSplitOptions.RemoveEmptyEntries); } Поддерживает также и одинарные кавычки. Можно переписать в виде генератора, будет немного поэффективнее.

понедельник, 30 декабря 2019 г.

Как заменить PowerShell в контекстном меню на командную строку?

#windows #cmd #консоль #powershell #командная_строка


Переустановил Windows и пропала командная строка из контекстного меню.
SHIFT+Right Button тоже ничего не дает, там только PowerShell, как его заменить?  


    


Ответы

Ответ 1



1) Добавление cmd в контекстное меню (оригинальная cтатья) Нажмите клавиши Win + R и введите regedit для запуска редактора реестра. Перейдите к разделу реестра HKEY_CLASSES_ROOT\Directrory\shell\cmd, нажмите правой кнопкой мыши по имени раздела и выберите пункт меню «Разрешения». В следующем окне нажмите кнопку Дополнительно. Нажмите Изменить рядом с пунктом «Владелец». В поле «Введите имена выбираемых объектов» введите имя вашего пользователя и нажмите Проверить имена, а затем — Ок. Примечание: если используется учетная запись Майкрософт, введите адрес электронной почты вместо имени пользователя. Отметьте пункт «Заменить владельца подконтейнеров и объектов» и «Заменить все записи разрешений дочернего объекта», затем нажмите Ок и подтвердите действие. Вы вернетесь в окно параметров безопасности раздела реестра, в нем выберите пункт «Администраторы» и установите отметку «Полный доступ», нажмите Ок. Вернувшись в редактор реестра, нажмите по значению HideBasedOnVelocityId (в правой части редактора реестра) правой кнопкой мыши и выберите пункт «Удалить». Повторите шаги 2-8 для разделов HKEY_CLASSES_ROOT\Directrory\Background\ shell\cmd и HKEY_CLASSES_ROOT\Drive\shell\cmd Результат при shift + right click`: 2) Замена PowerShell в win + x меню Откройте контекстное меню на панели задач и выберите пункт Параметры панели задач В появившемся меню отключите пункт Заменить командную строку оболочкой Windows PowerShell... Результат при win + x:

вторник, 24 декабря 2019 г.

Как вместо cmd сделать PowerShell Windows 10?

#cmd #windows_10 #powershell


Появилась проблема, почему-то, когда нажимаю Shift + ПКМ в нужной мне папке могу
открыть только обычную консоль cmd, а мне нужно именно PowerShell. Раньше был PowerShell,
потом долго не работал с ним, а теперь у меня cmd, ну, видимо,  

  

я что-то наклацал:) Помогите пожалуйста :D
    


Ответы

Ответ 1



я вспомнил, что в Visual Studio Code(я там работаю) есть возможность создать терминал, один из которых и есть powershell, открываеться сразу в нужной мне папке, так что, уже всё нормально.

пятница, 20 декабря 2019 г.

Как обновлять консоль в одном и том же месте без перезагрузки экрана?

#c_sharp #net #powershell


Подскажите как можно писать в консоль в тоже место асинхронно, как это делает докер
на следующем скрине:


    


Ответы

Ответ 1



Запоминаете текущие координаты курсора в консоли, потом устанавливаете их же. public static void Main(string[] args) { Console.Write("1 Downloading: "); var left1 = Console.CursorLeft; var top1 = Console.CursorTop; Console.WriteLine(); Console.Write("2 Downloading: "); var left2 = Console.CursorLeft; var top2 = Console.CursorTop; Console.CursorVisible = false; for (int i = 0; i < 1000; i++) { Console.SetCursorPosition(left1, top1); Console.Write(i + " MB"); Console.SetCursorPosition(left2, top2); Console.Write(i * 2 + " MB"); Thread.Sleep(100); } }

понедельник, 16 декабря 2019 г.

Узнать версию удаленной OS

#windows #bat #powershell


Есть удаленный компьютер, под какой-то версией Windows (начиная с WinXP Home и заканчивая
Win10). Компьютер не входит в домен, но на нем установлен RAdmin Server.

Нужно определить версию и редакцию ОС.

Т.к. компьютеров много (~300), то нужно что-то автоматизированное.

Пробовал

(Get-WmiObject Win32_OperatingSystem -computer "Имя компа").name


но для недоменных компьютеров возвращает "Отказано в доступе (E_ACCESSDENIED)"

Может можно как-то заскриптовать работу с RAdmin?

Update

Удалось автоматизировать вход на удаленную машину через Radmin Telnet. Теперь вопрос
- как получить редакцию ОС?

ver


возвращает

Microsoft Windows XP [Версия 5.1.2600]


а нужно еще редакцию Home или Professional

PowerShell на XP не установлен
    


Ответы

Ответ 1



wmic os get Caption,CSDVersion /value или (но у меня systeminfo думает ну очень долго) systeminfo | findstr /B /C:"OS Name" /C:"OS Version" Источник: https://www.windows-commandline.com/find-windows-os-version-from-command/

Ответ 2



Полный ответ выглядит так (решение на JScript) Запускаем RadminViewer в режиме telnet var proc = WshShell.Exec('radmin.exe /connect:' + host + ' /telnet'); Ждем какое-то время и через SendKeys вбиваем логин и пароль соединения WScript.Sleep(1000); WshShell.AppActivate(proc.ProcessID); WshShell.SendKeys("user{TAB}"); WshShell.SendKeys("pass{ENTER}"); если в системе существует и третья и вторая версия Radmin (которая не требует имени пользователя), то можно использовать такой код WshShell.AppActivate(proc.ProcessID); // Три Shift+Tab WshShell.SendKeys("+{TAB}+{TAB}+{TAB}"); // Если у нас вторая версия, то мы стоим на поле для ввода пароля WshShell.SendKeys("pass"); // Переместились на предыдущий контрол WshShell.SendKeys("+{TAB}"); // для второй версии мы попали на кнопку "Отмена", для третьей на поле для ввода пароля WshShell.SendKeys("pass"); // Переместились на предыдущий контрол WshShell.SendKeys("+{TAB}"); // для второй версии мы попали на кнопку "OK", для третьей на поле для ввода логина WshShell.SendKeys("user"); WshShell.SendKeys("{ENTER}"); Делаем паузу на установку соединения и на удаленной машине формируем bat-файл WScript.Sleep(1000); WshShell.AppActivate(proc.ProcessID); // Получение информации и сохранение ее в info.data cmd('echo systeminfo ^> info.data >> info.bat'); // На WinXP Home нет файла systeminfo, поэтому если вызов завершился неудачно cmd('if errorlevel 1 ( >> ' + cmdFile); // скачиваем его с FTP сервера cmd('echo ftp -s:get.ftp -n ' + ftpServer + ' >> info.bat'); cmd('echo expand systeminfo.cab systeminfo.exe >> ' + cmdFile); cmd('echo systeminfo ^> ' + datFile + ' >> ' + cmdFile); cmd('del systeminfo.exe >> ' + cmdFile); cmd('del systeminfo.cab >> ' + cmdFile); cmd(')>> ' + cmdFile); // Сжимаем полученный файл cmd('echo makecab info.data info.data.cab >> info.bat'); // И отправляем его с удаленной машины по FTP cmd('echo ftp -s:info.ftp -n ' + ftpServer + ' >> info.bat'); Формируем набор команд для скачивания файла с FTP cmd('echo USER ftp_user ftp_pass >> get.ftp'); cmd('echo GET systeminfo.cab >> get.ftp'); cmd('echo QUIT >> get.ftp'); Формируем набор команд для закачивания файла на FTP cmd('echo USER ftp_user ftp_pass >> info.ftp'); cmd('echo PUT info.data.cab >> info.ftp'); cmd('echo QUIT >> info.ftp'); Запускаем полученный bat-файл cmd("info.bat"); И закрываем сессию cmd("exit"); Функция cmd() определена так function cmd(command) { WshShell.SendKeys(command.replace(/[\^%+~\(\)]/g, "{$&}") + "{ENTER}"); WScript.Sleep(100); } Единственный минус метода - невозможность получить статус соединения от radmin С учетом того обстоятельства, что команды systeminfo нет в редакциях WinXP Home и его приходится заливать вручную, целесообразнее написать свою утилиту, которая скачается с FTP сервера и выполнит все необходимые манипуляции

Как сделать скриншот с удаленного рабочего стола?

#c_sharp #администрирование #vba #powershell #wmi


Допустим, есть 10 IP машин, на которых крутится какой - то процесс, который хочется
контролировать.

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

В приоритете решение на VBA (не путать сVB.NET) и без дополнительной установки софта.

Может быть можно решить задачу используя WMI?

Если нативно это сделать нельзя, то какими методами этого можно добиться? 
    


Ответы

Ответ 1



Готовый скрипт для Powershell, позволяющий сделать скриншот, всегда лежит в центре сценариев Technet Теперь об удаленном запуске. Собственно, сама возможность удаленного запуска должна быть разрешена. Вроде как это можно сделать при помощи PowerShell'овского Enable-PSRemoting-Force. Это запустит службу удаленного управления WinRM и пропишет исключения в брандмауэре. Но можно сделать для всего домена, используя механизм групповых политик. Как запустить? В голову приходят пара вариантов: Самый простой способ. ЕМНИП, начиная с XPюши: wmic /node:"имя_компа" process call create запускаемый_файл Через powershell: Invoke-Command -ComputerName имя_Компа -ScriptBlock { запускаемый_файл } -credential имя_пользователя # имя_пользователя - если необходимо Можно ещё работать с VB&WMI, но навскидку я не помню, как. Но, думаю, для решения задачи и двух вышеприведённых вариантов достаточно.

Ответ 2



для старых машин можно использовать psexec https://docs.microsoft.com/en-us/sysinternals/downloads/psexec для запуска утилиты.. например http://www.irfanview.com/ i_view32.exe /capture=0

суббота, 14 декабря 2019 г.

Вывод всех возможных ip-адресов из диапазона

#powershell


Нужно написать скрипт на powershell. Есть любой IP адрес сети и маска (к примеру:
10.151.96.0/21), нужно вывести все возможные ip-адреса, удовлетворяющие адресу сети
и его маске. Как организовать этот цикл, чтобы работал с любым начальным условием?
    


Ответы

Ответ 1



Пока суть да дело, вот код на C# накатал: using System; using System.Net; string rangeIP = "10.151.96.0"; int rangeMask = 21; int wildcard = 32 - rangeMask; byte[] ipb = IPAddress.Parse(rangeIP).GetAddressBytes(); Array.Reverse(ipb); int ip = BitConverter.ToInt32(ipb, 0); for (int i = 1; i < (1 << wildcard) - 1; i++) { int ipi = ip | i; byte[] ipib = BitConverter.GetBytes(ipi); Array.Reverse(ipib); Console.WriteLine(new IPAddress(ipib)); } Сейчас попробую PowerShell вспомнить... Во, так получилось: $rangeIP = "10.151.96.0" $rangeMask = 21 $wildcard = (32 - $rangeMask) $ipb = [Net.IPAddress]::Parse($rangeIP).GetAddressBytes() [Array]::Reverse($ipb) $ip = [BitConverter]::ToInt32($ipb, 0) For ($i = 1; $i -lt ((1 -shl $wildcard) - 1); $i++) { $ipi = ($ip -bor $i) $ipib = [BitConverter]::GetBytes($ipi) [Array]::Reverse($ipib) Write-Host (New-Object IPAddress(@(,$ipib))) } За соответствие кода канонам не отвечаю, я PS не знаю. :)

Распаковка массива zip архивов в одну папку с переименованием файлов

#windows #файлы #cmd #powershell #zip


Есть папка с большим количеством zip-архивов.
Каждый архив содержит внутри папку(имя папки то же, что и у архива) с 1+ файлов.
Как c помощью средств windows(и какого-нибудь архиватора)извлечь все файлы в одну
папку так, чтобы конечные файлы были переименованы по шаблону "<имя папки>-<имя файла>"?

    


Ответы

Ответ 1



Kак подсказал @nick_gabpe, нужно распаковать в папку: FOR %%Z IN ("%src_dir%\*.zip") DO ( 7z e "%%Z" -o"%tgt_dir%" ) Далее PowerShell скрипт выполнит остальное: $fiels = Get-ChildItem -Path . -rec -Filter "*.txt" # найти все файлы из директории, откуда запускается (.), с расширением txt foreach($f in $fiels){ $dirName = (Get-Item $f.FullName).Directory.Name # получаем имя папки # копируем файл с новым именем. Путь C:\temp\1111 должен существовать Copy-Item -Path $f.FullName -Destination "C:\temp\1111\$($dirName+ "-" + $f.Name)" }

Ответ 2



Вариант на чистом PowerShell (без использования внешних утилит): # Указываем папку с архивами $rootPath = 'D:\TEST' # Извлекаем и удаляем все архивы Add-Type -AssemblyName System.IO.Compression.FileSystem Get-Item "$rootPath\*.zip" | ForEach-Object { [System.IO.Compression.ZipFile]::ExtractToDirectory($_.FullName, $rootPath) Remove-Item $_.FullName -Verbose } # Избавляемся от папок Get-ChildItem $rootPath -Directory | ForEach-Object { Get-ChildItem $_.FullName | ForEach-Object { Move-Item $_.FullName -Destination "$($_.Directory.Parent.FullName)\$($_.Directory.BaseName)-$($_.Name)" -Verbose } Remove-Item $_.FullName -Verbose }

четверг, 5 декабря 2019 г.

Как описать документацию для PowerShell командлета на C#?

#c_sharp #powershell #документация


Не понимаю, откуда берёт документацию Get-Help, и как написать её для своих командлетов.
    


Ответы

Ответ 1



Для бинарных командлетов запрограммированных на C# Команда Get-Help ищет файл %moduleName%.dll-Help.xml в папке с самой скомпилированной сборкой модуля, содержащий документацию. Есть не очень внятный набор гайдов на msdn, написан коряво и не объясняет как и что. Есть пошаговый тутор с примерами, из которого уже понятно как это делать.

Настройка планировщика на подключение флешки

#windows #powershell #task #wmi #background_task


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


Ответы

Ответ 1



Я слегка слукавил, без планировщика не обойтись, хотя, наверное, можно и через автозагрузку решить всё это. Я для одного пожилого сотрудника когда-то использовал вот такой скрипт, который срабатывал, если вставлялась флэшка, автоопределяемая с буквой T и меткой "BP_flahka". Если буква диска не важна, то вместо if ($driveLetter -eq 'T:' -and $driveLabel -eq 'BP_flashka') можно использовать просто if ($driveLabel -eq 'ТутМеткаВашейФлэшки'). Код скрипта: #Requires -version 2.0 Register-WmiEvent -Class win32_VolumeChangeEvent -SourceIdentifier volumeChange write-host (get-date -format s) " Beginning script..." do{ $newEvent = Wait-Event -SourceIdentifier volumeChange $eventType = $newEvent.SourceEventArgs.NewEvent.EventType $eventTypeName = switch($eventType) { 1 {"Configuration changed"} 2 {"Device arrival"} 3 {"Device removal"} 4 {"docking"} } write-host (get-date -format s) " Event detected = " $eventTypeName if ($eventType -eq 2) { $driveLetter = $newEvent.SourceEventArgs.NewEvent.DriveName $driveLabel = ([wmi]"Win32_LogicalDisk='$driveLetter'").VolumeName write-host (get-date -format s) " Drive name = " $driveLetter write-host (get-date -format s) " Drive label = " $driveLabel # Запустить, если буква диска и метка совпали с нужными значениями if ($driveLetter -eq 'T:' -and $driveLabel -eq 'BP_flashka') { write-host (get-date -format s) " Starting task in 3 seconds..." start-sleep -seconds 3 start-process "E:\sync.bat" } } Remove-Event -SourceIdentifier volumeChange } while (1-eq1) #Идём в цикле дальше Unregister-Event -SourceIdentifier volumeChange Дальше всё просто. В планировщике создаём новое задание, с такими параметрами: Триггер: At log on Действие: Start a program Program/script: powershell Аргументы: -WindowStyle Hidden -ExecutionPolicy Unrestricted -File "Диск:\Путь\имя файла со скриптом.ps1" Update 1. Проверок для вставляемого хранилища можно устроить массу. Например: # узнаем тип файловой системы флэшки $fileSystem = ([wmi]"Win32_LogicalDisk='$driveLetter'").FileSystem # проверяем, сколько свободного места осталось (в байтах) на флэшке $freeSpace = ([wmi]"Win32_LogicalDisk='$driveLetter'").FreeSpace # или общий размер всей флэшки: $size = ([wmi]"Win32_LogicalDisk='$driveLetter'").Size # и так далее, а затем просто проверяем нужный нам параметр, например: if ($fileSystem -eq 'NTFS') { # в этом случае бэкап можно делать одним большим файлом } # и так далее Update 2. Работать будет, начиная с Windows Vista/Server 2008