microsoft / WSL

Issues found on WSL
https://docs.microsoft.com/windows/wsl
MIT License
17.05k stars 798 forks source link

Feature Request: Desktop Notifications #2466

Open jwhipp opened 6 years ago

jwhipp commented 6 years ago

Microsoft Windows [Version 10.0.15063]

Desktop notifications from Linux apps don't appear in Windows, it would be nice if this could work.

Example test:

$ sudo apt-get install libnotify-bin $ notify-send "TEST"

Feature request is to have the notification interface to allow the action center to receive notifications.

ghost commented 6 years ago

I agree. It probably does not have a huge priority presently though.

There will be a larger update towards the middle of October so perhaps afterwards some lower priority things may receive more attention. :)

sunilmut commented 6 years ago

Thanks for the idea. Marking it so. Please open a ticket at the WSL user voice for any feature requests. It helps us prioritize for future.

crozone commented 6 years ago

libnotify uses the Desktop Notifications Specification, which works on top of D-Bus.

This means that the solution can probably already be accomplished by writing a Windows-land daemon that connects to the Linux-land D-Bus daemon over TCP, and creates Windows notification popups. I might even give this a go in C# if it's not too hard.

Unless the BoUoW team want to enable a way for the Linux D-Bus to be shared in another way (like allow Windows applications to consume a Unix pipe/socket, somehow...), and also build the notification client into the terminal, I'm not sure how much they can do.

sunilmut commented 6 years ago

@crozone - Interesting. I am just trying to visualize how this would work. So, the notify-send (or any other command) would go over libnotify to the WSL D-Bus service, which can publish the message over to the Desktop Notification Specification interface. And, if there is a Win32 Desktop Notification server that can consume these messages, then it can create the necessary popups?

crozone commented 6 years ago

@sunilmut sorry for the massively delayed reply, but yes.

The trick is that the win32 application can connect to the Linux D-Bus using a TCP connection to localhost. In theory, it would make the most sense for an X Window Sever (like XMing) to implement it on the win32 side, since IIRC it already establishes a connection to a D-Bus channel relating to that desktop. However, failing that, a stand alone application can work, but I'm not 100% sure how it would find the right D-Bus channel.

therealkenc commented 6 years ago

it would make the most sense for an X Window Sever (like XMing) to implement it on the win32 side

Wrong protocol. All the dbus action happens on the WSL side; an X Server (be it XMing, VcXsrv, native Linux Xorg) has no knowledge of dbus or what is being displayed in a popup window. It speaks X11 protocol.

The guys who obscure half their screen with Ubuntu wallpaper over in #637 already have desktop notifications. notify-send works fine for them; or at least, it should. I think you can fire up unity-notifications alone and get exactly what you describe (ignoring that unity-notifications probably falls on its face without Unity around). The xfce4 guys have something similar.

If all you want is CLI notify-send, actual Win32 Desktop Notifications, and no X11 to speak of, you could write your own Desktop Notification Specification service like Sunil describes. But the dbus session server and the notification client still live on the WSL side, communicating over an AF_UNIX socket. Typically you'd talk to the service using ssh.

Basically, on the Windows side you write an app that remote launches (on WSL) some Python script that sits there waiting for Desktop Notification Specification messages to arrive, and spits the notification text out to stdout in some formatted manner. Then on the windows side when new message text arrives over ssh you push a Windows Desktop notification.

I mean, in a fever dream kind of way.

crozone commented 6 years ago

Wrong protocol. All the dbus action happens on the WSL side; an X Server (be it XMing, VcXsrv, native Linux Xorg) has no knowledge of dbus or what is being displayed in a popup window. It speaks X11 protocol.

Ahh, thanks. I thought there was some magic there that would allow X apps to "find" the D-Bus channel for that session, but maybe that's something else.

Basically, on the Windows side you write an app that remote launches (on WSL) some Python script that sits there waiting for Desktop Notification Specification messages to arrive, and spits the notification text out to stdout in some formatted manner. Then on the windows side when new message text arrives over ssh you push a Windows Desktop notification.

I'm pretty sure you don't need to do this though, you can get D-Bus to listen for TCP connections, instead of just the AF_UNIX socket. This would let the Windows-land client speak to the Linux-land D-Bus, and therefore the the notification protocol, entirely natively.

therealkenc commented 6 years ago

you can get D-Bus to listen for TCP connections

Yeah I almost mentioned that but didn't want to yammer (knowing in my heart someone would bring it up anyway). That is technically correct, but would mean the mother-of-all dependency inversions. In other words, installing a hypothetical "WSL desktop notify package" would mean forcing TCP on everything else. And no one would do that. This is why dbus-broker just scrapped the idea entirely (search "Local Only" in the article).

WSLUser commented 6 years ago

@therealkenc @sunilmut This can probably be looked at now using AF_Unix interop. Not sure how simple it would be but it would be nice to have this small but useful feature. There should probably be an option to toggle it on or off and ensure notifications respect becoming silenced using "Quiet Hours".

crozone commented 6 years ago

I was just thinking about how the new AF_UNIX interop stuff could fit into this. As far as I understand it, a socket can only be consumed from Win32 land if it is created within the path of a Win32 accessible filesystem, and can then only be accessed by the creator (on the UNIX side), and Win32 apps.

D-Bus should be able to create two UNIX sockets and listen on both, one for the unix side in /tmp, and one on the Win32 side, on an NTFS partition. This can be done with extra <listen> entries in the dbus config.

I still don't understand why TCP isn't a satisfactory solution to this though, since a D-Bus daemon can listen on both UNIX socket and TCP (the "ssh tunneling" mentioned by the article above still requires TCP connections). Now the dbus daemon will just be listening on two UNIX sockets instead.

therealkenc commented 6 years ago

I still don't understand why TCP isn't a satisfactory solution to this though

It isn't not a satisfactory solution. :)

It is just pointlessly complicated when you can use wsl.exe (aka WslLaunch) and listen to the messages on stdin. You can put another <listen> entry in the dbus conf (TCP socket, Unix named socket, Unix abstract socket matters not), but now you've made the Ubuntu dbus package dependent on your "WSL notifier" package; because dbus owns that configuration file. Which is upside-down.

So yes. You could write a Windows program with a port of the dbus protocol which opens a Unix socket or TCP socket, and write a postinstall script on the WSL side to fix up the dbus conf; which will be clobbered on the next dbus apt upgrade. Or... you could listen on stdin. Whichever makes for the most fun as a time sink I guess. Not much fun it would appear, because no one has since August.

therealkenc commented 6 years ago

Or the other direction; even easier.

In Windows, launch Powershell as Administrator and do:

PS C:\WINDOWS\system32> Install-Module -Name BurntToast

On WSL:

$ alias toast='powershell.exe -command New-BurntToastNotification'

And finally:

$ toast -Text hello

FTFY

therealkenc commented 6 years ago

So a follow-up on this, just because I took the time-sink to do a "what would it take" look. I hacked up notification-thing to spawn New-BurntToastNotification instead of popping up a GTK3+ window. It even has a liberal license. We're talking trivial changes here. That gets you a working notify-send from libnotify-bin as asked for in the OP.

Long story short (I've deleted a third of this post), The Desktop Notifications Specification operates in a session. This isn't related to the <listen> option in /usr/share/dbus-1/system.conf (AF_UNIX or otherwise). You can in theory and practice create a remote login dbus session for every WSL terminal, which goes to Ben's comment in #816 (here). But the end result is you're just talking to yourself. It doesn't matter whether you are connected to the session bus from the Windows side or the WSL side (there isn't really a "side" -- it is a bus). I'm pretty sure you could run the same hacked up notification-thing with dbus-python for Windows.

But either way, you are literally firing up a dbus session on every terminal for the privilege of sending a message right back to yourself to spawn New-BurntToastNotification (or your own re-implementation thereof). Which, you can just call directly per yesterday's message, and avoid the drama.

therealkenc commented 6 years ago

This puts the "feature request" in an awkward state. Possibilities being:

(1) People just want to get a Win 10 notification, somehow, from the WSL commandline. Which we could do since interop went live.

(2) People actually want a session bus started on every terminal instance. This would live in their /etc/pam.d/wsld on Debian derived distros. Which worms fast, and is why #1405 is frozen in time.

(3) This is a coded request for Gnome sessions, because GTK+ is In Real Life the only thing that calls libnotify. Which is out of scope.

alanaasmaa commented 5 years ago

It would be awesome to have a project that listeners some error logs and send notifications to windows accordingly.

It would also be awesome when i would have all my side project finished so i could build this

JacobDB commented 5 years ago

@therealkenc personally I'd be happy with the first option. I just want gulp-notify to be able to send me toast notifications.

therealkenc commented 5 years ago

personally I [would] be happy with the first option. I just want gulp-notify to be able to send me toast notifications.

Yep. Use a custom notifier and call 'powershell.exe -command New-BurntToastNotification' with child_process.exec().

JacobDB commented 5 years ago

@therealkenc oh that's awesome, completely missed that. Thanks, will try to get it integrated in to my system.

therealkenc commented 5 years ago

Thanks, will try to get it integrated in to my system.

Great.

I think your necropost is probably enough motivation to put this one to bed. The only way this issue can be turned into a WSL actionable is possibility (2). That is highly problematic because WSL is distribution agnostic, and any solution would necessitate overloading WSL's /init yet more and firing up a Desktop Notification Specification service on every bash session, presumably controlled by some wsl.conf setting. On the Windows side wslhost.exe (or whatever) would listen on some communication channel (which n.b. is not dbus because the dbus session server has to live in each WSL bash session on the WSL side). [To help visualize, imagine a Ubuntu WSL instance taking unity-notification messages and a simultaneously running OpenSUSE WSL instance taking our imagined /init-to-wslhost.exe mechanism.]

Which is just too horrible to contemplate, because having implemented all of that, it gets us nothing option (1) can't do. UserVoice won't save us here.

gravataLonga commented 4 years ago

Any update on this?

b-hayes commented 4 years ago

personally I [would] be happy with the first option. I just want gulp-notify to be able to send me toast notifications.

Yep. Use a custom notifier and call 'powershell.exe -command New-BurntToastNotification' with child_process.exec().

Like the idea of this one but seems there's a lot of hoops to jump through to get it working.

New-BurntToastNotification
New-BurntToastNotification : The 'New-BurntToastNotification' command was found in the module 'BurntToast', but the module could not be loaded. For more information, run
'Import-Module BurntToast'.
At line:1 char:1
+ New-BurntToastNotification
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (New-BurntToastNotification:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CouldNotAutoloadMatchingModule

PS C:\Windows\system32> Import-Module BurntToast
Import-Module : File C:\Program Files\WindowsPowerShell\Modules\BurntToast\0.7.1\BurntToast.psm1 cannot be loaded because running scripts is disabled on this system. For more
information, see about_Execution_Policies at https:/go.microsoft.com/fwlink/?LinkID=135170.
At line:1 char:1
+ Import-Module BurntToast
+ ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : SecurityError: (:) [Import-Module], PSSecurityException
    + FullyQualifiedErrorId : UnauthorizedAccess,Microsoft.PowerShell.Commands.ImportModuleCommand
ykhurshid commented 4 years ago

personally I [would] be happy with the first option. I just want gulp-notify to be able to send me toast notifications.

Yep. Use a custom notifier and call 'powershell.exe -command New-BurntToastNotification' with child_process.exec().

Like the idea of this one but seems there's a lot of hoops to jump through to get it working.

New-BurntToastNotification
New-BurntToastNotification : The 'New-BurntToastNotification' command was found in the module 'BurntToast', but the module could not be loaded. For more information, run
'Import-Module BurntToast'.
At line:1 char:1
+ New-BurntToastNotification
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (New-BurntToastNotification:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CouldNotAutoloadMatchingModule

PS C:\Windows\system32> Import-Module BurntToast
Import-Module : File C:\Program Files\WindowsPowerShell\Modules\BurntToast\0.7.1\BurntToast.psm1 cannot be loaded because running scripts is disabled on this system. For more
information, see about_Execution_Policies at https:/go.microsoft.com/fwlink/?LinkID=135170.
At line:1 char:1
+ Import-Module BurntToast
+ ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : SecurityError: (:) [Import-Module], PSSecurityException
    + FullyQualifiedErrorId : UnauthorizedAccess,Microsoft.PowerShell.Commands.ImportModuleCommand

You need to set your ExecutionPolicy to unrestricted to make it work. Run Powershell in administrator mode and run the command "Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope LocalMachine".

It worked for me after that though the alias was not working for text that ran beyond a single word so I instead made a bash function as follows

toast () { powershell.exe -command New-BurntToastNotification "-Text '$1'" }

Stick that into your bashrc (or whatever rc your particular shell happens to use) and you should be good to go.

Kallahan23 commented 4 years ago

Changing the execution policy directly using Set-ExecutionPolicy works, but leaves your machine open to malicious scripts. I'm not a fan of this approach. I think it's better to leave it set to Restricted.

Instead, I set my alias in WSL to this:

alias toast='powershell.exe -executionpolicy bypass -command New-BurntToastNotification'

I'm not an expert at Powershell by any means, but as far as I know, this bypasses the execution policy only for this call. That way Powershell can stay restricted by default, but this WSL alias will bypass this and run the toast.

WSLUser commented 3 years ago

@therealkenc Since we're getting GUI support for WSL2, I think this issue could be re-opened. This could now be done behind the scenes and also could simply be a configuration option in /etc/wsl.conf if we want Win 10 notifications vice native Linux notifications popping up. I think I'd prefer Win 10 though, easier to manage that way.

therealkenc commented 3 years ago

The ask isn't related to GUI support, which was explained in May 2018 (message). That is the case whether X11 or Wayland. You can of course get a Linux GUI notification, but that wasn't the ask. The ask was for Windows notifications. Linux GUI notification popups, meanwhile, would be all userspace.

That said, there is no User Voice anymore (there was in 2017), so, sure, re-opening on feature request loophole.

xuanruiqi commented 2 years ago

Would it be possible to make an alternate implementation of libnotify based on WSL-Windows interaction mechanisms?

bartdorsey commented 1 year ago

I've been trying to get the BurntToast notifier going in WSL.. and I constantly get this error... and I'mnot sure how to fix it..

Exception calling "CreateToastNotifier" with "1" argument(s): "The data area passed to a system call is too small. (Exception from
HRESULT: 0x8007007A)"
At C:\Program Files\WindowsPowerShell\Modules\BurntToast\0.8.5\BurntToast.psm1:2478 char:9
+         [Windows.UI.Notifications.ToastNotificationManager]::CreateTo ...
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : Exception
zadjii-msft commented 11 months ago

Not to bump an old thread, but a way this might be achievable is tracked in https://github.com/microsoft/terminal/issues/7718. The way I've got it implemented in https://github.com/microsoft/terminal/pull/14425, an app can do something like:

printf "\x1b]777;notify;Hello From the Terminal;This is a notification sent by the client application\x07"

And that'll send a Windows toast.

It's not exactly the same thing as all the dbus and notify-send chatter above, but I bet it'll achieve the same goal.

Davikar commented 11 months ago

I've been trying to get the BurntToast notifier going in WSL.. and I constantly get this error... and I'mnot sure how to fix it..

Exception calling "CreateToastNotifier" with "1" argument(s): "The data area passed to a system call is too small. (Exception from
HRESULT: 0x8007007A)"
At C:\Program Files\WindowsPowerShell\Modules\BurntToast\0.8.5\BurntToast.psm1:2478 char:9
+         [Windows.UI.Notifications.ToastNotificationManager]::CreateTo ...
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : Exception

Having the same issue. It works when done from the Windows side, but not inside WSL.

b-hayes commented 11 months ago

NGL I can't believe this is still not a thing. Every terminal on every system except windows can do this.

kmantel commented 10 months ago

I've been trying to get the BurntToast notifier going in WSL.. and I constantly get this error... and I'mnot sure how to fix it..

Exception calling "CreateToastNotifier" with "1" argument(s): "The data area passed to a system call is too small. (Exception from
HRESULT: 0x8007007A)"
At C:\Program Files\WindowsPowerShell\Modules\BurntToast\0.8.5\BurntToast.psm1:2478 char:9
+         [Windows.UI.Notifications.ToastNotificationManager]::CreateTo ...
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : Exception

This feels silly but worked for me

powershell powershell.exe -Command New-BurntToastNotification

moabel commented 9 months ago

I've been trying to get the BurntToast notifier going in WSL.. and I constantly get this error... and I'mnot sure how to fix it..

This feels silly but worked for me

powershell powershell.exe -Command New-BurntToastNotification

I can't believe this actually worked. I had to do it this way:

powershell.exe powershell.exe -Command New-BurntToastNotification

shanselman commented 5 months ago

Would be cool @craigloewen-msft

ultrabig commented 5 months ago

I created an impelementation using Windows native functionality. https://github.com/ultrabig/WslNotifyd

RAraghavarora commented 2 months ago

Boosting this for notifications more than single word!!

It worked for me after that though the alias was not working for text that ran beyond a single word so I instead made a bash function as follows

toast () { powershell.exe -command New-BurntToastNotification "-Text '$1'" }

Stick that into your bashrc (or whatever rc your particular shell happens to use) and you should be good to go.