POWERSHELL: расшифровка не работает должным образом после форматирования таблицы и нового элемента

Не могу понять, почему при запуске следующего скрипта в файле расшифровки не появляется второй "запись-вывод"???

start-transcript -Path "c:\temp\test_transcript.txt" -Append;
    
$acl = Get-Acl "c:\temp";
$acl | Format-Table -Wrap;

Write-Output "1) A very simple message BEFORE new-item.";
New-Item -Path "C:\temp" -Name "test_file_$(get-date -f "yyyyMMdd_HHmmss").txt" -ItemType File -Verbose -ErrorAction Stop;

#Why is th second message not included int the transcript log file ???
Write-Output "2) A very simple message AFTER new-item.";

Stop-Transcript;

Вот что я получаю в файле стенограммы:

Содержимое файла расшифровки

У кого-нибудь есть объяснение этому?

ФАЙЛ ТЕХНОЛОГИИ:

    Transcription démarrée, le fichier de sortie est c:\temp\test_transcript.txt
    
    
        Répertoire : C:\
    
    
    Path Owner              Access
    ---- -----              ------ temp MyDomain\MyUser BUILTIN\XXX Allow  FullControl
                            AUTORITE NT\XXX Allow  FullControl
                            BUILTIN\XXX Allow  ReadAndExecute, Synchronize
                            AUTORITE NT\XXX authentifiés Allow  Modify, Synchronize
    
    
    1) A very simple message BEFORE new-item.
EN CLAIR : Opération « Créer un fichier » en cours sur la cible « Destination : C:\temp\test_file_20230109_124005.txt ».
    
    **********************
Fin de la transcription Windows PowerShell
Heure de fin : 20230109124005
    **********************

КОНСОЛЬ :

Transcription démarrée, le fichier de sortie est c:\temp\test_transcript.txt


    Répertoire : C:\


Path Owner              Access
---- -----              ------
temp MyDomain\MyUser BUILTIN\XXX Allow  FullControl
                        AUTORITE NT\XXX Allow  FullControl
                        BUILTIN\XXX Allow  ReadAndExecute, Synchronize
                        AUTORITE NT\XXX authentifiés Allow  Modify, Synchronize


1) A very simple message BEFORE new-item.
EN CLAIR : Opération « Créer un fichier » en cours sur la cible « Destination : C:\temp\test_file_20230109_124005.txt ».


    Répertoire : C:\temp


Mode          LastWriteTime Length Name
----          ------------- ------ ----
-a---- 09/01/2023     12:40      0 test_file_20230109_124005.txt
2) A very simple message AFTER new-item.
Transcription arrêtée, le fichier de sortie est C:\temp\test_transcript.txt

New-Item завершается успешно? Поскольку -ErrorAction Stop вызывает эффект, который вы видите, сценарий останавливается в этой точке, если New-Item вызывает ошибку.

Scepticalist 09.01.2023 13:01

Оберните New-Item в блок try{}catch{} и посмотрите, что появится в стенограмме: try { New-Item -Path "C:\temp" -Name "test_file_$(get-date -f "yyyyMMdd_HHmmss").txt" -ItemType File -Verbose -ErrorAction Stop} catch {"New-Item failed!"} — я ожидаю, что если New-Item не удастся, вы увидите New-Item failed! в своей стенограмме.

Jeff Zeitlin 09.01.2023 13:12

Кроме того, чтобы избежать путаницы между оператором -f и параметром -FormatGet-Date, используйте -For вместо -f в качестве параметра Get-Date.

Jeff Zeitlin 09.01.2023 13:15

Спасибо. Новый элемент завершен успешно. Но я перепроверю, напишу try/catch, как вы говорите, и буду держать вас в курсе.

RaFla 09.01.2023 14:01

Точно такое же поведение с try...catch и -For вместо -f. Ошибок нет, но второе сообщение не появляется. Должен признаться, я заблудился...

RaFla 09.01.2023 14:14

@Scepticalist - на скриншоте показан нижний колонтитул в файле из Stop-Transcript, поэтому, предположительно, скрипт завершился. Я подумал, что это может быть связано с задержкой в ​​​​300 мс, встроенной в Format-Table дальше по сценарию, что означает, что Stop-Transcript вызывается до того, как весь вывод будет записан в расшифровку, но я не смог воспроизвести проблему локально, чтобы проверить это.

mclayton 09.01.2023 14:47

Интересно: я не знал об этой задержке в 300 мс: это может быть объяснением. Могу ли я вставить Start-Sleep() в конец моего скрипта? это решит проблему? Или есть какой-то метод flush()? Одно можно сказать наверняка: удаление строки таблицы форматов решает проблему.

RaFla 09.01.2023 15:43

Пахнет как эта известная проблема: github.com/PowerShell/PowerShell/issues/10994

Bacon Bits 09.01.2023 15:44

Спасибо @BaconBits: очень интересная ссылка. Я еще не все читал, но очень похоже.

RaFla 09.01.2023 15:48

Простым обходным решением было бы направить любой «неявный» вывод в Out-Host или Out-String, чтобы сделать его «явным». .например. Write-Output … | Out-Host, что превращает его в операцию блокировки, которая завершится до вызова следующей строки. Однако это добавит много мусора в ваш код. Я не думаю, что Start-Sleep сработает, потому что он блокирует Format-Table, насколько я помню, поэтому вы просто окажетесь в том же положении через 2 секунды. Не стесняйтесь попробовать и доказать, что я ошибаюсь :-)

mclayton 09.01.2023 18:59
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
10
60
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Опираясь на полезные комментарии:

тл;др

  • Вы видите ошибку (хотя она не классифицируется как таковая), которая является одним из нескольких проявлений асинхронного поведения, когда PowerShell неявно применяет Format-Table форматирование для отображения.

  • Обходные пути, все неоптимальные, к сожалению:

    • Для каждой команды [громоздкий, подверженный ошибкам]: явно используйте командлет Format-* с любым вызовом, который обычно приводит к форматированию таблицы по умолчанию, чтобы принудительно синхронизировать вывод; в вашем случае поставьте | Format-Table после звонка New-Item.

      • Примечание:
        • Использование Format-Table предотвращает захват вывода команды в виде данных, когда вы пытаетесь присвоить значение переменной или обработать вывод дальше в конвейере, потому что командлеты Format-* выдают инструкции по форматированию, а не данные.
    • Для всего скрипта [вводит задержку в 300 мс]: как вы обнаружили, вставка Start-Sleep в конце помогает при следующих условиях:

      • Сценарий должен заканчиваться командой, которая синхронно выводит в выходной поток успеха (т. е. он не должен быть неявно отформатирован в виде таблицы), в частности, путем вывода строки, например, в вашем вызове Write-Output "2) A very simple message AFTER new-item.". (Обратите внимание, что вы можете опустить Write-Output, чтобы воспользоваться неявным поведением вывода PowerShell).

      • Start-Sleep -MilliSeconds 300 должен быть размещен непосредственно перед ним, что заставляет следующий синхронный вывод также отображать ожидающий асинхронный вывод.

      • Однако из-за другого конструктивного ограничения в системе форматирования вывода PowerShell для отображения, которая отделена от асинхронного поведения (обратите внимание, что ни то, ни другое не относится к использованию Start-Transcript, но последнее проявляется способом, специфичным для этого командлета), существует общее ловушка, если вы не используете вызовы Format-Table явно:

        • Если первый неявно отформатированный в виде таблицы оператор в сценарии не использует предопределенных данных форматирования, он блокирует столбцы отображения для всех последующих неявно отформатированных в виде таблицы операторов, что может сделать вывод последних фактически невидимым — см. этот ответ.
        • Вызовы Format-Table для каждой команды избегают этой проблемы (а также принудительно синхронизируют вывод) за счет отсутствия вывода данных, как отмечалось выше.

Упрощенный пример:

Start-Transcript t.txt

# This triggers *implicit* Format-Table output that is *asynchronous*,
# due to the output object having 4 or fewer properties and
# its type not having formatting-data associated with, as with the
# Get-Acl output in your question.
# NOTE:
#  * Curiously, the asynchronous behavior is also triggered in this case
#    if you append | Format-Table, but only affects SUBSEQUENT 
#    implicitly table-formatted statements, including those whose 
#    output types DO have formatting-data.
[pscustomobject] @{ Foo = 'Bar' }

# WORKAROUND:
#  Sleep for 300 msecs., then output *synchronously* to the success output stream.
#  This forces pending asynchronous table output to print. 
Start-Sleep -Milliseconds 300
"==== Done."

Stop-Transcript

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

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

Соответствующие проблемы GitHub:

Отличный ответ! В итоге я добавил строку «Start-Sleep -Seconds 1;» перед моим последним вызовом записи-вывода. Конечно, это не элегантное решение msot, но это избавляет от необходимости ставить «| format-table» после каждого нестрокового объекта. Плюс 1-секундная задержка в конце скрипта в моем контексте не имеет большого значения. Спасибо за помощь !

RaFla 09.01.2023 16:53

Другие вопросы по теме