PowerShell:在ForEach-Object中正确处理哈希表生成.url文件
解决从XML生成Windows .url文件的循环处理问题
问题背景
需要从给定的XML文件生成对应的Windows .url快捷方式文件,已尝试将标题和URL存入有序哈希表,但循环处理时无法正确获取每一对标题和URL,要么所有内容拼接成一串,要么变量为空。
相关文件与代码
XML文件内容
<?xml version="1.0" encoding="UTF-16" ?> <items_list> <item> <title>About topics - PowerShell | Microsoft Learn</title> <url>https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about?view=powershell-7.3</url> </item> <item> <title>PowerShell HashTable - Everything you need to know — LazyAdmin</title> <url>https://lazyadmin.nl/powershell/powershell-hashtable/</url> </item> <item> <title>How a Regex Engine Works Internally</title> <url>https://www.regular-expressions.info/engine.html</url> </item> </items_list>
原哈希表构建代码
$InXML = [XML](Get-Content .\test.xml) $BookMarks = [ordered]@{ Title = (Select-Xml -xml $InXML -XPath "//title" | % {$_.Node.InnerXml}) -replace '\?|\\|/|:' URL = Select-Xml -xml $InXML -XPath "//url" | % {$_.Node.InnerXml} }
原循环处理代码(存在问题)
$wshshell = New-Object -ComObject WScript.Shell $BookMarks | ForEach-Object { $Title = $_.Title $Url = $_.Url Write-Output $shortcutFilePath # $shortcutFilePath = Join-Path -path "c:\temp" -ChildPath "$Title.Url" # $shortcut = $shell.CreateShortcut($shortcutFilePath) # $shortcut.TargetPath = "$Url" # $shortcut.Save() }
问题分析
原哈希表结构错误:$BookMarks中的Title和URL各自是包含所有条目值的数组,而非一一对应的键值对集合。用ForEach-Object遍历该哈希表时,实际遍历的是哈希表的两个键(Title和URL),无法同时获取同一item对应的标题和URL。此外,原代码还存在变量未定义($shell应为$wshshell)、提前输出未赋值变量的问题。
解决方法
方法一:直接遍历XML节点(推荐)
无需构建哈希表,直接遍历XML中的每个<item>节点,天然获取对应标题和URL,代码更简洁直观:
# 读取XML时指定UTF-16编码,避免乱码 $InXML = [XML](Get-Content .\test.xml -Encoding UTF16) $wshshell = New-Object -ComObject WScript.Shell $outputPath = "c:\temp" # 遍历每个item节点 foreach ($item in $InXML.items_list.item) { # 清理标题中的非法字符(Windows文件名不允许?\/:) $cleanTitle = $item.title -replace '\?|\\|/|:', '' $shortcutFilePath = Join-Path -Path $outputPath -ChildPath "$cleanTitle.url" # 创建并保存.url快捷方式 $shortcut = $wshshell.CreateShortcut($shortcutFilePath) $shortcut.TargetPath = $item.url $shortcut.Save() }
方法二:构建正确的哈希表数组
如果需要保留哈希表结构,需将每个item转换为独立的哈希表并存入数组,确保循环时能获取每一对标题和URL:
$InXML = [XML](Get-Content .\test.xml -Encoding UTF16) # 构建包含单个item信息的哈希表数组 $BookMarks = foreach ($item in $InXML.items_list.item) { [ordered]@{ Title = $item.title -replace '\?|\\|/|:', '' URL = $item.url } } $wshshell = New-Object -ComObject WScript.Shell $outputPath = "c:\temp" # 遍历哈希表数组,处理每个item $BookMarks | ForEach-Object { $shortcutFilePath = Join-Path -Path $outputPath -ChildPath "$($_.Title).url" $shortcut = $wshshell.CreateShortcut($shortcutFilePath) $shortcut.TargetPath = $_.URL $shortcut.Save() }
内容的提问来源于stack exchange,提问作者hellen_dorandt89
相关产品推荐
相关产品推荐

