How can I programmatically uninstall my MSIX python app? - python

I've just written my first MSIX app in python 3. I use pyinstaller to generate an EXE. Then I use WiX Toolset to generate an MSI. I then use MSIX Packaging Tool to create the MSIX. There's probably an easier way to go from code to MSIX, but that's what I've gotten to work so far.
Ideally, I'd like to capture an onuninstall event and throw a GUI prompt asking the user why they are uninstalling. I can do this in the MSI. However, my understanding is that MSIX offers no onuninstall event. Please let me know if you know differently!
Since I apparently can't catch the MSIX uninstall event, my next preference is to offer the user a way to uninstall the app from the tray icon. The user selects an uninstall tray menu button from my app's icon, which pops up a window where the app then asks them why they are uninstalling. They type in an answer, and then click the submit button. Then, the app should completely uninstall itself. This also works well in the MSI. However, I can't get it to work in the MSIX.
Here's what works in python with the MSI installed:
subprocess.call('msiexec.exe /x {' + myguid + '}', shell=True)
However, the MSIX, which is built from the MSI, throws this popup error message when that line runs, and never actually uninstalls the app:
This action is only valid for products that are currently installed.
I've tried using the GUID from my WXS file's <Product> entry, hard-coded, just to see if it would work. That one worked for uninstalling the MSI, but not the MSIX. I also tried getting the GUID dynamically, but that didn't work for either MSI or MSIX, both producing the same error as above. Here is how I got the GUID dynamically:
from System.Runtime.InteropServices import Marshal
from System import Reflection
myguid = str(Marshal.GetTypeLibGuidForAssembly(
Reflection.Assembly.GetExecutingAssembly()
)).upper()
While running the MSI (where I have far better logging than in the MSIX), it appears as though GetExecutingAssembly() gets an assembly with a FullName of Python.Runtime, which is certainly something I don't want to uninstall. GetCallingAssembly() produces the same result. GetEntryAssembly() produces a null value.
I looped through AppDomain.CurrentDomain.GetAssemblies() to see what was listed and my app was not listed, though I saw many libraries that it uses.
So, any thoughts on how I can get the app to programmatically uninstall? Maybe a suggestion on how I can get the correct GUID for the MSIX app, if that's the problem? DotNet code should be fine. I can probably figure out how to translate it to python.
Or better yet, any idea how I can catch the MSIX uninstall event and run some custom code?
Thanks in advance!

From what I know at this moment catching the uninstall event is not possible. I don't recommend implementing the approach you suggested (the tray icon) but to ask your question, you can use the MSIX PowerShell commandlets to install and uninstall MSIX packages programmatically.
Also, I noticed you are really torturing yourself to create the MSIX package.
The MSIX Packaging Tool was created by Microsoft for IT professionals that don't have access to the source code. Developers can either use the Windows Application Packaging Project project template (if they use Visual Studio) or other third-party tools, like Advanced Installer or Wix (from what I know there was a Wix extension that can be used to build MSIX packages).
Here is a quick tutorial on how to create an MSIX from scratch, easier with Advanced Installer:
https://www.advancedinstaller.com/create-msi-python-executable.html
Disclaimer: I work on the team building Advanced Installer.

I used Bogdan's Powershell suggestion and came up with the following code, which seems to work well:
import subprocess
powershellLocation = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
try:
# Use the name of the app (which I found manually using Get-AppPackage)
# to get the full name of the app, which seems to have some random numbers
# on the end of it.
powershell_tuple = subprocess.Popen([
powershellLocation,
"Get-AppPackage",
"-name",
'"' + myAppPackageName + '"'
],shell=True,stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE).communicate()
appStrings = powershell_tuple[0].decode('utf-8').strip()
except Exception as e:
pass
for appStr in appStrings.splitlines():
# Find the full name of the app
if appStr.startswith('PackageFullName'):
colonIndex = appStr.index(':') + 1
fullName = appStr[colonIndex:].strip()
if fullName:
# The MSIX package was found, and I now have its full name
subprocess.call(powershellLocation + ' Remove-AppPackage -Package "' + fullName + '"', shell=True)

Related

vscode "no refactorings available" for python

Ctrl + alt + R for extension python.python 2020.1.58038 always gives me a "No refactorings available" message.
Probably a configuration issue but I've tried several times to uninstall/reinstall and restart vs code to no avail.
Thought maybe I was missing python-rope but python -m pip install --upgrade rope
Requirement already up-to-date: rope in c:\users\cdoyle\appdata\roaming\python\python37\site-packages (0.16.0)
VS Code Version info :
Version: 1.42.0 (user setup)
Commit: ae08d5460b5a45169385ff3fd44208f431992451
Date: 2020-02-06T10:51:34.058Z
Electron: 6.1.6
Chrome: 76.0.3809.146
Node.js: 12.4.0
V8: 7.6.303.31-electron.0
OS: Windows_NT x64 10.0.18362
Also I don't see any open issues
https://github.com/Microsoft/vscode-python/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+refactoring
Not sure what to try next.
Thanks
I'm new to programming Python in VS Code and ran into the same problem. I successfully used the "Rename Symbol" command to rename a function and update all its references. More detail at https://code.visualstudio.com/docs/editor/refactoring . Hope this helps!
I would like to add further:
If you want to change a variable name / function name at one go, you can use "Rename Symbol" in VS Code editor by right clicking that particular name.
If your code has something related to both variable name and function name and you want to apply the change at both places, then you can use "Change all Occurrences".
Example of above-
test = "Hello"
def test_func():
print("World")
print(test)
test_func()
If i want to change variable "test" to "new" and function "test_func" to "new_func", i can use "Change all Occurrences".
But if i want to change only say variable name, then i have too use "Rename symbol".
Visual Studio Code and its Python extension is (at the time of writing this) very limited when it comes to refactoring. Out of the box it provides two refactoring actions: Extract Method and Extract Variable. The reason you're seeing "No refactorings available" is because the currently selected text doesn't match any of these actions. Try selecting a line of text and then press [Ctrl][Shift][R].
Rope support was removed in VSCode in favour of Language Server Protocol integration which is used by their Pylance language server extension. Pylance is now installed automatically with vscode-python extension, and it's actively developed - maybe they will implement more refactorings in the future. If you're looking for more robust refactoring, check out PyCharm refactoring, it is currently much more sophisticated.
For Python 3.10.2 use right-click, Change All Occurrences (CTRL-F2) on VSCode version 1.65.2
I think #Wayne Barrrass-Brown's answer is the best answer available, but just wanted to add something I've found helpful in similar situations.
Double click the variable you want to change, then CTRL+D (which will select the next occurrence of that text) until you've selected all the occurrences you want to change, then type in the new text you want for the selected variable/text.

Windows 10 notifications in python

I've tried a lot of methods found online to create notification bubbles through python, but none of them work. I suspect this has something to do with windows just not allowing them for the script, but how can I solve this?
For example, using the balloontip snippet, and in my own script:
import balloontip
Following with either of these just doesn't show any toast.
w=balloontip.WindowsBalloonTip('asdf', 'qwerty')
balloontip.balloon_tip('asdf', 'qwerty')
I've also tried using the win10toast package but still no such luck.
What's even weirder is that solutions entirely unrelated to python also don't work. For example this powershell script creates an icon in my tray but the message won't show.
Try to import all the modules used in the snippet, and include the snippet in your script. You might need to install win32api using pip install pypiwin32
This might help you identify the problem/check if it is indeed a problem with Windows notifications in general.
I was able to create a notification by adding the following code to the end:
balloon_tip("test title", "test message")
Check if you have blocked windows notifications:
http://www.howto-connect.com/disable-enable-app-notifications-on-windows-10/

add context menu to file manager (nautilus) with python

I'm trying to add a menu entry to file manager(nautilus) that call my own python/Qt program that do some work on the selected file/folder
i found
import nautilus
class ExampleMenuProvider(nautilus.MenuProvider):
def __init__(self):
pass
def get_file_items(self, window, files):
submenu = nautilus.Menu()
item = nautilus.MenuItem('Nautilus::sbi','Nau-T','image')
item.set_submenu(submenu)
item_two = nautilus.MenuItem('Nautilus::s','www','image')
submenu.append_item(item_two)
return item,
But i couldn't find the nautilus module anywhere to install
and i read somewhere that i should create a nautilus extension but installing nautilus-extension but if i install this package on my dev machine how can i garanty that in will be installed on the client machine
and thank you for your help
but if i install this package on my dev machine how can i garanty that in will be installed on the client machine
There are at least two options:
Document in your README how to get the dependencies installed.
Ship that module alongside your application.
I would personally prefer the former because that would allow users to benefit from the system-wide installation on their Linux machine.
For instance, if a bug is fixed in that module, they could update it on your system without you shipping a new version, or messing themselves with the installation directory.
It ain't that bad in my opinion, and after all, you have the same situation with the Python dependency and the Qt library. Presumably, you also let your users know where they can obtain them if they have difficulties.

WxPython GUI library installation error

After much search i choose WxPython as GUI library. I download it from here.
When i tried to install it, it showed
You would note in the Folder, it has set value , which is not just one location but many locations.
On clicking next it gives error that folder path can not have ; special characters.
When i gave it a path, it proceeds but again, it gives me an error :
And then i have to abort it.
I tried it with unicode wxpython only but with both release and development versions. Both failed at the same problem.
What should i do ?
I have never seen that before. I would try downloading wxPython 2.9 instead. Or reinstall Python itself and then try wxPython 2.8 again. If you continue to have issues, you should ask for additional help on the wxPython users list.

How to silently uninstall Python 2.7 on Windows?

Does anyone know how to silently uninstall Python 2.7 - i.e. uninstall it unattended, with no need for user interaction? I need to do it as part of an uninstallation script that installs a bunch of software silently.
I've tried running msiexec with the /x and /qn flags on the msi file that was originally installed, but it fails - it just throws up the general help message, implying that I'm using invalid options.
I've done a Google search, and can find help for earlier versions - they can be uninstalled silently by running the unwise.exe that's installed with them, with the right options. But 2.7 doesn't seem to include an unwise.exe, so I can't do that.
Does anyone know how to do this?
Edit: The answer turned out to be embarrassingly simple. Those were the correct command-line options all along - it's just that the order matters. The correct command was:
msiexec /x python-2.7.3.amd64.msi /qn
The important thing was to have the /qn option after the msi file.
Edit: Ignore what I previously said, here's the solution according to the Python 2.4 Documentation:
It is not necessary to have the MSI file available for uninstallation; alternatively, the package or product code can also be specified. You can find the product code by looking at the properties of the Uninstall shortcut that Python installs in the start menu.
Hit the Windows Key, search Python Uninstall, right click it and go to Properties. The Product Key is in the Target field, you can use that to uninstall by doing:
msiexec /x {03mY-L0NG-A77-K3Y}.msi /qn

Categories

Resources