Closing a file powershell - powershell

I am trying to write a script that opens all pdf files in a folder, prints them, and then closes the files. I have the first 2 parts working, however I can not find a way to close the files after. I've done some google searching but found nothing. I'm new to powershell so if there is a better way to doing this please let me know:
Get-ChildItem -Filter *.pdf |
Foreach-Object {
# File item variable is $_
Write-Host "Printing: $($_.Name)"
#Open the file with a print command.
Start-Process -FilePath $_.FullName -Verb Print
}
Any tips would be appreciated!

I don't have experience with this but was curious about the Start-Process cmdlet with print verb. I Googled that and came up with this that looks to be a good solution to your problem:
Start-Process -FilePath $.FullName -Verb Print -PassThru | %{sleep 10;$_} | kill
Source: http://gregcaporale.wordpress.com/2012/01/18/powershell-to-print-files-automatically/

Related

Is it possible to "-passthru" to Log file only and not the console when using "Start-Transcript -Path "$LogOutput"

I have a Powershell script where I want the console to output my custom messages only, but I would like to capture what the command is doing in a log only. Is this possible?
Just to make it clearer with an example below. I want to copy all the Sub Directories and Files as they are in their own directory to a new location:
Start-Transcript -Path "$LogOutput" -IncludeInvocationHeader -Append
Get-ChildItem -Path "$Source" | Copy-Item -Destination "$Destination" -Exclude "File*.xml" -Force -Recurse -PassThru
Stop-Transcript
I then use $? to get the success of the result on the console for my custom messages.
The above shows details I find helpful but it outputs the -PassThru on the console which I do not want to display there. If I don't specify it, it outputs nothing in the Transcript log either.
If I try appending to the copy command ...-PassThru | Out-File -FilePath "$LogOutput" -Append (The same Log used for Transcript) it fails as the log file is locked by the Transcript. Is there a way to make this possible, or will I have to append ...-PassThru | Out-File -FilePath "$LogOutput" -Append to all my commands individually?
Many thanks in advance.

Run all .exe in a folder

I'm playing with malware in a VM and every script I try gets stuck. Basically I need to run every .exe in a folder. Tried batch files using start, powershell, etc. The issue happens when AV moves some file to quarentine, or some process keep running then the script doesn't jump to the next one.
CMD start works but shows popups when doesn't find some file, then you have to keep clicking to jump to the next file.
These works but get stuck after a while:
Get-ChildItem 'C:\Users\LAB\Desktop\test' | ForEach-Object {
>> & $_.FullName
>> }
Same here:
for %%v in ("C:\Users\LAB\Desktop\test\*.exe") do start "" "%%~v"
and here:
for %%i in (C:\Users\LAB\Desktop\test\*.exe) do %%i
You need to provide some form of code to allow us to help you troubleshoot it; this is not a request a script page.
Anyways, you would be looking at something like this:
#Assuming the .exe's are located in C Root.
Get-ChildItem -Path C:\ | Where-Object {$_.Extension -like ".exe"}| Foreach {Start-Process $_.FullName}
#In Ps, we like to filter as far left as possible for faster results.
Get-ChildItem -Path C:\ -File "*.exe" | Foreach {Start-Process $_.FullName}
#Running the commands as jobs so it doesnt wait on any to finish before running the next.
Start-Job { Get-ChildItem -Path C:\ -File "*.exe" | Foreach {Start-Process $_.FullName} }
Start-Sleep 2
Get-Job | Remove-Job
Please refer to the following link: How to ask a question

Wait for file to finish writing before performing next script [duplicate]

I have a PowerShell 1.0 script to just open a bunch of applications. The first is a virtual machine and the others are development applications. I want the virtual machine to finish booting before the rest of the applications are opened.
In bash I could just say "cmd1 && cmd2"
This is what I've got...
C:\Applications\VirtualBox\vboxmanage startvm superdooper
&"C:\Applications\NetBeans 6.5\bin\netbeans.exe"
Normally, for internal commands PowerShell does wait before starting the next command. One exception to this rule is external Windows subsystem based EXE. The first trick is to pipeline to Out-Null like so:
Notepad.exe | Out-Null
PowerShell will wait until the Notepad.exe process has been exited before continuing. That is nifty but kind of subtle to pick up from reading the code. You can also use Start-Process with the -Wait parameter:
Start-Process <path to exe> -NoNewWindow -Wait
If you are using the PowerShell Community Extensions version it is:
$proc = Start-Process <path to exe> -NoNewWindow -PassThru
$proc.WaitForExit()
Another option in PowerShell 2.0 is to use a background job:
$job = Start-Job { invoke command here }
Wait-Job $job
Receive-Job $job
Besides using Start-Process -Wait, piping the output of an executable will make Powershell wait. Depending on the need, I will typically pipe to Out-Null, Out-Default, Out-String or Out-String -Stream. Here is a long list of some other output options.
# Saving output as a string to a variable.
$output = ping.exe example.com | Out-String
# Filtering the output.
ping stackoverflow.com | where { $_ -match '^reply' }
# Using Start-Process affords the most control.
Start-Process -Wait SomeExecutable.com
I do miss the CMD/Bash style operators that you referenced (&, &&, ||). It
seems we have to be more verbose with Powershell.
Just use "Wait-process" :
"notepad","calc","wmplayer" | ForEach-Object {Start-Process $_} | Wait-Process ;dir
job is done
If you use Start-Process <path to exe> -NoNewWindow -Wait
You can also use the -PassThru option to echo output.
Some programs can't process output stream very well, using pipe to Out-Null may not block it.
And Start-Process needs the -ArgumentList switch to pass arguments, not so convenient.
There is also another approach.
$exitCode = [Diagnostics.Process]::Start(<process>,<arguments>).WaitForExit(<timeout>)
Including the option -NoNewWindow gives me an error: Start-Process : This command cannot be executed due to the error: Access is denied.
The only way I could get it to work was to call:
Start-Process <path to exe> -Wait
The question was asked long ago, but since answers here are kind of references, I may mention an up to date usage. With the current implementation of PowerShell (it's 7.2 LTS as of writing) you can use && as you would do in Bash.
Conditionally execute the right-hand side pipeline based on the success of the left-hand side pipeline.
# If Get-Process successfully finds a process called notepad,
# Stop-Process -Name notepad is called
Get-Process notepad && Stop-Process -Name notepad
Further info on documentation
Taking it further you could even parse on the fly
e.g.
& "my.exe" | %{
if ($_ -match 'OK')
{ Write-Host $_ -f Green }
else if ($_ -match 'FAIL|ERROR')
{ Write-Host $_ -f Red }
else
{ Write-Host $_ }
}
Building upon #Justin & #Nathan Hartley 's answers:
& "my.exe" | Out-Null #go nowhere
& "my.exe" | Out-Default # go to default destination (e.g. console)
& "my.exe" | Out-String # return a string
the piping will return it in real-time
& "my.exe" | %{
if ($_ -match 'OK')
{ Write-Host $_ -f Green }
else if ($_ -match 'FAIL|ERROR')
{ Write-Host $_ -f Red }
else
{ Write-Host $_ }
}
Note: If the executed program returns anything other than a 0 exitcode, the piping will not work. You can force it to pipe with redirection operators such as 2>&1
& "my.exe" 2>&1 | Out-String
sources:
https://stackoverflow.com/a/7272390/254276
https://social.technet.microsoft.com/forums/windowsserver/en-US/b6691fba-0e92-4e9d-aec2-47f3d5a17419/start-process-and-redirect-output-to-powershell-window
There's always cmd.
cmd /c start /wait notepad
Or
notepad | out-host

Print PDFs to specific printers based on filename

I would just like to preface this by saying I am brand new to Powershell and have been trying to learn by picking things up here and there. I'm currently trying to automate a process within my company using strictly powershell and Adobe reader.
Our company currently is manually printing individual sets of records and a separate cover page, binding them, and sending them off. An idea to automate this process was to fill a folder with a zipped set of .pdfs for the day. This zip file would then be extracted and it's contents moved to another folder. PDFs with the normal set of records listed as "WO-xxxxxx Set" and the cover page as "WO-xxxxxx Cover". All I would need to do is create a simple script that prints these out in order, so that "WO-000001 Cover" is on top of "WO-000001 Set" and then print the next set in the order.
The complication I've run into is that Start-Process -FilePath $File.Fullname -Verb Print only allows me to target a default printer. Our Covers will need to be printed on thicker paper, and as such I thought the best course of action would be to create two printers on the network with the required printer settings. If I could have the script swap between the two printers based on file name then it would solve my issue.
This script is sending the documents to the printer in order but not actually swapping the default printer. I'm sure this is something I've done wrong in my IfElse cmdlet and would appreciate an experts eye in this.
Function UnZipEverything($src, $dest)
{
[System.Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem") | Out-Null
$zps = Get-ChildItem $src -Filter *.zip
foreach ($zp IN $zps)
{
$all = $src + $zp
[System.IO.Compression.ZipFile]::ExtractToDirectory($all, $dest)
}
}
UnZipEverything -src "C:\Users\admin\Desktop\Zip Test\" -dest'C:\Users\admin\Desktop\UnZip Test\'
Remove-Item "C:\Users\admin\Desktop\Zip Test\*.zip"
$files = Get-ChildItem “C:\Users\admin\Desktop\UnZip Test\*.*” -Recurse
ForEach ($file in $files){
If ($files -eq '*Cover*') {
(New-Object -ComObject WScript.Network).SetDefaultPrinter('Test')
Start-Process -FilePath $File.FullName -Verb Print -PassThru | %{ sleep 10;$_ } | kill
(New-Object -ComObject WScript.Network).SetDefaultPrinter('\\RFC-Print01\Collections Tray 6')
}
Else {Start-Process -FilePath $File.FullName -Verb Print -PassThru | %{ sleep 10;$_ } | kill
}
}
Any help would be greatly appreciated.
If you use the verb PrintTo instead of Print, you can specify the printer:
Start-Process -FilePath $File.FullName -Verb PrintTo '\\RFC-Print01\Collections Tray 6' -PassThru
This would allow you to remove the SetDefaultPrinter calls from the script.

Printing with Powershell and files in folders

I have a script which does some onsite printing. It doesnt work too well at the moment as the below runs for various file types which are sent to a folder to print, but the problem is it will only print 1 document at a time.
Start-Process –FilePath “c:\tests\*.docx” –Verb Print
I had the idea of doing this to get around it:
get-ChildItem "C:\Tests\*.docx" | `
foreach-object {
start-process -verb Print
}
This doesnt seem to work though. So then i tried this:
get-childitem "C:\Tests\*.xlsx" | `
foreach-object {
Start-Process -Filepath "C:\Program Files\Microsoft Office\Office14\EXCEL.exe" –Verb Print }
Also no luck,
Returns this error:
Start-Process : This command cannot be run due to the error: No application is associated with the specified file for this operation.
I think i am maybe not visualing the process here. Any ideas at all anyone on how to achieve printing of every file in a folder via powershell?
Windows 7 64 bit and $PSVersion = 5.0
Thanks in advance
You are very close, start-process needs the full path and name of the file:
Get-ChildItem "c:\tests\*.docx" | ForEach-Object {start-process $_.FullName –Verb Print}
Using a foreach loop should help you too:
$files = Get-ChildItem "c:\tests\*.docx"
foreach ($file in $files){
start-process -FilePath $file.fullName -Verb Print
}