代码在 Powershell 5 中完美运行,但在 Powershell 6 中运行不佳
Code works perfectly in Powershell 5 but not in Powershell 6
我的一项任务需要从文件列表创建 ISO 映像。我找到了 this gist(根据作者的说法,代码在 public 域中)。
我的公司只使用 Powershell 6.2.2,这是我必须处理的事实。问题是代码在 Powershell 5.1 中可以完美运行,但在 Powershell 6.2.2 中却不行!它给了我以下错误:
Add-Type : A parameter cannot be found that matches parameter name 'CompilerParameters'.
At E:\work\MSPV\New_ISOfile.ps1:19 char:11
+ Add-Type -CompilerParameters $cp -TypeDefinition @"
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Add-Type], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.AddTypeCommand
Unable to find type [My.FileUtil].
At E:\work\MSPV\New_ISOfile.ps1:52 char:2
+ [My.FileUtil]::WriteIStreamToFile($istream, $fileName)
+ ~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (My.FileUtil:TypeName) [], RuntimeException
+ FullyQualifiedErrorId : TypeNotFound
我唯一发现的是,根据 MS 文档,在 Powershell 6.x 中,Add-Type cmdlet 没有诸如“-CompilerParameters”之类的参数,但在 Powershell 5(5.1 即).尝试用“-CompilerOptions”替换它,但这没有帮助。同样的错误。
有什么方法可以让它在 Powershell 6.2 上运行吗?
实际上调用在 PS 6+ 中消失了,因为在文档中 -CompilerParameters
已被替换为 -CompilerOptions
并且它接受字符串参数。
你必须像下面这样直接调用它
Add-Type -CompilerOptions "/unsafe" -TypeDefinition
如果您来自 function New-IsoFile
,这里是完整代码
function New-IsoFile
{
[CmdletBinding(DefaultParameterSetName='Source')]Param(
[parameter(Position=1,Mandatory=$true,ValueFromPipeline=$true, ParameterSetName='Source')]$Source,
[parameter(Position=2)][string]$Path = "$env:temp$((Get-Date).ToString('yyyyMMdd-HHmmss.ffff')).iso",
[ValidateScript({Test-Path -LiteralPath $_ -PathType Leaf})][string]$BootFile = $null,
[ValidateSet('CDR','CDRW','DVDRAM','DVDPLUSR','DVDPLUSRW','DVDPLUSR_DUALLAYER','DVDDASHR','DVDDASHRW','DVDDASHR_DUALLAYER','DISK','DVDPLUSRW_DUALLAYER','BDR','BDRE')][string] $Media = 'DVDPLUSRW_DUALLAYER',
[string]$Title = (Get-Date).ToString("yyyyMMdd-HHmmss.ffff"),
[switch]$Force,
[parameter(ParameterSetName='Clipboard')][switch]$FromClipboard
)
Begin {
($cp = new-object System.CodeDom.Compiler.CompilerParameters).CompilerOptions = '/unsafe'
if (!('ISOFile' -as [type])) {
Add-Type -CompilerOptions "/unsafe" -TypeDefinition @'
public class ISOFile
{
public unsafe static void Create(string Path, object Stream, int BlockSize, int TotalBlocks)
{
int bytes = 0;
byte[] buf = new byte[BlockSize];
var ptr = (System.IntPtr)(&bytes);
var o = System.IO.File.OpenWrite(Path);
var i = Stream as System.Runtime.InteropServices.ComTypes.IStream;
if (o != null) {
while (TotalBlocks-- > 0) {
i.Read(buf, BlockSize, ptr); o.Write(buf, 0, bytes);
}
o.Flush(); o.Close();
}
}
}
'@
}
if ($BootFile) {
if('BDR','BDRE' -contains $Media) { Write-Warning "Bootable image doesn't seem to work with media type $Media" }
($Stream = New-Object -ComObject ADODB.Stream -Property @{Type=1}).Open() # adFileTypeBinary
$Stream.LoadFromFile((Get-Item -LiteralPath $BootFile).Fullname)
($Boot = New-Object -ComObject IMAPI2FS.BootOptions).AssignBootImage($Stream)
}
$MediaType = @('UNKNOWN','CDROM','CDR','CDRW','DVDROM','DVDRAM','DVDPLUSR','DVDPLUSRW','DVDPLUSR_DUALLAYER','DVDDASHR','DVDDASHRW','DVDDASHR_DUALLAYER','DISK','DVDPLUSRW_DUALLAYER','HDDVDROM','HDDVDR','HDDVDRAM','BDROM','BDR','BDRE')
Write-Verbose -Message "Selected media type is $Media with value $($MediaType.IndexOf($Media))"
($Image = New-Object -com IMAPI2FS.MsftFileSystemImage -Property @{VolumeName=$Title}).ChooseImageDefaultsForMediaType($MediaType.IndexOf($Media))
if (!($Target = New-Item -Path $Path -ItemType File -Force:$Force -ErrorAction SilentlyContinue)) { Write-Error -Message "Cannot create file $Path. Use -Force parameter to overwrite if the target file already exists."; break }
}
Process {
if($FromClipboard) {
if($PSVersionTable.PSVersion.Major -lt 5) { Write-Error -Message 'The -FromClipboard parameter is only supported on PowerShell v5 or higher'; break }
$Source = Get-Clipboard -Format FileDropList
}
foreach($item in $Source) {
if($item -isnot [System.IO.FileInfo] -and $item -isnot [System.IO.DirectoryInfo]) {
$item = Get-Item -LiteralPath $item
}
if($item) {
Write-Verbose -Message "Adding item to the target image: $($item.FullName)"
try { $Image.Root.AddTree($item.FullName, $true) } catch { Write-Error -Message ($_.Exception.Message.Trim() + ' Try a different media type.') }
}
}
}
End {
if ($Boot) { $Image.BootImageOptions=$Boot }
$Result = $Image.CreateResultImage()
[ISOFile]::Create($Target.FullName,$Result.ImageStream,$Result.BlockSize,$Result.TotalBlocks)
Write-Verbose -Message "Target image ($($Target.FullName)) has been created"
$Target
}
}
我的一项任务需要从文件列表创建 ISO 映像。我找到了 this gist(根据作者的说法,代码在 public 域中)。
我的公司只使用 Powershell 6.2.2,这是我必须处理的事实。问题是代码在 Powershell 5.1 中可以完美运行,但在 Powershell 6.2.2 中却不行!它给了我以下错误:
Add-Type : A parameter cannot be found that matches parameter name 'CompilerParameters'.
At E:\work\MSPV\New_ISOfile.ps1:19 char:11
+ Add-Type -CompilerParameters $cp -TypeDefinition @"
+ ~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Add-Type], ParameterBindingException
+ FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.AddTypeCommand
Unable to find type [My.FileUtil].
At E:\work\MSPV\New_ISOfile.ps1:52 char:2
+ [My.FileUtil]::WriteIStreamToFile($istream, $fileName)
+ ~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (My.FileUtil:TypeName) [], RuntimeException
+ FullyQualifiedErrorId : TypeNotFound
我唯一发现的是,根据 MS 文档,在 Powershell 6.x 中,Add-Type cmdlet 没有诸如“-CompilerParameters”之类的参数,但在 Powershell 5(5.1 即).尝试用“-CompilerOptions”替换它,但这没有帮助。同样的错误。
有什么方法可以让它在 Powershell 6.2 上运行吗?
实际上调用在 PS 6+ 中消失了,因为在文档中 -CompilerParameters
已被替换为 -CompilerOptions
并且它接受字符串参数。
你必须像下面这样直接调用它
Add-Type -CompilerOptions "/unsafe" -TypeDefinition
如果您来自 function New-IsoFile
,这里是完整代码
function New-IsoFile
{
[CmdletBinding(DefaultParameterSetName='Source')]Param(
[parameter(Position=1,Mandatory=$true,ValueFromPipeline=$true, ParameterSetName='Source')]$Source,
[parameter(Position=2)][string]$Path = "$env:temp$((Get-Date).ToString('yyyyMMdd-HHmmss.ffff')).iso",
[ValidateScript({Test-Path -LiteralPath $_ -PathType Leaf})][string]$BootFile = $null,
[ValidateSet('CDR','CDRW','DVDRAM','DVDPLUSR','DVDPLUSRW','DVDPLUSR_DUALLAYER','DVDDASHR','DVDDASHRW','DVDDASHR_DUALLAYER','DISK','DVDPLUSRW_DUALLAYER','BDR','BDRE')][string] $Media = 'DVDPLUSRW_DUALLAYER',
[string]$Title = (Get-Date).ToString("yyyyMMdd-HHmmss.ffff"),
[switch]$Force,
[parameter(ParameterSetName='Clipboard')][switch]$FromClipboard
)
Begin {
($cp = new-object System.CodeDom.Compiler.CompilerParameters).CompilerOptions = '/unsafe'
if (!('ISOFile' -as [type])) {
Add-Type -CompilerOptions "/unsafe" -TypeDefinition @'
public class ISOFile
{
public unsafe static void Create(string Path, object Stream, int BlockSize, int TotalBlocks)
{
int bytes = 0;
byte[] buf = new byte[BlockSize];
var ptr = (System.IntPtr)(&bytes);
var o = System.IO.File.OpenWrite(Path);
var i = Stream as System.Runtime.InteropServices.ComTypes.IStream;
if (o != null) {
while (TotalBlocks-- > 0) {
i.Read(buf, BlockSize, ptr); o.Write(buf, 0, bytes);
}
o.Flush(); o.Close();
}
}
}
'@
}
if ($BootFile) {
if('BDR','BDRE' -contains $Media) { Write-Warning "Bootable image doesn't seem to work with media type $Media" }
($Stream = New-Object -ComObject ADODB.Stream -Property @{Type=1}).Open() # adFileTypeBinary
$Stream.LoadFromFile((Get-Item -LiteralPath $BootFile).Fullname)
($Boot = New-Object -ComObject IMAPI2FS.BootOptions).AssignBootImage($Stream)
}
$MediaType = @('UNKNOWN','CDROM','CDR','CDRW','DVDROM','DVDRAM','DVDPLUSR','DVDPLUSRW','DVDPLUSR_DUALLAYER','DVDDASHR','DVDDASHRW','DVDDASHR_DUALLAYER','DISK','DVDPLUSRW_DUALLAYER','HDDVDROM','HDDVDR','HDDVDRAM','BDROM','BDR','BDRE')
Write-Verbose -Message "Selected media type is $Media with value $($MediaType.IndexOf($Media))"
($Image = New-Object -com IMAPI2FS.MsftFileSystemImage -Property @{VolumeName=$Title}).ChooseImageDefaultsForMediaType($MediaType.IndexOf($Media))
if (!($Target = New-Item -Path $Path -ItemType File -Force:$Force -ErrorAction SilentlyContinue)) { Write-Error -Message "Cannot create file $Path. Use -Force parameter to overwrite if the target file already exists."; break }
}
Process {
if($FromClipboard) {
if($PSVersionTable.PSVersion.Major -lt 5) { Write-Error -Message 'The -FromClipboard parameter is only supported on PowerShell v5 or higher'; break }
$Source = Get-Clipboard -Format FileDropList
}
foreach($item in $Source) {
if($item -isnot [System.IO.FileInfo] -and $item -isnot [System.IO.DirectoryInfo]) {
$item = Get-Item -LiteralPath $item
}
if($item) {
Write-Verbose -Message "Adding item to the target image: $($item.FullName)"
try { $Image.Root.AddTree($item.FullName, $true) } catch { Write-Error -Message ($_.Exception.Message.Trim() + ' Try a different media type.') }
}
}
}
End {
if ($Boot) { $Image.BootImageOptions=$Boot }
$Result = $Image.CreateResultImage()
[ISOFile]::Create($Target.FullName,$Result.ImageStream,$Result.BlockSize,$Result.TotalBlocks)
Write-Verbose -Message "Target image ($($Target.FullName)) has been created"
$Target
}
}