2017-01-24 11 views
0

Windows 7クライアントでログオンしているユーザーのマップされたドライブを取得しようとしています。以下のコードは、管理者アカウントを使用して実行した場合、私たちのためにこれを行います。予定タスクの結果

唯一のことは、新しいクライアントで初めてコードを実行するときに、最初の実行時に 'PS_Data.txt'ファイルの結果を返さないことです。 2回目の実行時には、データが正しく返されます。 1つまたは複数の理由により、ファイルには正しいデータが取り込まれますが、取り出されません。

私はタスクが速すぎて削除されていると考えていたので、ここでは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' 
+1

私は再現するために必要なコードの唯一の絶対的な最小量が含まれている簡単な例を提供することをお勧め問題。 –

答えて

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&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' 
関連する問題