WinBatch® Technical Support Forum

All Things WinBatch => WinBatch => Topic started by: daz_1234 on May 20, 2021, 04:21:00 AM

Title: How to generate a Windows 10 desktop notification
Post by: daz_1234 on May 20, 2021, 04:21:00 AM
Hi all, first time poster, long time Winbatch user but probably not much past novice ...

Is it possible to generate standard Windows 10 desktop notifications in Winbatch? (sometimes called 'toaster' notification). And even better, can we create an action to run when the notification is clicked?

similar to say Outlook notification and when clicked it opens the email.

(I have unsuccessfully already tried to search this forum and the online db)

Many thanks,
Darren.
Title: Re: How to generate a Windows 10 desktop notification
Post by: td on May 20, 2021, 12:35:12 PM
There is no means that I am aware of to create notifications in a WinBatch script. 

[edit] That said there is some possibility that you could do something in a script that would cause another application to produce a notification.
Title: Re: How to generate a Windows 10 desktop notification
Post by: JTaylor on May 20, 2021, 01:22:07 PM
No idea if you can do something in C# that would work in WinBatch or not but assuming this is what you mean...

           https://docs.microsoft.com/en-us/windows/uwp/design/shell/tiles-and-notifications/send-local-toast?tabs=uwp

Here is a place to check.

Jim
Title: Re: How to generate a Windows 10 desktop notification
Post by: td on May 20, 2021, 01:29:21 PM
or you could make a WinBatch script a system tray app and have it pop up a window based on a trigger. It would be more or less faking a notification...

https://docs.winbatch.com/mergedProjects/WindowsInterfaceLanguage/html/WILAK_I__085.htm (https://docs.winbatch.com/mergedProjects/WindowsInterfaceLanguage/html/WILAK_I__085.htm)

Not sure that the .Net approach will work because it likely requires something called a delegate underneath the hood and the CLR does not permit using delegates in WinBatch scripts. That means it would require some investigation just to figure out if it is even possible.

Title: Re: How to generate a Windows 10 desktop notification
Post by: daz_1234 on May 24, 2021, 06:20:49 AM
Thanks for your replies guys.
Title: Re: How to generate a Windows 10 desktop notification
Post by: ChuckC on May 26, 2021, 12:27:54 PM
I took some time to read thru the "Send local toast notification from C# apps" article referred to in a previous message, and it does look like it should work OK from WinBatch using CLR hosting.  There don't appear to be any delegates required.  The documentation indicates that .NET Framework desktop apps are supported, so that also meets the requirements for use with CLR hosting.  The only caveat, if you will, is that a specific NuGet package is required to provide the support class that actually does the low-level work of sending the notification.
Title: Re: How to generate a Windows 10 desktop notification
Post by: td on May 26, 2021, 01:45:21 PM
Delegates are not necessarily presented to the would-be user of a framework or API. They can be hidden behind the facade. Anything named "OnActivated" raised the possibility of a hidden delegate. Not saying that it will not work but given how the underlying native code API is put together, it is a possibility.
Title: Re: How to generate a Windows 10 desktop notification
Post by: ChuckC on May 26, 2021, 03:39:13 PM
Understood.

What I read about how the gadget that receives the "toast" notifications is that if it has to communicate back to the application that sent the notification, it either sends a window activate message via normal desktop window messaging or it can even launch the source application with a command line parameter used to convey context information back to the application so that it understands why it was launched.  It seems to allow for a great degree of decoupling between the sources of toast notifications the gadget that displays & manages them, with all toast notifications ultimately being nothing more than an XML payload that gets communicated.  The NuGet package that is required is for a library that provides data objects to C# & C++ client code such that the data object can be configured via method calls and setting properties, after which they are rendered into XML and dispatched.
Title: Re: How to generate a Windows 10 desktop notification
Post by: td on May 27, 2021, 08:15:36 AM
If a user presents a working script using dotNet and WIL CLR hosting, great! But until then I will remain skeptical.
Title: Re: How to generate a Windows 10 desktop notification
Post by: ChuckC on May 27, 2021, 12:43:53 PM
As of this afternoon, after quite a bit of monkeying around with extracting some assemblies from some NuGet packages, I have it working under both PowerShell v7.1.3 w/.NET Core 5.x and Windows PowerShell [ISE].

I'll convert it to WIL code and get it posted in the near future.

There is a dependency on retrieving a NuGet package and then manually extracting a specific assembly DLL file from it.  Given that there's no guarantee that a WinBatch script developer will have Visual Studio handy do the dirty work, I'll include some instructions on what is needed to get the necessary assembly DLL file out of the package.
Title: Re: How to generate a Windows 10 desktop notification
Post by: td on May 27, 2021, 01:16:45 PM
I hope you don't need to use .Net Core and can use the FCL instead because you can't use .Net core with WIL CLR hosting. Otherwise, you would have to launch a PS script from WIL CLR hosting or whatever.  That said, it would be a great addition to the Tech. Database.
Title: Re: How to generate a Windows 10 desktop notification
Post by: ChuckC on May 27, 2021, 01:26:55 PM
The assembly in question has builds for .NET Framework, .NET Standard and .NET Core.

Some of the functions on the TestContentBuilder class turn out to have a number of optional parameters implemented as nullable types along the lines of "bool? hintWrap", which induces aggravation in WIL's CLR support.


Invoking the Toast functionality via PowerShell is feasible and may be the most expedient way of doing so.

The NuGet package that is required is as follows:

https://www.nuget.org/packages/Microsoft.Toolkit.Uwp.Notifications/

Choose the "Download package" link and save the file "microsoft.toolkit.uwp.notifications.7.0.2.nupkg" to a convenient local location.

Rename the ".nupkg" extension to ".zip" and then drill down into it and extract "lib\net461\Microsoft.Toolkit.Uwp.Notifications.dll".  Be sure to clear the zone identifier that flags it as having come from an untrusted network location, as failing to do so will result in the assembly failing to load.  Ideally, put the assembly in the same location as the WinBatch script and, optionally, the .ps1 file that are going to make use of it.


Here's the PowerShell code:

#  TestToast-01.ps1

if (-not ("Microsoft.Toolkit.Uwp.Notifications.ToastContentBuilder" -as [Type]))
{
    if ($PSEdition -eq "Core")
    {
        #  For PowerShell Core v6.x & PowerShell v7+

        Add-Type -Path $(Join-Path $env:USERPROFILE "Documents\AppDevProjects\NuGet\microsoft.windows.sdk.net.ref.10.0.19041.17\lib\Microsoft.Windows.SDK.NET.dll")

        Add-Type -Path $(Join-Path $env:USERPROFILE "Documents\AppDevProjects\NuGet\microsoft.windows.sdk.net.ref.10.0.19041.17\lib\WinRT.Runtime.dll")
   
        Add-Type -Path $(Join-Path $env:USERPROFILE "Documents\AppDevProjects\NuGet\Microsoft.Toolkit.Uwp.Notifications\lib\net5.0-windows10.0.17763\Microsoft.Toolkit.Uwp.Notifications.dll")
    }
    else
    {
        #  For Windows PowerShell and Windows PowerShell_ISE

        Add-Type -Path $(Join-Path $env:USERPROFILE "Documents\AppDevProjects\NuGet\Microsoft.Toolkit.Uwp.Notifications\lib\net461\Microsoft.Toolkit.Uwp.Notifications.dll")
    }
}


$toast = [Microsoft.Toolkit.Uwp.Notifications.ToastContentBuilder]::new()

#  This can be considered to the the "title" text on line #1.
#  A minimum of 1 line of text is required when preparing a
#  Toast Notification.

$toast.AddText("<Text Element #1>")

#  The remaining 2nd & 3rd text lines are optional.

$toast.AddText("<Text Element #2>")

$toast.AddText("<Text Element #3>")

#  The attribution text is optional.

$toast.AddAttributionText("<Attribution Text>")


#  Make the notification appear on the desktop.

$toast.Show()


Please note that the Add-Type command needs to be altered to refer to the correction location for the assembly.

Title: Re: How to generate a Windows 10 desktop notification
Post by: td on May 27, 2021, 03:05:35 PM
Usually, method not found problems can be fixed by creating a full method signature but not luck this time. Just produces an "Invalid parameter" error.  Maybe someone else can see something I missed.

Code (winbatch) Select
;; Add types to parameters as necessary to assist in building the method's signature
;; Since WIL CLR hosting does not support named parameters.
hintStyle = ObjectClrType('Microsoft.Toolkit.Uwp.Notifications.AdaptiveTextStyle',0)
hintWrap = ObjectClrType('System.Boolean', 0)
hintMaxLines = 2
hintMinLines = 1
hintAlign = ObjectClrType('Microsoft.Toolkit.Uwp.Notifications.AdaptiveTextAlign',0)
language = "en-US"

objToast.AddText("<Text Element #1>", hintStyle, hintWrap, hintMaxLines, hintMinLines, hintAlign, language)
;objToast.AddText("<Text Element #2>", hintStyle, hintWrap, hintMaxLines, hintMinLines, hintAlign, language)
;objToast.AddAttributionText("<Attribution Text>", hintStyle, hintMaxLines, hintMinLines, hintAlign, language)

objToast.Show()

exit
Title: Re: How to generate a Windows 10 desktop notification
Post by: ChuckC on May 27, 2021, 05:39:52 PM
You have almost exactly the same WIL code that I had written in my attempt to port the logic from PowerShell to WIL.

If you look at the docs for the TestContentBuilder's AddText() instance method, you'll quickly see the crux of the problem:

https://docs.microsoft.com/en-us/dotnet/api/microsoft.toolkit.uwp.notifications.toastcontentbuilder.addtext?view=win-comm-toolkit-dotnet-7.0

public Microsoft.Toolkit.Uwp.Notifications.ToastContentBuilder AddText (string text, Microsoft.Toolkit.Uwp.Notifications.AdaptiveTextStyle? hintStyle = default, bool? hintWrap = default, int? hintMaxLines = default, int? hintMinLines = default, Microsoft.Toolkit.Uwp.Notifications.AdaptiveTextAlign? hintAlign = default, string language = default);

There are optional nullable parameters in the signature.  Sometimes, those will even give PowerShell fits and seizures, but that wasn't the case this time.  It's just WIL's CLR support that's pitching a fit over it.

In WIL, how does one pass an untyped null the parameter for a formal argument that is of a nullable type?

I think we had an earlier discussion a few months back regarding WIL having issues with generic types, to the Nullable<T> type is out of the question to work around "bool? hintWrap = default" by passing null cast to Nullable<bool>.

Even reflection seemed outside the reach of WIL in this case.  I've had a number of times that I needed to invoke a class method, instance or static, that was scoped internal or private, and that is easy to do in C# with just a few lines of code.  However, even reflection requires being able identify the types of each of the formal arguments in the signature if attempting to get a specific method overload when there are numerous overloads with similar signatures.  Then again, perhaps one of the alternative reflection methods that returns an IEnumerable<> of method information instances would serve better in this case since it would return a container with only a single item in it.  I may do some more dinking around with that to see if I can obtain method information, and if I can, then invoking the method becomes trivial if I can get WIL to produce proper null values to use when calling the method via its method information.  The other thing that is needed is to determine what the WIL CLR equivalent is of C#'s "typeof(some-class-or-struct-type)".


Title: Re: How to generate a Windows 10 desktop notification
Post by: td on May 27, 2021, 10:28:26 PM
I had viewed the documentation before I posted the test example. Neither "nullable" nor "optional" parameters should give WIL CLR issues by themselves since they have regular values in the example above. The CLR is successfully finding the correct method based on the passed parameters. This fact is known based on the error message generated and by viewing the call in the "native" debugger.  Uninstantiated template classes will cause issues. However, it appears to be a CLR internal implementation contradiction to have the CLR find the method using the specified types but not accept the very same types in the actual method call.
Title: Re: How to generate a Windows 10 desktop notification
Post by: stanl on May 28, 2021, 02:53:33 AM
I take it the CLR cannot work with the Windows.UI.Notifications / Windows.UI.Notifications.ToastNotificationManager class/methods.
Title: Re: How to generate a Windows 10 desktop notification
Post by: ChuckC on May 28, 2021, 05:04:03 AM
Tony would have to weigh in on the issue in terms of whether or not any modifications to WinBatch/WIL are required to make it possible for the class method in question to be accessible from a script.

In the mean time, there are 2 work-arounds:

1)  Use a WinBatch script to provide the notification content and then have it utilize a captive PowerShell instance to actually send the notification.  PowerShell can be instructed to simply invoke an external .ps1 file wile passing parameters to it, or PowerShell can have statements injected into it to send the notification without making use of an external .ps1 file.

2)  Use a WinBatch script with utilizes the CLR to dynamically compile some C# code into an in-memory assembly which can then be used to send the notification.

Title: Re: How to generate a Windows 10 desktop notification
Post by: td on May 28, 2021, 09:47:35 AM
The only way to "fix" support for this particular set of classes would be to first eliminate WinBatch support for older versions of Windows and for most non-current versions of dotNet.  Then we could completely rewrite the CLR hosting implementation. And no it is not possible to support the current implementation and a new one in a single DLL/executable. Basically, it would require splitting the WIL interpreter into two DLLs and that is not something we are willing to do at this time.
Title: Re: How to generate a Windows 10 desktop notification
Post by: ChuckC on May 28, 2021, 10:23:20 AM
Got it working.  Dynamically creating an in-memory assembly and then using reflection to call into a static method did the trick.

Make sure that the "net461" targeted "Microsoft.Toolkit.Uwp.Notifications.dll" file is in the same directory as the script.


; TestToast-01.wbt

ObjectClrOption('appbase', DirScript())


ObjectClrOption('useany', 'System')

ObjectClrOption('useany', 'System.Collections')

ObjectClrOption('useany', 'System.Reflection')


oCSharp = ObjectClrNew('Microsoft.CSharp.CSharpCodeProvider')

oParams = ObjectClrNew('System.CodeDom.Compiler.CompilerParameters')

oParams.ReferencedAssemblies.Add( "system.dll" )

oParams.ReferencedAssemblies.Add( "system.collections.dll" )

oParams.ReferencedAssemblies.Add( "system.core.dll" )

oParams.ReferencedAssemblies.Add( "system.runtime.dll" )

oParams.ReferencedAssemblies.Add( "mscorlib.dll" )

oParams.ReferencedAssemblies.Add( "Microsoft.Toolkit.Uwp.Notifications.dll" )


sCode = ''

sCode = sCode : 'using System;' : @CRLF

sCode = sCode : 'using System.Collections;' : @CRLF

sCode = sCode : 'using System.Collections.Generic;' : @CRLF

sCode = sCode : 'using System.Linq;' : @CRLF

sCode = sCode : 'using Microsoft.Toolkit.Uwp.Notifications;' : @CRLF

sCode = sCode : '' : @CRLF

sCode = sCode : 'namespace wb.toast' : @CRLF

sCode = sCode : '{' : @CRLF

sCode = sCode : '  public static class WBToast' : @CRLF

sCode = sCode : '  {' : @CRLF

sCode = sCode : '    public static void SendToastNotification(string TextLine1In, string TextLine2In, string TextLine3In, string AttributionTextIn)' : @CRLF

sCode = sCode : '    {' : @CRLF

sCode = sCode : '        var toast = new ToastContentBuilder();' : @CRLF

sCode = sCode : '' : @CRLF

sCode = sCode : '        if (TextLine1In != null) toast.AddText(TextLine1In);' : @CRLF

sCode = sCode : '' : @CRLF


sCode = sCode : '        if (TextLine2In != null) toast.AddText(TextLine2In);' : @CRLF

sCode = sCode : '' : @CRLF

sCode = sCode : '        if (TextLine3In != null) toast.AddText(TextLine3In);' : @CRLF

sCode = sCode : '' : @CRLF

sCode = sCode : '        if (AttributionTextIn != null) toast.AddAttributionText(AttributionTextIn);' : @CRLF

sCode = sCode : '' : @CRLF

sCode = sCode : '        toast.Show();' : @CRLF

sCode = sCode : '' : @CRLF

sCode = sCode : '    }' : @CRLF

sCode = sCode : '  }' : @CRLF

sCode = sCode : '}' : @CRLF

sCode = sCode : '' : @CRLF


aSource[0] = sCode


oCR = oCSharp.CompileAssemblyFromSource(oParams, BSTR:aSource)

;  Check for compiler errors.

if oCR.Errors.Count > 0

  foreach error In oCR.Errors
    Pause("Error", error.ToString())
  next

  exit

endif


args[0] = '<Text Element #1>'

args[1] = '<Text Element #2>'

args[2] = '<Text Element #3>'

args[3] = '<Attribution Text>'


modules = oCR.CompiledAssembly.GetModules()

method = modules[0].GetType("wb.toast.WBToast").GetMethod("SendToastNotification")

method.Invoke(0, args)


exit
Title: Re: How to generate a Windows 10 desktop notification
Post by: JTaylor on May 28, 2021, 10:48:36 AM
Very Nice. 

Jim
Title: Re: How to generate a Windows 10 desktop notification
Post by: td on May 28, 2021, 12:41:22 PM
The c# compiler option is always an option to work around the limitations of WIL CLR hosting. It has been documented several times on this forum and in the Tech Database.  The reason I don't mention it is because most users have no interest in it. I can only speculate about why that is...

[edit] Here is but one example:

https://techsupt.winbatch.com/webcgi/webbatch.exe?techsupt/nftechsupt.web+WinBatch/dotNet/System_Drawing+Use~System.Drawing~for~Steganograhpy.txt (https://techsupt.winbatch.com/webcgi/webbatch.exe?techsupt/nftechsupt.web+WinBatch/dotNet/System_Drawing+Use~System.Drawing~for~Steganograhpy.txt)
Title: Re: How to generate a Windows 10 desktop notification
Post by: JTaylor on May 28, 2021, 02:28:04 PM
Yep.  I have found it extremely useful over the years.

Jim
Title: Re: How to generate a Windows 10 desktop notification
Post by: JTaylor on May 28, 2021, 02:53:54 PM
Here is a variation on Chuck's fine work that some may find useful...

Code (winbatch) Select



#DefineFunction Loadem_Toastem()

  ObjectClrOption('appbase', DirScript())
  ObjectClrOption('useany', 'System')
  ObjectClrOption('useany', 'System.Collections')
  ObjectClrOption('useany', 'System.Reflection')
 
  oCSharp = ObjectClrNew('Microsoft.CSharp.CSharpCodeProvider')
  oParams = ObjectClrNew('System.CodeDom.Compiler.CompilerParameters')
  oParams.ReferencedAssemblies.Add( "system.dll" )
  oParams.ReferencedAssemblies.Add( "system.collections.dll" )
  oParams.ReferencedAssemblies.Add( "system.core.dll" )
  oParams.ReferencedAssemblies.Add( "system.runtime.dll" )
  oParams.ReferencedAssemblies.Add( "mscorlib.dll" )
  oParams.ReferencedAssemblies.Add( "Microsoft.Toolkit.Uwp.Notifications.dll" )
  oParams.GenerateInMemory = ObjectType( "VT_BOOL", 1 ) ;TRUE
 
  sCode = $"using System;
            using System.Collections;
            using System.Collections.Generic;
            using System.Linq;
            using Microsoft.Toolkit.Uwp.Notifications;
   
            namespace wb_toast {
               public static class WBToast {
                 public static void STN(string TextLine1In, string TextLine2In, string TextLine3In, string AttributionTextIn) {
                    var toast = new ToastContentBuilder();
                    if (TextLine1In != null) toast.AddText(TextLine1In);
                    if (TextLine2In != null) toast.AddText(TextLine2In);
                    if (TextLine3In != null) toast.AddText(TextLine3In);
                    if (AttributionTextIn != null) toast.AddAttributionText(AttributionTextIn);
                    toast.Show();
                 }
              }
            }
         $"

  aSource[0] = sCode
 
  oCR = oCSharp.CompileAssemblyFromSource(oParams, BSTR:aSource)
 
  ;  Check for compiler errors.
  If oCR.Errors.Count > 0
    Foreach error In oCR.Errors
      Pause("Error", error.ToString())
    Next
    Return 0
  EndIf
 
  Return 1

#EndFunction

 
Loadem_Toastem()
tcall = ObjectClrNew( 'wb_toast.WBToast' )



  arg0 = "arg0"
  arg1 = "arg1"
  arg2 = "arg2"
  arg3 = "arg3"
 
  resp  = tcall.STN(arg0,arg1,arg2,arg3)

  arg0 = "g0"
  arg1 = "g1"
  arg2 = "g2"
  arg3 = "g3"
 
  resp  = tcall.STN(arg0,arg1,arg2,arg3)

Title: Re: How to generate a Windows 10 desktop notification
Post by: ChuckC on May 28, 2021, 03:54:18 PM
run with it...

at least now we know that we have toast.  of course, i'm not sure if it's sour dough, some sort of crostini or if it's actually champagne or scotch...

if it is some sort of bread, i expect that the next question will be whether it's buttered, or not, and is, on which side?

Title: Re: How to generate a Windows 10 desktop notification
Post by: JTaylor on May 28, 2021, 05:10:11 PM
Let the Butter Battle begin.

Jim
Title: Re: How to generate a Windows 10 desktop notification
Post by: ChuckC on May 29, 2021, 04:18:42 AM
There is more to to the Toast notifications than just a couple of lines of text.   When looking over the examples showing various way of using them, there are options to include pictures, web links, buttons and other data that allows acknowledgement of the notification to result in communicating back to the originating application with a windows message or by launching a program and passing command line parameters to it.

If I get some time to play around with it, I'll see how feasible those are to wrap up for use in WinBatch.  It may well be something that works best as a UDF library that includes a .CS source code file with a "toast" wrapper class in it that provides multiple static class methods that encapsulate the more complex toast-related class methods with easy to use "send toast notification type XYZ" methods.


oh, and when it coms to which side the toast is buttered on, don't forget that you can butter the crust on the sides... or, per one of the orphans in "The Matrix", the 1st thing to know that there is no toast...
Title: Re: How to generate a Windows 10 desktop notification
Post by: JTaylor on May 29, 2021, 09:43:21 AM
Not sure if this is the best method, and it is a work-in-progress, but thought maybe we could all come up with a useful set of Methods for Toasts.   Happy for names to change or for a completely different approach.

I broke out many of the options for Toasts into their own Methods.  Hopefully everything is, reasonably, self-explanatory.

Things I haven't figured out yet and/or haven't gotten to yet.   

        How to make use of the Buttons.   Tells me Specified Batch File Not Found.   Not sure if that can only be specified in XML and if so, how to make use of XML in script.
        Audio.   Nothing seemed to work.  Didn't get errors.  Just no sound.

Note:  You will need to change image path.

Jim


Code (winbatch) Select



#DefineFunction Load_Toaster()

  ObjectClrOption('appbase', DirScript())
  ObjectClrOption('useany', 'System')
  ObjectClrOption('useany', 'System.Collections')
  ObjectClrOption('useany', 'System.Reflection')
 
  oCSharp = ObjectClrNew('Microsoft.CSharp.CSharpCodeProvider')
  oParams = ObjectClrNew('System.CodeDom.Compiler.CompilerParameters')
  oParams.ReferencedAssemblies.Add( "system.dll" )
  oParams.ReferencedAssemblies.Add( "system.collections.dll" )
  oParams.ReferencedAssemblies.Add( "system.core.dll" )
  oParams.ReferencedAssemblies.Add( "system.runtime.dll" )
  oParams.ReferencedAssemblies.Add( "mscorlib.dll" )
  oParams.ReferencedAssemblies.Add( "Microsoft.Toolkit.Uwp.Notifications.dll" )
  oParams.GenerateInMemory = ObjectType( "VT_BOOL", 1 ) ;TRUE
 
  sCode = $"using System;
            using System.Collections;
            using System.Collections.Generic;
            using System.Linq;
            using Microsoft.Toolkit.Uwp.Notifications;

            namespace WBToast {
               public static class Toaster {

                 public static void STN(string TextLine1In, string TextLine2In, string TextLine3In, string AttributionTextIn) {
                    var toast = new ToastContentBuilder();
                    if (TextLine1In != "") toast.AddText(TextLine1In);
                    if (TextLine2In != "") toast.AddText(TextLine2In);
                    if (TextLine3In != "") toast.AddText(TextLine3In);
                    if (AttributionTextIn != "") toast.AddAttributionText(AttributionTextIn);
                    toast.Show();
                 }


                 public static ToastContentBuilder Toast()
                 {
                     var toast = new ToastContentBuilder();
                     return toast;
                 }
         

                 public static void Popup(ToastContentBuilder toast)
                 {
                     toast.Show();
                 }
         

                 public static void AddText(ToastContentBuilder toast, string TextLine)
                 {
                     toast.AddText(TextLine);
                 }
         
         
                 public static void AddAttributionText(ToastContentBuilder toast, string AttributionTextIn)
                 {
                     if (AttributionTextIn != "") toast.AddAttributionText(AttributionTextIn);
                 }
         

                 public static void AddImage(ToastContentBuilder toast, string ImageURL)
                 {
         
                     if (ImageURL != "") toast.AddInlineImage(new Uri(ImageURL));
                 }
         
         
                 public static void AddAppLogo(ToastContentBuilder toast, string ImageURL, string lstyle = "circle")
                 {
                     if (lstyle == "circle")
                       toast.AddAppLogoOverride(new Uri(ImageURL), ToastGenericAppLogoCrop.Circle);
                     else
                       toast.AddAppLogoOverride(new Uri(ImageURL));
                 }
         
         
         
                 public static void AddArgument(ToastContentBuilder toast, string ArgName, string ArgValue)
                 {
                     if (ArgName != "") toast.AddArgument(ArgName, ArgValue);
                 }
         
         
                 public static void AddArgument(ToastContentBuilder toast, string ArgName, int ArgValue)
                 {
                     if (ArgName != "") toast.AddArgument(ArgName, ArgValue);
                 }
         
         
                 public static void AddButton(ToastContentBuilder toast, string BText, string BArgName, string BArgValue)
                 {
             
                    toast.AddButton(new ToastButton() 
                         .SetContent(BText)
                         .AddArgument(BArgName, BArgValue)
                         .SetBackgroundActivation() );
                 }
         
         
                 public static void TextBox(ToastContentBuilder toast, string ReplyVar, string PlaceHolder)
                 {
                     toast.AddInputTextBox(ReplyVar, placeHolderContent:: PlaceHolder);
                 }
         




              }  //End Class
            }    // End Namespace
         $"

  aSource[0] = sCode
 
  oCR = oCSharp.CompileAssemblyFromSource(oParams, BSTR:aSource)
 
  ;  Check for compiler errors.
  If oCR.Errors.Count > 0
    Foreach error In oCR.Errors
      Pause("Error", error.ToString())
    Next
    Return 0
  EndIf
 
  Return 1

#EndFunction

 
Load_Toaster()



tcall = ObjectClrNew( 'WBToast.Toaster' )

toast = tcall.Toast;

tcall.AddText(toast, "Jim")

tcall.AddImage(toast, "C:\gbat\wb_test\Toasts\coffee.jpg")
tcall.AddAppLogo(toast, "C:\gbat\wb_test\Toasts\coffee.jpg","circle")
tcall.AddArgument(toast, "ID",123)
tcall.AddButton(toast, "Reply","action","reply")
tcall.AddButton(toast, "View","action","view")
tcall.TextBox(toast, "reply_var","Type a Reply")

tcall.Popup(toast)


;Below is the original single call for a simple Text Toast.

  arg0 = "arg0"
  arg1 = "arg1"
  arg2 = "arg2"
  arg3 = "arg3"
 
; resp  = tcall.STN(arg0,arg1,arg2,arg3)



Title: Re: How to generate a Windows 10 desktop notification
Post by: stanl on May 30, 2021, 03:28:02 AM
Jim;


cute ;D
Title: Re: How to generate a Windows 10 desktop notification
Post by: ChuckC on May 30, 2021, 07:37:25 AM
nice touch with the verbatim string to clean up the concatenation i was using.

after looking thru the online WIL consolidated help, locally installed consolidated help, the tech support database and the FAQ, i saw zero references to verbatim string support.

i'd hazard to guess the introduction of the feature was in the release notes for a specific version of WinBatch, but i also didn't see a comprehensive cumulative release notes anywhere on the site.

what version of WinBatch introduced verbatim strings and is there a cumulative collection of the release notes for all WinBatch versions somewhere on the site?
Title: Re: How to generate a Windows 10 desktop notification
Post by: JTaylor on May 30, 2021, 07:51:14 AM
Search for "String" in the Index and then Choose "Constants".   Always takes me a bit to find it, even knowing it is there.

Jim
Title: Re: How to generate a Windows 10 desktop notification
Post by: stanl on May 30, 2021, 09:00:18 AM
WB took a few hints from Powershell :)

Title: Re: How to generate a Windows 10 desktop notification
Post by: td on May 31, 2021, 07:57:42 AM
Actually, the "hint" came from a background in Unix scripting and a user named snowsnowsnow. Both of which have been around a lot longer than PS. The documentation can be found here:

https://docs.winbatch.com/mergedProjects/WindowsInterfaceLanguage/html/HTMLWIL_SC_001.htm (https://docs.winbatch.com/mergedProjects/WindowsInterfaceLanguage/html/HTMLWIL_SC_001.htm)

and in the release notes here:

https://www.winbatch.com/winbatchversions.html#WB2016B
(https://www.winbatch.com/winbatchversions.html#WB2016B)

Admittedly, it doesn't show up in any indices. However, each WinBatch installation includes a file called "The list of fixes and improvements.txt". It can be searched with your favorite text editor. You can also search the on-line release notes by selecting the lastest release from the WinBatch Versions page and using your browser's page search functionality. For example, in Firefox navigate to the release notes by selecting Whats's New from the WinBatch Home page, select the current latest version, use the cntl+f key combination, and then type "Multiline text" sans quotes.
Title: Re: How to generate a Windows 10 desktop notification
Post by: td on May 31, 2021, 09:05:48 AM
A Wikipedia article that describes the "Here Document" which is the inspiration for WIL "Multiline text" as used in several Unix shells and other language environments.

https://en.wikipedia.org/wiki/Here_document (https://en.wikipedia.org/wiki/Here_document)
Title: Re: How to generate a Windows 10 desktop notification
Post by: stanl on May 31, 2021, 12:47:32 PM
I was joking about the PS comment as I figured it would get you to comment. But on the topic of C# compilation. Jim's code could be compiled into a physical .dll, if read as a .cs file. Maybe an abstract or pointless ask: but if possible could the .dll be wrapped into a WB Service that could be accessed by any number of WB scripts?
Title: Re: How to generate a Windows 10 desktop notification
Post by: JTaylor on May 31, 2021, 03:31:34 PM
Not sure what you mean by a WB Service but could easily make it a COM accessible DLL.    If having a separate file is acceptable it would probably be easier to Encode it for Calls from Exes....although that might not accomplish what you are asking.  In any event, I have found the Encoding options extremely useful when I want data available but reasonably secure.

Jim
Title: Re: How to generate a Windows 10 desktop notification
Post by: td on May 31, 2021, 05:39:01 PM
Quote from: stanl on May 31, 2021, 12:47:32 PM
I was joking about the PS comment as I figured it would get you to comment.

Just wanted to give due credit where credit was due.
Title: Re: How to generate a Windows 10 desktop notification
Post by: stanl on June 01, 2021, 01:07:47 PM
Quote from: td on May 31, 2021, 05:39:01 PM
Just wanted to give due credit where credit was due.


Tony:  understood


Jim: Don't take what I wrote with any importance. I have no need for notifications but the concept of compiling C# should be of interest to all, so hope you get more feedback on that. I'm surprised no interest in the Power Query scripts I posted but such is the nature of things.
Title: Re: How to generate a Windows 10 desktop notification
Post by: JTaylor on June 01, 2021, 01:35:55 PM
No problem Stan.  I am not sure I have any use for Toasts either but was just something interesting to work on.   I am very glad this went the way it did because the in-memory compiling code I have used for years stopped working for some reason I couldn't figure out.  This thread provided an example that worked so happy on that front as well.


Jim   
Title: Re: How to generate a Windows 10 desktop notification
Post by: ChuckC on June 02, 2021, 04:23:00 AM
If you have a WinBatch script running in the SysTray or otherwise running in the background [minimized], Toast notifications would serve nicely as a way to deliver a notification to the user in a way that doesn't require the script to be blocked by using the Display() function or having to use the Dialog() or Box*() functions.

That's one usage case that stands out to me.  I'm certain that a little more experimental coding and testing will get embedded images, playing of sound and configurable action buttons would make usage of Toast notifications even more desirable.

As for the in-memory compilation, I use it extensively in my PowerShell script development.  One thing I had to account for in the C# code I originally posted is that the built-in C# compiler that is present with .NET Framework v4.x is for a much older language version than what is currently available with Visual Studio.  The C# compiler, code name "Roslyn", is available for use outside of Visual Studio and exists as a redistributable set of binaries that I use with PowerShell.  I can see about posting a WinBatch script that does in-memory compilation of C# code using Roslyn so that all kinds of newer C# language features are accessible.

Title: Re: How to generate a Windows 10 desktop notification
Post by: JTaylor on June 02, 2021, 12:37:17 PM
Sounds good to me, if you get the time.

Thanks.

Jim
Title: Re: How to generate a Windows 10 desktop notification
Post by: seckner on June 04, 2021, 03:16:18 PM
Not sure if this will help but I found this script buried in the basement of the WinBatch office building. It will post a notification on one or many clients. Overnight jobs will post a message and not fade it out, daily jobs would post a notify an fade out in x seconds or minutes. The original web site has been changed and there are many GitHub sites with it. I don't know if the files are safe anymore. I have all the original files if needed. It's not fancy but it works.

https://techsupt.winbatch.com/webcgi/webbatch.exe?techsupt/nftechsupt.web+WinBatch/Samples~from~Users+Growl~Notify~~UDF.txtf

If there is any interest I'll gather the Files.
Title: Re: How to generate a Windows 10 desktop notification
Post by: td on June 04, 2021, 11:14:55 PM
 Looks like you have an extra character at the end of your URL. It should be

https://techsupt.winbatch.com/webcgi/webbatch.exe?techsupt/nftechsupt.web+WinBatch/Samples~from~Users+Growl~Notify~~UDF.txt (https://techsupt.winbatch.com/webcgi/webbatch.exe?techsupt/nftechsupt.web+WinBatch/Samples~from~Users+Growl~Notify~~UDF.txt)

with the "f" removed from the end.
Title: Re: How to generate a Windows 10 desktop notification
Post by: stanl on June 05, 2021, 04:44:56 AM
Quote from: seckner on June 04, 2021, 03:16:18 PM
If there is any interest I'll gather the Files.


There is a March 2021 release on FileHippo, which is clean. The script you referenced does work, but it probably needs an IsGrowlRunning() in order for notifications to show up. Good find especially for the Op's original question.
Title: Re: How to generate a Windows 10 desktop notification
Post by: td on June 05, 2021, 08:03:05 AM
The (hopefully) useful stuff users find in the Tech Database never ceases to amaze.
Title: Re: How to generate a Windows 10 desktop notification
Post by: kdmoyers on June 08, 2021, 12:54:32 PM
Quote from: stanl on June 05, 2021, 04:44:56 AM
There is a March 2021 release on FileHippo, which is clean.

Stan,
Just want to be sure I'm getting the same version you got. 
(The file I see on Hippo is dated march of 2012, not 2021.)

is it version 2.0.9.1 ?  with the file Gowl_v2.0.msi shows a CRC-32 of 5143A96A?

Thanks!!
-Kirby
Title: Re: How to generate a Windows 10 desktop notification
Post by: ChuckC on June 08, 2021, 01:33:44 PM
I got things working with PowerShell generating toast notifications which contain images.

PS code snippets:


$inlineImageFileSpec = Join-Path $PSScriptRoot "ButteredToast.jpg"

$appLogoImageFileSpec = Join-Path $PSScriptRoot "Toaster.jpg"

$heroImageFileSpec = Join-Path $PSScriptRoot "A toast to you.jpg"


$toast = [Microsoft.Toolkit.Uwp.Notifications.ToastContentBuilder]::new()


#  An inline image is optional

$toast.AddInlineImage([System.Uri]::new("file://$($inlineImageFileSpec.Replace("\", "/"))"))


#  A profile [app logo override] image is optional

$toast.AddAppLogoOverride([System.Uri]::new("file://$($appLogoImageFileSpec.Replace("\", "/"))"))


#  This can be considered to the the "title" text on line #1.
#  A minimum of 1 line of text is required when preparing a
#  Toast Notification.

$toast.AddText("<Text Element #1>")

#  The remaining 2nd & 3rd text lines are optional.

$toast.AddText("<Text Element #2>")

$toast.AddText("<Text Element #3>")

#  The attribution text is optional.

$toast.AddAttributionText("<Attribution Text>")


#  A hero image is optional.  Maximum image dimensions
#  are 364x180 pixels at 100% scaling.

$toast.AddHeroImage([System.Uri]::new("file://$($heroImageFileSpec.Replace("\", "/"))"))


#  Make the notification appear on the desktop.

$toast.Show()


The pertinent lines of code can readily be adapted to the cleaned up dynamically compiled C# code that JT contributed in an earlier post in this thread.

For testing with PowerShell, the code above was written assuming that the files were in the same location as the .ps1 script file itself.  Please note that the paths must be converted to "file://" URI format where all back slashes in the path are converted to forward slashes.  The image files I used are quite small, but are apparently too large to attach here.
Title: Re: How to generate a Windows 10 desktop notification
Post by: JTaylor on June 08, 2021, 07:12:03 PM
Just out of curiosity...did you do something different than what I did with images?   You mentioned adapting it to what I posted so was curious as what I posted handled images along with other features.   Want to make sure I don't miss something interesting.

Jim

Quote from: ChuckC on June 08, 2021, 01:33:44 PM
I got things working with PowerShell generating toast notifications which contain images.



The pertinent lines of code can readily be adapted to the cleaned up dynamically compiled C# code that JT contributed in an earlier post in this thread.

For testing with PowerShell, the code above was written assuming that the files were in the same location as the .ps1 script file itself.  Please note that the paths must be converted to "file://" URI format where all back slashes in the path are converted to forward slashes.  The image files I used are quite small, but are apparently too large to attach here.
Title: Re: How to generate a Windows 10 desktop notification
Post by: stanl on June 09, 2021, 02:49:33 AM
Quote from: kdmoyers on June 08, 2021, 12:54:32 PM

Stan,
Just want to be sure I'm getting the same version you got. 
(The file I see on Hippo is dated march of 2012, not 2021.)

is it version 2.0.9.1 ?  with the file Gowl_v2.0.msi shows a CRC-32 of 5143A96A?

Thanks!!
-Kirby


I think 2012 was when it was first added to Hippo, but you probably got the latest release [still 2.09].

Title: Re: How to generate a Windows 10 desktop notification
Post by: ChuckC on June 09, 2021, 08:15:37 AM
Quote from: JTaylor on June 08, 2021, 07:12:03 PM
Just out of curiosity...did you do something different than what I did with images?


Ignore my post.  I was busily pasting in portions of code from different scripts and writing up the rest of the posting and then realized that I needed to go back and modify some of the sample PowerShell code to make use of an alternate method of utilizing Toast Notifications that may well eliminate the need for dynamically compiled C# code.  I meant to discard the incomplete posting... instead I clicked thru the post button in my haste to go pursue a "shiny thing".

The alternate method of using Toast Notifications involves directly composing the underlying XML that is sent to the listener that receives & displays the notifications.  It also allows proper population of XML elements that make it more readily possible to invoke a script as an action.  I was already doing some of that in PowerShell, but realized the respond-to-notification-being-clicked functionality won't port to WinBatch in a way that allows the script instance that generated the toast notification to get called back.  However, the fallback mechanism will allow a script to be invoked, with parameters, even though it won't be the exact same instance of the script that generated the toast notification.
Title: Re: How to generate a Windows 10 desktop notification
Post by: JTaylor on June 09, 2021, 08:39:33 AM
Okay.

The button-click/script call was something I was going to investigate more along with the XML.  Didn't see an immediate way to do that via WinBatch but intended to follow up.

Jim