PowerShell scheduled job to restart console application - scheduled-tasks

I am trying to use PowerShell scheduled job to logoff my machine at specific time.
$trigger = New-JobTrigger -Daily -At (Get-Date).AddMinutes(2)
Register-ScheduledJob -Trigger $Trigger -Name "LogoffComputer5" -ScriptBlock {
shutdown /l /f
Get-Process | Out-File -FilePath "c:\process.txt"
} -Credential $credential
I thought it is permission so I used Invoke-Command with credentials, also I used shutdown with full path.
I tried command as following
Start-Process "cmd.exe" "/C shutdown /l /f"
All the commands works from PowerShell but not from scheduled job.
Import-Module PSScheduledJob;
$jobDef = [Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition]::LoadFromStore('LogoffComputer5', 'C:\Users\wkassem\AppData\Local\Microsoft\Windows\PowerShell\ScheduledJobs');
$jobDef.Run()
The above command works if I run from PowerShell.

Related

How to create working Powershell task to stop process hung Firefox process?

I tried to script code to stop hung Firefox process, I want the script to stop all Firefox browser processes periodically.
$trigger = New-JobTrigger -Daily -At 14:20
$options = New-ScheduledJobOption -WakeToRun
Register-ScheduledJob -Name StopFirefox -ScriptBlock {Stop-Process -Name "Firefox" -Force} -Trigger $trigger -ScheduledJobOption $options
But I get Task Scheduled answer that 2147942402 which translates to "File not Found" for both:
{Stop-Process -Name "Firefox" -Force} and {Get-Process -Name "Firefox" | Stop-Process}
You have to add the permission to the job to by adding a user under which the Job runs and who can stop your process, because the process was launched unter a certain user.
If I you add -Credential (Get-Credential) to the Register-ScheduledJob Cmdlet then you should be prompted once for entering your credentials and after that your code should run fine and stop your Firefox process.

Get the current ScheduledJob name

In Powershell, I created a ScheduledJob using the command Register-ScheduledJob -ScriptBlock {...}. This ScheduledJob executes a ScriptBlock. How can I retrieve the name of the currently running ScheduledJob from the ScriptBlock?
E.g.
Register-ScheduledJob -ScriptBlock { $CurrentScheduledJob | Out-File -FilePath ScheduledJob.txt}
The task in the Windows Task Scheduler is running the command:
powershell.exe -NoLogo -NonInteractive -WindowStyle Hidden -Command
"Import-Module PSScheduledJob; $jobDef =
[Microsoft.PowerShell.ScheduledJob.ScheduledJobDefinition]::LoadFromStore('asdfdsafsdf',
'C:\Windows\system32\config\systemprofile\AppData\Local\Microsoft\Windows\PowerShell\ScheduledJobs');
$jobDef.Run()"
I tried to save the variable $jobDef but it is empty.
Thank you
I ran a ScheduledJob and exported all variable and environment variable and did not find the name or id of the job.
I found a work around:
$jobName = 'testName'
Register-ScheduledJob -ScriptBlock { param($name)
$name | out-file C:\name.txt
} -name $jobName -ArgumentList #($jobName)
If using a parameter is not a solution for you, and you absolutely must retrieve it at run time, then this is a feature request. You can ask for this at the PowerShell user voice

Powershell process 'hanging' when running remote batch file

I'm trying to run a batch file on a remote server via a drive mapping as follows, but the process hangs...
Enable-WSManCredSSP -Role Client -DelegateComputer someserver -Force
$credential = Get-Credential -Credential domain\user (then I supply the password in the popup)
$RemoteSession = New-PSSession -ComputerName someserver -Credential $credential -Authentication Credssp
Invoke-Command -Session $RemoteSession -ScriptBlock { Enable-WSManCredSSP -Role Server -Force }
Invoke-Command -Session $RemoteSession -ScriptBlock { New-PSDrive -Name I -PSProvider FileSystem -Root \\server\share$ }
Everything seems fine up to this point and I can 'dir' the I drive and see the expected content.
When I execute the following, the process hangs -
Invoke-Command -Session $RemoteSession -ScriptBlock { Start-Process I:\temp.bat }
The temp.bat file executes the following command and I've verified manually that it works
echo Scott was here > C:\temp.txt
However, the command runs for over 5 minutes without any response.
Can anyone help? What have I done wrong?
Although this is not a direct solution to your question, my suggestion from many weeks of banging my head against my keyboard is to just take a different path.
$taskName = whocares
$command = I:\Temp.bat
$serverName = theServer
$userName = domain\user
$pass = pl4inT3xtPassword
$date = (Get-Date).addMinutes(1)
$formats = $date.getDateTimeFormats()
$startTime = $formats[113]
schtasks.exe /create /sc ONCE /tn $taskName /tr $command /s $serverName /u $userName /p $pass /ru $userName /rp $pass /st $startTime
This will create a task, start the process in the next minute, and then remove itself from the scheduler. There is also a /z flag in there to remove after it runs, but if your like me and on XP then this probably won't be available to you. If you notice your task isnt being removed after it runs you can always wait a minute and then kill it... or you can get a little bit more fancy with it:
while(($timer -lt 60) -and (!$running)) {
schtasks.exe /query /S $serverName /FO CSV /v /u $userName /p $pass | ConvertFrom-CSV | `
% {if($_.Status -eq "Running") {
Write-Host "IT WORKED!"
Write-host $_
$running = $true
}
}
if(!$running) {
$timer++
}
sleep 1
}
schtasks.exe /delete /s $serverName /u $userName /p $pass /tn $taskName /f
This bit just queries the task every second to check if its running... once it is it will delete the old scheduled task and your process will continue to run (until its finished).
The task scheduler is the only clean way I have found to start processes remotely with PowerShell. Instead of being a child process of your PSremote.exe, it will be under System. Also, unlike remote-session, if you X out of your powershell session, the process will persist on the remote computer.
I know it is a lot more than just your one liner, but I hope it is useful, and if you parameterize it or even build a windows forms application on top it will save you a lot of time and headache.
more on schtasks Here
Thanks for your suggestions.
Due to other issues (with the process that we're ultimately trying to run), we've put this down for the minute, without finding a solution
Thanks for your help and suggestions. Will hopefully pick this back up in a few weeks
Scott
Try putting an -AsJob at the end of your Invoke-Command lines?
As an FYI if Invoke-Command always hangs it may be the service or firewall:
Try a simple command to system :
Invoke-Command -ComputerName XXXXX -ScriptBlock { Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion }
Start the Windows Remote Management Service (on that system)
Check for the listening port:
netstat -aon | findstr "5985"
TCP 0.0.0.0:5985 0.0.0.0:0 LISTENING 4
TCP [::]:5985 [::]:0 LISTENING 4

Powershell Start-Process msiexec on a remote machine not working

For some reason Start-Process msiexec won't work when run through invoke command on a remote machine. I looked it up and while some people recommend using psiexec i have seen a lot of people using the plain old invoke-command to start msi installers on remote machines.
This is the code i am currently using:
$session = New-PSSession -computername $computerName -ea stop
$command = {
Param(
[Parameter()]
[string]$computerName,
[Parameter()]
[string]$domain,
[Parameter()]
[string]$user,
[Parameter()]
[string]$password,
[Parameter()]
[string]$installDir
)
$msiArgumentList = "/i C:\Installer.msi /l c:\log.txt /quiet /qr /norestart IAGREE=Yes DOMAIN=$domain ACCOUNT=$user PASSWORD=$password PASSWORDCONFIRM=$password INSTALLDIR=$installDir"
Start-Process msiexec -ArgumentList $msiArgumentList -Wait
}
Invoke-Command -session $session -ScriptBlock $command -ArgumentList $computerName, $domain, $user, $password, $installDir
Remove-PSsession -session $session
I used the same method to install services remotely using intallutil and it worked. Scripting is enabled on target machine as well as remoting so by all accounts it should work. Both computers have the same credentials but i still tried adding credentials to both invoke-command and the pssession. I tested the code locally and the installation worked. Remotely it doesn't and no errors what so ever. i can see on the target machine in taskmanager that msiexec is started but nothing happens. I even tried disabling the firewall and still nothing. i tried the & operator to start msiexec and still nothing.
Not sure what else i could try.
Maybe you try another way, if you don't come forward?
Use Task scheduler, to start the command line e.g by creating and executing a task on the remote machine:
SchTasks /CREATE /XML mycommand.xml /TN "thiscommand"
SchTasks /RUN /TN "thiscommand"
This is for starting a task (like) on the local computer.
With parameter /S you can create tasks on remote computers as in:
SchTasks /S thatPC /CREATE /XML mycommand.xml /TN "thiscommand"
SchTasks /S thatPC /RUN /TN "thiscommand"
For details of parameters and for syntax of the .xml file defining the task you can look into the help.
You could try executing Start-Process with Passthru to see if an error is being returned:
(Start-Process -FilePath msiexec.exe -ArgumentList $msiArgumentList -Wait -Passthru).ExitCode
The other thing that may help is increasing your logging to /l*v
Update 1
Can you try the following, just to check remote commands for msi are working, it should result in 1619.
(Start-Process -FilePath msiexec.exe -ArgumentList "/i no.msi /quiet /qb!" -Wait -Passthru).ExitCode
It seems the problem was a combination of how the msi installer was build and the restrictions windows server has towards interactive processes. I ended up using psexec to bypass this problem.
The only solution that worked for me was to poll the process status. This can be run inside a scriptblock in a remote powershell session.
$res = Start-Process -FilePath $process -ArgumentList $arguments -Wait -PassThru
while ($res.HasExited -eq $false) {
Write-Host "Waiting for $process..."
Start-Sleep -s 1
}
$exitCode = $res.ExitCode
Using the answers above I ended up with
$session = New-PSSession -ComputerName $serverName -Credential $mycred
invoke-command -Session $session -ScriptBlock { param ($argxs) write-host $argxs; start-process msiexec.exe -ArgumentList $argxs } -ArgumentList "/i `"$pathToMsi`" /qn /L*V `"E:\package.log`""
The write-host is just there to verify the augments are correctly escaped but proved invaluable in debugging.

Schedule a Job in Powershell 3.0

I am working on PS script that will run a task once the computer has been logged in. Here is how I schedule the task:
$trigger = New-JobTrigger -AtLogOn
Register-ScheduledJob -Name TestSchedule -FilePath <filepath> -Trigger $trigger
The script scheduled to run does nothing but launch the command prompt, however nothing is being run once I log in to the computer. I have tried tinkering with it all I could but I get nothing.
Maybe not the best best solution but you could try putting the other script into this "job-script". Like This. Works Fine for me.
$jobname = "xyz"
$JobTrigger = New-JobTrigger -Weekly -At "03:00 AM" -DaysOfWeek Saturday
$MyOptions = New-ScheduledJobOption -ContinueIfGoingOnBattery -HideInTaskScheduler
Register-ScheduledJob -name "$jobname" -scriptblock {$myscript} -trigger $JobTrigger –ScheduledJobOption $MyOptions
I think your code lacks this command:
Set-ScheduledTask -TaskName $name -TaskPath Microsoft\Windows\PowerShell\ScheduledJobs -Principal (New-ScheduledTaskPrincipal -L Interactive -U $env:USERNAME)
$name is the name of your scheduledjob, this command makes the job interactive to the user, if your code still doesn't work, check out this script:
https://gallery.technet.microsoft.com/scriptcenter/PC-Utilities-Downloader-355e5bfe