upload successful

# 前言

最近在协助前东家实施一个 EPM 操作系统部署的项目,我主要帮忙编写相关自动化部署脚本,期间遇到两个比较有意思的脚本运行问题,在此记录一下,或许可以帮助到遇到同样问题的小伙伴

# invoke-webrequest 下载慢

其中有一个负责下载镜像和驱动的脚本文件,我是用了 iwr 来下载,但是在实际运行时发现下载不能跑满速,下载驱动和镜像需要花费一个多小时

老实说,我以前经常用 iwr 下载文件,并没有发现这个问题,是因为我以前用来下载的都是小文件,毕竟以前用这个命令比较多的地方还是无文件落地这方面,所以不会下载很大的文件

我开始怀疑是不是因为 iwr 命令的问题,但是后续我尝试了使用 wget 下载也一样慢

最后发现只需要将 $ProgressPreference 变量的默认值 Continue 更改成 SilentlyContinue 即可满速下载

本地测试一下更改前后的下载时间,下载一个 4G 左右的 win10 镜像,更改前用时 11 分钟

upload successful

更改后,用时 18 秒

upload successful

最终测试最优解是用 Start-BitsTransfer 命令下载大文件,下载速度要优于 iwr ,且不需要更改 $ProgressPreference 变量

按照微软文档的描述, $ProgressPreference 默认值为 Continue 时,脚本命令会在当前窗口生成一个进度栏,以描述运行中脚本状态

我不太明白如果仅仅是显示进度栏,应该不至于会导致下载速度变得如此之慢,具体的原因还是等以后自己有能力分析的时候再深入研究

参考文档: https://learn.microsoft.com/zh-cn/powershell/module/microsoft.powershell.core/about/about_preference_variables?view=powershell-7.4

# 在 32 位模式下运行 64 位应用

在安装完操作系统后,系统进入桌面后会自动调用安装驱动的脚本中,执行 pnputil 命令的时候返回 ObjectNotFound , 即使我指定绝对路径也不行

l
# 指定备份驱动程序文件夹的路径
$backupFolderPath = "c:\driver"
# 获取备份文件夹中所有的 INF 文件
$infFiles = Get-ChildItem -Path $backupFolderPath -Filter "*.inf" -File -Recurse
# 遍历并安装每个 INF 文件
foreach ($infFile in $infFiles) {
    # 安装驱动程序
    pnputil.exe /add-driver $infFile.FullName /install
   
}

upload successful

经过测试发现,EPM 模板默认调用的是 32 位powershell 执行脚本,所以才导致无法执行 64 位pnputil 命令,即使我写一个计划任务脚本,将这个安装驱动的脚本添加到计划任务中执行,结果也依然一样

最终只能更改脚本内容,通过 %windir%\Sysnative 虚拟目录 32 位powershell 执行 64 位powershell 再调用 pnputil 命令安装驱动

l
# 指定备份驱动程序文件夹的路径
$backupFolderPath = "C:\driver\"
# 获取备份文件夹中所有的 INF 文件
$infFiles = Get-ChildItem -Path $backupFolderPath -Filter "*.inf" -File -Recurse
# 构建要在 64 位 PowerShell 中运行的命令
$commands = @()
foreach ($infFile in $infFiles) {
    $commands += "pnputil.exe /add-driver `"$($infFile.FullName)`" /install"
}
# 将命令转换为字符串并以;进行分割
$commandString = $commands -join "; "
# 创建一个临时脚本文件来存储命令
$tempScriptPath = [System.IO.Path]::GetTempFileName() + ".ps1"
Set-Content -Path $tempScriptPath -Value $commandString
# 使用 64 位 PowerShell 执行临时脚本
$sysNativePath = "$env:windir\Sysnative\WindowsPowerShell\v1.0\powershell.exe"
Start-Process -FilePath $sysNativePath -ArgumentList "-ExecutionPolicy Bypass -File `"$tempScriptPath`"" -Wait
# 删除临时脚本文件
Remove-Item -Path $tempScriptPath

参考文档: https://learn.microsoft.com/zh-cn/windows/win32/winprog64/file-system-redirector