Powershell script on VM as scheduled task - powershell

I wrote a simple script to move files that contain a specific substring in the file name from one folder to another.
$Source = Get-ChildItem -Path "C:\source" -Filter *.xlsm
$Target = "C:\target"
$substring = 'copy'
foreach ($file in $Source) {
if($file.Name -match $substring){
Move-Item -Path $file.FullName -Destination $Target -Force
}
}
I want to automate it on VM. It works fine when I'm running it manually and via task scheduler when I'm logged in VM, however when I switch to 'run whether logged on or logged off' in task scheduler (script properties) it won't work. I run it with following parameters:
-noprofile -executionpolicy unrestricted -noninteractive -file "path to my script"
Any ideas?

When the option "Run whether user is logged on or not" is selected, the scheduled task runs on a different session.
This means that it does not have access to the mapped network drives !.
So, you need to either map drives in your script or use the fully qualified name (i.e., \server name\share name)
More details here as well

Related

Workflow not working when called by another script

I have a script, let's call it A.ps1 that uses a workflow called Copy-Parallel (the workflow is defined in the beginning of the script). I created a GUI.ps1 script that I use to easily select between multiple scripts, it calls the desired script with "Start-Process". In the end I created a shortcut, so I could run the GUI by double-click.
All resources are located on a server and the two scripts are in the same folder called Res. The shortcut is located in the same folder as Res. When we use the shortcut, the script works fine for me but other users get the: term 'Copy-Parallel' is not recognized as the name of a cmdlet, function... error.
We tried to run the A.ps1 script directly and it works fine for me and other users. We tried running the GUI.ps1 via a .bat file, the results were similar to the ones when we used the shortcut.
A.ps1:
workflow Copy-Parallel {
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[array]
$Files,
[Parameter(Mandatory)]
[string]
$Destination
)
foreach -parallel -throttlelimit 20 ($File in $Files) {
Copy-Item -LiteralPath $File -Destination $Destination -Force
}
}
Copy-Parallel -Files $SourceFiles.FullName -Destination $DestinationPath
GUI.ps1 calls the script as follows:
$ScriptToRun = "$PSScriptRoot\A.ps1"
Start-Process PowerShell.exe -ArgumentList $ScriptToRun -NoNewWindow
The target for the shortcut that starts the GUI is: %windir%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -WindowStyle Hidden -NonInteractive -ExecutionPolicy bypass -File "Res\GUI.ps1"

PowerShell Script not running when set in the task scheduler

I'm attempting to create a task via powershell to delete some files older then 6 hours, if I execute the script from powershell there are no issues, if I try to execute from task scheduler nothing happens..
Call the Powershell.exe in my schedulded task:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
Set this Parameters :
-NoProfile -ExecutionPolicy Bypass -Command -NonInteractive -File "C:\Scripts\DeleteFilesDiff3H.PS1"
What could be the problem of the task scheduler not launching my script?
Tried to aply some solutions provide to similar issues without success
$Path = "E:\MyPath"
$now = Get-Date
Get-Childitem * |
Where-Object { $_.LastWriteTime -le $now.AddHours(-6) } |
Remove-Item -Recurse -Force
I got this messages:
Task Scheduler started "{38dcd44b-4210-473b-921e-3cc1442ff03b}" instance of the "\Delete Files 3H" task for user "my user".
Task Engine "S-1-5-21-159114655-2248028564-2417230598-213599:My User:Interactive:LUA[2]" received a message from Task Scheduler service requesting to launch task "\Delete Files 3H" .
Task Scheduler launched "{38dcd44b-4210-473b-921e-3cc1442ff03b}" instance of task "\Delete Files 3H" due to a time trigger condition.
Task Scheduler successfully completed task "\Delete Files 3H" , instance "{618e6f44-b523-4c56-ae0b-04d3552391cc}" , action "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" with return code 0.
You don't make use of the defined variable $path so Get-ChildItem will never look there. Update your code to the following and check if this works for you:
$Path = "E:\MyPath"
$now = Get-Date
Get-Childitem -path $Path |
Where-Object { $_.LastWriteTime -le $now.AddHours(-6) } |
Remove-Item -Recurse -Force

Copy-item runas Administrator to program file fail

i would like to copy the license folder and overwrite the existing folder, since it is program file (x86), i have to run the elevated powershell, i am able to copy it when i launch it manually, just wonder is it possible to get all run at one line (all at once) ? really appreicated
$net = new-object -ComObject WScript.Network
$net.MapNetworkDrive("R:", "\\roa\smdd\Software\Mest", $false)
Start-process Powershell.exe -ArgumentList " Copy-Item "R:\Licenses\" "C:\Program Files `(x86`)\Mest Research S.L\Mest\licenses"" -force -recurse -wait
You don't need to map a drive or invoke powershell.exe. The code is PowerShell, so you don't need to spin up a new copy of PowerShell to run the Copy-Item cmdlet to copy files. You only need one PowerShell command:
Copy-Item "\\roa\smdd\Software\Mest\Licenses\*" "${Env:ProgramFiles(x86)}\Mest Research S.L\Mest\licenses" -Force -Recurse
Note that you will likely need to open PowerShell as administrator (elevated) to be able to copy items into that directory.

How powershell handles returns from & calls

We have field devices that we decided to use a powershell script to help us handle 'updates' in the future. It runs every 5 minutes to execute rsync to see if it should download any new files. The script, if it sees any file types of .ps1, .exe, .bat ,etc. will then attempt to execute those files using the & operator. At the conclusion of execution, the script will write the file executed an excludes file (so that rsync will not download again) and remove the file. My problem is that the return from the executed code (called by &) behaves differently, depending on how the main script is called.
This is the main 'guts' of the script:
Get-ChildItem -Path $ScriptDir\Installs\* -Include #("*.ps1","*.exe","*.cmd","*.VBS","*.MSI") | ForEach {
Write-Verbose "Executing: $_"
& $_
$CommandName = Split-Path -Leaf $_
Write-Verbose "Adding $CommandName to rsync excludes"
Write-Output "$CommandName" | Out-File -FilePath $ScriptDir\excludes -Append -Encoding ASCII
Write-Verbose "Deleting '$_'"
Remove-Item $_
}
When invoking powershell (powershell.exe -ExecutionPolicy bypass) and then executing the script (.\Update.ps1 -Verbose), the script runs perfectly (i.e. the file is written to excludes and deleted) and you can see the verbose output (writing and deleting).
If you run the following (similar to task scheduler) powershell.exe -ExecutionPolicy bypass -NoProfile -File "C:\Update.ps1" -Verbose, you can see the new script get executed but none of the steps afterwards will execute (i.e. no adding to excludes or removing the file or the verbose outputs).

Right Click context - Search folder .txt & .log files

Still new to PowerShell and have been creating automation scripts, checks and balances and anything I can think of to make our jobs easier day to day. The contract we are working on are extremely tight when it comes to applications and forbids opensource\freeware applications. So I have been working on using powershell to do the job.
Here is what I have so far:
1. Created HKCR\Directory\Shell\powershell (default) Reg_sz Search Folder Text & Log files
2. Created HKCR\Directory\Shell\powershell\command (default) Reg_sz
C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe -file c:\temp\RightClickSearch.ps1 -NoExit -Command Set-Location -LiteralPath '%L'
I was able to get the right click to launch and the script opens up and prompts me for my keyword to search. Problem is, I can't seem to figure out how to pass the location to the script properly.
RightClickSearch.ps1 (I know the $path isn't set, before it was hardcoded and I know I have to pass a variable to it from the menu)
$promt = (Read-Host -Prompt "Enter Search Keyword")
Get-ChildItem -Path $Path -Include *.txt, *.log -Recurse | Select-String -Pattern $promt | Format-table -AutoSize -Property LineNumber,Filename,Path
Pause
There are two problems with your call to powershell.exe:
You can't specify both the -File and -Command parameters. You can only specify one of them.
Whichever one you do specify, it has to be the last parameter in the command. In your example, the -NoExit and -Command parameters would be ignored. (Type powershell.exe -? for an explanation.)
The good news is that PowerShell scripts themselves can accept arguments by using the param keyword. Simply declare the parameter at the top of your script:
param ($Path)
$promt = (Read-Host -Prompt "Enter Search Keyword")
Get-ChildItem -Path $Path -Include *.txt, *.log -Recurse | Select-String -Pattern $promt | Format-table -AutoSize -Property LineNumber,Filename,Path
Pause
You call it from the command line like this:
C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe -File c:\temp\RightClickSearch.ps1 -Path '%L'
Since $Path is the one and only parameter, you don't even have to specify its name:
C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe -File c:\temp\RightClickSearch.ps1 '%L'
Ironically, you could use the -Command parameter in exactly the same way. The only difference is that your script file will not be dot-sourced, but that won't matter in the example you gave.