在针对从任务计划程序导出的XML文件运行时,使用此 PowerShell 查询以正确格式获取所需结果时遇到问题。我最终会针对转发到同一个XML文件的所有任务计划程序导出的作业进行此操作,但我现在只从一个开始。
PowerShell逻辑 (不工作)
$file = "C:\folder\test.xml"
$Xml = [xml](Get-Content $file)
$Xml.SelectNodes("//*").ChildNodes | Select URI,Command |
Where-Object { ($_.URI -ne $null) -or ($_.Command -ne $null) } | FL
也许在循环中使用 PowerShell 进行更好或更明确的方式,或嵌入一些 C#代码并使用PowerShell等执行此操作。我想我我在这里问别人,因为经过大量的测试和研究后我无法理解这一点,但我愿意接受所有的想法,以帮助我得到想要的结果或类似的东西(见下文)。如果我需要 SQL Server 的结果,我会使用FOR XML PATH
。
当前结果格式 (不需要)
URI : \_Test\Test
Command :
URI :
Command : C:\Folder\process1.exe
URI :
Command : C:\Folder\process2.exe
所需的结果格式 (或类似)
URI : \_Test\Test
Command : C:\Folder\process1.exe
Command : C:\Folder\process2.exe
示例XML
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<RegistrationInfo>
<Date>2017-03-09T09:36:56.2658334</Date>
<Author>FBI-PC1\User</Author>
<URI>\_Test\Test</URI>
</RegistrationInfo>
<Triggers />
<Principals>
<Principal id="Author">
<UserId>S-1-5-21-3517161704-4063526634-2635523359-1001</UserId>
<LogonType>InteractiveToken</LogonType>
<RunLevel>LeastPrivilege</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
<AllowHardTerminate>true</AllowHardTerminate>
<StartWhenAvailable>false</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>true</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>false</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT72H</ExecutionTimeLimit>
<Priority>7</Priority>
</Settings>
<Actions Context="Author">
<Exec>
<Command>C:\Folder\process1.exe</Command>
</Exec>
<Exec>
<Command>C:\Folder\process2.exe</Command>
</Exec>
</Actions>
</Task>
系统规格 (需要使用)
答案 0 :(得分:3)
由于您正在同时选择两个对象应用where条件,因此为了将相等性保持为单个对象,它就是这样显示的。
在您的情况下,您可以做的是将结果存储在 arraylist 中,并在那里对所有命令进行操作:
$file = "C:\folder\test.xml"
$Xml = [xml](Get-Content $file)
$URI= $Xml.SelectNodes("//*").ChildNodes | Select URI| Where-Object { $_.URI -ne $null}
$Command= $Xml.SelectNodes("//*").ChildNodes | Select Command| Where-Object { $_.Command -ne $null}
$arraylisttable = New-Object System.Collections.ArrayList
$arraylisttable.Add($URI) | Out-Null
foreach($cmd in $Command)
{
$arraylisttable.Add($Cmd) | Out-Null
}
$arraylisttable | fl
<强> 输出: 强>
希望它有所帮助。
答案 1 :(得分:3)
$Xml.SelectNodes("//*[local-name()='Command' or local-name()='URI']") | select Name, "#text"
Name #text
---- -----
URI \_Test\Test
Command C:\Folder\process1.exe
Command C:\Folder\process2.exe
这样您就可以将选择逻辑移动到Xpath。注意事项:
//*
选择所有节点[]
内的文字是XPath过滤条件。local-name()
XPath函数是一种避免混淆命名空间的技巧请注意,XPath比较区分大小写。不幸的是,XPath 1.0没有lower-case()
之类的功能。要进行不区分大小写的比较(如Powershell所做的那样),请使用translate()
函数:
$Xml.SelectNodes("//*[translate(local-name(), 'COMAND', 'comand')='command' or translate(local-name(), 'uri', 'URI')='URI']") | select Name, "#text"
如果你更喜欢纯粹的Powershell而不是XPath,那么这是另一种解决方案:
$xml.SelectNodes('//*') | ? {$_.Name -in ('command', 'uri')} | select Name, "#text"
关于任务的另外一件事。您不必转储它们。它们本身作为xml驻留在C:\Windows\Tasks
或。{
C:\Windows\System32\Tasks
个文件夹取决于操作系统。对于Win7,它是C:\Windows\System32\Tasks
。您需要管理员权限才能阅读它们。
修改:要使完全输出相同的内容:
$xml.SelectNodes('//*') | ? { $_.Name -in ('command', 'uri') } |
select Name, @{Name = 'Value'; Expression = {": $($_.'#text')" } } |
ft -HideTableHeaders
URI : \_Test\Test
Command : C:\Folder\process1.exe
Command : C:\Folder\process2.exe
自定义对象:
$customObject = [pscustomObject]@{
URI = ($xml.SelectNodes("//*[local-name()='URI']")).'#text'
Command = ($xml.SelectNodes("//*[local-name()='Command']")).'#text'
}
$customObject | fl
URI : \_Test\Test
Command : {C:\Folder\process1.exe, C:\Folder\process2.exe}