我们正在尝试在Windows 7客户端上检索已登录用户的映射驱动器。以下代码在使用管理员帐户运行时为我们执行此操作。
唯一的问题是,偶尔(首次在新客户端上运行代码时),它不会返回' PS_Data.txt'的结果。第一次运行时的文件。第二次运行时,数据会正确返回。由于某种原因,文件中填充了正确的数据,但未检索到该文件。
我一直认为任务删除速度太快,所以我尝试在这里和那里玩一些Start-Sleep
CmdLets,但没有真正解决它。
#$Computer = 'ClientName'; $User = 'LoggedOnUserSamAccountName'
$VerbosePreference = 'Continue'
Invoke-Command -ScriptBlock {
Param (
[Parameter(Mandatory)]
[String]$User,
[Parameter(Mandatory)]
[String]$TaskName
)
$VerbosePreference = [System.Management.Automation.ActionPreference]$Using:VerbosePreference
$DebugPreference = [System.Management.Automation.ActionPreference]$Using:DebugPreference
$CurrentDir = 'C:\Users\' + $User + '\AppData\Local\Temp'
$Script = $CurrentDir + '\PS_Script.ps1'
$Launcher = $CurrentDir + '\PS_Launcher.vbs'
$File = $CurrentDir + '\PS_Data.txt'
$File, $Script, $Launcher | Remove-Item -EA Ignore
# VB is only needed to kick-of the script and suppress the PowerShell window
# and to set the workdir
$VBCode = @"
'run window totally hidden
Dim oSHELL
Set oSHELL = CreateObject("WScript.Shell")
oSHELL.CurrentDirectory = "$CurrentDir"
oSHELL.Run "powershell.exe -ExecutionPolicy Bypass -NoLogo -File .\PS_Script.ps1", 0
Set oSHELL = Nothing
"@
$PSCode = {
Get-WmiObject -Class win32_mappedlogicaldisk | Select-Object Name, ProviderName |
Export-Csv .\PS_Data.txt -NoTypeInformation
}
Try {
$VBCode | Set-Content $Launcher -EA Stop
Write-Verbose ($env:COMPUTERNAME + " Temp file created '$Launcher'")
$PSCode | Set-Content $Script -EA Stop
Write-Verbose ($env:COMPUTERNAME + " Temp file created '$Script'")
}
Catch {
throw "User profile folder '$CurrentDir' not found on '$env:COMPUTERNAME'"
}
Try {
#schtasks /create /F /RL HIGHEST /SC ONCE /ST 23:00 /TN $TaskName /TR "wscript.exe $Launcher" /RU "$env:USERDNSDOMAIN\$User"
$Task = New-Object -ComObject "Schedule.Service"
$Task.Connect($env:COMPUTERNAME)
$Task_Folder = $Task.GetFolder('\')
$Task_TaskDefinition = $Task.NewTask(0)
$Task_RegistrationInfo = $Task_TaskDefinition.RegistrationInfo
$Task_RegistrationInfo.Description = 'This task is created with PowerShell to run with user credentials'
$Task_RegistrationInfo.Author = 'Powershell'
$Task_Settings = $Task_TaskDefinition.Settings
$Task_Settings.Enabled = $True
$Task_Settings.StartWhenAvailable = $True
$Task_Settings.Hidden = $False
$Task_Settings.AllowDemandStart = $True
$Task_Settings.WakeToRun = $True
$Task_Settings.StopIfGoingOnBatteries = $False
$Task_Action = $Task_TaskDefinition.Actions.Create(0)
$Task_Action.Path = 'wscript.exe'
$Task_Action.Arguments = $Launcher
$Task_Action.WorkingDirectory = $CurrentDir
$Task_Folder.RegisterTaskDefinition($TaskName, $Task_TaskDefinition, 6, ($env:USERDNSDOMAIN + '\' + $User), $null, 3) | Out-Null
Write-Verbose ($env:COMPUTERNAME + " Scheduled task '$TaskName' is created")
schtasks /run /TN $TaskName | Write-Verbose
Write-Verbose ($env:COMPUTERNAME + " Scheduled task '$TaskName' is started as user '$User'")
#Start-Sleep -Seconds 3
# Wait for scheduled task to finish
while ((& schtasks.exe /query /TN $TaskName /FO CSV | ConvertFrom-Csv | Select-Object -ExpandProperty Status -First 1) -eq 'Running') {
Write-Verbose ($env:COMPUTERNAME + " Scheduled Task '$TaskName' is running")
Start-Sleep -Milliseconds 500
}
Write-Verbose ($env:COMPUTERNAME + " Scheduled task '$TaskName' is finished")
}
Catch {
throw "Failed creating/running the scheduled rask '$TaskName' on '$env:COMPUTERNAME': $_"
}
# Wait for the data file to be available
for ($i = 0; $i -le 5; $i++) {
if (Test-Path $File) {
Import-Csv $File | Select-Object * -ExcludeProperty RunspaceID
Write-Verbose ($env:COMPUTERNAME + " Temp file created and data imported '$File'")
$Data = $True
Break
}
else {
Start-Sleep -Seconds 1
}
}
if (-not $Data) {
Write-Verbose ($env:COMPUTERNAME + " No data found")
}
#schtasks /delete /F /TN $TaskName
$Task_Folder.DeleteTask($TaskName, 0)
Write-Verbose ($env:COMPUTERNAME + " Scheduled task '$TaskName' is deleted")
#$File, $Script, $Launcher | Remove-Item -EA Ignore
Write-Verbose ($env:COMPUTERNAME + " Temp files removed")
} -ComputerName $Computer -ArgumentList $User, 'Test'
答案 0 :(得分:0)
问题已解决,似乎计划任务仅踢了脚本,但在完成之前没有保持状态Running
。通过将VB代码修改为以下内容来解决此问题:
oSHELL.Run "powershell.exe -ExecutionPolicy Bypass -NoLogo -File .\PS_Script.ps1", 0, True
希望这有助于某人。
在完整版和增强版之下,正确暂停以正确创建和检查计划任务:
Invoke-Command -ScriptBlock {
Param (
[Parameter(Mandatory)]
[String]$User,
[Parameter(Mandatory)]
[String]$TaskName
)
$VerbosePreference = [System.Management.Automation.ActionPreference]$Using:VerbosePreference
$DebugPreference = [System.Management.Automation.ActionPreference]$Using:DebugPreference
$CurrentDir = 'C:\Users\' + $User + '\AppData\Local\Temp'
$Script = $CurrentDir + '\PS_Script.ps1'
$Launcher = $CurrentDir + '\PS_Launcher.vbs'
$File = $CurrentDir + '\PS_Data.txt'
$File, $Script, $Launcher | Remove-Item -EA Ignore
#region Create temp files
Try {
# VB is only needed to kick-of the script and suppress the PowerShell window and to set the workdir
$VBCode = @"
'run window totally hidden
Dim oSHELL
Set oSHELL = CreateObject("WScript.Shell")
oSHELL.CurrentDirectory = "$CurrentDir"
oSHELL.Run "powershell.exe -ExecutionPolicy Bypass -NoLogo -File .\PS_Script.ps1", 0, True
Set oSHELL = Nothing
"@
$VBCode | Set-Content $Launcher -EA Stop
Write-Verbose ($env:COMPUTERNAME + " Temp file created '$Launcher'")
$PSCode = {
Start-Sleep -Seconds 5
Get-WmiObject -Class win32_mappedlogicaldisk | Select-Object Name, ProviderName |
Export-Csv .\PS_Data.txt -NoTypeInformation
}
$PSCode | Set-Content $Script -EA Stop
Write-Verbose ($env:COMPUTERNAME + " Temp file created '$Script'")
}
Catch {
throw "User profile folder '$CurrentDir' not found on '$env:COMPUTERNAME'"
}
#endregion
Try {
#region Create scheduled task
#schtasks /create /F /RL HIGHEST /SC ONCE /ST 23:00 /TN $TaskName /TR "wscript.exe $Launcher" /RU "$env:USERDNSDOMAIN\$User"
$Task = New-Object -ComObject "Schedule.Service"
$Task.Connect($env:COMPUTERNAME)
$Task_Folder = $Task.GetFolder('\')
$Task_TaskDefinition = $Task.NewTask(0)
$Task_RegistrationInfo = $Task_TaskDefinition.RegistrationInfo
$Task_RegistrationInfo.Description = 'This task is created with PowerShell to run with user credentials'
$Task_RegistrationInfo.Author = 'Powershell'
$Task_Settings = $Task_TaskDefinition.Settings
$Task_Settings.Enabled = $True
$Task_Settings.StartWhenAvailable = $True
$Task_Settings.Hidden = $False
$Task_Settings.AllowDemandStart = $True
$Task_Settings.WakeToRun = $True
$Task_Settings.StopIfGoingOnBatteries = $False
$Task_Settings.DisallowStartIfOnBatteries = $False
$Task_Action = $Task_TaskDefinition.Actions.Create(0)
$Task_Action.Path = 'wscript.exe'
$Task_Action.Arguments = $Launcher
$Task_Action.WorkingDirectory = $CurrentDir
$Task_Folder.RegisterTaskDefinition($TaskName, $Task_TaskDefinition, 6, ($env:USERDNSDOMAIN + '\' + $User), $null, 3) | Out-Null
Write-Verbose ($env:COMPUTERNAME + " Scheduled task '$TaskName' is created")
#endregion
#region Run scheduled task
$StartDateUTC = (Get-Date).ToUniversalTime()
schtasks /run /TN $TaskName | Write-Verbose
Write-Verbose ($env:COMPUTERNAME + " Scheduled task '$TaskName' is started as user '$User'")
#endregion
#region Wait for scheduled task to finish
# Initial wait time because tasks don't start fast enough
Start-Sleep -Seconds 1
while ($Task_Folder.GetTask($TaskName).State -ne 3) {
Write-Verbose ($env:COMPUTERNAME + " Scheduled Task '$TaskName' is running")
Start-Sleep -Seconds 1
}
Write-Verbose ($env:COMPUTERNAME + " Scheduled task '$TaskName' is finished")
#endregion
#region Check eventlog for failures because user might not be logged in
$Date ="{0}-{1}-{2}T{3}:{4}:{5}.{6}z" -f $StartDateUTC.Year, $StartDateUTC.Month, $StartDateUTC.Day,
$StartDateUTC.Hour, $StartDateUTC.Minute, $StartDateUTC.Second, $StartDateUTC.Millisecond
# Initial wait time for the task to write to the eventlog
Start-Sleep -Seconds 1
$Problems = Get-WinEvent -ErrorAction Ignore -FilterXml @"
<QueryList>
<Query Id="0" Path="Microsoft-Windows-TaskScheduler/Operational">
<Select Path="Microsoft-Windows-TaskScheduler/Operational">
*[EventData/Data[@Name='TaskName']='\$TaskName'] and
*[System[Provider[@Name='Microsoft-Windows-TaskScheduler'] and
(Level=1 or Level=2 or Level=3) and
TimeCreated[@SystemTime>='$Date']]]</Select>
</Query>
</QueryList>
"@
if ($Problems) {
if ($Problems.Message -like '*2147943645*') {
throw "The scheduled task can only run when the user is logged on to the client, because we use the user's credentials to run this task."
}
else {
throw $Problems.Message
}
}
#endregion
}
Catch {
throw "Failed creating/running the scheduled rask '$TaskName' on '$env:COMPUTERNAME': $_"
}
#region Get results
if (Test-Path $File) {
Import-Csv $File | Select-Object * -ExcludeProperty RunspaceID
Write-Verbose ($env:COMPUTERNAME + " Temp file created and data imported '$File'")
}
else {
Write-Verbose ($env:COMPUTERNAME + " No data found")
}
#endregion
#region Delete temp files and task
#schtasks /delete /F /TN $TaskName
$Task_Folder.DeleteTask($TaskName, 0)
Write-Verbose ($env:COMPUTERNAME + " Scheduled task '$TaskName' is deleted")
$File, $Script, $Launcher | Remove-Item -EA Ignore
Write-Verbose ($env:COMPUTERNAME + " Temp files removed")
#endregion
} -ComputerName $Computer -ArgumentList $User, 'Test'