我不明白为什么在运行下面的脚本时,第二个"write-output"没有出现在成绩单文件中??
start-transcript -Path "c:temptest_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;
这是我在成绩单文件中得到的内容:
记录文件内容
有人能解释一下吗?
TRANSCRIPT FILE:
Transcription démarrée, le fichier de sortie est c:temptest_transcript.txt
Répertoire : C:
Path Owner Access
---- ----- ------ temp MyDomainMyUser BUILTINXXX Allow FullControl
AUTORITE NTXXX Allow FullControl
BUILTINXXX Allow ReadAndExecute, Synchronize
AUTORITE NTXXX 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:temptest_file_20230109_124005.txt ».
**********************
Fin de la transcription Windows PowerShell
Heure de fin : 20230109124005
**********************
控制台:
Transcription démarrée, le fichier de sortie est c:temptest_transcript.txt
Répertoire : C:
Path Owner Access
---- ----- ------
temp MyDomainMyUser BUILTINXXX Allow FullControl
AUTORITE NTXXX Allow FullControl
BUILTINXXX Allow ReadAndExecute, Synchronize
AUTORITE NTXXX 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:temptest_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:temptest_transcript.txt
基于有用的注释:
tl;博士
-
你看到错误当PowerShell隐式应用
Format-Table
for-display格式时,这是异步行为的几种表现之一。 -
变通方法,所有次优不幸的是:
-
各命令(繁琐,容易出错):使用
Format-*
cmdlet显式与任何调用通常导致表格式化默认,以强制同步输出;在您的情况下,| Format-Table
在New-Item
之后。- 注意:
- 使用
Format-Table
可以防止在尝试给变量赋值或在管道中进一步处理输出时捕获命令的输出作为数据,因为Format-*
cmdlet发出的是格式化指令,而不是数据。
- 使用
- 注意:
-
脚本范围[引入300毫秒延迟]正如您所发现的,在末尾插入
Start-Sleep
有帮助,在以下条件下:-
脚本必须以同步输出到success输出流的命令结束。(即它必须而不是隐式表格格式),特别是通过输出字符串,例如在
Write-Output "2) A very simple message AFTER new-item."
调用中。(注意,您可以省略Write-Output
以利用PowerShell的隐式输出行为)。 -
Start-Sleep -MilliSeconds 300
必须将放在之前,它强制以下同步输出也呈现挂起的异步输出。 -
然而,由于PowerShell的for-display输出格式化系统与异步行为分开的另一个设计限制(注意两者都不是特定于
Start-Transcript
的使用,但后者以特定于该cmdlet的方式显示),如果不显式地使用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 CLI也可能发生数据丢失。参见下面的GitHub问题。
相关的GitHub问题:
GitHub issue #10994: the problem at hand (
Start-Transcript
相关).- 不幸的结论似乎是这将不是固定的。
GitHub issue #4594:讨论令人惊讶的异步行为一般(输出出现无序)。
GitHub问题#13985:潜在的数据丢失当使用CLI。