PowerShell 技能连载 - 学习在Powershell中使用管道的3种有效方法

在Powershell中,管道是一个简单但有效的概念之一。在本教程中,我们将学习如何正确使用管道,并使我们的脚本在Powershell中整洁。

什么是管道?

Windows Powershell通过管道运行命令。我们看到的每个命令行都是一个管道。一个管道可以包含一个或多个命令,多个命令用竖线字符“|”分隔。

命令从左到右执行,每个命令的输出被传送或传递给其后面的命令。管道中最后一个命令的输出就是显示在屏幕上的内容。

1
2
3
4
Get-Service #it is a single commad pipeline

#Multicommand pipelines looks similar
Get-Service| out-file servicelist.txt

Get-Service |out-file servicelist.txt 没有显示任何输出,你知道为什么吗?

嗯,它会直接将输出存储到管道后面提到的文本文件中。如果你理解了这一点,那么你就走在正确的道路上。

选择、排序和测量对象

您必须已经理解了流水线的概念。现在让我们看看如何使用 select-object, sort-object,measure-object 结合流水线。让我们通过一些示例来看看如何使用上述管道。

根据属性对对象进行排序

Sort-Object 可以重新对管道中的对象进行排序。

1
Get-Service | Sort-Object Name Descending

类似地,您可以尝试在上面尝试 Ascending 并查看输出结果。

根据属性测量对象

Measure-Object 可以测量管道中的对象。我们需要添加 -Property 来指定单个数值属性。 在 -Property 后面,我们可以添加以下内容:

  •  计算平均值用 -Average
  • 显示最大值用 -Maximum
  • 显示最小值用 -Minimum
  • 显示总和用   -\Sum

输出将是一个可度量或测量的对象而不是我们传入的任何东西。 让我们来检查一下您可以在自己电脑上尝试的几个示例。

1
2
3
4
5
6
7
Get-Service | Measure-Object

Get-process | Measure-Object

2,0,5,6 | Measure-Object -Sum

2,0,5,6 | Measure-Object -maximum

选择对象的子集

Select-object 完全没有智能,正如其名称所示,它用于选择。让我们看看它实际上在哪些地方使用以及如何在脚本中使用。

以下是可与 Select-Object 一起使用的一些参数。

  • -First 用于开始。
  • -Last 用于结束。
  • -Skip 在选择之前跳过若干行。

我们无法指定任何选择特定行的标准。让我们看看可以尝试在计算机上运行的一些示例。

1
2
3
Get-Service | select-object -first 10

Get-process | select-object -first 10

这是使用 Select-ObjectSelect 的一种方式,让我们看看另一种可以使用 Select-object 的方法。

1
get-service |select-object -property Name -first 10

在上面的示例中,我们正在选择一个特定属性即已选取了 Name 并且还选取了前十个结果。同样地,我们可以尝试其他示例。

结论

在本教程中,我们了解了 Powershell 中管道是什么、为什么要使用它以及如何使用它。 我们还学习了如何选择、排序和测量对象以及可以将其与示例结合应用的位置。 您可以尝试每个示例并确保您的计算机安装有 Powershell 。 让我们很快见到您,并希望您从今天学到了点东西。

PowerShell 技能连载 - 选择最适当的文件格式(第 1 部分)

PowerShell支持各种文本文件格式,那么保存和读取数据的最佳方法是什么呢?

这主要取决于数据的类型,下面是实际指南的第一部分:

  • 一维数据:当数据只有一个维度,例如服务器名称列表时,最好将其保存为纯文本文件。首选的命令是使用“Content”名词的命令:Get-Content 用于读取,Set-Content 用于写入,Add-Content 用于追加。纯文本文件存储字符串数组。注意事项:在保存和读取时,需要使用相同的文本编码,因此最好使用 UTF-8 编码。注意事项#2:如果您想将字符串数组文件内容读取到变量中,添加 -ReadCount 0 参数。这比默认方式快很多倍。
  • 二维数据:列和行形式的数据最好保存为CSV格式。首选的命令是使用“Csv”名词的命令:Export-CsvImport-Csv。CSV 文件存储对象数组。CSV 列名定义了对象属性。注意事项:由于 CSV 基于文本,请确保主动选择良好的文本编码,如 UTF-8。注意事项#2:CSV 文件可以使用许多不同的分隔符,因此要么使用 -Delimiter 来始终定义分隔符,要么使用-UseCulture,如果您希望自动选择的分隔符与其他应用程序在同一系统上匹配,例如,当您计划稍后在 Microsoft Excel 中打开 CSV 文件时。

PowerShell 技能连载 - 7个用于管理DHCP的最佳PowerShell脚本

最近,Foreach 和 Foreach-object 成为讨论的焦点,我们对此有所了解。循环是任何代码或脚本的核心,我们必须确保正确执行。但你是否想过哪种更适合在多台服务器上运行特定代码呢?让我们在这篇文章中探讨一下,并获取一些有用的知识。

对比:Foreach-object 和 Foreach

当选择 invoke-command 和 where { } 时,Foreach 是其中一个备受关注的选项。

拥有 foreach 的优势在于可以将值存储在 Excel 中的一个字符串中,这是一个福音。同样,在选择 foreach () 时,我们有两个不同的选项,一个是 foreach 本身,另一个是 foreach-object。但当你看到对象时它们看起来很相似对吧。

我进行了测试以便能够挑选出胜者。

ForEach-Object 在通过管道发送数据时效果最佳,因为它会继续将对象流式传输到管道中的下一条命令中去。

Foreach-object 和 Foreach 之间的速度测试

以下是测试代码:这将测试循环完成所需的实际时间。

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
30
31
32
33
34
35
36
37
38
39
40
41
42
$a=Get-ChildItem –File C:\users\dhrub\ -Recurse
$time = (Measure-Command {

$a | ForEach-Object {

$_

}

}).TotalMilliseconds

[pscustomobject]@{

Type = 'ForEach-Object'

Time_ms = $Time

}
$Time = (Measure-Command {

ForEach ($i in ($a)) {

$i

}

}).TotalMilliseconds

[pscustomobject]@{

Type = 'ForEach'

Time_ms = $Time

}

Output:

Type Time_ms
---- -------
ForEach-Object 213.3006
ForEach 64.8013

输出一定会让你大吃一惊!

判决:该使用哪个?

ForEach 语句在处理每个项目之前将所有项目提前加载到集合中。

ForEach-Object 预期通过管道流式传输项目,从而降低内存需求,但同时会影响性能。

Forach 总是比 Foreach-Object 更快,但这并不意味着你不能使用 **Foreach-Object。具体取决于工作的要求。

PowerShell 技能连载 - 测试驱动 PowerShellGet 版本 3

PowerShellGet 是一个模块,包含重要的 cmdlet,比如 Install-Module,因此该模块实际上是下载和安装其他模块的先决条件,即从 powershellgallery.com 下载和安装模块的先决条件。

终于,期待已久的第 3 版该模块作为预览版在 PowerShell Gallery 中可用,有很多理由说明你应该使用这个新版本。

以下是安装步骤:

1
PS> Install-Module -Name PowerShellGet -AllowPrerelease -Scope CurrentUser

你应该更新的一个原因是,你可能再也无法这样做了。很可能你的 Install-Module cmdlet 缺少 -AllowPrerelease 参数,因此无法安装任何预发布模块。对于任何使用语义版本的现代模块都是如此。

悲伤的事实是,PowerShellGet 在 Windows 10/11 映像中的初始版本 1.0.0.1 中被包含进去,并且从那时起从未自动更新。版本 1.0.0.1 现在已经过时,无法在许多情况下正常工作。

为了解决这个问题,你应该先手动强制安装 PowerShellGet 2.x。这将安装你安装 PowerShellGet 3.x 所需的先决条件:

1
PS> Install-Module -Name PowerShellGet -Scope CurrentUser -Force -AllowClobber

运行这行命令并重新启动 PowerShell 后,Install-Module 应该具有 -AllowPrelease 参数,因此现在你可以运行第一个代码行并安装 PowerShellGet 3.x。

最终,PowerShellGet 3 版将希望解决所有这些问题,并为 PowerShell 的模块交换机制提供更强大的支持。

PowerShell 技能连载 - SpeculationControl:使用 PowerShell 检查风险

微软几年前发布了一个模块(最近 3 周更新),您可以使用该模块来检测您的硬件是否容易受到 Spectre 和 Meltdown 威胁的攻击。要尝试这个功能,请从 PowerShell Gallery 安装该模块:

1
Install-Module -Name SpeculationControl -Scope CurrentUser

要运行测试套件并查看结果,请输入以下命令:

1
PS> Get-SpeculationControlSettings

这将显示您的计算机的测试结果,可能类似于以下内容:

For more information about the output below, please refer to https://support.microsoft.com/help/4074629

Speculation control settings for CVE-2017-5715 [branch target injection]

Hardware support for branch target injection mitigation is present: True
Windows OS support for branch target injection mitigation is present: True
Windows OS support for branch target injection mitigation is enabled: True

Speculation control settings for CVE-2017-5754 [rogue data cache load]

Hardware is vulnerable to rogue data cache load: False

Hardware requires kernel VA shadowing: False

Speculation control settings for CVE-2018-3639 [speculative store bypass]

Hardware is vulnerable to speculative store bypass: True
Hardware support for speculative store bypass disable is present: True
Windows OS support for speculative store bypass disable is present: True
Windows OS support for speculative store bypass disable is enabled system-wide: False

Speculation control settings for CVE-2018-3620 [L1 terminal fault]

Hardware is vulnerable to L1 terminal fault: False

Speculation control settings for MDS [microarchitectural data sampling]

Windows OS support for MDS mitigation is present: True
Hardware is vulnerable to MDS: False

Speculation control settings for SBDR [shared buffers data read]

Windows OS support for SBDR mitigation is present: True
Hardware is vulnerable to SBDR: True
Windows OS support for SBDR mitigation is enabled: False

Speculation control settings for FBSDP [fill buffer stale data propagator]

Windows OS support for FBSDP mitigation is present: True
Hardware is vulnerable to FBSDP: True
Windows OS support for FBSDP mitigation is enabled: False

Speculation control settings for PSDP [primary stale data propagator]

Windows OS support for PSDP mitigation is present: True
Hardware is vulnerable to PSDP: True
Windows OS support for PSDP mitigation is enabled: False

Suggested actions

* Follow the guidance for enabling Windows Client support for speculation control
mitigations described in https://support.microsoft.com/help/4073119


BTIHardwarePresent                  : True
BTIWindowsSupportPresent            : True
BTIWindowsSupportEnabled            : True
BTIDisabledBySystemPolicy           : False
BTIDisabledByNoHardwareSupport      : False
BTIKernelRetpolineEnabled           : False
BTIKernelImportOptimizationEnabled  : True
RdclHardwareProtectedReported       : True
RdclHardwareProtected               : True
KVAShadowRequired                   : False
KVAShadowWindowsSupportPresent      : True
KVAShadowWindowsSupportEnabled      : False
KVAShadowPcidEnabled                : False
SSBDWindowsSupportPresent           : True
SSBDHardwareVulnerable              : True
SSBDHardwarePresent                 : True
SSBDWindowsSupportEnabledSystemWide : False
L1TFHardwareVulnerable              : False
L1TFWindowsSupportPresent           : True
L1TFWindowsSupportEnabled           : False
L1TFInvalidPteBit                   : 0
L1DFlushSupported                   : True
HvL1tfStatusAvailable               : True
HvL1tfProcessorNotAffected          : True
MDSWindowsSupportPresent            : True
MDSHardwareVulnerable               : False
MDSWindowsSupportEnabled            : False
FBClearWindowsSupportPresent        : True
SBDRSSDPHardwareVulnerable          : True
FBSDPHardwareVulnerable             : True
PSDPHardwareVulnerable              : True
FBClearWindowsSupportEnabled        : False


PS>

PowerShell 技能连载 - 获取父级文化

大部分情况下,本地化资源都会标有类似 “en-us” 或 “de-de” 这样的文化名称。如果你想知道这种标识代表什么,只需将其转换为 [System.Globalization.CultureInfo] 对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
PS> [System.Globalization.CultureInfo]'en-us'

LCID Name DisplayName
---- ---- -----------
1033 en-US English (United States)



PS> [System.Globalization.CultureInfo]'de-de'

LCID Name DisplayName
---- ---- -----------
1031 de-DE German (Germany)

正如你所见,文化名称非常细致。例如,有 106 个子文化都属于同一个英语基础文化:

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
PS> [System.Globalization.CultureInfo]::GetCultures( [System.Globalization.CultureTypes]::AllCultures) | Where-Object Parent -eq 'en'

LCID Name DisplayName
---- ---- -----------
4096 en-001 English (World)
9225 en-029 English (Caribbean)
4096 en-150 English (Europe)
19465 en-AE English (United Arab Emirates)
4096 en-AG English (Antigua and Barbuda)
4096 en-AI English (Anguilla)
4096 en-AS English (American Samoa)
4096 en-AT English (Austria)
3081 en-AU English (Australia)
4096 en-BB English (Barbados)
4096 en-BE English (Belgium)
4096 en-BI English (Burundi)
4096 en-BM English (Bermuda)
4096 en-BS English (Bahamas)
4096 en-BW English (Botswana)
10249 en-BZ English (Belize)
4105 en-CA English (Canada)
4096 en-CC English (Cocos [Keeling] Islands)
4096 en-CH English (Switzerland)
4096 en-CK English (Cook Islands)
4096 en-CM English (Cameroon)
4096 en-CX English (Christmas Island)
4096 en-CY English (Cyprus)
4096 en-DE English (Germany)
4096 en-DK English (Denmark)
4096 en-DM English (Dominica)
4096 en-ER English (Eritrea)
4096 en-FI English (Finland)
4096 en-FJ English (Fiji)
4096 en-FK English (Falkland Islands)
4096 en-FM English (Micronesia)
2057 en-GB English (United Kingdom)
4096 en-GD English (Grenada)
4096 en-GG English (Guernsey)
4096 en-GH English (Ghana)
4096 en-GI English (Gibraltar)
4096 en-GM English (Gambia)
4096 en-GU English (Guam)
4096 en-GY English (Guyana)
15369 en-HK English (Hong Kong SAR)
14345 en-ID English (Indonesia)
6153 en-IE English (Ireland)
4096 en-IL English (Israel)
4096 en-IM English (Isle of Man)
16393 en-IN English (India)
4096 en-IO English (British Indian Ocean Territory)
4096 en-JE English (Jersey)
8201 en-JM English (Jamaica)
4096 en-KE English (Kenya)
4096 en-KI English (Kiribati)
4096 en-KN English (Saint Kitts and Nevis)
4096 en-KY English (Cayman Islands)
4096 en-LC English (Saint Lucia)
4096 en-LR English (Liberia)
4096 en-LS English (Lesotho)
4096 en-MG English (Madagascar)
4096 en-MH English (Marshall Islands)
4096 en-MO English (Macao SAR)
4096 en-MP English (Northern Mariana Islands)
4096 en-MS English (Montserrat)
4096 en-MT English (Malta)
4096 en-MU English (Mauritius)
4096 en-MW English (Malawi)
17417 en-MY English (Malaysia)
4096 en-NA English (Namibia)
4096 en-NF English (Norfolk Island)
4096 en-NG English (Nigeria)
4096 en-NL English (Netherlands)
4096 en-NR English (Nauru)
4096 en-NU English (Niue)
5129 en-NZ English (New Zealand)
4096 en-PG English (Papua New Guinea)
13321 en-PH English (Republic of the Philippines)
4096 en-PK English (Pakistan)
4096 en-PN English (Pitcairn Islands)
4096 en-PR English (Puerto Rico)
4096 en-PW English (Palau)
4096 en-RW English (Rwanda)
4096 en-SB English (Solomon Islands)
4096 en-SC English (Seychelles)
4096 en-SD English (Sudan)
4096 en-SE English (Sweden)
18441 en-SG English (Singapore)
4096 en-SH English (St Helena, Ascension, Tristan da Cunha)
4096 en-SI English (Slovenia)
4096 en-SL English (Sierra Leone)
4096 en-SS English (South Sudan)
4096 en-SX English (Sint Maarten)
4096 en-SZ English (Swaziland)
4096 en-TC English (Turks and Caicos Islands)
4096 en-TK English (Tokelau)
4096 en-TO English (Tonga)
11273 en-TT English (Trinidad and Tobago)
4096 en-TV English (Tuvalu)
4096 en-TZ English (Tanzania)
4096 en-UG English (Uganda)
4096 en-UM English (US Minor Outlying Islands)
1033 en-US English (United States)
4096 en-VC English (Saint Vincent and the Grenadines)
4096 en-VG English (British Virgin Islands)
4096 en-VI English (US Virgin Islands)
4096 en-VU English (Vanuatu)
4096 en-WS English (Samoa)
7177 en-ZA English (South Africa)
4096 en-ZM English (Zambia)
12297 en-ZW English (Zimbabwe)

如果您的代码最终需要检查给定的资源区域设置是否与您的兴趣相匹配,而不是将资源区域设置与您的用户界面区域设置进行比较,您可能希望获取您的用户界面区域设置和资源的父级区域设置,并查看它们是否匹配。

这样,英国用户(en-GB)也将找到美国的文档(en-us)。同样,瑞士用户(de-ch)将找到德国的资源(de-de)。

PowerShell 技能连载 - Invoke-RestMethod 退出错误

无论是 Invoke-WebRequest 还是 Invoke-RestMethod,都是简单易用的命令,用于从网络上下载信息。例如,以下简单代码可以查询任何公共 IP 地址的注册信息并返回其注册所有者:

1
2
3
4
5
6
7
8
9
10
11
12
$IPAddress = '51.107.59.180'
Invoke-RestMethod -Uri "http://ipinfo.io/$IPAddress/json" -UseBasicParsing

ip : 51.107.59.180
city : Zürich
region : Zurich
country : CH
loc : 47.3667,8.5500
org : AS8075 Microsoft Corporation
postal : 8090
timezone : Europe/Zurich
readme : https://ipinfo.io/missingauth

如果在你的代码与互联网通信时出现问题,在 Windows PowerShell 中有一个硬编码的超时时间为 300 秒。因此,即使你的路由器出现故障,你的 PowerShell 脚本最终也会返回。

在 PowerShell 7 中,这两个命令的内部工作方式发生了重大改变。它们目前不再具有连接超时功能,因此如果你的连接中断,你的脚本将永远挂起。

幸运的是,这个错误目前正在解决中,并将在即将推出的 PowerShell 7 更新中修复。

PowerShell 技能连载 - 两种类型转换(和一个 bug)

为了明确将一个数据类型转换为另一个数据类型,PowerShell提供了两种方法:

1
2
3
4
5
PS> [int]5.6
6

PS> 5.6 -as [int]
6

虽然这两种方法在大多数情况下都会产生相同的结果,但存在细微差异:

  • 当你在数据之前添加目标类型时,PowerShell 使用美国文化,并在转换失败时引发异常。
  • 当你使用 “-as“ 运算符时,PowerShell 使用你的本地文化,在转换失败时不引发异常。

当你在非英语系统上进行字符串到日期时间的转换时,不同的文化变得重要:

1
2
3
4
5
6
7
PS> [datetime]'1.5.23'

Donnerstag, 5. Januar 2023 00:00:00

PS> '1.5.23' -as [datetime]

Montag, 1. Mai 2023 00:00:00

最后,这两种方法都存在一个奇怪的错误,即使输入的字符串明显损坏,类型转换仍然有效:

PS> [Type] ‘int]whatever’

IsPublic IsSerial Name BaseType


True True Int32 System.ValueType

PS> ‘int]whatever’ -as [Type]

IsPublic IsSerial Name BaseType


True True Int32 System.ValueType

不过,不要利用这个错误,因为在 PowerShell 7 中很快会修复它。

PowerShell 技能连载 - 挂载 ISO 文件

在我们之前的提示中,我们展示了如何轻松将本地文件夹转换为 ISO 文件镜像。今天,我们来看一下如何挂载(以及卸载)您自己和其他任何 ISO 文件,以便它们可以像本地文件系统驱动器一样使用。

挂载 ISO 文件很简单:

1
2
3
4
# 确保您调整此路径,使其指向现有的ISO文件:
$Path = "$env:temp\myImageFile.iso"
$result = Mount-DiskImage -ImagePath $Path -PassThru
$result

执行此代码后,Windows 资源管理器中会出现一个新的光驱,可以像其他驱动器一样使用。基于 ISO 镜像的驱动器当然是只读的,因为它们的行为就像常规的 CD-ROM。

虽然 Mount-DiskImage 可以成功挂载 ISO 镜像,但它不会将分配的驱动器字母返回给您。如果您想从脚本内部访问 ISO 镜像的内容,下面是如何找出它分配的驱动器字母:

1
2
3
4
5
6
7
8
9
# 确保您调整此路径,使其指向现有的ISO文件:
$Path = "$env:temp\myImageFile.iso"
$result = Mount-DiskImage -ImagePath $Path -PassThru
$result

$volume = $result | Get-Volume
$letter = $volume.Driveletter + ":\"

explorer $letter

在使用后卸载驱动器,请运行 Dismount-DiskImage 并指定您之前挂载的ISO文件的路径:

1
Dismount-DiskImage -ImagePath $Path

PowerShell 技能连载 - 创建 ISO 文件

PowerShell 可以将普通文件夹转换为 ISO 文件。ISO 文件是二进制文件,可以被挂载并表现得像只读 CD-ROM 驱动器。

过去,ISO 文件常用于挂载安装媒体。如今,您可以轻松地创建自己的 ISO 文件,这些文件是从您自己的文件夹和文件中创建的。这样,您可以创建一个简单的备份系统,或者轻松地在同事之间共享项目。由于 ISO 文件只是一个单一的文件,因此可以轻松地共享,而且由于 Windows 通过双击挂载它们,并在 Windows 资源管理器中显示它们作为 CD-ROM 驱动器,您可以立即使用数据而无需提取或解压任何内容。

与 VHD 映像文件不同,挂载 ISO 文件不需要管理员特权。任何人都可以挂载和使用 ISO 文件。

由于没有内置的 cmdlet 将文件夹结构转换为 ISO 文件,您需要自己调用内部 API。下面的代码定义了新函数 New-IsoFile

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
function New-IsoFile
{
param
(
# path to local folder to store in
# new ISO file (must exist)
[Parameter(Mandatory)]
[String]
$SourceFilePath,

# name of new ISO image (arbitrary,
# turns later into drive label)
[String]
$ImageName = 'MyCDROM',

# path to ISO file to be created
[Parameter(Mandatory)]
[String]
$NewIsoFilePath,

# if specified, the source base folder is
# included into the image file
[switch]
$IncludeRoot
)

# use this COM object to create the ISO file:
$fsi = New-Object -ComObject IMAPI2FS.MsftFileSystemImage

# use this helper object to write a COM stream to a file:
# compile the helper code using these parameters:
$cp = [CodeDom.Compiler.CompilerParameters]::new()
$cp.CompilerOptions = '/unsafe'
$cp.WarningLevel = 4
$cp.TreatWarningsAsErrors = $true
$code = '
using System;
using System.IO;
using System.Runtime.InteropServices.ComTypes;

namespace CustomConverter
{
public static class Helper
{
// writes a stream that came from COM to a filesystem file
public static void WriteStreamToFile(object stream, string filePath)
{
// open output stream to new file
IStream inputStream = stream as IStream;
FileStream outputFileStream = File.OpenWrite(filePath);
int bytesRead = 0;
byte[] data;

// read stream in chunks of 2048 bytes and write to filesystem stream:
do
{
data = Read(inputStream, 2048, out bytesRead);
outputFileStream.Write(data, 0, bytesRead);
} while (bytesRead == 2048);

outputFileStream.Flush();
outputFileStream.Close();
}

// read bytes from stream:
unsafe static private byte[] Read(IStream stream, int byteCount, out int readCount)
{
// create a new buffer to hold the read bytes:
byte[] buffer = new byte[byteCount];
// provide a pointer to the location where the actually read bytes are reported:
int bytesRead = 0;
int* ptr = &bytesRead;
// do the read:
stream.Read(buffer, byteCount, (IntPtr)ptr);
// return the read bytes by reference to the caller:
readCount = bytesRead;
// return the read bytes to the caller:
return buffer;
}
}
}'

Add-Type -CompilerParameters $cp -TypeDefinition $code

# define the ISO file properties:

# create CDROM, Joliet and UDF file systems
$fsi.FileSystemsToCreate = 7
$fsi.VolumeName = $ImageName
# allow larger-than-CRRom-Sizes
$fsi.FreeMediaBlocks = -1

$msg = 'Creating ISO File - this can take a couple of minutes.'
Write-Host $msg -ForegroundColor Green

# define folder structure to be written to image:
$fsi.Root.AddTreeWithNamedStreams($SourceFilePath,$IncludeRoot.IsPresent)

# create image and provide a stream to read it:
$resultimage = $fsi.CreateResultImage()
$resultStream = $resultimage.ImageStream

# write stream to file
[CustomConverter.Helper]::WriteStreamToFile($resultStream, $NewIsoFilePath)

Write-Host 'DONE.' -ForegroundColor Green

}

运行此代码后,您现在将拥有一个名为“New-IsoFile”的新命令。从现有文件夹结构创建ISO文件现在变得轻而易举 - 只需确保源文件路径存在即可:

1
PS> New-IsoFile -NewIsoFilePath $env:temp\MyTest.iso -ImageName Holiday -SourceFilePath 'C:\HolidayPics'

您将在临时文件夹(或您指定的其他文件路径)中获得一个新的 ISO 文件。如果您按照示例操作,只需打开临时文件夹:

1
PS> explorer /select,$env:temp\MyTest.iso

当你在Windows资源管理器中双击ISO文件时,该映像将作为一个新的光驱挂载,你可以立即看到映像文件中存储的数据的副本。

在Windows资源管理器中右键单击新的光驱,并从上下文菜单中选择“弹出”将卸载该光驱。