首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >定时任务结果

定时任务结果
EN

Stack Overflow用户
提问于 2017-01-24 21:04:40
回答 1查看 302关注 0票数 0

我们正在尝试检索Windows 7客户端上登录用户的映射驱动器。下面的代码在使用管理员帐户运行时会为我们执行此操作。

唯一的问题是,偶尔(当第一次在新客户机上运行代码时),它不会在第一次运行时返回'PS_Data.txt‘文件的结果。当第二次运行时,数据被正确返回。由于这样或那样的原因,文件中填充了正确的数据,但没有检索到。

我一直在想,这个任务删除得太快了,所以我试着到处玩一些Start-Sleep CmdLets,但什么都没有真正解决它。

代码语言:javascript
复制
#$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'
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-01-26 22:39:54

问题已修复,似乎计划任务只踢了脚本,但在完成之前不会停留在Running状态。通过将VB代码修改为以下代码,已修复此问题:

代码语言:javascript
复制
oSHELL.Run "powershell.exe -ExecutionPolicy Bypass -NoLogo -File .\PS_Script.ps1", 0, True

希望这对某些人有帮助。

在完整版和增强版下面,所有正确的停顿都是为了正确创建和检查计划任务:

代码语言:javascript
复制
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&gt;='$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'
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41828987

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档