Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] запуск скрипта в powershell 7 и вывод информацию в консоли на русском (http://forum.oszone.net/showthread.php?t=352141)

Njem 17-10-2022 12:28 2994340

запуск скрипта в powershell 7 и вывод информацию в консоли на русском
 
Добрый день, народ!

У меня есть задача: на постоянное основе в файл JSON добавлять изменения. Сделал эту задачу через скрипт на поше через конвертацию. Однако, конвертация обратно из объекта в джейсон не корректно отрабатывает, то есть при преобразовании сдвигает все ключи/значенния вправо.
Решил данную задачу можно через Powershell версии 7. Но столкнулся с проблемой, что при запуске скрипта используется дефолтный пош на машине. Подскажите, пожалуйста, как мне добавить в скрипт информацию, чтобы он запускал мой скрипт через pwsh? Весь инет перерыл, нигде нет такой информации((
В скрипт добавил тихую установку поша 7й версии и по разному пробовал добавить запуск pwsh с дальнейшими действиями моего скрипта, но увы... всё без результатно он либо продолжает использовать 5.1 версию, либо просто останавливает скрипт на моменте запуска 7й версии :(

И ещё, дополнительно, тоже не могу понять: когда я конвертирую ps1 в exe у меня при запуске русские буквы просто не отображаются...
Тобишь есть вот обычный вывод в консоль:
Код:

Write-Host -ForegroundColor Green -Object "Процесс обновления строки Json завершен"
Но в консоль выводится только ...json... то есть русских букв в принципе нет.
Пробовал и через такую команду:
Код:

[Console]::OutputEncoding = [System.Text.Encoding]::GetEncoding("cp866")
Однако, это не помогает, как я понял это работает только перед запуском скрипта в той же консоли, где ты запускаешь и в последующем запуске это снова нужно вводить.

Помогите, пожалуйста.

Спасибо!

Foreigner 17-10-2022 14:19 2994344

Цитата:

Цитата Njem
это работает только перед запуском скрипта в той же консоли »

Прямо из скрипта не работает? На счет приоритета запуска pwsh вместо powershell на ум приходит только смена позиций в переменной $env:Path. Или выдумывать проверку с перезапуском:

Код:

if ($PSVersionTable.PSEdition -ne 'Core') { pwsh -file $MyInvocation.MyCommand.Source; return }

# code


DJ Mogarych 17-10-2022 14:35 2994345

Код:

pwsh -file "c:\путь\к\скрипту\скрипт.ps1"

Njem 17-10-2022 15:18 2994346

Цитата:

Цитата DJ Mogarych
pwsh -file "c:\путь\к\скрипту\скрипт.ps1" »

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

Цитата:

Цитата Foreigner
Прямо из скрипта не работает? »

Если прям из по VSC запустить всё нормально, если из под поша тоже всё норм, а вот когда преобразовываешь в .exe то теряется кодировка и он тупо русский не видит(
я так понял что-то должно быть внутри в коде, чтобы он понимал русский язык..

Njem 17-10-2022 15:44 2994349

Цитата:

Цитата Foreigner
Или выдумывать проверку с перезапуском:
Код: »

слушай-ка, а работает, ого
круто! идёт запуск с pwsh, пасибо!)
осталось только понять как сделать отображаение русских букв, когда выводит консоль

DJ Mogarych 17-10-2022 15:49 2994350

Цитата:

Цитата Njem
каждый раз новый путь прописывать »

Не надо ничего прописывать, pwsh работает без указания пути, если он установлен в систему.
Можете при установке PS7 указать, чтобы он встраивался в контекстное меню.
Можно запускать из ярлыка.

Вариантов масса.

Njem 17-10-2022 16:19 2994351

Цитата:

Цитата DJ Mogarych
Не надо ничего прописывать, pwsh работает без указания пути, если он установлен в систему.
Можете при установке PS7 указать, чтобы он встраивался в контекстное меню.
Можно запускать из ярлыка. »

хм... звучит интересно
я ж имел ввиду что вот в коде:
Код:

pwsh -file "c:\путь\к\скрипту\скрипт.ps1"
Нужно каждый раз прописывать путь к скрипту, который нужно запустить в pwsh

А нет случаем идеи, как бы заграть в скрипт функцию проверки pwsh в системе?
Тип если pwsh есть, то юзать...{код}
если нет то он устанавливает pwsh и идёт по новой к первому пункту
Я установку pwsh сделал через команды:
Код:

Install-PackageProvider -Name chocolatey -Force
Код:

Set-PackageSource -Name Chocolatey -Trusted
Код:

Install-PackageProvider -Name ChocolateyGet
Код:

Install-Package -Name pwsh -Source Chocolatey -Provider ChocolateyGet -Force -Verbose
мб ваще есть какой-то проще вариант с тихой установкой

Просто проверка через
Код:

Find-Package -Name pwsh -Force
не срабатывает... валится ошибка: No match was found for the specified search criteria and package name 'pwsh'. Try Get-PackageSource to see all available registered package sources.
Но вот если руками попробовать тот же код юзануть, то он найдёт спокойно установленный pwsh у меня

Foreigner 17-10-2022 17:04 2994353

Цитата:

Цитата Njem
А нет случаем идеи, как бы заграть в скрипт функцию проверки pwsh в системе? »

Код:

if (Get-Command pwsh) { 'что-то делаем' } else { return }
Или от обратного

Код:

if (-not (Get-Command pwsh)) { return }
'что-то делаем'


Foreigner 17-10-2022 17:20 2994354

Чтобы не убивать ошибки и варианты других программ лучше заменить "pwsh" на "pwsh.exe*":

Код:

if (-not (Get-Command pwsh.exe*)) { return }
или добавить -ea 4 (-ErrorAction 'Ignore')

Njem 18-10-2022 12:55 2994372

Цитата:

Цитата Foreigner
Чтобы не убивать ошибки и варианты других программ лучше заменить "pwsh" на "pwsh.exe*":
Код:
if (-not (Get-Command pwsh.exe*)) { return }
или добавить -ea 4 (-ErrorAction 'Ignore') »

Так... вроде понял, но что-то видимо не до конца понял)
Получается, идёт проверка на наличие pwsh.exe:
Код:

if (-not (Get-Command pwsh.exe*)) {
    return
    }

Если проверка с false, то выполняются команды сделующие:
Код:

Install-PackageProvider -Name chocolatey -Force
Set-PackageSource -Name Chocolatey -Trusted
Install-PackageProvider -Name ChocolateyGet
Install-Package -Name pwsh -Source Chocolatey -Provider ChocolateyGet -Force -Verbose

И уже дальше идёт мой код, верно?
Тобишь и получается как-то так в самом начале:
Код:

if (-not (Get-Command pwsh.exe*)) {
    return
    }
    Install-PackageProvider -Name chocolatey -Force
    Set-PackageSource -Name Chocolatey -Trusted
    Install-PackageProvider -Name ChocolateyGet
    Install-Package -Name pwsh -Source Chocolatey -Provider ChocolateyGet -Force -Verbose
    if ($PSVersionTable.PSEdition -ne 'Core') {
        pwsh -file $MyInvocation.MyCommand.Source; return
      }
    {'мой код'}

Или что-то не так?
Просто по факту оно каждый раз запускает инсталятор pwsh, хотя когда он есть, надо скрип...

Njem 18-10-2022 13:17 2994373

Так... вроде разобрался, только не понимаю на сколько это будет правильно и адекватно с точки зрения самого кода..)

В общем визуально получилось вот так:
Код:

if (-not (Get-Command pwsh.exe*)) {
    return
    Install-PackageProvider -Name chocolatey -Force
    Set-PackageSource -Name Chocolatey -Trusted
    Install-PackageProvider -Name ChocolateyGet
    Install-Package -Name pwsh -Source Chocolatey -Provider ChocolateyGet -Force -Verbose
    }
   
else {
    if ($PSVersionTable.PSEdition -ne 'Core') {
        pwsh -file $MyInvocation.MyCommand.Source;
        return
        Write-Host -Object "ERROR RUN PWSH.EXE"
      }
    else {
        'Пошёл мой код'
      }
}

Тип он проверяет на наличие установленного в система pwsh.exe, далее он переходит к else и выполняет свой внутренний if и ещё раз проверяет pwsh и запускает его, после идёт на else
не знаю, есть ли смысл делать elseif как дополнительный параметр, если вдруг у него не получилось запустить pwsh?
да и вообще нужна ли вторая проверка и запуск самого поша 7 ещё раз, тоже не знаю...
работать то (вроде) работает, а вот сильно ли это костыльно и херово (мол пока что работает и ладно) вот это не знааю.. хотелось бы, конечно, сделать грамотно и чотко)

p.s. хотя я смотрю косяк возникает когда я из этого .ps1 формируют .exe...
первое что он выдаёт это ошибку: The command cannot be run because the File parameter requires a fine path. Supply a path for the File parameter and then try the command again.

Это 101% не в моё коде, ибо если мой код также преобразовать в .exe то там всё отрабатывает как нужно и красиво, а вот если добавляешь эту часть с установкой.. проверкой pwsh то такая фигня((


Методом проб и ошибок, ругается он на вот эту команду: pwsh.exe -file $MyInvocation.MyCommand.Source
и ничего дальше не запускает.. точно также (если выделить именно этот объект и запустить его)
тогда не понимаю, почему он в .ps1 полноценно это всё отрабатывает и никаких ошибок не вызывает...

Foreigner 18-10-2022 16:29 2994379

Код:

# Проверка на наличие pwsh.exe в $env:Path, если нет скрипт завершается

if (-not (Get-Command pwsh.exe*))
{
    return
}

# Проверка редакции PowerShell, в которой выполняется скрипт.
# Если скрипт выполняет powershell.exe, а не pwsh.exe, скрипт перезапускается в pwsh.exe
# Этот экземпляр завершается

if ($PSVersionTable.PSEdition -ne 'Core')
{
        pwsh -file $MyInvocation.MyCommand.Source
        return
}

# Здесь весь остальной код


Serguei Kouzmine 19-10-2022 03:46 2994398

... и все это ради индентации json на два пробела..

Njem 21-10-2022 12:56 2994590

Вложений: 2
Цитата:

Цитата Serguei Kouzmine
... и все это ради индентации json на два пробела.. »

Там не просто два пробела) там весь JSON улетает в целом)
Даже если просто два пробела ему указать, всё равно улетает всё также, как и улетало, только при 4х пробелов))

Специально для тебя, чтоб понимал приложил скриншот как выглядило до и после конвертации джейсона)

Serguei Kouzmine 22-10-2022 18:43 2994698

вот пример "pretty-print"

Код:

$r = @'
{"a" : 1
,
    "b" : {
"c" :[
2,3,4]
}   
}
'@

статичесими фактори методами классов Newtonsoft.Json
Код:

$y =  [Newtonsoft.Json.JsonConvert]::DeserializeObject($r)

$n = [Newtonsoft.Json.JsonConvert]::SerializeObject($y, [Newtonsoft.Json.Formatting]::Indented)

write-output $n


Код:

{
  "a": 1,
  "b": {
    "c": [
      2,
      3,
      4
    ]
  }
}


как конфиурировать indent






то есть если надо чтобы выглядело как

Код:

{
          "a": 1,
          "b": {
                    "c": [
                              2,
                              3,
                              4
                    ]
          }
}

написано в
https://www.newtonsoft.com/json/help...zeObject_3.htm
https://www.newtonsoft.com/json/help...formatting.htm
https://www.newtonsoft.com/json/help...ndentation.htm


Время: 23:51.

Время: 23:51.
© OSzone.net 2001-