Automate Logos (Notes) with Powershell

Pieter J.
Pieter J. Member Posts: 533 ✭✭
edited November 2024 in English Forum

Note Automation

Creating Notes from a Template could be useful in some situations. I created this powershell solution to do just that. I tried to keep the implementation as simple as possible.

  1. Download and extract all files in AutoNotes.zip file to one directory
  2. Drag the "Sample Template.vbs" into Logos to create a Button on the ToolBar
  3. Create an empty Note Document
  4. Make sure the Active Panel is the Note you created
  5. Click the Button you created
  6. It will create 7 Notes from the Template

This is what the sample script will generate:

Your own Template

To create your own template:

  1. Make a copy of "Template1.ps1" and save it with any name
  2. Edit the content of the new file
  3. Make a copy of "Sample Template.vbs" and save with a new name
  4. Change the "tmp" variable to point to the copy of "Template1.ps1" file you modified
  5. Drag and drop the vbscript file to create a button in Logos
  6. Create an empty Note Document
  7. Make sure it's the Active Panel
  8. Click the Button you created

System

  • Win 10
  • Powershell  5 (10586)
  • Logos Bible Software 6.8 (6.8.0.0049)

Notes

I used Keyboard shortcuts to Toggle Bold, so please do not do anything until the template is complete. I'm investigating to use TogglePattern.Pattern.Invoke on all buttons in the Notes Panel.

The syntax for Template creation is in the "Template1.ps1" file.

Enjoy - and please inform me of any bugs

Comments

  • MJ. Smith
    MJ. Smith MVP Posts: 54,750

    Excellent!

    Orthodox Bishop Alfeyev: "To be a theologian means to have experience of a personal encounter with God through prayer and worship."; Orthodox proverb: "We know where the Church is, we do not know where it is not."

  • Pieter J.
    Pieter J. Member Posts: 533 ✭✭

    Does anyone know how to add EventHandlers for LogosComApi in Powershell? I know I'm missing something: $this.ComApplication holds the Launcher.Application object.

    Register-ObjectEvent -InputObject $this.ComApplication -EventName PanelActivated -Action {
            Out-Host "<PanelActivated>"
            }

    I want to improve the Note script to do much more. Behind the scenes of the sample script is much more power (I'll add the complete version later). You can automate almost anything like with AutoIt, just a lot easier, right in PowerShell.

    Sample:

    $Logos = [Logos]::new()

    With ($Logos.Home){

     .Show($)

     .Customize.Show().Select("Start Prayer List")

    }


    With ($Logos.CommandBox){

     .SetText("Close All")
     .Execute($)

    }

    $Logos.Search.Invoke()

    $Logos.Panels.Select(0)

    With ($Logos.Panels.Automation){

     .SearchBasic($)

     .SearchText("Paul")

     .Search($)

    }

    The idea is to make use of PowerShell as an easy MacroEditor. Here is a preview of the MacroEngine.

    NB: The Withblock is a custom function, always pass a ($) and not empty brackets (), otherwise the script will crash.

    8182.MacroEngine.zip

  • Beloved Amodeo
    Beloved Amodeo Member Posts: 4,200 ✭✭✭

    Meanwhile, Jesus kept on growing wiser and more mature, and in favor with God and his fellow man.

    International Standard Version. (2011). (Lk 2:52). Yorba Linda, CA: ISV Foundation.

    MacBook Pro MacOS Sequoia 15.3 1TB SSD

  • Pieter J.
    Pieter J. Member Posts: 533 ✭✭

    Does it block the download or the script from execution?

  • Beloved Amodeo
    Beloved Amodeo Member Posts: 4,200 ✭✭✭

    Meanwhile, Jesus kept on growing wiser and more mature, and in favor with God and his fellow man.

    International Standard Version. (2011). (Lk 2:52). Yorba Linda, CA: ISV Foundation.

    MacBook Pro MacOS Sequoia 15.3 1TB SSD

  • Pieter J.
    Pieter J. Member Posts: 533 ✭✭

    AutoNotes.Zip

    AutoNotes.ps1

    #Logos Bible Software Note Automation
    #Created : Des 2015
    #Developer: PJ Kotze

    $AssemblyPath = "$env:programfiles\Reference Assemblies\Microsoft\Framework\v3.0"
    [void][System.Reflection.Assembly]::LoadWithPartialName("UIAutomationClient")
    [void][System.Reflection.Assembly]::LoadWithPartialName("UIAutomationTypes")
    add-type -AssemblyName System.Windows.Forms
    [Reflection.Assembly]::LoadWithPartialName("System.Drawing") | Out-Null
    $DebugViewWindow_TypeDef = @'
    [DllImport("user32.dll")]
    public static extern IntPtr FindWindow(string ClassName, string Title);
    [DllImport("user32.dll")]
    public static extern IntPtr GetForegroundWindow();
    [DllImport("user32.dll")]
    public static extern bool SetCursorPos(int X, int Y);
    [DllImport("user32.dll")]
    public static extern bool GetCursorPos(out System.Drawing.Point pt);
     
    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
    public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);
     
    private const int MOUSEEVENTF_LEFTDOWN = 0x02;
    private const int MOUSEEVENTF_LEFTUP = 0x04;
    private const int MOUSEEVENTF_RIGHTDOWN = 0x08;
    private const int MOUSEEVENTF_RIGHTUP = 0x10;
     
    public static void LeftClick(){
        mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);

    }
     
    public static void RightClick(){
        mouse_event(MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
    }

    Add-Type -MemberDefinition $DebugViewWindow_TypeDef -Namespace AutoClicker -Name Temp -ReferencedAssemblies System.Drawing

    #=========================================
    # FUNCTIONS
    #=========================================

    Function GetLogosWindow
    {
       
        #Get Logos Window
            $AppCon = New-Object Windows.Automation.PropertyCondition([Windows.Automation.AutomationElement]::NameProperty, "Logos Bible Software")
            $ClassCon = New-Object Windows.Automation.PropertyCondition([Windows.Automation.AutomationElement]::ClassNameProperty, "Window")
            $AndCon = New-Object Windows.Automation.AndCondition($AppCon, $ClassCon)

            return [Windows.Automation.AutomationElement]$Desktop.FindFirst([Windows.Automation.TreeScope]::Descendants, $AndCon) 
         
       
    }
    Function GetNotePanel($Title){
        $TabCon = New-Object Windows.Automation.PropertyCondition([Windows.Automation.AutomationElement]::NameProperty, $Title)
        $ClassCon = New-Object Windows.Automation.PropertyCondition([Windows.Automation.AutomationElement]::ClassNameProperty, "TabItem")
        $AndCon = New-Object Windows.Automation.AndCondition($TabCon, $ClassCon)
        return [Windows.Automation.AutomationElement]$Logos.FindFirst([Windows.Automation.TreeScope]::Descendants, $AndCon)
    }
    Function GetDesktopWindow
    {
        return [Windows.Automation.AutomationElement]::RootElement
    }
    Function GetAddNote
    {
        $con = New-Object Windows.Automation.PropertyCondition([Windows.Automation.AutomationElement]::NameProperty, "Add note")
        $btn = [Windows.Automation.AutomationElement]$Notes.FindFirst([Windows.Automation.TreeScope]::Descendants, $con)
        return 

  • Pieter J.
    Pieter J. Member Posts: 533 ✭✭

    This is the original file as in the zip. I did learn a lot about powershell by writing this code so there is an improved version available later if anyone should be interested to use or maybe improve on the idea.

    MacroEngine.ps1

    #region "References"
    #MACROENGINE
    #PJ KOTZE
    #2015
    $AssemblyPath = "$env:programfiles\Reference Assemblies\Microsoft\Framework\v3.0"
    [void][System.Reflection.Assembly]::LoadWithPartialName("UIAutomationClient")
    [void][System.Reflection.Assembly]::LoadWithPartialName("UIAutomationTypes")
    add-type -AssemblyName System.Windows.Forms
    [Reflection.Assembly]::LoadWithPartialName("System.Drawing") | Out-Null
    $DebugViewWindow_TypeDef = @'
    [DllImport("user32.dll")]
    public static extern IntPtr FindWindow(string ClassName, string Title);
    [DllImport("user32.dll")]
    public static extern IntPtr GetForegroundWindow();
    [DllImport("user32.dll")]
    public static extern bool SetCursorPos(int X, int Y);
    [DllImport("user32.dll")]
    public static extern bool GetCursorPos(out System.Drawing.Point pt);
     
    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
    public static extern void mouse_event(long dwFlags, long dx, long dy, long cButtons, long dwExtraInfo);
     
    private const int MOUSEEVENTF_LEFTDOWN = 0x02;
    private const int MOUSEEVENTF_LEFTUP = 0x04;
    private const int MOUSEEVENTF_RIGHTDOWN = 0x08;
    private const int MOUSEEVENTF_RIGHTUP = 0x10;
     
    public static void LeftClick(){
        mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);

    }
     
    public static void RightClick(){
        mouse_event(MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_RIGHTUP, 0, 0, 0, 0);
    }

    Add-Type -MemberDefinition $DebugViewWindow_TypeDef -Namespace AutoClicker -Name Temp -ReferencedAssemblies System.Drawing
    #endregion

    #region "Application"
    [Windows.Automation.AutomationElement]$Global:AutomationElement
    [int32]$WaitDefault
    #region "Functions
        Function Click-Element($elem){
                $cpt = $elem.GetClickablePoint()           
            
                [System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point(($cpt.X), ($cpt.Y))
                [AutoClicker.Temp]::LeftClick()
        }
        Function Get-Element($className, $Property, $propertyValue,$parent){
                try
                {

                $NameCon = New-Object Windows.Automation.PropertyCondition($Property, $propertyValue)
                $ClassCon = New-Object Windows.Automation.PropertyCondition([Windows.Automation.AutomationElement]::ClassNameProperty, $className)
                $AndCon = New-Object Windows.Automation.AndCondition($NameCon, $ClassCon)
                $EnabledCon = New-Object Windows.Automation.PropertyCondition([Windows.Automation.AutomationElement]::IsEnabledProperty, $True)
                $AndCon = New-Object Windows.Automation.AndCondition($EnabledCon, $AndCon)

                return [Windows.Automation.AutomationElement]$parent.FindFirst([Windows.Automation.TreeScope]::Descendants, $AndCon)
                } catch {
                    return $null
                }
            }
        Function Set-Text($txtBox,$text){
                $pattern

  • Pieter J.
    Pieter J. Member Posts: 533 ✭✭

    Line 130-132 in the above code should be commented. It will generate an error because I did no error handling.

    Or set:  $ErrorActionPreference = "silentlycontinue"

  • Beloved Amodeo
    Beloved Amodeo Member Posts: 4,200 ✭✭✭

    AutoNotes.ps1

    #Logos Bible Software Note Automation
    #Created : Des 2015
    #Developer: PJ Kotze

    Thanks Pieter for your reply.

    But, what do I do with this code? Do I copy and paste into Notepad?

    Meanwhile, Jesus kept on growing wiser and more mature, and in favor with God and his fellow man.

    International Standard Version. (2011). (Lk 2:52). Yorba Linda, CA: ISV Foundation.

    MacBook Pro MacOS Sequoia 15.3 1TB SSD

  • Pieter J.
    Pieter J. Member Posts: 533 ✭✭

    Yes you can. Copy each and save it with the filename provided above the block of code. Just make sure when you "save as" to select "All Files (*.*)" as "Save as type:". Save all files into one directory. Then follow the instructions in the first post.

    If you never used powershell you will propably run into a nasty error in red stating that the code can't run. You will need to set the execution policy. Start Powershell as Administrator then type the policy you want into the console and press enter.

    Policy:

    • Restricted: Default execution policy, does not run scripts, interactive commands only.
    • All Signed: Runs scripts; all scripts and configuration files must be signed by a publisher that you trust; opens you to the risk of running signed (but malicious) scripts, after confirming that you trust the publisher.
    • Remote Signed: Local scripts run without signature. Any downloaded scripts need a digital signature, even a UNC path.
    • Unrestricted:Runs scripts; all scripts and configuration files downloaded from communication applications such as Microsoft Outlook, Internet Explorer, Outlook Express and Windows Messenger run after confirming that you understand the file originated from the Internet; no digital signature is required; opens you to the risk of running unsigned, malicious scripts downloaded from these applications

    Set-ExecutionPolicy [PolicyName]

    example: Set-ExecutionPolicy Unrestricted

  • Pieter J.
    Pieter J. Member Posts: 533 ✭✭

    See Creating Note Templates for other existing solutions and a AutoHotKey Solution. (Do not use this script before you moved/backup Note Files in Documents\Libronix DLS\Annotations folder)

    54