Войти

Показать полную графическую версию : [решено] запуск скрипта в powershell 7 и вывод информацию в консоли на русском


Njem
17-10-2022, 12:28
Добрый день, народ!

У меня есть задача: на постоянное основе в файл 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
это работает только перед запуском скрипта в той же консоли »

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


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

# code

DJ Mogarych
17-10-2022, 14:35
pwsh -file "c:\путь\к\скрипту\скрипт.ps1"

Njem
17-10-2022, 15:18
pwsh -file "c:\путь\к\скрипту\скрипт.ps1" »
хм.. так тоже думал, но это же получается отдельный файл с этой командой запуска, которая обращается к моему скрипту)
возможно, это вариант, но не думаю что хороший способ просто эти два файла потом перекидывать, если потребуется и так далее, думаю всё запихнуть в один и чтоб один файл запускать уже где угодно
и опять же, файлы то будут не на одной машине, а могут перемещаться, тобишь каждый раз новый путь прописывать тоже не камельфо

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

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

Njem
17-10-2022, 15:44
Или выдумывать проверку с перезапуском:
Код: »
слушай-ка, а работает, ого
круто! идёт запуск с pwsh, пасибо!)
осталось только понять как сделать отображаение русских букв, когда выводит консоль

DJ Mogarych
17-10-2022, 15:49
каждый раз новый путь прописывать »
Не надо ничего прописывать, pwsh работает без указания пути, если он установлен в систему.
Можете при установке PS7 указать, чтобы он встраивался в контекстное меню.
Можно запускать из ярлыка.

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

Njem
17-10-2022, 16:19
Не надо ничего прописывать, 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
А нет случаем идеи, как бы заграть в скрипт функцию проверки pwsh в системе? »

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

Или от обратного


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

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

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

или добавить -ea 4 (-ErrorAction 'Ignore')

Njem
18-10-2022, 12:55
Чтобы не убивать ошибки и варианты других программ лучше заменить "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
Так... вроде разобрался, только не понимаю на сколько это будет правильно и адекватно с точки зрения самого кода..)

В общем визуально получилось вот так:
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
# Проверка на наличие 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
... и все это ради индентации json на два пробела..

Njem
21-10-2022, 12:56
... и все это ради индентации json на два пробела.. »

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

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

Serguei Kouzmine
22-10-2022, 18:43
вот пример "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/html/M_Newtonsoft_Json_JsonConvert_SerializeObject_3.htm
https://www.newtonsoft.com/json/help/html/t_newtonsoft_json_formatting.htm
https://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_JsonTextWriter_Indentation.htm




© OSzone.net 2001-2012