Euphoria Ticket #197: -icon binding option broken?

The -icon binding option used to work with an older build, but now my exe has the windows default icon when i run this:

euiw %EUDIR%\source\bind.ex -icon aaa.ico bbb.ex

Details

Type: Bug Report Severity: Normal Category: Binder
Assigned To: unknown Status: New Reported Release:
Fixed in SVN #: View VCS: none Milestone: 4.1.0

1. Comment by DerekParnell Oct 03, 2010

Works for me. What is the size of your icon file? Are you getting any error messages?

2. Comment by mattlewis Oct 22, 2010

Other users have confirmed that it works.

3. Comment by DerekParnell Oct 27, 2010

Seems to work for everyone else. No change is needed.

4. Comment by jimcbrown Dec 05, 2010

Reopening, as it was duplicated in ticket:502

5. Comment by jimcbrown Dec 05, 2010

The information in this thread should at least provide a workaround: http://openeuphoria.org/forum/112480.wc

6. Comment by jimcbrown Dec 06, 2010

Jeremy just tried it and said it's working. Perhaps if someone could upload an icon that is failing, we might be able to make progress on this?

7. Comment by jeremy Dec 06, 2010

I said it was not working, however I just read the limitations. Wow! That's a pretty small Icon. Any modern Icon is much larger than our spec. Is this limitation based on the size of icon we put into the exe ourselves (the euphoria icon) or some other limitation?

8. Comment by jeremy Dec 06, 2010

I was finally able to create an icon this small from existing Icons I found. Most of the Icons I found for use were ~200-300k, not 2.2k. I had to covert to PNG, then resize to 32x32, then to 256 colors, then export as png, and use an online png2ico converter. In the end I have a 32x32 icon that is 2,238, same size as euphoria.ico. eubind -icon paper2.ico test.ex did not work. No errors.

I've placed my icon online at: http://jeremy.cowgar.com/files/paper2.ico

Really what needs to happen is eubind needs to accept a more modern Icon. This should probably be done after we select a new logo. I wonder if this ticket should move to 4.0.0 milestone as we are not going to have a new logo before RC2.

9. Comment by jimcbrown Dec 06, 2010

Uh... can we at least document it before RC2 and final go out?

10. Comment by jeremy Dec 07, 2010

Resource handling was added to euc and eubind is not going to be the simplest problem to fix correctly. Thus it has been moved to 4.1. Those on Windows wishing to use an icon can use euc as a work around to this issue. An example is:

C:\proj> echo myproj ICON SRCDIR\myicon.ico > myproj.rc 
C:\proj> euc -rc-file myproj.rc myproj.ex 

With this new ability, you may wish to use euc all the time for distribution as resource files can contain product and version information as well. With eubind you cannot.

11. Comment by jimcbrown Dec 07, 2010

Well, I came up with the following code for eubind (untested). It doesn't actually look that difficult.

include std/dll.e 
include std/io.e 
include std/filesys.e 
include std/machine.e 
 
function slice(sequence s, integer i) 
	if i < 1 or i > length(s) then 
		return "" 
	else 
		return s[i] 
	end if 
end function 
function get_file_size(sequence s) 
	object o = dir(s) 
	if sequence(o) and length(o) = 1 then 
		return o[1][D_SIZE] 
	end if 
	return 0 
end function 
 
integer fn = open(slice(command_line(), 4), "rb") 
sequence icon = get_bytes(fn, get_file_size(slice(command_line(), 4))) 
close(fn) 
 
-- winnt.h 
--#define LANG_NEUTRAL    0x00 
--#define SUBLANG_DEFAULT 0x01 
constant LANG_NEUTRAL = 0, SUBLANG_DEFAULT = 1 
function MAKELANGID(atom p, atom s) 
-- #define MAKELANGID(p,s) ((((WORD)(s))<<10)|(WORD)(p)) 
	return or_bits(s*power(2,10), p) 
end function 
-- winuser.h 
function MAKEINTRESOURCE(atom a) 
-- #define MAKEINTRESOURCEA(i) (LPSTR)((DWORD)((WORD)(i))) 
	return a 
end function 
-- #define RT_ICON MAKEINTRESOURCE(3) 
constant RT_ICON = MAKEINTRESOURCE(3) 
 
constant kernel = open_dll("kernel32.dll"), 
beginupdateresource = define_c_func(kernel, "BeginUpdateResourceA", 
{C_POINTER, C_INT}, C_POINTER), 
endupdateresource = define_c_func(kernel, "EndUpdateResourceA", 
{C_POINTER, C_INT}, C_INT), 
updateresource = define_c_func(kernel, "UpdateResourceA", 
{C_POINTER, C_POINTER, C_POINTER, C_USHORT, C_POINTER, C_ULONG}, C_INT) 
 
function BeginUpdateResource(sequence filename, integer b) 
	atom ptr = allocate_string(filename) 
	atom ret = c_func(beginupdateresource, {ptr, b}) 
	free(ptr) 
	return ret 
end function 
function EndUpdateResource(atom h, integer b) 
	return c_func(endupdateresource, {h, b}) 
end function 
function UpdateResource(atom h, atom t, sequence f, integer w, sequence b, integer n) 
	atom ret, ptr, fptr 
	ptr = allocate_string(b) 
	fptr = allocate_string(f) 
	ret = c_func(updateresource, {h, t, fptr, w, ptr, n}) 
	free(ptr) 
	free(fptr) 
	return ret 
end function 
 
atom res 
res = BeginUpdateResource(slice(command_line(), 3), 0) 
if res = 0 then 
	puts(1, "BeginUpdateResource failed\n") 
	abort(0) 
end if 
--if UpdateResource(res, RT_ICON, MAKERESOURCEID(1), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), icon, length(icon)) then 
if UpdateResource(res, RT_ICON, "eui", MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), icon, length(icon)) then 
	-- update worked 
	? EndUpdateResource(res, 0) 
else 
	-- update failed 
	puts(1, "UpdateResource failed\n") 
	? EndUpdateResource(res, 1) 
end if 

12. Comment by jimcbrown Feb 04, 2011

This is what I have. This seemed to work, but corrupted the .exe

This is most of what you need to do, minus the processing and handling of .ico files.

That is described here, but is more involved than I wanted to do.

http://www.codeguru.com/cpp/w-p/win32/tutorials/print.php/c12873__1

Although it can be done using Euphoria code, the complexity is approaching that of an independent project.

(Incidently, it turns out to be a lot easier to simply copy the icon resource from another, preexisting .exe)

include std/dll.e 
include std/io.e 
include std/filesys.e 
include std/machine.e 
include std/console.e 
 
function slice(sequence s, integer i) 
        if i < 1 or i > length(s) then 
                return "" 
        else 
                return s[i] 
        end if 
end function 
function get_file_size(sequence s) 
        object o = dir(s) 
        if sequence(o) and length(o) = 1 then 
                return o[1][D_SIZE] 
        end if 
        return 0 
end function 
 
integer fn = open(slice(command_line(), 4), "rb") 
sequence icon = get_bytes(fn, get_file_size(slice(command_line(), 4))) 
close(fn) 
 
-- winnt.h 
--#define LANG_NEUTRAL    0x00 
--#define SUBLANG_DEFAULT 0x01 
constant LANG_NEUTRAL = 0, SUBLANG_DEFAULT = 1 
function MAKELANGID(atom p, atom s) 
-- #define MAKELANGID(p,s) ((((WORD)(s))<<10)|(WORD)(p)) 
        return or_bits(s*power(2,10), p) 
end function 
-- winuser.h 
function MAKEINTRESOURCE(atom a) 
-- #define MAKEINTRESOURCEA(i) (LPSTR)((DWORD)((WORD)(i))) 
        return a 
end function 
-- #define RT_ICON MAKEINTRESOURCE(3) 
constant RT_ICON = MAKEINTRESOURCE(3) 
-- #define RT_GROUP_ICON MAKEINTRESOURCE( 11 + R_ICON ) 
constant RT_GROUP_ICON = MAKEINTRESOURCE(14) 
function IS_INTRESOURCE(atom a) 
-- #define IS_INTRESOURCE(x)   (((ULONG_PTR)(x) >> 16) == 0) 
	-- TODO handle signed negative values 
	return (a <= 65536) 
end function 
-- i don't know, maybe winbase.h 
constant LOAD_LIBRARY_AS_DATAFILE = 2 
 
constant kernel = open_dll("kernel32.dll"), 
loadlibrary = define_c_func(kernel, "LoadLibraryExA", 
{C_POINTER, C_POINTER, C_ULONG}, C_POINTER), 
freelibrary = define_c_func(kernel, "FreeLibrary", {C_POINTER}, C_INT), 
enumresourcetypes = define_c_func(kernel, "EnumResourceTypesA", 
{C_POINTER, C_POINTER, C_POINTER}, C_INT), 
enumresourcenames = define_c_func(kernel, "EnumResourceNamesA", 
{C_POINTER, C_POINTER, C_POINTER, C_POINTER}, C_INT), 
enumresourcelangs = define_c_func(kernel, "EnumResourceLanguagesA", 
{C_POINTER, C_POINTER, C_POINTER, C_POINTER, C_POINTER}, C_INT), 
beginupdateresource = define_c_func(kernel, "BeginUpdateResourceA", 
{C_POINTER, C_INT}, C_POINTER), 
endupdateresource = define_c_func(kernel, "EndUpdateResourceA", 
{C_POINTER, C_INT}, C_INT), 
updateresource = define_c_func(kernel, "UpdateResourceA", 
{C_POINTER, C_POINTER, C_POINTER, C_USHORT, C_POINTER, C_ULONG}, C_INT) 
 
sequence all_types = {}, all_resources = {}, all_langs = {} 
sequence theicon = {0,0}, theiconlangs = {"", ""} 
constant ICON_HWDEP = 1, ICON_INDEP = 2 
 
function make_str(atom type_ptr) 
	sequence type_str 
	if IS_INTRESOURCE(type_ptr) then 
		type_str = sprintf("#%d", {type_ptr}) 
	else 
		type_str = peek_string(type_ptr) 
	end if 
	return type_str 
end function 
 
function enumrestypescb(atom open_dll_ret, atom type_ptr, atom p) 
	--printf(2, "|%s|\n", {make_str(type_ptr)}) 
	if not find(type_ptr, all_types) then 
		all_types &= type_ptr 
		all_resources &= {""} 
	end if 
	return 1 
end function 
constant enumrestypes_cb = call_back(routine_id("enumrestypescb")) 
function enumresnamescb(atom open_dll_ret, atom type_ptr, atom name_ptr, atom p) 
	--printf(2, "|%s| & |%s|\n", {make_str(name_ptr), make_str(type_ptr)}) 
	all_resources[find(type_ptr, all_types)] &= {make_str(name_ptr)} 
	if type_ptr = RT_GROUP_ICON then 
		--theicon = {open_dll_ret, make_str(name_ptr)} 
		theicon[ICON_INDEP] = make_str(name_ptr) 
	elsif type_ptr = RT_ICON then 
		theicon[ICON_HWDEP] = make_str(name_ptr) 
	end if 
	return 1 
end function 
constant enumresnames_cb = call_back(routine_id("enumresnamescb")) 
function enumreslangscb(atom open_dll_ret, atom type_ptr, atom name_ptr, atom lang, atom p) 
	--printf(2, "|%s| & |%s| & |%d|\n", {make_str(name_ptr), make_str(type_ptr), lang}) 
	all_langs &= lang 
	if type_ptr = RT_GROUP_ICON then 
		if not find(lang, theiconlangs) then 
		theiconlangs[ICON_INDEP] &= lang 
		end if 
	elsif type_ptr = RT_ICON then 
		if not find(lang, theiconlangs) then 
		theiconlangs[ICON_HWDEP] &= lang 
		end if 
	end if 
	return 1 
end function 
constant enumreslangs_cb = call_back(routine_id("enumreslangscb")) 
 
function LoadLibraryEx(sequence filename, atom reserved, atom flags) 
        atom ptr = allocate_string(filename) 
        atom ret = c_func(loadlibrary, {ptr, reserved, flags}) 
        free(ptr) 
        return ret 
end function 
function FreeLibrary(atom handle) 
	return c_func(freelibrary, {handle}) 
end function 
function EnumResourceTypes(atom open_dll_ret, atom cb, atom p) 
	return c_func(enumresourcetypes, {open_dll_ret, cb, p}) 
end function 
function EnumResourceNames(atom open_dll_ret, object t, atom cb, atom p) 
	atom ptr 
	if sequence(t) then 
		ptr = allocate_string(t) 
	else 
		ptr = t 
	end if 
	atom ret = c_func(enumresourcenames, {open_dll_ret, ptr, cb, p}) 
	if sequence(t) then 
		free(ptr) 
	end if 
	return ret 
end function 
function EnumResourceLanguages(atom open_dll_ret, object t, object n, atom cb, atom p) 
	atom tptr 
	if sequence(t) then 
		tptr = allocate_string(n) 
	else 
		tptr = t 
	end if 
	atom nptr 
	if sequence(n) then 
		nptr = allocate_string(n) 
	else 
		nptr = n 
	end if 
	atom ret = c_func(enumresourcelangs, {open_dll_ret, tptr, nptr, cb, p}) 
	if sequence(t) then 
		free(tptr) 
	end if 
	if sequence(n) then 
		free(nptr) 
	end if 
	return ret 
end function 
function BeginUpdateResource(sequence filename, integer b) 
        atom ptr = allocate_string(filename) 
        atom ret = c_func(beginupdateresource, {ptr, b}) 
        free(ptr) 
        return ret 
end function 
function EndUpdateResource(atom h, integer b) 
        return c_func(endupdateresource, {h, b}) 
end function 
function UpdateResource(atom h, atom t, sequence f, integer w, sequence b, integer n) 
        atom ret, ptr, fptr 
        ptr = allocate_string(b) 
        fptr = allocate_string(f) 
        ret = c_func(updateresource, {h, t, fptr, w, ptr, n}) 
        free(ptr) 
        free(fptr) 
        return ret 
end function 
 
atom res 
res = LoadLibraryEx(slice(command_line(), 3), 0, LOAD_LIBRARY_AS_DATAFILE) 
if res = 0 then 
        puts(1, "OpenHandle failed\n") 
        abort(0) 
end if 
if not EnumResourceTypes(res, enumrestypes_cb, 0) then 
        puts(1, "EnumResourceTypes failed\n") 
end if 
for i = 1 to length(all_types) do 
	if not EnumResourceNames(res, all_types[i], enumresnames_cb, 0) then 
        	printf(1, "EnumResourceNames failed for type %d, i = %d\n", 
			{all_types[i], i}) 
	end if 
end for 
for i = 1 to length(all_resources) do 
	for j = 1 to length(all_resources[i]) do 
	if not EnumResourceLanguages(res, all_types[i], all_resources[i][j], enumreslangs_cb, 0) then 
        	printf(1, "EnumResourceLanguagess failed for type %d, name %s, i = %d, j = %d\n", 
			{all_types[i], all_resources[i][j], i, j}) 
	end if 
	end for 
end for 
--? c_func(define_c_func(kernel, "GetLastError", {}, C_ULONG), {}) 
if not FreeLibrary(res) then 
        puts(1, "CloseHandle failed\n") 
        abort(0) 
end if 
res = BeginUpdateResource(slice(command_line(), 3), 0) 
if res = 0 then 
        puts(1, "BeginUpdateResource failed\n") 
        abort(0) 
end if 
--if UpdateResource(res, RT_ICON, MAKERESOURCEID(1), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), icon, length(icon)) then 
--if UpdateResource(res, RT_ICON, "eui", MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), icon, length(icon)) then 
for i = 1 to length(theiconlangs[ICON_INDEP]) do 
--if theiconlangs[ICON_INDEP][i] != 0 and UpdateResource(res, RT_GROUP_ICON, theicon[ICON_INDEP], theiconlangs[ICON_INDEP][i], icon, length(icon)) then 
        -- update worked 
--elsif theiconlangs[ICON_INDEP][i] = 0 then 
if UpdateResource(res, RT_GROUP_ICON, theicon[ICON_INDEP], theiconlangs[ICON_INDEP][i], icon, length(icon)) then 
else 
        -- update failed 
        printf(1, "UpdateResource GROUP_ICON failed for lang %d, i = %d\n", {theiconlangs[ICON_INDEP][i], i}) 
        ? EndUpdateResource(res, 1) 
	abort(0) 
end if 
end for 
for i = 1 to length(theiconlangs[ICON_HWDEP]) do 
--if theiconlangs[ICON_HWDEP][i] != 0 and UpdateResource(res, RT_ICON, theicon[ICON_HWDEP], theiconlangs[ICON_HWDEP][i], icon, length(icon)) then 
        -- update worked 
--elsif theiconlangs[ICON_HWDEP][i] = 0 then 
if UpdateResource(res, RT_ICON, theicon[ICON_HWDEP], theiconlangs[ICON_HWDEP][i], icon, length(icon)) then 
else 
        -- update failed 
        printf(1, "UpdateResource ICON failed for lang %d, i = %d\n", {theiconlangs[ICON_HWDEP][i], i}) 
        ? EndUpdateResource(res, 1) 
end if 
end for 
? EndUpdateResource(res, 0) 

Search



Quick Links

User menu

Not signed in.

Misc Menu