Powershell script does not run via Windows Scheduled Tasks - powershell

I have a VB application which generates a PDF file then runs a powershell script which prints it.
If I run the application manually (by double-clicking on it or through the DOS screen) everything works. The pdf gets generated & printed.
If I run the application through windows scheduled tasks the pdf gets generated but it doesn't get printed!
This is my powershell script:
Start-Process –FilePath $DocumentName –Verb PrintTo $PrinterName -PassThru | %{sleep 20;$_} | kill
at run time it becomes something like this:
Start-Process –FilePath E:\MyFolder\mydocument.pdf –Verb PrintTo MyPrinter -PassThru | %{sleep 30;$_} | kill
I tried changing it to this:
Start-Process –FilePath "E:\MyFolder\mydocument.pdf" –Verb PrintTo MyPrinter -PassThru | %{sleep 30;$_} | kill
but that hasn't worked either.
If paste it in powershell command line, it works fine!
Any suggestion anyone?
Thanks
System: Windows Server 2012 R2
This is my VB code for executing the powershell script:
Dim MyRunSpace As Runspace = RunspaceFactory.CreateRunspace()
MyRunSpace.Open()
Dim MyPipeline As Pipeline = MyRunSpace.CreatePipeline()
MyPipeline.Commands.AddScript(scriptText)

Related

Restarting a PowerShell script after the last process is closed

I wrote a script, which opens 7 programs approximately 10 times (yes its a prankscript).
My question is, is there a way to observe, if the last process is closed and if so, restarting the whole script again?
while ($start -le 10){
Start-Process mspaint.exe
Start-Process notepad.exe
Start-Process write.exe
Start-Process cmd.exe
Start-Process explorer.exe
Start-Process control.exe
Start-Process calc.exe
$start =+ 1
}
My script now looks like following:
$start; $process
PowerShell.exe -windowstyle hidden { script.ps1 }
while ($start -le 10){
Start-Process mspaint.exe
Start-Process notepad.exe
Start-Process write.exe
Start-Process cmd.exe
Start-Process explorer.exe
Start-Process control.exe
Start-Process calc.exe
$start =+ 1
}
$process = Get-Process mspaint.exe
if ($process = $false){
Start-Process -FilePath c:/script.ps1
}
I did test this, but it starts all over again... I think that I use Get-Process wrong...
Is there another way to observe, if the process is closed or not?
If it's acceptable to handle the re-launching inside the same, indefinitely running script:
# Note: This runs indefinitely.
# If run in the foreground, you can use Ctrl-C to stop.
while ($true) {
1..10 | ForEach-Object {
# Launch all processes and pass information
# about them through (-PassThru)
'mspaint.exe',
'notepad.exe',
'write.exe',
'cmd.exe',
'explorer.exe',
'control.exe',
'calc.exe' | ForEach-Object {
Start-Process -PassThru $_
}
} | Wait-Process # Wait for all processes to terminate.
# Continue the loop, which launches the programs again.
}
You could then launch the script invisibly in the background, via Start-Process; e.g.:
Start-Process -WindowStyle Hidden powershell.exe '-File c:\script.ps1'
Caveat: To stop the operation, you'll have to locate the hidden PowerShell process and terminate it. If you add -PassThru, you'll get a process-information object representing the hidden process back.
More work is needed if you want to be able to call the script itself normally, and let it spawn a hidden background process that monitors the launched processes and then reinvokes the script (invisibly):
# Launch all processes 10 times and
# collect the new processes' IDs (PIDs)
$allPids = (
1..10 | ForEach-Object {
'mspaint.exe',
'notepad.exe',
'write.exe',
'cmd.exe',
'explorer.exe',
'control.exe',
'calc.exe' | ForEach-Object {
Start-Process -PassThru $_
}
}
).Id
# Launch a hidden PowerShell instance
# in the background that waits for all launched processes
# to terminate and then invisibly reinvokes this script:
Start-Process -WindowStyle Hidden powershell.exe #"
-Command Wait-Process -Id $($allPids -join ',');
Start-Process -WindowStyle Hidden powershell.exe '-File \"$PSCommandPath\"'
"#
Caveat: To stop the operation, you'll have to locate the hidden PowerShell process and terminate it.
Without seeing your actual script you can use something along the lines of
$validate = Get-Process -Name pwsh
if ($validate){
Start-Process -FilePath c:/script.ps1
}

My powershell script is not stopping a process that I am opening

I am creating a basic powershell script that will open the calculator app, get its process id, and then eventually stop the process itself with confirmation. But when I run the following script on my computer (through Powershell ISE, but it also doesn't seem to work on regular powershell in admin mode), it does not kill the calculator process. I am running Windows 10 Version 21H1.
Start-Process calc.exe; Get-Process calc; Stop-Process -Name calc -whatif; Stop-Process -Name calc -Confirm -PassThru
I had to use the name Calculator instead of calc for Get-Process. I also had to add a delay between the launching of calc.exe and Stop-Process. Without the delay, it could not find the process to stop it.
Start-Process -FilePath calc.exe
Start-Sleep -Seconds 3
Get-Process -Name Calculator | Stop-Process

Calling another executable and capturing output

Using a PowerShell script I'm trying to execute SqlPackage.exe to update a database. The problem is that it spawns a new CMD window and I can't capture the output effectively.
Here is my script:
&$SqlPackage "/Action:Script", "/SourceFile:$($Environment.PackageFile)", "/Profile:$($Environment.PublishProfile)", "/OutputPath:$($Environment.ScriptFile)";
where SqlPackage = "SQLPackage\SqlPackage.exe";.
Strangely when I execute the script on a Windows 2008 R2 web server the output is inline with the PowerShell output, which is ideally what I want. On my Windows 7 machine it spawns a new CMD window.
How can I route the output to the PowerShell window all the time, or at least pipe to another file?
Edit
Full solution with waiting for process to finish:
$p = Start-Process $SqlPackage -ArgumentList #("/Action:Script", "/SourceFile:$($Environment.PackageFile)", "/Profile:$($Environment.PublishProfile)", "/OutputPath:$($Environment.ScriptFile)") -NoNewWindow -Wait -Passthru
$p.WaitForExit()
You should be able to get the result you are looking for if you use Start-Process with the -NoNewWindow parameter:
Start-Process $SqlPackage -ArgumentList #("/Action:Script", "/SourceFile:$($Environment.PackageFile)", "/Profile:$($Environment.PublishProfile)", "/OutputPath:$($Environment.ScriptFile)") -NoNewWindow
If you need to direct the output to a file you can also use the -RedirectStandardOutput / -RedirectStandardError parameters of Start-Process

Print pdf job won't work (powellshell scripts) after scheduled user is not logged in

We try to use a powershell scripts to print pdf files from a directory. It works fine if you schedule this scripts as task with option "Run only as user is logged on", but if you schedule the job as "Run whether user is logged on or not", the print pdf doesn't work at all. Here is the powershell scripts used to print:
$process = Start-Process -WindowStyle Hidden -FilePath $outfile -Verb Print -PassThru -Wait | %{sleep 5; $_} | kill
if ($process.StandardError)
{
log $process.StandardError
}
Any suggestions are welcome!

Find exit code for executing a cmd command through PowerShell

I am using a silent installation command to install software. I am running this command from PowerShell 3.0.
$silentInstall = C:\Users\Admin\Documents\Setup-2.0.exe exe /s /v"EULAACCEPTED=\"Yes\" /l*v c:\install.log /qn"
Invoke-Expression $silentInstall
This runs the command which installs the software, but it does not wait for it to complete and goes ahead with the next lines of code. I want to have control over the installation so that I would know if it's completed or not.
How do I get an error code for the Invoke-Expression cmdlet so that I can get to know if the cmd executed successfully or not?
It depends on how the EXE file runs - sometimes it will kick off a separate process and return immediately, and in such cases this usually works -
$p = Start-Process -FilePath <path> -ArgumentList <args> -Wait -NoNewWindow -PassThru
$p.ExitCode
Otherwise this usually works -
& <path> <args>
$LASTEXITCODE
Or sometimes this -
& cmd.exe /c <path> <args>
$LASTEXITCODE
It looks like you're running an MSI installer. When running from the console, control is immediately returned while MSI forks a new process to run the installer. There is no way to change this behavior.
What you'll probably need to do is use Get-Process to find a process named msiexec, and wait for it to finish. There is always an msiexec process running, which handles starting new installers, so you'll need to find the msiexec process that started after your install began.
$msiexecd = Get-Process -Name 'msiexec'
C:\Users\Admin\Documents\Setup-2.0.exe exe `
/s `
/v"EULAACCEPTED=\"Yes\" /l*v c:\install.log /qn"
$myMsi = Get-Process -Name 'msiexec' |
Where-Object { $_.Id -ne $msiexecd.Id }
$myMsi.WaitForExit()
Write-Verbose $myMsi.ExitCode
You shouldn't need to use Invoke-Expression:
& C:\Users\Admin\Documents\Setup-2.0.exe /s /vEULAACCEPTED=Yes /l*v C:\install.log /qn