Locating and opening programs based on a word in python - windows

I have a script where a user will input a program to open, and that script will open the program. The way I've done it isn't very efficient and so I'm leading into problems.
If I input "Open chrome", the script starts a search for a file called chrome.exe on your computer and then launches it. This works for a few programs like chrome.exe, steam.exe etc, but there are programs where their exe file is named differently.
For example, "Open word". The script will search for a program named word.exe, but the Microsoft Word exe file is actually named WINWORD.EXE, so the search will fail.
So my question is how can I make this more efficient? I know I could add exceptions and find the directory of the file myself but this would be impractical to do for many programs.
with sr.Microphone() as source:
success = False
print (">")
audio = r.listen(source)
try:
print("Processing...")
t = r.recognize_google(audio)
print (": " + t)
except sr.UnknownValueError:
print("Unknown input")
continue
except sr.RequestError as e:
print("An error occured at GAPI\nA common cause is lack of internet connection")
continue
if "open" in t:
t = t.replace("open","")
t = t.replace(" ","")
z = t
speak = "Opening " + z
t = t + ".exe"
print (t)
for a,d,f in os.walk("C:\\"):
for files in f:
if files == t.lower() or files == t.capitalize() or files == t.upper():
s.Speak(speak)
pat = os.path.join(a,files)
print (pat)
sp.call([pat])
success = True
Edit:
I did some research and found out about something called filename pattern searching. I've been unable get it running, any ideas?

Related

VLC Media Player LUA Extension fails detecting whether the media file actually exists or not in Windows

As I stated in Q-title, I am trying to utilize an existing VLC extension developed in LUA programming language.
The Lua extension can be referred from here, when I correctly place this extension in %ProgramFiles%\VideoLAN\VLC\lua\extensions path and then open any video/audio file and run it and then when I select View > Remove current file from playlist and disk option, it closes the currently playing media file & throws this error: lua info: [vlc-delete] error: File does not exist.
Not sure but I suspect this is due to Windows quotes issue when FileName and/or FilePath contains spaces in them. And also from the error, it seems that io.popen("if exist " .. file .. " (echo 1)") : read "*l" == "1" isn't reliable for correctly detecting whether file actually exists or not.
I am relatively new to Lua programming, so can anyone assist about any better methods for checking whether file exists or not that works in latest VLC versions like 3.x+(cause I am using VLC 3.0.17.4 64Bit in Windows 10/11 64Bit), or just assist fix this mentioned issue ?
Note that when the script calls fileExists method, it does takes care of quotes properly: if not fileExists("\"" .. file .. "\"") then return nil, "File does not exist" end
After hours of troubleshooting, I was able to fix the issue, which was due to the way the quoted(space-containing) file path was passed to another function and the Lua library method of os.remove not working on the passed parameter.
So I just had an idea, I am mainly using Windows OS only, then why not convert the script to rely on Windows OS core(batch/cmd) functions only and do the safe checking of whether file exists and then delete with those core Windows functions too.
And so I just did that and got the plugin to actually check whether the file exists and delete the file, if it does then delete it. Here's the working code:
-- Copy this file to %ProgramFiles%\VideoLAN\VLC\lua\extensions\ and restart VLC Media player.
function descriptor()
return {
title = "VLC Delete Media File(Windows only)";
version = "1.0";
author = "Vicky Dev";
shortdesc = "&Remove current file from playlist and disk";
description = [[
<h1>VLC Delete Media File(Windows only)</h1>"
When you're playing a file, use this to easily
delete the current file from your <b>playlist</b> and <b>disk</b> with one click.<br>
Disclaimer: The author is not responsible for damage caused by this extension.
]];
}
end
function sleep(seconds)
local t0 = os.clock()
local tOriginal = t0
while os.clock() - t0 <= seconds and os.clock() >= tOriginal do end
end
function removeItem()
local id = vlc.playlist.current()
vlc.playlist.delete(id)
vlc.playlist.gotoitem(id + 1)
vlc.deactivate()
end
function activate()
local item = vlc.input.item()
local uri = item:uri()
uri = string.gsub(uri, "^file:///", "")
uri = vlc.strings.decode_uri(uri)
path = string.gsub(uri, "/", "\\")
vlc.msg.info("[VLC Delete Media File(Windows only)] removing: "..uri.." : "..path)
removeItem()
retval, err = os.execute("if exist ".."\""..path.."\"".." #(call )")
if (type(retval) == 'number' and retval == 0) then
os.execute("del /f /a /q ".."\""..path.."\"")
end
end
function click_ok()
d:delete()
vlc.deactivate()
end
function deactivate()
vlc.deactivate()
end
function close()
deactivate()
end
function meta_changed()
end
Hope this helps anyone who wants this cool feature of deleting the media files from player itself, instead of going to the location and doing it.

print an image from command line and await print job completion on Windows

I needed to write a solution to write data on and then print RFID labels en-masse, each generated as .png images from a template python script and data taken from a database or excel file.
To print the program simply calls the relative system utility (CUPS on unix systems) using subprocess.check_call(print_cmd) passing the image file (saved on a ram-mounted file system for minimal disk usage)
Now, it also needs to run on Windows systems, but there is not really a decent system utility for that, and solutions under a similar question command line tool for print picture? don't account for print-job completion or if the job results in an error, the margins are all screwed and the image is always rotated 90 degrees for some reason.
How can I sanely print an image using a command or a script in Windows and wait for it to complete successfully or return an error if the job results in an error?
Possibly with no dependencies
If you can install dependencies, there are many programs that offer a solution out-of-the-box.
The only sane way i could find to solve this issue with no dependencies is by creating a powershell script to account for this
[CmdletBinding()]
param (
[string] $file = $(throw "parameter is mandatory"),
[string] $printer = "EXACT PRINTER NAME HERE"
)
$ERR = "UserIntervention|Error|Jammed"
$status = (Get-Printer -Name $printer).PrinterStatus.ToString()
if ($status -match $ERR){ exit 1 }
# https://stackoverflow.com/a/20402656/17350905
# only sends the print job to the printer
rundll32 C:\Windows\System32\shimgvw.dll,ImageView_PrintTo $file $printer
# wait until printer is in printing status
do {
$status = (Get-Printer -Name $printer).PrinterStatus.ToString()
if ($status -match $ERR){ exit 1 }
Start-Sleep -Milliseconds 100
} until ( $status -eq "Printing" )
# wait until printing is done
do {
$status = (Get-Printer -Name $printer).PrinterStatus.ToString()
if ($status -match $ERR){ exit 1 }
Start-Sleep -Milliseconds 100
} until ( $status -eq "Normal" )
I would then need to slightly modify the print subprocess call to
powershell -File "path\to\print.ps1" "C:\absolute\path\to\file.png"
Then there are a couple of necessary setup steps:
(discaimer, I don't use windows in english so i don't know how the english thigs are supposed to be called. i will use cursive for those)
create an example image, right click and then select Print
from the print dialog that opens then set up all the default options you want, like orientation, margins, paper type, etc etc for the specific printer you're gonna use.
Go to printer settings, under tools then edit Printer Status Monitoring
edit monitoring frequency to "only during print jobs". it should be disabled by default
in the next tab, modify polling frequency to the minimum available, 100ms during print jobs (you can use a lower one for the while not printing option
Assuming the following:
only your program is running this script
theres always only 1 printing job at a time for a given printer
the printer drivers were not written by a monkey and they actually report the current, correct printer status
This little hack will allow to print an image from a command and await job completion, with error management; and uses only windows preinstalled software
Further optimization could be done by keeping powershell subprocess active and only passing it scripts in the & "path\to\print.ps1" "C:\absolute\path\to\file.png" format, waiting for standard output to report an OK or a KO; but only if mass printing is required.
Having had to work on this again, just wanted to add a simpler solution in "pure" python using the pywin32 package
import time
import subprocess
from typing import List
try:
import win32print as wprint
PRINTERS: List[str] = [p[2] for p in wprint.EnumPrinters(wprint.PRINTER_ENUM_LOCAL)]
PRINTER_DEFAULT = wprint.GetDefaultPrinter()
WIN32_SUPPORTED = True
except:
print("[!!] an error occured while retrieving printers")
# you could throw an exception or whatever
# bla bla do other stuff
if "WIN32_SUPPORTED" in globals():
__printImg_win32(file, printer_name)
def __printImg_win32(file: str, printer: str = ""):
if not printer:
printer = PRINTER_DEFAULT
# verify prerequisites here
# i still do prefer to print calling rundll32 directly,
# because of the default printer settings shenaningans
# and also because i've reliably used it to spool millions of jobs
subprocess.check_call(
[
"C:\\Windows\\System32\\rundll32",
"C:\\Windows\\System32\\shimgvw.dll,ImageView_PrintTo",
file,
printer,
]
)
__monitorJob_win32(printer)
pass
def __monitorJob_win32(printer: str, timeout=16.0):
p = wprint.OpenPrinter(printer)
# wait for job to be sheduled
t0 = time.time()
while (time.time()-t0) < timeout:
ptrr = wprint.GetPrinter(p, 2)
# unsure about those flags, but definitively not errors.
# it seems they are "moving paper forward"
if ptrr["Status"] != 0 and ptrr["Status"] not in [1024,1048576]:
raise Error("Printer is in error (status %d)!" % ptrr["Status"])
if ptrr["cJobs"] > 0:
break
time.sleep(0.1)
else:
raise Error("Printer timeout sheduling job!")
# await job completion
t0 = time.time()
while (time.time()-t0) < timeout:
ptrr = wprint.GetPrinter(p, 2)
if ptrr["Status"] != 0 and ptrr["Status"] not in [1024,1048576]:
raise Error("Printer is in error (status %d)!" % ptrr["Status"])
if ptrr["cJobs"] == 0 and ptrr["Status"] == 0:
break
time.sleep(0.1)
else:
raise Error("Printer timeout waiting for completion!")
wprint.ClosePrinter(p)
return
useful additional resources
Print image files using python
Catch events from printer in Windows
pywin32's win32print "documentation"

Python Speech Recognition Program Tends To Hang In A Certain Place

This program is not complete but is a work in progress.
import speech_recognition as sr
import subprocess as sp
import time, os
r = sr.Recognizer()
print("Voice Recognition Software\n\n******************************************************************************\n")
while True:
r.energy_threshold = 8000
t = None
with sr.Microphone() as source:
success = False
print (">")
audio = r.listen(source)
try:
print("Processing...")
t = r.recognize_google(audio)
print (": " + t)
except sr.UnknownValueError:
print("Unknown input")
continue
except sr.RequestError as e:
print("An error occured at GAPI\nA common cause is lack of internet connection")
continue
if "open" in t:
t = t.replace("open","")
t = t.replace(" ","")
t = t + ".exe"
print (t)
for a,d,f in os.walk("C:\\"):
for files in f:
if files == t.lower() or files == t.capitalize() or files == t.upper():
pat = os.path.join(a,files)
print (pat)
sp.call([pat])
success = True
if success == True:
continue
The problem I'm facing is that after > or Processing the program sometimes stops responding. No error messages or anything, in the shell it just prints > or Processing and stays there.
This happens randomly, the program can function continuously for a long time but at any given moment for whatever reason it freezes. Usually after a minute or 2 it moves onto the next part and starts responding again but that isn't always the case.
I've attempted to create a sort of fail-safe so if it takes too long to respond the program closes and opens again but I was unsuccessful with that so now I'm trying to figure out the root cause of the problem.
Can someone with experience with this sort of thing help me understand why this is happening?
Edit:
I was able to solve the problem. Turns out there is a timeout parameter here r.listen(source).
I was able to solve the problem. Turns out there is a timeout parameter here r.listen(source).

Strict searching against two different files

I have two questions regarding the following code:
import subprocess
macSource1 = (r"\\Server\path\name\here\dhcp-dump.txt")
macSource2 = (r"\\Server\path\name\here\dhcp-dump-ops.txt")
with open (r"specific-pcs.txt") as file:
line = []
for line in file:
pcName = line.strip().upper()
with open (macSource1) as source1, open (macSource2) as source2:
items = []
for items in source1:
if pcName in items:
items_split = items.rstrip("\n").split('\t')
ip = items_split[0]
mac = items_split[4]
mac2 = ':'.join(s.encode('hex') for s in mac.decode('hex')).lower() # Puts the :'s between the pairs.
print mac2
print pcName
print ip
Firstly, as you can see, the script is searching for the contents of "specific-pcs.txt" against the contents of macSource1 to get various details. How do I get it to search against BOTH macSource1 & 2 (as the details could be in either file)??
And secondly, I need to have a stricter matching process as at the moment a machine called 'itroom02' will not only find it's own details, but also provide the details for another machine called '2nd-itroom02'. How would I get that?
Many thanks for your assistance in advance!
Chris.
Perhaps you should restructure it a bit more like this:
macSources = [ r"\\Server\path\name\here\dhcp-dump.txt",
r"\\Server\path\name\here\dhcp-dump-ops.txt" ]
with open (r"specific-pcs.txt") as file:
for line in file:
# ....
for target in macSources:
with open (target) as source:
for items in source:
# ....
There's no need to do e.g. line = [] immediately before you do for line in ...:.
As far as the "stricter matching" goes, since you don't give examples of the format of your files, I can only guess - but you might want to try something like if items_split[1] == pcName: after you've done the split, instead of the if pcName in items: before you split (assuming the name is in the second column - adjust accordingly if not).

Saving Tab names and ConqueShells along with Vim sessions

Is there any way to get vim to save the tab names (assigned via the Tab Name script) and/or a terminal emulator (set up via the Conque Shell script) upon issuing the :mksession [fileName] command?
Observe below (zoom in), I have a working session on the left, and the same session loaded via the vim -S fileName command, on the right. The assigned tab labels revert to absolute paths, ConqueShell terminal is interpreted as a file.
After learning some basic VimScript I just gave up and used Python instead (to cite one example, you can't save global information to a session if it is a list). Here is a solution I found for saving tab names (will post a solution for ConqueShell if I find one)
Put the following in your .vimrc file and use whatever mapping you want to quickly save and load your sessions
"Tokenize it so it has the following form (without spaces)
"Label1 JJ Label2 JJ Label3 JJ Label4
"Or if you prefer use something other than 'JJ' but DO NOT
"use symbols as they could interfere with the shell command
"line
function RecordTabNames()
"Start at the first tab with no tab names assigned
let g:TabNames = ''
tabfirst
"Iterate over all the tabs and determine whether g:TabNames
"needs to be updated
for i in range(1, tabpagenr('$'))
"If tabnames.vim created the variable 't:tab_name', append it
"to g:TabNames, otherwise, append nothing, but the delimiter
if exists('t:tab_name')
let g:TabNames = g:TabNames . t:tab_name . 'JJ'
else
let g:TabNames = g:TabNames . 'JJ'
endif
"iterate to next tab
tabnext
endfor
endfunction
func! MakeFullSession()
call RecordTabNames()
mksession! ~/.vim/sessions/Session.vim
"Call the Pythin script, passing to it as an argument, all the
"tab names. Make sure to put g:TabNames in double quotes, o.w.
"a tab label with spaces will be passed as two separate arguments
execute "!mksession.py '" . g:TabNames . "'"
endfunc
func! LoadFullSession()
source ~/.vim/sessions/Session.vim
endfunc
nnoremap <leader>mks :call MakeFullSession()<CR>
nnoremap <leader>lks :call LoadFullSession()<CR>
Now create the following text file and put it somewhere in your PATH variable (echo $PATH to get it, mine is at /home/user/bin/mksession.py) and make sure to make it executable (chmod 0700 /home/user/bin/mksession.py)
#!/usr/bin/env python
"""This script attempts to fix the Session.vim file by saving the
tab names. The tab names must be passed at the command line,
delimitted by a unique string (in this case 'JJ'). Also, although
spaces are handled, symbols such as '!' can lead to problems.
Steer clear of symbols and file names with 'JJ' in them (Sorry JJ
Abrams, that's what you get for making the worst TV show in history,
you jerk)
"""
import sys
import copy
if __name__ == "__main__":
labels = sys.argv[1].split('JJ')
labels = labels[:len(labels)-1]
"""read the session file to add commands after tabedit
" "(replace 'USER' with your username)
"
f = open('/home/USER/.vim/sessions/Session.vim', 'r')
text = f.read()
f.close()
"""If the text file does not contain the word "tabedit" that means there
" "are no tabs. Therefore, do not continue
"""
if text.find('tabedit') >=0:
text = text.split('\n')
"""Must start at index 1 as the first "tab" is technically not a tab
" "until the second tab is added
"""
labelIndex = 1
newText = ''
for i, line in enumerate(text):
newText +=line + '\n'
"""Remember that vim is not very smart with tabs. It does not understand
" "the concept of a single tab. Therefore, the first "tab" is opened
" "as a buffer. In other words, first look for the keyword 'edit', then
" "subsequently look for 'tabedit'. However, when being sourced, the
" "first tab opened is still a buffer, therefore, at the end we will
" "have to return and take care of the first "tab"
"""
if line.startswith('tabedit'):
"""If the labelIndex is empty that means it was never set,
" "therefore, do nothing
"""
if labels[labelIndex] != '':
newText += 'TName "%s"\n'%(labels[labelIndex])
labelIndex += 1
"""Now that the tabbed windowing environment has been established,
" "we can return to the first "tab" and set its name. This serves
" "the double purpose of selecting the first tab (if it has not
" "already been selected)
"""
newText += "tabfirst\n"
newText += 'TName "%s"\n'%(labels[0])
#(replace 'USER' with your username)
f = open('/home/USER/.vim/sessions/Session.vim', 'w')
f.write(newText)
f.close()

Resources