PowerShell 技能连载 - 使用 NTFS 流(第 4 部分)

每当您从 Internet(或其他不受信任的来源)下载文件并将其存储在 NTFS 驱动器上时,Windows 就会使用区域标识符对这些文件进行静默标记。例如,这就是为什么 PowerShell 拒绝执行从域外部下载的脚本的原因。

You can actually look at the Zone Identifier. Just make sure you download a file from the Internet and store it on a NTFS drive. Next, use this line to view the Zone Identifier:
您实际上可以查看区域标识符。只要确保您从 Internet 下载文件并将其存储在 NTFS 驱动器上即可。接下来,使用此行查看区域标识符:

1
Get-Content -Path C:\users\tobia\Downloads\Flyer2021.rar -Stream Zone.Identifier

如果存在该流,则您会看到类似以下信息:

[ZoneTransfer]
ZoneId=3
ReferrerUrl=https://shop.laserkino.de/
HostUrl=https://www.somecompany/Flyer2021.rar

它暴露了文件的来源以及从中检索文件的远程区域的类型。如果没有附加到文件的区域信息,则上述命令将引发异常。

若要从文件中删除区域信息(并删除所有限制),请使用 Unblock-File cmdlet。例如,要取消阻止“下载”文件夹中的所有文件,请尝试以下操作:

1
Get-ChildItem -Path C:\users\tobia\Downloads\ -File | Unblock-File -WhatIf

删除 -WhatIf 参数以实际删除该保护流。

评论

PowerShell 技能连载 - 使用 NTFS 流(第 3 部分)

在上一个技能中,我们解释了 NTFS 流是如何工作的。但是,不可能发现隐藏文件流的名称。在 PowerShell 5及更高版本中,大多数访问文件系统的 cmdlet 都新增了一个名为 -Stream 的新参数。有了它,现在访问 NTFS 流变得很简单,因此现在可以重写以前脚本中使用路径名称中的冒号表示的示例,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# create a sample file
$desktop = [Environment]::GetFolderPath('Desktop')
$path = Join-Path -Path $desktop -ChildPath 'testfile.txt'
'Test' | Out-File -FilePath $Path

# attach hidden info to the file
'this is hidden' | Set-Content -Path $path -Stream myHiddenStream

# get hidden info from the file
Get-Content -Path $path -Stream myHiddenStream

# remove hidden streams
Remove-Item -Path $Path -Stream myHiddenStream

# show file
explorer /select,$Path

现在,还可以查看(并发现)隐藏的 NTFS 流。让我们创建一个带有一堆流的示例文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
# create a sample file
$desktop = [Environment]::GetFolderPath('Desktop')
$path = Join-Path -Path $desktop -ChildPath 'testfile.txt'
'Test' | Out-File -FilePath $Path

# attach hidden info to the file
'this is hidden' | Set-Content -Path $path -Stream myHiddenStream
'more info' | Set-Content -Path $path -Stream additionalInfo
'anotherone' | Set-Content -Path $path -Stream 'blanks work, too'
'last' | Set-Content -Path $path -Stream finalStream

# find stream names:
Get-Item -Path $Path -Stream * | Select-Object -Property Stream, Length

现在,Get-Item 可以暴露 NTFS 流,并且输出可能如下所示:

Stream           Length
------           ------
:$DATA               14
additionalInfo       11
blanks work, too     12
finalStream           6
myHiddenStream       16

如您所见,您现在可以发现所有流的名称。流 “:$DATA” 表示文件的“可见的”主要内容。

评论

PowerShell 技能连载 - 使用NTFS流(第 2 部分)

在上一个技巧中,我们解释了 NTFS 流如何存储有关文件的其他数据,这引发了一个问题,即如何删除此类流或首先发现隐藏的 NTFS 流。

要删除隐藏的命名流,请使用 Remove-Item——就像您要删除整个文件一样。这是一个简单的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# create a sample file
$path = "$env:temp\test.txt"
'Test' | Out-File -FilePath $Path

# attach hidden info to the file
'this is hidden' | Set-Content -Path "${path}:myHiddenStream"

# get hidden info from the file
Get-Content -Path "${path}:myHiddenStream"

# remove hidden streams
Remove-Item -Path "${path}:myHiddenStream"

# stream is gone, this raises an error:
Get-Content -Path "${path}:myHiddenStream"

# file with main stream is still there:
explorer /select,$Path

尽管您可以像创建单个文件一样创建和删除 NTFS 流,只需添加一个冒号和流名称即可,但没有找到流名称的简单方法。至少不是我们在这里访问流的方式。在第 3 部分中,我们最终将发现隐藏的流名称。

评论

PowerShell 技能连载 - 使用 NTFS 流(第 2 部分)

在上一个技巧中,我们解释了 NTFS 流如何存储有关文件的其他数据,这引发了一个问题,即如何删除此类流或首先发现隐藏的 NTFS 流。

要删除隐藏的命名流,请使用 Remove-Item——就像您要删除整个文件一样。这是一个简单的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# create a sample file
$path = "$env:temp\test.txt"
'Test' | Out-File -FilePath $Path

# attach hidden info to the file
'this is hidden' | Set-Content -Path "${path}:myHiddenStream"

# get hidden info from the file
Get-Content -Path "${path}:myHiddenStream"

# remove hidden streams
Remove-Item -Path "${path}:myHiddenStream"

# stream is gone, this raises an error:
Get-Content -Path "${path}:myHiddenStream"

# file with main stream is still there:
explorer /select,$Path

尽管您可以像创建单个文件一样创建和删除 NTFS 流,只需添加一个冒号和流名称即可,但没有找到流名称的简单方法。至少不是我们在这里访问流的方式。在第 3 部分中,我们最终将发现隐藏的流名称。

评论

PowerShell 技能连载 - 使用NTFS流(第 1 部分)

在 NTFS 文件系统上,您可以将其他信息存储在隐藏的文件流中。传统上,PowerShell 通过冒号访问文件流,因此这会将隐藏的文本信息附加到纯文本文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
# create a sample file
$desktop = [Environment]::GetFolderPath('Desktop')
$path = Join-Path -Path $desktop -ChildPath 'testfile.txt'
'Test' | Out-File -FilePath $Path

# attach hidden info to the file
'this is hidden' | Set-Content -Path "${path}:myHiddenStream"

# attach even more hidden info to the file
'this is also hidden' | Set-Content -Path "${path}:myOtherHiddenStream"

# show file
explorer /select,$Path

该代码首先确定到您的桌面的路径,然后创建一个示例纯文本文件。

接下来,它在名为 “myHiddenStream” 和 “myOtherHiddenStream” 的两个流中添加隐藏信息。当您在资源管理器中查看文件时,这些流仍然不可见。

PowerShell 仍然可以像下面这样访问这些流:

1
2
3
# get hidden info from the file
Get-Content -Path "${path}:myHiddenStream"
Get-Content -Path "${path}:myOtherHiddenStream"

请注意,这些流仅存在于使用 NTFS 文件系统的存储中。当您将这些文件复制到其他文件系统时,即使用 exFat 将它们复制到USB记忆棒中,Windows 将显示一个警告对话框,提示所有流将被删除。

评论

PowerShell 技能连载 - 使用 NTFS 流(第 1 部分)

在 NTFS 文件系统上,您可以将其他信息存储在隐藏的文件流中。传统上,PowerShell 通过冒号访问文件流,因此这会将隐藏的文本信息附加到纯文本文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
# create a sample file
$desktop = [Environment]::GetFolderPath('Desktop')
$path = Join-Path -Path $desktop -ChildPath 'testfile.txt'
'Test' | Out-File -FilePath $Path

# attach hidden info to the file
'this is hidden' | Set-Content -Path "${path}:myHiddenStream"

# attach even more hidden info to the file
'this is also hidden' | Set-Content -Path "${path}:myOtherHiddenStream"

# show file
explorer /select,$Path

该代码首先确定到您的桌面的路径,然后创建一个示例纯文本文件。

接下来,它在名为 “myHiddenStream” 和 “myOtherHiddenStream” 的两个流中添加隐藏信息。当您在资源管理器中查看文件时,这些流仍然不可见。

PowerShell 仍然可以像下面这样访问这些流:

1
2
3
# get hidden info from the file
Get-Content -Path "${path}:myHiddenStream"
Get-Content -Path "${path}:myOtherHiddenStream"

请注意,这些流仅存在于使用 NTFS 文件系统的存储中。当您将这些文件复制到其他文件系统时,即使用 exFat 将它们复制到USB记忆棒中,Windows 将显示一个警告对话框,提示所有流将被删除。

评论

PowerShell 技能连载 - 观看德国电视节目

German public broadcasting companies maintain rich TV archives and let users view their shows through web interfaces. There is typically no way to download shows or easily find their download URLs.
德国公共广播公司保留着丰富的电视档案,并允许用户通过 Web 界面观看其节目。通常无法下载节目或轻松找到其下载 URL。

以下脚本下载了所有节目及其网络位置的非官方目录:

1
2
3
4
# download the German mediathek database as JSON file
$path = "$env:temp\tv.json"
$url = 'http://www.mediathekdirekt.de/good.json'
Invoke-RestMethod -Uri $url -UseBasicParsing -OutFile $path

下载该文件后,您可以使用其他脚本来显示选择对话框,并浏览要观看的电视节目。然后,您可以选择一个或多个节目,并要求 PowerShell 将这些视频自动下载到您的计算机上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
$Path = "$env:temp\tv.json"

$data = Get-Content -Path $Path -Raw |
ConvertFrom-Json |
ForEach-Object { $_ } |
ForEach-Object {
# define a string describing the video. This string will be shown in a grid view window
$title = '{0,5} [{2}] "{1}" ({3})' -f ([Object[]]$_)
# add the original data to the string so when the user select a video,
# the details i.e. download URL is still available
$title | Add-Member -MemberType NoteProperty -Name Data -Value $_ -PassThru
}

$data |
Sort-Object |
Out-GridView -Title 'Select Video(s)' -OutputMode Multiple |
ForEach-Object {
# take the download URL from the attached original data
$url = $_.Data[5]
$filename = Split-Path -Path $url -Leaf
$filepath = Join-Path -Path $env:temp -ChildPath $filename
$title = 'Video download {0} ({1})' -f $_.Data[1], $_.Data[0]
Start-BitsTransfer -Description $title -Source $url -Destination $filepath
# you can use a simple web request as well in case BITS isn't available
# Invoke-WebRequest -Uri $url -OutFile $filepath -UseBasicParsing

# open video in associated player
Invoke-Item -Path $filepath
}
评论

PowerShell 技能连载 - 观看德国电视节目

German public broadcasting companies maintain rich TV archives and let users view their shows through web interfaces. There is typically no way to download shows or easily find their download URLs.
德国公共广播公司保留着丰富的电视档案,并允许用户通过 Web 界面观看其节目。通常无法下载节目或轻松找到其下载 URL。

以下脚本下载了所有节目及其网络位置的非官方目录:

1
2
3
4
# download the German mediathek database as JSON file
$path = "$env:temp\tv.json"
$url = 'http://www.mediathekdirekt.de/good.json'
Invoke-RestMethod -Uri $url -UseBasicParsing -OutFile $path

下载该文件后,您可以使用其他脚本来显示选择对话框,并浏览要观看的电视节目。然后,您可以选择一个或多个节目,并要求 PowerShell 将这些视频自动下载到您的计算机上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
$Path = "$env:temp\tv.json"

$data = Get-Content -Path $Path -Raw |
ConvertFrom-Json |
ForEach-Object { $_ } |
ForEach-Object {
# define a string describing the video. This string will be shown in a grid view window
$title = '{0,5} [{2}] "{1}" ({3})' -f ([Object[]]$_)
# add the original data to the string so when the user select a video,
# the details i.e. download URL is still available
$title | Add-Member -MemberType NoteProperty -Name Data -Value $_ -PassThru
}

$data |
Sort-Object |
Out-GridView -Title 'Select Video(s)' -OutputMode Multiple |
ForEach-Object {
# take the download URL from the attached original data
$url = $_.Data[5]
$filename = Split-Path -Path $url -Leaf
$filepath = Join-Path -Path $env:temp -ChildPath $filename
$title = 'Video download {0} ({1})' -f $_.Data[1], $_.Data[0]
Start-BitsTransfer -Description $title -Source $url -Destination $filepath
# you can use a simple web request as well in case BITS isn't available
# Invoke-WebRequest -Uri $url -OutFile $filepath -UseBasicParsing

# open video in associated player
Invoke-Item -Path $filepath
}
评论

PowerShell 技能连载 - 查找上次登录的用户

要查找有关 Windows 上最后登录的用户的详细信息,可以查询注册表:

1
2
Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI" |
Select-Object -Property LastLo*, Idle*

结果看起来像这样:

LastLoggedOnDisplayName : Tobias Weltner
LastLoggedOnProvider    : {D6886603-9D2F-4EB2-B667-1971041FA96B}
LastLoggedOnSAMUser     : .\tobia
LastLoggedOnUser        : .\tobia
LastLoggedOnUserSID     : S-1-5-21-2770831484-2260150476-2133527644-1001
IdleTime                : 62486093

同样,此行返回 Windows 注册表中注册的所有用户配置文件:

1
2
Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\profilelist\*' |
Select-Object -Property ProfileImagePath, FullProfile
评论

PowerShell 技能连载 - 使用 BITS 来下载文件(第 2 部分)

BITS(背景智能传输系统)是Windows用于下载大文件(例如操作系统更新)的技术。您也可以使用该服务,例如异步下载文件。执行此操作时,您无需等待下载完成,甚至可以在几天内跨越多次重启下载超大文件。每当用户再次登录时,下载就会继续。

下面的示例代码以较低优先级的异步后台任务下载 NASA 火星报告:

1
2
3
$url = 'https://mars.nasa.gov/system/downloadable_items/41764_20180703_marsreport-1920.mp4'
$targetfolder = $env:temp
Start-BitsTransfer -Source $url -Destination $targetfolder -Asynchronous -Priority Low

异步 BITS 传输的缺点是您需要手动完成文件传输,因为 BITS 会将数据下载到隐藏的缓存中。由您决定何时运行 Get-BitsTransfer 并确定已完成的作业,然后使用 Complete-BitsTransfer 完成文件传输。

本示例将检查是否已完成传输并完成下载:

1
2
3
4
5
6
7
8
9
10
11
12
Get-BitsTransfer |
ForEach-Object {
Write-Warning $_.FileList.RemoteName
$_
} |
Where-Object { $_.jobstate -eq 'Transferred' } |
ForEach-Object {
#$_ | Select-Object -Property *
$file = $_.FileList.LocalName
Write-Warning "Copy file $file..."
$_ | Complete-BitsTransfer
}

Windows 正在使用相同的技术来下载大量的操作系统更新。如果您具有管理员特权,则可以检查由其他用户(包括操作系统)发起的 BITS 传输:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
PS> Get-BitsTransfer -AllUsers

JobId DisplayName TransferType JobState
----- ----------- ------------ ------
18514439-0e92-4ca8-88b4-4b2aa0036114 MicrosoftMapsBingGeoStore Download Sus...
9e76ff92-65e2-4b3c-bb01-263e485e986a Dell_Asimov.C18EE5B49BDB373421EFA627336E417FC7EBB5B3 Download Sus...
7bd117fe-2326-4198-a2a6-884022acb3ad Dell_Asimov.F10AAAECCA3ED0E344B68351EB619B5356E6C3C5 Download Sus...

PS> Get-BitsTransfer -AllUsers | Select-Object OwnerAccount, Priority, FileList

OwnerAccount Priority FileList
------------ -------- --------
NT AUTHORITY\NETWORK SERVICE Normal {}
NT AUTHORITY\SYSTEM Foreground {https://downloads.dell.com/catalog/CatalogIndexPC.cab}
NT AUTHORITY\SYSTEM Foreground {https://dellupdater.dell.com/non_du/ClientService/Catalog/CatalogI...
评论