1. [Windows] Associate file extensions with a program
Hi all,
I wrote two small routines, that allow to associate file extensions with
a program on Windows.
Does anyone see a mistake/bug in the code? The code seems to work fine
on Win 98. Is it also appropriate for other Windows versions? How can I
"uninstall" these associations? Can it be done in a similar simple way,
or will I have to use Windows API functions for that purpose?
-- tested with Eu 2.4
include wildcard.e -- for lower()
function escape (sequence fileName)
sequence ret
integer char
ret = ""
for i = 1 to length(fileName) do
char = fileName[i]
if char = '\\' then
ret &= "\\\\"
else
ret &= char
end if
end for
return ret
end function
global function registry_associate (
sequence regFile,
sequence extensionList,
sequence fileType,
sequence description,
sequence iconFile,
integer iconNo,
sequence progFile
)
-- Produces the file <regFile>.
-- When on Windows then <regFile> is double-clicked, files with
-- an extension contained in <extensionList> will be associated with
-- the denoted icon and with program <progFile>.
integer fw
if not equal(lower(regFile[length(regFile)-3..length(regFile)]), ".reg") then
regFile &= ".reg"
end if
fw = open(regFile, "w")
if fw = -1 then
return -1 -- error
end if
puts(fw, "REGEDIT4\n\n")
for i = 1 to length(extensionList) do
printf(fw, "[HKEY_CLASSES_ROOT\\.%s]\n", {extensionList[i]})
printf(fw, "@=\"%s\"\n\n", {fileType})
end for
printf(fw, "[HKEY_CLASSES_ROOT\\%s]\n", {fileType})
printf(fw, "@=\"%s\"\n\n", {description})
printf(fw, "[HKEY_CLASSES_ROOT\\%s\\DefaultIcon]\n", {fileType})
printf(fw, "@=\"%s,%d\"\n\n", {escape(iconFile), iconNo})
printf(fw, "[HKEY_CLASSES_ROOT\\%s\\shell\\open\\command]\n", {fileType})
printf(fw, "@=\"\\\"%s\\\" \\\"%%1\\\"\"\n\n", {escape(progFile)})
close(fw)
return 0 -- success
end function
-- Demo: Write a REG file, that associates the extension "exw" with
-- "C:\\Programs\\Euphoria\\Bin\\exw.exe"
? registry_associate(
"test.reg",
{"exw"},
"EuWinApp",
"Euphoria Windows App",
"C:\\Programs\\Euphoria\\Bin\\exw.exe",
0,
"C:\\Programs\\Euphoria\\Bin\\exw.exe"
)
TIA,
Juergen
--
We don't know where to GOTO if we don't know where we've COME FROM.
http://www.fortran.com/fortran/come_from.html
2. Re: [Windows] Associate file extensions with a program
On Sun, 10 Oct 2004 21:37:40 +0200, Juergen Luethje <j.lue at gmx.de>
wrote:
>How can I "uninstall" these associations?
According to www.wotsit.org/search.asp?page=3&s=windows :
Delete the key & all it's subkeys by beginning it with -, eg
> printf(fw, "[-HKEY_CLASSES_ROOT\\%s\\DefaultIcon]\n", {fileType})
Delete individual values using a single unquoted minus sign, eg
> printf(fw, "@=-\n", {})
Regards,
Pete
> return 0 -- success
PS: Please do not return False to indicate success.
3. Re: [Windows] Associate file extensions with a program
Pete Lomax wrote:
> On Sun, 10 Oct 2004 21:37:40 +0200, Juergen Luethje <j.lue at gmx.de>
> wrote:
>
>> How can I "uninstall" these associations?
>
> According to www.wotsit.org/search.asp?page=3&s=windows :
> Delete the key & all it's subkeys by beginning it with -, eg
>
>> printf(fw, "[-HKEY_CLASSES_ROOT\\%s\\DefaultIcon]\n", {fileType})
>
> Delete individual values using a single unquoted minus sign, eg
>
>> printf(fw, "@=-\n", {})
>
> Regards,
> Pete
Thanks, Pete!
>> return 0 -- success
>
> PS: Please do not return False to indicate success.
It's a habit of mine. I can't remember when/why I started to do so,
maybe I borrowed it from Euphoria's seek().
What do you suggest? True to indicate success, 0 and negative integers
for errors (if possible)?
Regards,
Juergen
4. Re: [Windows] Associate file extensions with a program
Pete Lomax wrote:
[snip]
> > return 0 -- success
> PS: Please do not return False to indicate success.
He didn't. He returned *zero*. I'm sure you are not saying that every
0 is also a 'false', just as every 1 is not a 'true'. Just because
RDS chose to represent a falsehood with integer zero, doesn't mean that
every use of zero implies a falsehood, nor every use of a one implies a
truth.
Truth and Falsehood are not numbers. RDS represents these concepts by
using numbers, but that is a mere convenience.
In Juergen's routine, 0 *represents* a success not a falsehood.
One might argue that using zero for success makes reading code a problem
if you write code thus ...
if not SomeFunc() then
-- Success!
DoSuccess()
else
-- Failure
DoFailed()
end if
I maintain that a 'better' way to write such code is more like ...
constant SUCCESS = 0
if SomeFunc() = SUCCESS then
DoSuccess()
else
Do Failed()
end if
--
Derek Parnell
Melbourne, Australia
5. Re: [Windows] Associate file extensions with a program
I totally agree with Derek - I stopped using 0 and 1 as success indicators
after I spent an entire weekend debugging some code. I now use:
global constant Good = #FFFF, Bad = -#FFFF
if my_function(blah)= Good then <code goes here> Endif
It may look funny, but trust me; in the long run you'll save much debugging
time (and hair pulling).
Yours, OtterDad
Don't sweat it -- it's not real life. It's only ones and zeroes. Gene Spafford
6. Re: [Windows] Associate file extensions with a program
- Posted by Pete Lomax <petelomax at blueyonder.co.uk>
Oct 11, 2004
-
Last edited Oct 12, 2004
On Mon, 11 Oct 2004 12:43:40 +0200, Juergen Luethje <j.lue at gmx.de>
wrote:
>Pete Lomax wrote:
>> PS: Please do not return False to indicate success.
>
>It's a habit of mine.
OK, if it's a habit, then I withdraw my request. I guess it is only a
habit of mine to return 1, since I rarely bother to return specific
error conditions.
Regards,
Pete
7. Re: [Windows] Associate file extensions with a program
Pete Lomax wrote:
> On Mon, 11 Oct 2004 12:43:40 +0200, Juergen Luethje <j.lue at gmx.de>
> wrote:
>
>> Pete Lomax wrote:
>>> PS: Please do not return False to indicate success.
>>
>> It's a habit of mine.
> OK, if it's a habit, then I withdraw my request. I guess it is only a
> habit of mine to return 1, since I rarely bother to return specific
> error conditions.
Unfortunately, it's not possible anyhow, to consistently return errors
as function values. E.g. in many math functions, we can't return a
number such as -1, 0 or 1 as error values, because these values might be
normal results of that function.
We could return e.g. {} to inicate an error, or even {1}, {2} to
indicate specific errors. But there are also functions, that legally can
return arbitrary objects.
I'll think about my habits in this regard. Maybe it's cleaner to use a
global error variable.
Regards,
Juergen
--
We don't know where to GOTO if we don't know where we've COME FROM.
http://www.fortran.com/fortran/come_from.html
8. Re: [Windows] Associate file extensions with a program
Juergen Luethje wrote:
>
> Pete Lomax wrote:
>
> > On Mon, 11 Oct 2004 12:43:40 +0200, Juergen Luethje <j.lue at gmx.de>
> > wrote:
> >
> >> Pete Lomax wrote:
> >>> PS: Please do not return False to indicate success.
> >>
> >> It's a habit of mine.
> > OK, if it's a habit, then I withdraw my request. I guess it is only a
> > habit of mine to return 1, since I rarely bother to return specific
> > error conditions.
>
> Unfortunately, it's not possible anyhow, to consistently return errors
> as function values. E.g. in many math functions, we can't return a
> number such as -1, 0 or 1 as error values, because these values might be
> normal results of that function.
> We could return e.g. {} to inicate an error, or even {1}, {2} to
> indicate specific errors. But there are also functions, that legally can
> return arbitrary objects.
I've been using the method of always returning a sequence; the first
element is the return code and the second is the function value.
> I'll think about my habits in this regard. Maybe it's cleaner to use a
> global error variable.
A simple global error variable is a *bad* idea. It can lead to subtle
bugs if you cannot guarentee that the function you called is the *only*
function that sets the single shared error variable.
--
Derek Parnell
Melbourne, Australia
9. Re: [Windows] Associate file extensions with a program
Derek Parnell wrote:
> Juergen Luethje wrote:
<snip>
>> Unfortunately, it's not possible anyhow, to consistently return errors
>> as function values. E.g. in many math functions, we can't return a
>> number such as -1, 0 or 1 as error values, because these values might be
>> normal results of that function.
>> We could return e.g. {} to inicate an error, or even {1}, {2} to
>> indicate specific errors. But there are also functions, that legally can
>> return arbitrary objects.
>
> I've been using the method of always returning a sequence; the first
> element is the return code and the second is the function value.
Ah, yes.. I couldn't see the wood for the trees.
>> I'll think about my habits in this regard. Maybe it's cleaner to use a
>> global error variable.
>
> A simple global error variable is a *bad* idea. It can lead to subtle
> bugs if you cannot guarentee that the function you called is the *only*
> function that sets the single shared error variable.
I'd be interested in your opinion about the following two
implementations.
-- Implementation #1
integer ErrNo
ErrNo = 0 -- no error at the beginning
procedure proc1()
if <some error> then
ErrNo = 27
elsif <another error> then
ErrNo = 5
else
ErrNo = 0
end if
end procedure
procedure proc2()
if <some error> then
ErrNo = 3
elsif <another error> then
ErrNo = 22
else
ErrNo = 0
end if
end procedure
proc1()
proc2()
I think here is a problem, when there is an error in proc1(), and no
error in proc2(). proc2() then will clear the variable 'ErrNo', and the
information about the error in proc1() is lost.
-- Implementation #2
integer ErrNo
ErrNo = 0 -- no error at the beginning
procedure proc1()
if <some error> then
ErrNo = 27
elsif <another error> then
ErrNo = 5
end if
end procedure
procedure proc2()
if <some error> then
ErrNo = 3
elsif <another error> then
ErrNo = 22
end if
end procedure
proc1()
proc2()
The same as above, but without
else ErrNo = 0.
In this case, 'ErrNo' never will be cleared, and it always holds the
number of the last error that occured.
I can see that implementation #1 is not a good idea, but what about
implementation #2?
Regards,
Juergen
10. Re: [Windows] Associate file extensions with a program
- Posted by Pete Lomax <petelomax at blueyonder.co.uk>
Oct 12, 2004
-
Last edited Oct 13, 2004
On Tue, 12 Oct 2004 20:32:38 +0200, Juergen Luethje <j.lue at gmx.de>
wrote:
>I can see that implementation #1 is not a good idea, but what about
>implementation #2?
If there is an error in proc1, such as FileDoesNotExist, then it would
not help matters to replace this with ErrorWritingToFile in proc2.
In fact, wouldn't most error conditions tend to daisy-chain?
Regards,
Pete
11. Re: [Windows] Associate file extensions with a program
- Posted by Derek Parnell <ddparnell at bigpond.com>
Oct 12, 2004
-
Last edited Oct 13, 2004
Juergen Luethje wrote:
[snip]
>
> I'd be interested in your opinion about the following two
> implementations.
>
> }}}
<eucode>
> -- Implementation #1
> integer ErrNo
> ErrNo = 0 -- no error at the beginning
>
> procedure proc1()
> if <some error> then
> ErrNo = 27
> elsif <another error> then
> ErrNo = 5
> else
> ErrNo = 0
> end if
> end procedure
>
> procedure proc2()
> if <some error> then
> ErrNo = 3
> elsif <another error> then
> ErrNo = 22
> else
> ErrNo = 0
> end if
> end procedure
>
> proc1()
> proc2()
> </eucode>
{{{
>
> I think here is a problem, when there is an error in proc1(), and no
> error in proc2(). proc2() then will clear the variable 'ErrNo', and the
> information about the error in proc1() is lost.
>
> }}}
<eucode>
> -- Implementation #2
> integer ErrNo
> ErrNo = 0 -- no error at the beginning
>
> procedure proc1()
> if <some error> then
> ErrNo = 27
> elsif <another error> then
> ErrNo = 5
> end if
> end procedure
>
> procedure proc2()
> if <some error> then
> ErrNo = 3
> elsif <another error> then
> ErrNo = 22
> end if
> end procedure
>
> proc1()
> proc2()
> </eucode>
{{{
>
> The same as above, but without
> else ErrNo = 0.
> In this case, 'ErrNo' never will be cleared, and it always holds the
> number of the last error that occured.
>
> I can see that implementation #1 is not a good idea, but what about
> implementation #2?
Well we are using Euphoria so why not take advantage of that?
sequence ErrNo
ErrNo = {} -- no error at the beginning
procedure proc3()
if <some error> then
ErrNo &= {{"proc3",7}}
elsif <another error> then
ErrNo &= {{"proc3",8}}
end if
end procedure
procedure proc1()
if <some error> then
ErrNo &= {{"proc1",27}}
elsif <another error> then
ErrNo &= {{"proc1",5}}
end if
end procedure
procedure proc2()
proc3()
if <some error> then
ErrNo &= {{"proc2",3}}
elsif <another error> then
ErrNo &= {{"proc2",22}}
end if
end procedure
ErrNo = {}
proc1()
proc2()
for i = 1 to length(ErrNo) do
if equal("proc1", ErrNo[i][1]) then
. . .
elsif equal("proc2", ErrNo[i][1]) then
. . .
elsif equal("proc3", ErrNo[i][1]) then
. . .
end if
end for
--
Derek Parnell
Melbourne, Australia
12. Re: [Windows] Associate file extensions with a program
- Posted by "Juergen Luethje" <j.lue at gmx.de>
Oct 12, 2004
-
Last edited Oct 13, 2004
Pete Lomax wrote:
> On Tue, 12 Oct 2004 20:32:38 +0200, Juergen Luethje <j.lue at gmx.de>
> wrote:
>
>> I can see that implementation #1 is not a good idea, but what about
>> implementation #2?
>
> If there is an error in proc1, such as FileDoesNotExist, then it would
> not help matters to replace this with ErrorWritingToFile in proc2.
>
> In fact, wouldn't most error conditions tend to daisy-chain?
Probably yes.
But it's up to the author of the main program (maybe myself) anyway, to
check early and often for errors, regardless wether errors are returned
as results of functions, or in a local/global variable.
Regards,
Juergen
13. Re: [Windows] Associate file extensions with a program
- Posted by "Juergen Luethje" <j.lue at gmx.de>
Oct 12, 2004
-
Last edited Oct 13, 2004
Derek Parnell wrote:
> Juergen Luethje wrote:
>
> [snip]
>>
>> I'd be interested in your opinion about the following two
>> implementations.
<snip>
> Well we are using Euphoria so why not take advantage of that?
<snip>
Cool
Thanks, Derek!
Regards,
Juergen
14. Re: [Windows] Associate file extensions with a program
- Posted by Bernard Ryan <xotron at bluefrog.com>
Oct 12, 2004
-
Last edited Oct 13, 2004
Juergen Luethje wrote:
>
> Derek Parnell wrote:
>
> > Juergen Luethje wrote:
>
>
-- Implementation #another
integer error
sequence ErrNo
ErrNo &= {} -- no error at the beginning
procedure proc1()
if <some error> then
ErrNo &= 27
elsif <another error> then
ErrNo &= 5
end if
end procedure
procedure proc2()
if <some error> then
ErrNo &= 3
elsif <another error> then
ErrNo &= 22
end if
end procedure
proc1()
proc2()
error = not find(0,ErrNo)
if error then
puts(1,ErrNo[error]&"\n" end if
end if
Bernie
My files in archive:
http://www.rapideuphoria.com/w32engin.zip
http://www.rapideuphoria.com/mixedlib.zip
http://www.rapideuphoria.com/eu_engin.zip
http://www.rapideuphoria.com/win32eru.zip
15. Re: [Windows] Associate file extensions with a program
> [snip]
> > > return 0 -- success
> > PS: Please do not return False to indicate success.
>
> He didn't. He returned *zero*. I'm sure you are not saying that every
> 0 is also a 'false', just as every 1 is not a 'true'. Just because
> RDS chose to represent a falsehood with integer zero, doesn't mean that
> every use of zero implies a falsehood, nor every use of a one implies a
> truth.
>
> Truth and Falsehood are not numbers. RDS represents these concepts by
> using numbers, but that is a mere convenience.
almost every commandline tool I use returns an error level of zero
to indicate success. It seems broadly adopted.
16. Re: [Windows] Associate file extensions with a program
Michael Raley wrote:
>
> > [snip]
> > > > return 0 -- success
> > > PS: Please do not return False to indicate success.
> >
> > He didn't. He returned *zero*. I'm sure you are not saying that every
> > 0 is also a 'false', just as every 1 is not a 'true'. Just because
> > RDS chose to represent a falsehood with integer zero, doesn't mean that
> > every use of zero implies a falsehood, nor every use of a one implies a
> > truth.
> >
> > Truth and Falsehood are not numbers. RDS represents these concepts by
> > using numbers, but that is a mere convenience.
>
> almost every commandline tool I use returns an error level of zero
> to indicate success. It seems broadly adopted.
>
Including the Eu interpreter itself.*
* see abort(i) ;)
17. Re: [Windows] Associate file extensions with a program
Bernard Ryan wrote:
> Juergen Luethje wrote:
>>
>> Derek Parnell wrote:
>>
>>> Juergen Luethje wrote:
>>
>
> }}}
<eucode>
> -- Implementation #another
> integer error
> sequence ErrNo
> ErrNo &= {} -- no error at the beginning
>
> procedure proc1()
> if <some error> then
> ErrNo &= 27
> elsif <another error> then
> ErrNo &= 5
> end if
> end procedure
>
> procedure proc2()
> if <some error> then
> ErrNo &= 3
> elsif <another error> then
> ErrNo &= 22
> end if
> end procedure
>
> proc1()
> proc2()
>
> error = not find(0,ErrNo)
As implemented above, ErrNo never will contain a 0, so 'find(0,ErrNo)'
always will be 0, and 'error = not 0' will result in 'error = 1'.
> if error then
> puts(1,ErrNo[error]&"\n" end if
> end if
> </eucode>
{{{
if length(ErrNo) then
print(ErrNo)
end if
works for me.
Thanks,
Juergen
18. Re: [Windows] Associate file extensions with a program
Brian Broker wrote:
> Michael Raley wrote:
<snip>
>> almost every commandline tool I use returns an error level of zero
>> to indicate success. It seems broadly adopted.
>>
>
> Including the Eu interpreter itself.*
>
> * see abort(i) ;)
Yep.
Regards,
Juergen
19. Re: [Windows] Associate file extensions with a program
Pete Lomax wrote:
>
> Juergen Luethje wrote:
>
> > I can see that implementation #1 is not a good idea, but what about
> > implementation #2?
>
> If there is an error in proc1, such as FileDoesNotExist, then it would
> not help matters to replace this with ErrorWritingToFile in proc2.
>
> In fact, wouldn't most error conditions tend to daisy-chain?
Yes. It's important to allow for errors to propagate back up through
the call chain. I've done this a couple of different ways in EuSQL and
in matheval. In EuSQL, all functions return a sequence on success, and
an integer on failure. After pretty much every call from a library
routine to another, I check this condition, and simply return the error
code. There is also an extended error message that can be set, and that
an application can request.
In matheval, I defined a separate type, called INVALID. Each matheval
type is smart enough to only operate on other types that it understands,
so the INVALID type is simply passed back. Part of the INVALID type is
an error message.
Matt Lewis