PowerShell通过Invoke-WebRequest/COM对象下载日志文件遇阻
解决PowerShell自动下载KACE日志文件的问题
我来帮你一步步搞定这个自动下载日志的问题,先从你遇到的Invoke-WebRequest问题说起,再聊IE COM对象的解决方案。
一、修复Invoke-WebRequest下载失败的问题
你目前的问题核心是请求下载链接时被重定向回登录页,虽然补了Referer头,但可能还有几个关键点没注意到:
1. 确保请求的是正确的下载URL
你提到日志下载链接是https://some.thing.com/common/download_logs.php,但你之前执行的命令是POST到settings_support.php——这不对,应该直接请求下载链接本身。
2. 完善请求头与会话传递
除了Referer,还要确保会话$ms是登录后的有效会话,同时检查是否需要将CSRF Token作为表单参数提交(有些网站会要求POST请求时携带CSRF Token,而不仅仅是放在Cookie里)。
试试这个修正后的命令:
# 构造完整请求头 $headers = @{ "User-Agent" = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 Edge/15.15063" "Referer" = "https://some.thing.com/adminui/settings_support.php" "Accept-Encoding" = "gzip, deflate" "Accept" = "text/html, application/xhtml+xml, image/jxr, */*" "Accept-Language" = "en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3" } # 直接请求下载链接,用WebSession传递登录状态,指定OutFile保存文件 Invoke-WebRequest -Uri "https://some.thing.com/common/download_logs.php" ` -WebSession $ms ` -Headers $headers ` -OutFile "C:\your\save\path\kbox_logs.tgz"
3. 排查CSRF Token的传递方式
如果上面的命令还是失败,抓包对比浏览器请求:
- 看浏览器请求
download_logs.php时用的是GET还是POST方法 - 如果是POST,检查表单里是否有
KACE_CSRF_TOKEN字段,有的话需要在请求里加上:$formParams = @{ "KACE_CSRF_TOKEN" = "aad3f8c254d2f25bd24e35c51d654541822080da825d6353937a7fe294216089689cc68480299b657f4fb1e9be77ac711a658a96e2df50ffc5e242b94bd9baf4" } Invoke-WebRequest -Uri "https://some.thing.com/common/download_logs.php" ` -WebSession $ms ` -Headers $headers ` -Method POST ` -Body $formParams ` -OutFile "kbox_logs.tgz"
二、解决IE COM对象的两个问题
1. 修复无法点击下载链接的问题
你的代码里点击链接的语法有误,过滤元素后需要确保拿到正确的DOM对象再调用click()。修正后的代码片段:
# 导航到支持页面后,查找下载链接 $ie.navigate("http://some.thing.com/adminui/settings_support.php") while ($ie.busy -eq $true) { Start-Sleep 1 } # 正确获取并点击链接 $downloadLink = $ie.document.getElementsByTagName("a") | Where-Object { $_.innerText -eq 'Retrieve appliance activity logs' } if ($downloadLink) { $downloadLink.click() } else { Write-Host "找不到下载链接,请检查innerText是否匹配" }
2. 后台自动保存下载文件
用快捷键S确实不够优雅,你可以通过修改IE的注册表设置,让它自动保存指定类型的文件,再监控下载文件夹获取文件:
步骤1:修改IE自动下载设置
# 修改IE安全区域设置,允许自动保存.tgz文件(0=允许,1=提示,3=禁止) Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\3" -Name "1803" -Value 0
步骤2:监控下载文件夹并处理文件
$shell = New-Object -ComObject Shell.Application $downloadFolder = $shell.Namespace(0x0010) # 系统默认下载文件夹路径 $targetPath = "C:\your\target\path\kbox_logs.tgz" # 等待下载完成 while (-not ($downloadFolder.Items() | Where-Object { $_.Name -eq 'kbox_logs.tgz' })) { Start-Sleep 1 } # 移动文件到指定位置 Move-Item -Path (Join-Path $downloadFolder.Self.Path 'kbox_logs.tgz') -Destination $targetPath -Force
总结
优先推荐Invoke-WebRequest的方案,不需要GUI,效率更高;如果必须用IE COM对象,按上面的方法修复点击逻辑和自动保存问题。
内容的提问来源于stack exchange,提问作者Rrrrr5r




