Liberty BASIC Community Forum
« Liberty BASIC File Association manager »

Welcome Guest. Please Login or Register.
Dec 14th, 2017, 6:38pm


Rules|Home|Help|Search|Recent Posts|Notification


« Previous Topic | Next Topic »
Pages: 1 2  Notify Send Topic Print
 hotthread  Author  Topic: Liberty BASIC File Association manager  (Read 508 times)
Chris Iverson
Administrator
ImageImageImageImageImage


member is offline

Avatar

20% Cooler


Homepage PM

Gender: Male
Posts: 2289
xx Liberty BASIC File Association manager
« Thread started on: Jan 12th, 2016, 9:43pm »

Here we go, version 1 of a .bas file association manager.

Took this long because I was thinking backwards, and implementing all of the complex features, such as auto-locating LB installs, before I actually had a working base program.

Here's the working base program, so far.

I've tested it on my own Windows 10 PC, switching between LB 4.04, LB 4.5, LB Pro v4.04, Just BASIC v1.01, and Notepad(the last two just for kicks).

The way it works is, after locating an executable you want to use, it creates a new association identifier(LibertyBASIC.BasFile), sets the .bas handler to use that identifier, and sets the chosen path in that identifier.

If it's unable to set that identifier for some reason, it restores the .bas handler to what it was.

The first time you use this to switch associations, the next time you open a .bas file, you may get a prompt from Windows asking you to confirm the new association.

Code:
'Form created with the help of Freeform 3 v07-15-08
'Generated on Jan 12, 2016 at 21:03:30


[setup.m.Window]

    '-----Begin code for #m

    call InitRegistry
    nomainwin
    WindowWidth = 520
    WindowHeight = 220
    UpperLeftX=int((DisplayWidth-WindowWidth)/2)
    UpperLeftY=int((DisplayHeight-WindowHeight)/2)


    '-----Begin GUI objects code

    button #m.btnFindExe,"Locate LB executable",[findEXE], UL, 170,  22, 140,  25
    TextboxColor$ = "white"
    textbox #m.tbExePath,  40,  82, 415,  25
    button #m.btnSetAssociation,"Set Association",[setAssociation], UL, 190, 137, 103,  25

    '-----End GUI objects code

    open "Set BAS file association" for window as #m
    print #m, "font ms_sans_serif 10"
    print #m, "trapclose [quit.m]"
    #m.btnSetAssociation, "!disable"


[m.inputLoop]   'wait here for input event
    wait



[findEXE]   'Perform action for the button named 'btnFindExe'

    'Insert your own code here

    filedialog "Locate LB exe...", "*.exe", LBPath$
    if LBPath$ = "" then
        #m.tbExePath, "<no EXE file selected>"
        #m.btnSetAssociation, "!disable"
    else
        #m.btnSetAssociation, "!enable"
    end if

    #m.tbExePath, LBPath$

    wait


[setAssociation]   'Perform action for the button named 'btnSetAssociation'

    'Insert your own code here
    assocPath$ = chr$(34) + LBPath$ + chr$(34) + " " + chr$(34) + "%1" + chr$(34)
    a = RegCreateKeyEx(_HKEY_CURRENT_USER, "Software\Classes\.bas", 0, _KEY_ALL_ACCESS, hBas)
    If a <> 0 then
        errMsg$ = "Registry error" + chr$(13) + "Unable to open HKCU\Software\Classes\.bas for writing."
        errMsg$ = errMsg$ + chr$(13) + chr$(13) + "RegCreateKeyEx() returned ";a
        notice errMsg$
        wait
    end if

    bufSize = 0
[bufferLoop]
    buf$ = space$(bufSize)

    a = RegQueryValueEx(hBas, "", buf$, bufSize)
    if a = ERROR.MORE.DATA then [bufferLoop]

    if a <> 0 then
        errMsg$ = "Registry error" + chr$(13) + "Unable to get current BAS association."
        errMsg$ = errMsg$ + chr$(13) + chr$(13) + "RegQueryValueEx() returned ";a
        notice errMsg$
        a = RegCloseKey(hBas)
        wait
    end if

    originalBasAssocation$ = trim$(buf$)

    a = RegSetValueEx(hBas, "", "LibertyBASIC.BasFile")
    If a <> 0 then
        errMsg$ = "Registry error" + chr$(13) + _
            "Unable to write new association identifier to HKCU\Software\Classes\.bas\(default)."
        errMsg$ = errMsg$ + chr$(13) + chr$(13) + "RegSetValueEx() returned ";a
        notice errMsg$
        a = RegCloseKey(hBas)
        wait
    End If

    a = RegCreateKeyEx(_HKEY_CURRENT_USER, "Software\Classes\LibertyBASIC.BasFile\shell\open\command",_
        0, _KEY_ALL_ACCESS, hCommand)

    If a <> 0 then
        errMsg$ = "Registry error" + chr$(13) + _
            "Unable to open HKCU\Software\Classes\LibertyBASIC.BasFile\shell\open\command for writing."
        errMsg$ = errMsg$ + chr$(13) + chr$(13) + "RegCreateKeyEx() returned ";a
        notice errMsg$

        'Restore the original BAS association
        a = RegSetValueEx(hBas, "", originalBasAssociation$)
        a = RegCloseKey(hBas)
        wait
    end if

    a = RegSetValueEx(hCommand, "", assocPath$)
    If a <> 0 then
        errMsg$ = "Registry error" + chr$(13) + _
            "Unable to write new association to HKCU\Software\Classes\LibertyBASIC.BasFile\shell\open\command\(default)"
        errMsg$ = errMsg$ + chr$(13) + chr$(13) + "RegSetValueEx() returned ";a
        notice errMsg$

        'Restore the original BAS association
        a = RegSetValueEx(hBas, "", originalBasAssociation$)
        a = RegCloseKey(hCommand)
        a = RegCloseKey(hBas)
        wait
    end if

    Call SHNotifyAssocChange

    a = RegCloseKey(hCommand)
    a = RegCloseKey(hBas)

    Notice "New association set!"
    wait

[quit.m] 'End the program
    call EndRegistry
    close #m
    end


'===============================================
'          SUBS/FUNCTIONS BELOW
'===============================================

Sub SHNotifyAssocChange
    SHCNE.ASSOCCHANGED = hexdec("08000000")
    SHCNF.IDLIST = 0

    CallDLL #shell32, "SHChangeNotify",_
    SHCNE.ASSOCCHANGED as long,_
    SHCNF.IDLIST as long,_
    0 as long,_
    0 as long,_
    ret as void
End Sub

Sub InitRegistry
    Open "advapi32" for DLL as #advapi32
    Global ERROR.MORE.DATA : ERROR.MORE.DATA = 234
End Sub

Sub EndRegistry
    close #advapi32
End Sub

Function RegCreateKeyEx(hKey, subKey$, dwOptions, samDesired, byref phkResult)
    struct res, a as ulong

    CallDLL #advapi32, "RegCreateKeyExA",_
    hKey as ulong,_
    subKey$ as ptr,_
    0 as long,_             'Reserved, must be 0.
    0 as ulong,_            'User-defined class type of key.
    _                       'Very unlikely to be used, so 0.
    dwOptions as long,_
    samDesired as long,_
    0 as ulong,_            'lpSecurityAttributes, used for setting permissions on
    _                       'the key, among other things. Unlikely to be used.
    res as struct,_
    0 as ulong,_            'lpDisposition, tells us if the key was opened or created.
    _                       'Again, unlikely to be used, so 0.
    RegCreateKeyEx as long

    phkResult = res.a.struct
End Function

'For ease of function use, all registry keys will be strings.
Function RegSetValueEx(hKey, valueName$, data$)
    cbSize = len(data$)
    CallDLL #advapi32, "RegSetValueExA",_
    hKey as ulong,_
    valueName$ as ptr,_
    0 as long,_             'Reserved.
    _REG_SZ as long,_       'Always string.
    data$ as ptr,_
    cbSize as long,_
    RegSetValueEx as long
End Function

Function RegQueryValueEx(hKey, valueName$, byref data$, byref bufSize)
    struct a, size as long
    a.size.struct = bufSize

    CallDLL #advapi32, "RegQueryValueExA",_
    hKey as ulong,_
    valueName$ as ptr,_
    0 as long,_             'Reserved.
    0 as ulong,_            'Datatype.  Not used, this function only uses REG_SZ.
    data$ as ptr,_
    a as struct,_
    RegQueryValueEx as long

    bufSize = a.size.struct
End Function

Function RegDeleteValue(hKey, valueName$)
    CallDLL #advapi32, "RegDeleteValueA",_
    hKey as ulong,_
    valueName$ as ptr,_
    RegDeleteValue as long
End Function

Function RegDeleteKey(hKey, keyName$)
    CallDLL #advapi32, "RegDeleteKeyA",_
    hKey as ulong,_
    keyName$ as ptr,_
    RegDeleteKey as long
End Function

Function RegCloseKey(hKey)
    CallDLL #advapi32, "RegCloseKey",_
    hKey as ulong,_
    RegCloseKey as long
End Function 
User IP Logged

"Do you believe in destiny?" - Pyrrha Nikos, RWBY
"With what wish will your Soul Gem shine?" - Kyubey, Puella Magi Madoka Magica
Jim Hiley
Full Member
ImageImageImage


member is offline

Avatar




PM


Posts: 202
xx Re: Liberty BASIC File Association manager
« Reply #1 on: Jan 12th, 2016, 11:24pm »

Works well - thank you.
I tried to use it to associate file with my own LB created application.
Association seems to work but clicking on a file and I get the error message
"Unable to locate myapp.TKN"

The only way I have found around that is to create a batch file or other program to change the working folder to the program folder before opening myapp.

Not a nice thing to have to do but your code can help me hide the workaround form my endusers.

Jim
User IP Logged

Chris Iverson
Administrator
ImageImageImageImageImage


member is offline

Avatar

20% Cooler


Homepage PM

Gender: Male
Posts: 2289
xx Re: Liberty BASIC File Association manager
« Reply #2 on: Jan 12th, 2016, 11:33pm »

This is only meant to associate .bas files to LB.

If you're modifying the code to create your own file associations to use with LB-compiled applications, then you need to make an additional change, because the TKN file needs to be specified as the first file on the path if the startup folder is not the same as where the EXE is located.

In other words, LB apps, compiled, should use this form as their registration string:

Code:
"<path to exe>" "<path to TKN>" "%1" 



So you'd need to change:

Code:
assocPath$ = chr$(34) + LBPath$ + chr$(34) + " " + chr$(34) + "%1" + chr$(34) 


To:

Code:
assocPath$ = chr$(34) + LBPath$ + chr$(34) + " " + chr$(34) + TKNPath$ + chr$(34) + _
 " " + chr$(34) + "%1" + chr$(34) 



For example:
Code:
LBPath$ = "C:\Program Files (x86)\MyCompany\My Program.exe"
TKNPath$ = "C:\Program Files (x86)\MyCompany\My Program.tkn"
assocPath$ = chr$(34) + LBPath$ + chr$(34) + " " + chr$(34) + TKNPath$ + chr$(34) + _
 " " + chr$(34) + "%1" + chr$(34) 


Note that the TKN file being the first entry on the command line WILL change what the CommandLine$ variable receives, so you'll need to adjust accordingly.

EDIT: That last part isn't true(anymore?)
« Last Edit: Jan 13th, 2016, 07:53am by Chris Iverson » User IP Logged

"Do you believe in destiny?" - Pyrrha Nikos, RWBY
"With what wish will your Soul Gem shine?" - Kyubey, Puella Magi Madoka Magica
Jim Hiley
Full Member
ImageImageImage


member is offline

Avatar




PM


Posts: 202
xx Re: Liberty BASIC File Association manager
« Reply #3 on: Jan 13th, 2016, 12:24am »

Thank you again.
That works well now and I didn't have to change the commandline reading code at all.
The "path-to-tkn" is not passed on to the application.

Using the same method, I have added the TKN path to the target in my desktop shortcut and drag-and-drop to the shortcut now works again. (V4.5 stopped that from working)

There are a few more scenarios to test but it looks like I will have a few happy endusers.

Jim
User IP Logged

Chris Iverson
Administrator
ImageImageImageImageImage


member is offline

Avatar

20% Cooler


Homepage PM

Gender: Male
Posts: 2289
xx Re: Liberty BASIC File Association manager
« Reply #4 on: Jan 13th, 2016, 07:56am »

on Jan 13th, 2016, 12:24am, Jim Hiley wrote:
The "path-to-tkn" is not passed on to the application.


Huh. I must be misremembering something.

Good to know!
User IP Logged

"Do you believe in destiny?" - Pyrrha Nikos, RWBY
"With what wish will your Soul Gem shine?" - Kyubey, Puella Magi Madoka Magica
CarlGundel
Administrator
ImageImageImageImageImage


member is offline

Avatar

author of Liberty BASIC


Homepage PM


Posts: 2833
xx Re: Liberty BASIC File Association manager
« Reply #5 on: Jan 13th, 2016, 11:37am »

Thanks for your effort and generosity Chris!

I have made mention of this in my blog.

http://basicprogramming.blogspot.com

-Carl
User IP Logged

author of Liberty BASIC
http://www.libertybasic.com
Alyce Watson
Administrator
ImageImageImageImageImage


member is offline

Avatar




Homepage PM

Gender: Female
Posts: 14918
xx Re: Liberty BASIC File Association manager
« Reply #6 on: Jan 13th, 2016, 12:59pm »

Chris, if you get time in the future to expand this into an article, we'd LOVE to see it on LBPE!
User IP Logged

Alyce
Liberty BASIC Workshop - a complete IDE for Liberty BASIC


Alyce's Restaurant
for Liberty BASIC code, tools and references
tsh73
Board Moderator

member is offline

Avatar

Anatoly (real name)


PM

Gender: Male
Posts: 1709
xx Re: Liberty BASIC File Association manager
« Reply #7 on: Jan 14th, 2016, 01:43am »

Quote:
I have made mention of this in my blog.

I'm sorry to say but very little people will see that.

How about making it into EXE and putting in some visible place on http://www.libertybasic.com/
?
User IP Logged

damned Dog in the Manger
CarlGundel
Administrator
ImageImageImageImageImage


member is offline

Avatar

author of Liberty BASIC


Homepage PM


Posts: 2833
xx Re: Liberty BASIC File Association manager
« Reply #8 on: Jan 14th, 2016, 07:07am »

on Jan 14th, 2016, 01:43am, tsh73 wrote:
I'm sorry to say but very little people will see that.

How about making it into EXE and putting in some visible place on http://www.libertybasic.com/
?

Why do you say that? That blog has more than 100 visits daily.

-Carl
User IP Logged

author of Liberty BASIC
http://www.libertybasic.com
tsh73
Board Moderator

member is offline

Avatar

Anatoly (real name)


PM

Gender: Male
Posts: 1709
xx Re: Liberty BASIC File Association manager
« Reply #9 on: Jan 14th, 2016, 08:19am »

Quote:
Why do you say that? That blog has more than 100 visits daily.

If I have a problem with Windows, do I go to Windows homepage / Windows support center / whatever
or do I start searching for Bill Gates' blog?

It's just a wrong place.
User IP Logged

damned Dog in the Manger
CarlGundel
Administrator
ImageImageImageImageImage


member is offline

Avatar

author of Liberty BASIC


Homepage PM


Posts: 2833
xx Re: Liberty BASIC File Association manager
« Reply #10 on: Jan 14th, 2016, 10:02am »

on Jan 14th, 2016, 08:19am, tsh73 wrote:
If I have a problem with Windows, do I go to Windows homepage / Windows support center / whatever
or do I start searching for Bill Gates' blog?

It's just a wrong place.

Not at all. The information is already posted here, and my blog post is just one more reference.

Any reference from a long standing site (such as my blog) to this site or to any other Liberty BASIC site gets the attention of search engines. This causes traffic to increase greatly. Since I restarted blogging last month traffic to the Liberty BASIC site has doubled, and it's free traffic at least in terms of dollars spent.

This is called marketing.

-Carl
« Last Edit: Jan 14th, 2016, 10:03am by CarlGundel » User IP Logged

author of Liberty BASIC
http://www.libertybasic.com
Mystic
Junior Member
ImageImage


member is offline

Avatar




Homepage PM

Gender: Male
Posts: 97
xx Re: Liberty BASIC File Association manager
« Reply #11 on: Jan 14th, 2016, 10:13am »

on Jan 14th, 2016, 07:07am, CarlGundel wrote:
Why do you say that? That blog has more than 100 visits daily.

-Carl


Yes, but they're all me! <kidding... Couldn't resist the opening.>
User IP Logged

- Rick
Programming BASIC since the 80's starting with a TRS-80.
Chris Iverson
Administrator
ImageImageImageImageImage


member is offline

Avatar

20% Cooler


Homepage PM

Gender: Male
Posts: 2289
xx Re: Liberty BASIC File Association manager
« Reply #12 on: Jan 15th, 2016, 10:29pm »

New version, this is a long one, but it auto-searches for LB installs and has them as options for setting association, without having to manually locate them.

(Manual option still exists, in case the automatic finder doesn't find yours)

Screenshot:

User Image


== At this point, program became too large to share in one forum post. I'm going to post the full source of the new version on the Wiki. ==

EDIT: Available here: http://basic.wikispaces.com/BAS+File+Association+Utility
« Last Edit: Jan 15th, 2016, 10:39pm by Chris Iverson » User IP Logged

"Do you believe in destiny?" - Pyrrha Nikos, RWBY
"With what wish will your Soul Gem shine?" - Kyubey, Puella Magi Madoka Magica
cundo
Guru
ImageImageImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 628
xx Re: Liberty BASIC File Association manager
« Reply #13 on: Jan 16th, 2016, 3:38pm »

Hey Chris, got this error message (under Xp):

Registry Error
Unable to get current BAS association.
RegQueryValueEX() returned 2
huh

Anyway, I was just testing your code, because I already have BAS files working fine.

Both exes got detected correctly (LB and JB).
User IP Logged

cundo
Chris Iverson
Administrator
ImageImageImageImageImage


member is offline

Avatar

20% Cooler


Homepage PM

Gender: Male
Posts: 2289
xx Re: Liberty BASIC File Association manager
« Reply #14 on: Jan 16th, 2016, 4:50pm »

Hmm, 2 is ERROR_FILE_NOT_FOUND, which, in the context of registry query, means the key it's looking for isn't found.


The only place RegQueryValueEx() is used is to get the current .BAS association, under HKEY_CURRENT_USER.

What I suspect happened in the case of XP is that the association you set for .BAS files got placed in HKEY_LOCAL_MACHINE, instead.

Now that I think about it, I should be checking in HKEY_CLASSES_ROOT when looking for current associations to back up, and writing to HKEY_CURRENT_USER when saving options.

Additionally, it's quite possible that a current association for BAS files doesn't exist at all yet, and my program would fail to run in that case.

It should have the option of creating an association from scratch. Not being able to create an association kind of defeats the purpose of this program!

Thanks for the report!


EDIT: Thinking about it further, I should not be modifying the .BAS entry first, and then undoing what I wrote if I can't write the association handler. I should write the handler first, and then only change the BAS entry to use it upon success.

I'll probably also change the permissions asked for when querying the data, so it doesn't try to accidentally open something for writing in HKEY_CLASSES_ROOT that it wouldn't have access to change.


EDIT2: Thinking again, it's strange that it would return value not found, when the RegCreateKeyEx() should have created it. I'll need to do some more experimentation, but the changes I mentioned above will be good for following best practices, anyway.

EDIT3: Ahh, not even the "default" value is created by default, it has to be written to before being available for reading.
« Last Edit: Jan 16th, 2016, 4:59pm by Chris Iverson » User IP Logged

"Do you believe in destiny?" - Pyrrha Nikos, RWBY
"With what wish will your Soul Gem shine?" - Kyubey, Puella Magi Madoka Magica
Pages: 1 2  Notify Send Topic Print
« Previous Topic | Next Topic »

Rules|Home|Help|Search|Recent Posts|Notification

Donate $6.99 for 50,000 Ad-Free Pageviews!

| |

This forum powered for FREE by Conforums ©
Sign up for your own Free Message Board today!
Terms of Service | Privacy Policy | Conforums Support | Parental Controls