Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - Quin

Pages: [1] 2 3 ... 9
1
Awesome 👍

2
Tips & Tricks / Re: Read Registry One-liner
« on: Today at 09:46:41 AM »
I am impressed with BCX!
Me too! Wait until you see how it can call COM! :)

3
I feel like every time I show up here I end up with at least one of these, haha.
This code works flawlessly on Windows 11, but on Windows 10, the menu always stays active if I click on settings and the dialog doesn't show up, and if I click exit the application crashes.
Code: [Select]
#include <shellapi.h>

Gui "BatteryMeterWndClass"

Const ID_TrayIcon = 101

Enum
    ID_TrayCallback = WM_USER + 1
    IDT_CheckBattery
    ID_MenuSettings
    ID_MenuExit
    ID_IntervalLabel
    ID_IntervalField
    ID_RunAtStartupBox
End Enum

Global Note As NOTIFYICONDATA
Global MainForm As HWND
Global ReportInterval = 10
Global RunAtStartup As Bool
Global Voice As Object

Sub Formload
    MakeSingleInstance("BatteryMeter")
    MainForm = Bcx_Form("BatteryMeter", 0, 0, 150, 100)
    With Note
        .cbSize = Sizeof(Note)
        .hWnd = MainForm
        .uID = ID_TrayIcon
        .uFlags |= NIF_MESSAGE | NIF_TIP
        .uCallbackMessage = ID_TrayCallback
        lstrcpy(.szTip, TEXT("Battery Meter"))
    End With
    Shell_NotifyIcon(NIM_ADD, &Note)
    Voice = Com("SAPI.SpVoice")
    Dim Power As SYSTEM_POWER_STATUS
    GetSystemPowerStatus(&Power)
    ' Currently commented out to allow for testing of code on desktop computer
    ' If Power.BatteryFlag = 128 Then ' No system battery
    ' Voice.Speak "This computer does not appear to have a battery. Exiting..."
    ' Uncom(Voice)
    ' Shell_NotifyIcon(NIM_DELETE, &Note)
    ' End
    ' End If
    If Exist(Curdir$ & "\\BatteryMeter.ini") Then
        ReportInterval = GetPrivateProfileInt("Settings", "Interval", 10, Curdir$ & "\\BatteryMeter.ini")
        RunAtStartup = GetPrivateProfileInt("Settings", "RunAtStartup", False, Curdir$ & "\\BatteryMeter.ini")
        Dim LinkPath$, AppPath$
        LinkPath$ = StartupFolder$() & "BatteryMeter.lnk"
        AppPath$ = Appexepath$ & Appexename$
        If RunAtStartup Then
            CreateLink(AppPath$, LinkPath$, "", "Battery Meter")
        Else
            If Exist(LinkPath$) Then
                Kill LinkPath$
            End If
        End If
    End If
    Beep(440, 100)
    Voice.Speak "Running"
    SetTimer(MainForm, IDT_CheckBattery, 100, NULL)
End Sub

Begin Events
    Select Case Cbmsg
        Case WM_DESTROY, WM_QUIT, WM_CLOSE
        Uncom(Voice)
        Shell_NotifyIcon(NIM_DELETE, &Note)
        End
        Exit Function
        Case ID_TrayCallback Then
        If Cblparam = WM_LBUTTONDOWN Then
            PostMessage(hWnd, WM_QUIT, 0, 0)
            Exit Function
        Else If Cblparam = WM_RBUTTONDOWN Then
            Dim Menu As HMENU
            Menu = CreatePopupMenu()
            InsertMenu(Menu, -1, MF_BYPOSITION | MF_STRING, ID_MenuSettings, "&Settings")
            InsertMenu(Menu, -1, MF_BYPOSITION | MF_STRING, ID_MenuExit, "E&xit")
            Dim pt As POINT
            Hide (MainForm)
            GetCursorPos(&pt)
            SetForegroundWindow(hWnd)
            TrackPopupMenuEx (Menu, TPM_LEFTALIGN Or TPM_RIGHTBUTTON, pt.x, pt.y, hWnd, NULL)
            PostMessage(hWnd, WM_NULL, 0, 0)
        End If
        Case WM_TIMER Then
        Call CheckBattery
        Case WM_COMMAND
        Select Case Cbctl
            Case ID_MenuExit
            If IsObject(Voice) Then Uncom(Voice)
            PostMessage(hWnd, WM_QUIT, 0, 0)
            Exit Function
            Case ID_MenuSettings
            Bcx_Dialog(SettingsDlgProc, "Settings", MainForm, 0, 0, 300, 150)
            Exit Function
        End Select
    End Select
End Events

Begin Dialog As SettingsDlgProc
    Static As HWND IntervalLabel, IntervalField, RunAtStartupBox, SaveBtn, CancelBtn
    Select Case Cbmsg
        Case WM_INITDIALOG
        IntervalLabel = Bcx_Label("&Interval to report battery percentage in", hWnd, ID_IntervalLabel, 5, 5, 30, 5)
        IntervalField = Bcx_Input(Str$(ReportInterval, 1), hWnd, ID_IntervalField, 5, 15, 50, 20)
        RunAtStartupBox = Bcx_Checkbox("&Run at startup", hWnd, ID_RunAtStartupBox, 100, 5, 20, 20)
        SaveBtn = Bcx_Button("&OK", hWnd, IDOK, 100, 10, 30, 30)
        CancelBtn = Bcx_Button("&Cancel", hWnd, IDCANCEL, 100, 50, 30, 30)
        Show(hWnd)
        SetFocus(IntervalField)
        Case WM_COMMAND
        Select Case Cbctl
            Case IDCANCEL
            Closedialog
            Case IDOK
            ReportInterval = Val(Bcx_Get_Text$(IntervalField))
            WritePrivateProfileString("Settings", "Interval", Str$(ReportInterval, 1), Curdir$ & "\\BatteryMeter.ini")
            Closedialog
        End Select
    End Select
End Dialog

Sub CheckBattery
    Static LastReported = 0
    Dim Percentage
    Dim Power As SYSTEM_POWER_STATUS
    GetSystemPowerStatus(&Power)
    Percentage = Power.BatteryLifePercent
    If Percentage % ReportInterval = 0 And LastReported <> Percentage Then
        Dim Frequency = 260 + ((Percentage - 10) / (100 - 10)) * (440 - 260)
        Beep(Frequency, 700)
        Dim ToSpeak As String
        If Percentage = 100 Then
            ToSpeak$ = "Battery is full"
        Else
            ToSpeak$ = "Battery " & Str$(Percentage, 1) & "%"
        End If
        Voice.Speak ToSpeak$
        LastReported = Percentage
    End If
End Sub

Sub MakeSingleInstance(AppID As String)
    Local As HANDLE hMutex
    hMutex = OpenMutex(MUTEX_ALL_ACCESS, 0, AppID + "_IsAlreadyRunning")
    If Not hMutex Then
        hMutex = CreateMutex(0, 0, AppID + "_IsAlreadyRunning")
    Else
        Msgbox "Another instance of " & AppID & " is already running.", "Error", MB_ICONERROR
        End
    End If
End Sub

Function StartupFolder$()
    Local Res$, WShell As Object
    Comset WShell = CreateObject("Wscript.Shell")
    Res$ = WShell.SpecialFolders("Startup") & "\\"
    Comset WShell = Nothing
    Return Res$
End Function

Function CreateLink(Exe$, Link$, Args$, Desc$) As HRESULT
    Local Res As HRESULT
    Local PSL As IShellLink Ptr
    Dim PPF As IPersistFile Ptr
    Local W[MAX_PATH] As WORD
    CoInitialize(NULL)
    $Ifdef __cplusplus
        Res = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&PSL)
    $Else
        Res = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (LPVOID*)&PSL)
    $Endif
    If SUCCEEDED(Res) Then
        PSL->lpVtbl->SetPath(PSL, Exe$)
        PSL->lpVtbl->SetDescription(PSL, Desc$)
        PSL->lpVtbl->SetShowCmd(PSL, SW_SHOWNORMAL)
        PSL->lpVtbl->SetArguments(PSL, Args$)
        $Ifdef __cplusplus
            Res = PSL->lpVtbl->QueryInterface(PSL, IID_IPersistFile, (LPVOID*)&PPF)
        $Else
            Res = PSL->lpVtbl->QueryInterface(PSL, &IID_IPersistFile, (LPVOID*)&PPF)
        $Endif
        If SUCCEEDED(Res) Then
            MultiByteToWideChar(CP_ACP, 0, Link$, -1, (LPWSTR)W, MAX_PATH)
            Res = PPF->lpVtbl->Save(PPF, (LPCOLESTR)W, True)
            PPF->lpVtbl->Release(PPF)
        End If
        PSL->lpVtbl->Release(PSL)
    End If
    CoUninitialize()
    Return Res
End Function

4
Announcements / Re: BCX Editor (BED) 3.67 available for download
« on: January 10, 2025, 06:23:03 PM »
Very cool, thanks MrBCX!
More fun C compiler stuff to tinker with! Woot!

5
Hi, Quin.

I tried this:
Code: [Select]
For I = 0 To NumSelections - 1
    Dim CurIndex
    CurIndex = Val(ToHide[I])
    If CurIndex <= 0 Or CurIndex > NumUpdates Then Continue
    Comset Update = Updates.Item(CurIndex - 1)
    If IsObject(Update) Then
        Dim Title$
        Title$ = Update.Title
        Update.IsHidden = True
        Print "Hid " & Title$
        Uncom(Update)
    End If
Next

And it successfully executed with no issue.  I ran the resulting binary as Admin (I didn't include the .res file that configures the .exe for elevation, for testing purposes).

AIR.

Edit:  Compiled with the UAC res file, no apparent issues.  Ran it through WinDBG, no crashes.
Hi Airr,
Sorry for leaving you on read for so long, life got crazy there for a few months, you know how it is.
Unfortunately I and another friend still can make this program show the standard "_ has stopped working dialog". You have to actually hide an update to get it to happen, but it still does.
I might've given the instructions earlier in this thread, but to do that, make a new DWORD at hklm\software\microsoft\windows\windows error reporting\DontShowUI, keep it at 0, then try. No reboots needed.
Here's the full code in case I missed another modification.
Code: [Select]
#include <wuapi.h>

BCX_Show_COM_Errors(True)

Dim As Object Session, Searcher, SearchResult, Update, Updates
Dim NumUpdates, I
Comset Session = Com("Microsoft.Update.Session")
Comset Searcher = Session.CreateupdateSearcher()
Searcher.ClientApplicationID = "uphide"
Print "Checking for updates..."
Comset SearchResult = Searcher.Search("IsInstalled=0 And IsHidden=0")
NumUpdates = SearchResult.Updates.Count
If NumUpdates = 0 Then
    Print "No updates were found."
    Uncom(SearchResult)
    Uncom(Searcher)
    Uncom(Session)
    End
End If
Print "Enter the numbers of the updates you want to hide, seperated by spaces, and press enter. Leave blank to exit."
Dim Index = 1
Comset Updates = SearchResult.Updates
For Each Item In Updates
    Dim Title$
    Title$ = Item.Title
    Print Str$(Index, 1) & ": " & Title$
    Index++
Next
Dim Input$
Input Input$
If Input$ = "" Then
    Uncom(Updates)
    Uncom(SearchResult)
    Uncom(Searcher)
    Uncom(Session)
    End
End If
Dim NumSelections
Dim ToHide[100] As String
NumSelections = Split(ToHide, Input$, " ", 0)
For I = 0 To NumSelections - 1
    Dim CurIndex
    CurIndex = Val(ToHide[I])
    If CurIndex <= 0 Or CurIndex > NumUpdates Then Continue
    Comset Update = Updates.Item(CurIndex - 1)
    If IsObject(Update) Then
        Dim Title$
        Title$ = Update.Title
        Update.IsHidden = True
        Print "Hid " & Title$
        Uncom(Update)
    End If
Next
Pause
Uncom(Updates)
Uncom(SearchResult)
Uncom(Searcher)
Uncom(Session)
Thanks as always for all your help!

6
I don't know if a change in name would necessarily help this as much as more word being spread about the language. I saw one PowerBasic developer, Chris Boss, talking about porting Ezgui, his powerful PowerBasic library, to BCX. I never was a PowerBasic user myself, but it seems fairly close to BCX in terms of syntax, unlike PureBasic. While it's a great language it's not like conventional basic, e.g. variables use . instead of as for types, etc etc.
BCX definitely deserves a larger community though, it's an absolutely delightful tool!

7
Announcements / Re: BCX Documentation Version 8.2.0, December 27, 2024
« on: January 10, 2025, 04:35:20 PM »
Thanks for the great work as always Robert! :)

8
Announcements / Re: BCX v8.2.0 is available for download
« on: January 10, 2025, 04:34:39 PM »
Coming back to BCX after a bit of a break, thanks as always MrBCX! Every time I stop coding for a bit and come back, I always see you doing great work :)

9
Questions & Answers / Embedding data files inside a BCX executable
« on: December 08, 2024, 05:12:32 AM »
Hi,
In my app, I have multiple data files that get read and parsed on application start. They're all in a particular subfolder, but when I ship this application I don't want users to be able to tamper with them. Is there a way for me to embed them inside my executable and read them at runtime, maybe in the .data section?
Thanks,
Quin.

10
Kevin,
Yes, I've tried it in powershell, and it works perfectly fine. Just to be clear, it works perfectly fine here, too, the updates get hidden and don't show up again, but it's crashing somewhere after hiding all of them on exit.

11
I completely expected this to fix it, but it actually didn't, bafflingly enough. All I did was move the Uncom(Update) line to right after the Update.IsHidden = True line, and I fixed the case on that line too. The same crash occurs, only after successfully hiding at least one update.

12
Robert,
Thanks for all your help! Unfortunately though, that doesn't seem to have fixed it. If I don't type anything and let those uncom statements run there's no crash, it's only after I've successfully hidden at least one update that it crashes.
Latest code for reference:
Code: [Select]
#include <wuapi.h>

BCX_Show_COM_Errors(True)

Dim As Object Session, Searcher, SearchResult, Update, Updates
Dim NumUpdates, I
Comset Session = Com("Microsoft.Update.Session")
Comset Searcher = Session.CreateupdateSearcher()
Searcher.ClientApplicationID = "uphide"
Print "Checking for updates..."
Comset SearchResult = Searcher.Search("IsInstalled=0 And IsHidden=0")
NumUpdates = SearchResult.Updates.Count
If NumUpdates = 0 Then
    Print "No updates were found."
    Uncom(SearchResult)
    Uncom(Searcher)
    Uncom(Session)
    End
End If
Print "Enter the numbers of the updates you want to hide, seperated by spaces, and press enter. Leave blank to exit."
Dim Index = 1
Comset Updates = SearchResult.Updates
For Each Item In Updates
    Dim Title$
    Title$ = Item.Title
    Print Str$(Index, 1) & ": " & Title$
    Index++
Next
Dim Input$
Input Input$
If Input$ = "" Then
    Uncom(Updates)
    Uncom(SearchResult)
    Uncom(Searcher)
    Uncom(Session)
    End
End If
Dim NumSelections
Dim ToHide[100] As String
NumSelections = Split(ToHide, Input$, " ", 0)
For I = 0 To NumSelections - 1
    Dim CurIndex
    CurIndex = Val(ToHide[I])
    If CurIndex <= 0 Or CurIndex > NumUpdates Then Continue
    Comset Update = Updates.Item(CurIndex - 1)
    Dim Title$
    Title$ = Update.Title
    Update.Ishidden = True
    Print "Hid " & Title$
Next
Pause
Uncom(Update)
Uncom(Updates)
Uncom(SearchResult)
Uncom(Searcher)
Uncom(Session)
Did I miss something?'Thanks,
Quin.

13
Announcements / Re: BCX Documentation Version 8.1.7, October 6, 2024
« on: October 18, 2024, 07:55:21 AM »
Thanks, Robert.

For the Windows Update COM example, Quin was the one who kicked that all off, just want to make sure they are recognized for that.... :D

AIR.
Oh that's neat, my days of sifting through Microsoft docs paid off in more ways than just an application. :)

Hi Quin:

I apologize for not posting an acknowledgment for your contribution to the BCX Documentation Version 8.1.7 example showing how to call the Windows Update using COM.

I will revise the list of acknowledgments to credit you and Armando, both, for the creation of that example.

Thank you.
Hi Robert,
Thanks a ton, it's appreciated! :)

14
Airr,
I can confirm that this did in fact fix the crash in the battery utility. Thanks for all your help!
I'll do more testing with that update utility and see what I can find.

15
The Voice Object is already a global.

Going back to your original code, I tried this:

Code: [Select]
        Case ID_MenuExit
            If IsObject(Voice) Then UNCOM(Voice)
            PostMessage(hWnd, WM_QUIT, 0, 0)
            Exit Function

And the crashing went away...

AIR.
Very interesting! I have utterly no idea why that would be, but thanks for your help! I wonder if the same thing would apply to the update hiding utility?
Unfortunately, long-covid currently has me firmly in its grasps and so probably no coding for the next couple days :( once I'm back in the game though this looks quite promising.
Thanks again for all your help!

Pages: [1] 2 3 ... 9