PowerShell Script to play video with Windows Media Player - powershell

I have a requirement to run a video via windows Media Player. And also track the duration it play.
Suppose I close the video in 5 Sec it should give the duration 5. The below is the script I wrote. But there is problem with this. As the video do not launch nor I am able to the application getting launched . I am only able to here the audio.
Add-Type -AssemblyName presentationCore
$filepath = [uri] "C:\Temp\test\Wildlife.wmv"
$wmplayer = New-Object System.Windows.Media.MediaPlayer
$wmplayer.Open($filepath)
Start-Sleep 2 # This allows the $wmplayer time to load the audio file
$duration = $wmplayer.NaturalDuration.TimeSpan.Seconds
$wmplayer.Play()
Start-Sleep $duration
$wmplayer.Stop()
$wmplayer.Close()
Write-Host $duration
Please help...
Regards,
Suman Rout

You need to be creating a form that shows up, then creating a VideoDrawing, then a DrawingBrush, and then applying it as the background of some portion of the form. From my understanding, MediaElement is easier to use - but regardless you're not starting media player here, you're using Windows Media objects without creating a form to display them on.
If you merely mean to open the video and close it, try launching the Windows Media Player application instead. I used your code and did something like maybe you're intending:
Add-Type -AssemblyName presentationCore
$filepath = "C:\Temp\test\Wildlife.wmv"
#Here we use your code to get the duration of the video
$wmplayer = New-Object System.Windows.Media.MediaPlayer
$wmplayer.Open($filepath)
Start-Sleep 2
$duration = $wmplayer.NaturalDuration.TimeSpan.Seconds
$wmplayer.Close()
#Here we just open media player and play the file, with an extra second for it to start playing
$proc = Start-process -FilePath wmplayer.exe -ArgumentList $filepath -PassThru
Start-Sleep ($duration + 1)
#Here we kill the media player
Stop-Process $proc.Id -force
Write-Host $duration

Related

How to send keyboard input only to a specific application

I'm very new to Powershell. I wrote a simple script basically to automate grinding in a video game when I'm away from my computer. I wanted to know if there's a way instead to 'target' the button presses to a particular window/application/etc. while still working on the same machine in other windows. As it stands, I have to have the game window focused for the script to work so it's only really useful if I'm AFK. But if I could have it running in the background while working on other things that would be useful.
$WShell = New-Object -Com Wscript.Shell
while (1) {sleep 1; [System.Windows.Forms.SendKeys]::SendWait("{LEFT}"*80);
[System.Windows.Forms.SendKeys]::SendWait("{RIGHT}"*80);sleep 1;
[System.Windows.Forms.SendKeys]::SendWait("{C}"*20)}
Since I'm new to Powershell I'm not sure if this is doable or not. If not, it's no problem, this is a pretty frivolous use case, I was just curious.
Think about what you're currently doing. . .it's almost the same as tying the shoe laces on a pair of shoes, just to put on different ones;) You're not using the $wShell anywhere in your script.
. . .but, you're almost there already. We can start by loading the required assemblies, and then have it point to the application which you want to interact with:
Add-Type -AssemblyName Microsoft.VisualBasic
Add-Type -AssemblyName System.Windows.Forms
[Microsoft.VisualBasic.Interaction]::AppActivate('Notepad')
Start-Sleep -Milliseconds 1000
[System.Windows.Forms.SendKeys]::SendWait("H")
Start-Sleep -Milliseconds 100
[System.Windows.Forms.SendKeys]::SendWait("E")
Start-Sleep -Milliseconds 100
[System.Windows.Forms.SendKeys]::SendWait("L")
Start-Sleep -Milliseconds 100
[System.Windows.Forms.SendKeys]::SendWait("L")
Start-Sleep -Milliseconds 100
[System.Windows.Forms.SendKeys]::SendWait("O")
Take note of notepad in [Microsoft.VisualBasic.Interaction]::AppActivate('Notepad'), as it will be what ever program you're trying to interact with. In this case, you're just sending "HELLO" to the notepad that's already on started.

Referencing 5 random URL`s from a file of 50 URL`s and automatically opening all 5 in a browser. Repeated every 5 mins

Overview:
Have around 50 websites in work, all URL`s have been added to a CSV file. We want a selection of 5 random sites to pop up in a web browser every 5 minutes and using a browser tab rotator to rotate through all 5 web pages. Browser closes, then another random 5 web sites from the CSV open etc.
Problem:
Apologies for the noob question, I am extremely new to programming and Powershell, I cannot find a way to reference $URL1 or $URL2 etc at the end of the -FilePath Firefox -ArgumentList statement.
Code:
$importPath = "C:\URLlist.csv"
$list = Import-Csv -Path $importPath
$URL1 = Get-Random -InputObject $list
$URL2 = Get-Random -InputObject $list ...
$URL5 = Get-Random -InputObject $list
Start-Process -FilePath Firefox -ArgumentList ????
Assuming you geniuses will know of a more efficient way, so any advice or direction greatly appreciated.
Many thanks
Charlie

Race condition in PowerShell

I need to play all videos in a playlist so I came up with this code.
Foreach ($line in get-content playlist)
{ $line | invoke-item }
Which should go through the file and play each line using the default player.
The problem that it creates a race condition, the processes will start and end so fast that one can only see the last file.
How to overcome this, I tried /path/to/player $line | out-null but the player will stop and needs user intervention in order to proceed.
I would not call this a race condition but the problem that Invoke-Item does not wait for the process to finish. Try to use Start-Process -wait instead.
Update: since it is hard to make Windows Media Player exit after the movie finishes, you could try to invoke vlc instead:
Foreach ($line in get-content pl.txt)
{ Start-Process -wait "C:\...\VideoLAN\VLC\vlc.exe" -ArgumentList "$line vlc://quit" }
Maybe you should approach the problem differently and use the parameters for Media player classic. I don't have it installed here, but this code should give you the general idea:
Make sure all your files are in the same folder
This will play all the files in that folder mpc-hc64.exe "c:\mpcfiles" /play
More information here.

How to play mp3 with powershell (simple)?

How do I play mp3 with Powershell?
What I tried:
powershell -c (New-Object Media.SoundPlayer "Track.mp3").Play();
You can play an mp3 from powershell, you just need to use
system.windows.media.mediaplayer
instead of
System.Media.SoundPlayer
It works in Windows 10
I followed a snipped from http://eddiejackson.net/wp/?p=9268
# Play a single file
Add-Type -AssemblyName presentationCore
$mediaPlayer = New-Object system.windows.media.mediaplayer
$mediaPlayer.open('C:\sounds\bike.mp3')
$mediaPlayer.Play()
This is an old question but I just went through this so if anyone is interested in learning or knowing how to do this in a more simple manner use the following answer.
As long as you have a media player that has good command line switches such as VLC and other similar types of versatile players (perhaps media player classic) you CAN make a one line command to run a MP3 file. Here is my example, enjoy! :)
& 'C:\Program Files\VideoLAN\VLC\vlc.exe' --qt-start-minimized --play-and-exit --qt-notification=0 "D:\SystemSettings\51Hz.mp3"
This would run 51Hz.mp3 file with neither notifications to take place nor any other user interaction.
This works only for wav files:
$Song = New-Object System.Media.SoundPlayer
$Song.SoundLocation = "path\to\track.wav"
$Song.Play()
Simplest way is to just use the Invoke-Item cmdlet, it will open whatever Windows has set as the default handler for the file type. When I used it on an mp3 file it opened Groove Music. I'm sure if I installed winamp or mpc or whatever and set the default to that it would open in there instead.
From URL
$MediaPlayer = [Windows.Media.Playback.MediaPlayer, Windows.Media, ContentType = WindowsRuntime]::New()
$MediaPlayer.Source = [Windows.Media.Core.MediaSource]::CreateFromUri('https://nyanpass.com/nyanpass.mp3')
$MediaPlayer.Play()
From File
$MediaPlayer = [Windows.Media.Playback.MediaPlayer, Windows.Media, ContentType = WindowsRuntime]::New()
$MediaPlayer.Source = [Windows.Media.Core.MediaSource]::CreateFromUri('C:\Users\Admin\Downloads\nyanpass.mp3')
$MediaPlayer.Play()
SoundPlayer can only play *.wav files. There is no easy 1 line way of playing mp3 files. However this can be done by writing a script using the MediaPlayer class.
This worked for me
$Song = New-Object System.Media.SoundPlayer
$Song.SoundLocation = "path\to\track.mp3"
$Song.Play()
I guess you cannot pass the file location through new-object
I can confirm this works:
$player = New-Object System.Media.SoundPlayer "$env:windir\Media\notify.wav"
$player.Play()
Source: http://community.idera.com/powershell/powertips/b/tips/posts/playing-wav-files

How to perform keystroke inside powershell?

I have ps1 script to grab some information from the vmware cluster environment.
In some place of ps1 script requires the ENTER button keystroke.
So, How to do that ?
-Thanks
If I understand correctly, you want PowerShell to send the ENTER keystroke to some interactive application?
$wshell = New-Object -ComObject wscript.shell;
$wshell.AppActivate('title of the application window')
Sleep 1
$wshell.SendKeys('~')
If that interactive application is a PowerShell script, just use whatever is in the title bar of the PowerShell window as the argument to AppActivate (by default, the path to powershell.exe). To avoid ambiguity, you can have your script retitle its own window by using the title 'new window title' command.
A few notes:
The tilde (~) represents the ENTER keystroke. You can also use {ENTER}, though they're not identical - that's the keypad's ENTER key. A complete list is available here: http://msdn.microsoft.com/en-us/library/office/aa202943%28v=office.10%29.aspx.
The reason for the Sleep 1 statement is to wait 1 second because it takes a moment for the window to activate, and if you invoke SendKeys immediately, it'll send the keys to the PowerShell window, or to nowhere.
Be aware that this can be tripped up, if you type anything or click the mouse during the second that it's waiting, preventing to window you activate with AppActivate from being active. You can experiment with reducing the amount of time to find the minimum that's reliably sufficient on your system (Sleep accepts decimals, so you could try .5 for half a second). I find that on my 2.6 GHz Core i7 Win7 laptop, anything less than .8 seconds has a significant failure rate. I use 1 second to be safe.
IMPORTANT WARNING: Be extra careful if you're using this method to send a password, because activating a different window between invoking AppActivate and invoking SendKeys will cause the password to be sent to that different window in plain text!
Sometimes wscript.shell's SendKeys method can be a little quirky, so if you run into problems, replace the fourth line above with this:
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.SendKeys]::SendWait('~');
function Do-SendKeys {
param (
$SENDKEYS,
$WINDOWTITLE
)
$wshell = New-Object -ComObject wscript.shell;
IF ($WINDOWTITLE) {$wshell.AppActivate($WINDOWTITLE)}
Sleep 1
IF ($SENDKEYS) {$wshell.SendKeys($SENDKEYS)}
}
Do-SendKeys -WINDOWTITLE Print -SENDKEYS '{TAB}{TAB}'
Do-SendKeys -WINDOWTITLE Print
Do-SendKeys -SENDKEYS '%{f4}'
Send "Enter" key to an App, for example for pressing "OK". Works great:
Add-Type -AssemblyName microsoft.VisualBasic
Add-Type -AssemblyName System.Windows.Forms
# Get the desired process:
$ProcessName = Get-Process -Name Calculator
Start-Sleep -Seconds 1
# If the process is actually running, bring it to front:
If ($ProcessName)
{
(New-Object -ComObject.Wscript.Shell).AppActivate((Get-Process $ProcessName -ErrorAction SilentlyContinue).MainWindowTitle)
}
# Send "Enter" key to the app:
[Microsoft.VisualBasic.Interaction]::AppActivate($ProcessName.ProcessName)
[System.Windows.Forms.SendKeys]::SendWait({'~'})
Also the $wshell = New-Object -ComObject wscript.shell; helped a script that was running in the background, it worked fine with just but adding $wshell. fixed it from running as background! [Microsoft.VisualBasic.Interaction]::AppActivate("App Name")