Stamping EXEs And DMGs
Here’s a brief Ruby scriptone that demos Shoes’ events and animationand it’s been injected into an EXE and a DMG:
These are web installers. Using native calls on each platform, they’ll install Shoes if no Shoes is found on the system. (If you already have Shoes installed, though, it won’t update for you.) Not a big deal, not worth mentioning really. Installers.
But, hold up. What if I told you that Shoes can build EXEs and DMGs on any of its platforms? Without needing a compiler. You can build EXEs and DMGs from Windows. And from Linux. And from OS X.
This is the built-in packager, which can be brought up with shoes -p
(or shoes --package
on Windows and Linux. On OS X, it’s in the Shoes main menu. (Or ⌘-x.)
Even as Ron Popeil is to the unflavored turkey, so is Shoes to these most willing binaries.
The magic is a little Ruby extension I use for manipulating EXEs and DMGs. It’s based on two programs: anal_pe and xpwn.
If you poke around with a hex editor inside Windows’ PE binary format, you’ll find an .rsrc section at the end of the file which contains the icons and dialog boxes. I insert the Ruby script into this mess.
binj = Binject::EXE.new("blank.exe")
binj.inject("SHOES_FILENAME", "simple-accordion.rb")
File.open("simple-accordion.rb") do |f|
binj.inject("SHOES_PAYLOAD", f)
end
binj.save("accordion.exe")
The blank.exe is the empty web installer. It’s an executable that scans its own resources and then bases its moves on what it finds. If it finds a Ruby script (or Shy file) in the SHOES_PAYLOAD
resource, it’ll run it. And if it finds an installer in the SHOES_SETUP
resource, it’ll run the installer rather than going out to the web.
So, yeah, blank.exe comes with Shoes and we inject when you go to package. Yeah?
Fabricating DMGs is a different kind of binary hacking. In this case, we’ve got to build an HFS+ partition and then convert that to a DMG.
One would start by making a small, raw HFS+ file and gzipping it.
$ dd if=/dev/zero of=blank.hfs bs=512K count=1
$ mkfs.hfsplus -v Shoes blank.hfs
$ gzip blank.hfs
$ mv blank.hfs.gz blank.hfz
This blank disk gets included with Shoes as well. And at runtime, we use our extension to build the innards of the DMG.
binj = Binject::DMG.new("blank.hfz", "Accordion")
binj.inject_dir("Accordion.app", "/tmp/accordion.app")
binj.chmod_file(0755, "Accordion.app/Contents/MacOS/accordion-launch")
binj.save("accordion.dmg")
This amazing code is only possible due to tons of incredible work by the XPwn dev team. First of all, their DMG and HFS+ code is totally portable and only depends on zlib. But also, the API is just too easy. Their project is going to catch on big, not only in jail breaking the iPhone from any platform, but in building DMGs from the commandline on OS X itself!
Since both anal_pe and XPwn are GPL, I’m afraid this extension must be GPL as well. The rest of Shoes is MIT. Which is okay I guess since the packager isn’t really needed to run Shoes apps.
This is all a bleeding fresh part of today’s builds.
As for Linux. I’m not decided as to what to do about generating Linux binaries. Either using makeself or plain shell scripting will do. But do I download binaries or automate package manager steps? The unsurety.
tstrokes
Man this is awesome stuff. Shoes was already cool but now it is on a completely different level.
Inferis
Wow, this is super. We can actually give our apps to other people now :)
Phil
I’m going to ask people to give back the apps I’ve already given to them.
I wrote anal_pe
I wrote anal_pe and I have no problem with changing the license to accommodate what you’re doing. You should have emailed me to let me know…
/mike
Dr Nic
This is a new level of inspired genius.
Re: linux, on debian/ubu I’d… well… I can’t think of the last thing I installed that was’t a rubygem or via apt-get or via source. I only live in that world on ui-less production boxes, so no fancy Shoes apps in that world anyway. I could have not written this paragraph.
Dr Nic
Those are great programs. Nice find indeed.
_why
mike (of anal_pe): Since XPwn is GPL as well, I’m perfectly okay with this licensing. I’m not down on the GNU way, that was just a note. Thankyou for your nice work, of course!
Will
It’s like being able to wear and tie your shoes. Great!
technomancy
> But do I download binaries or automate package manager steps?
I’d suggest creating a .deb file and uploading it to a Launchpad PPA maybe? Launchpad is to debs as github is to gems in a way. If the client supports apturl, things are easy peasy. (Ignoring fedora/gentoo users.)
Feoh
Seems like downloading binaries for Linux is the way to go. If you’re reasonably conservative about the shlibs you require a fairly vanilla Linux binary will run in virtually every distribution. The package approach would be nice but you’d need to support at least .deb and .rpm which could be more pain than it’s worth.
_why
Feoh: I think I’ll follow your suggestion, only relying on openssl and zlib to be present on the system. I guess I could probably have the shell script sniff out exactly what it needs. That could prevent the download of gtk, glib, cairo, pango and vlc.
ms_windows
Whoa, this is truly awesome. Congrats. However you would do well to remove your rubies from my TEMP after you’re done.
oh yeah
as awesome as this is, it doesn’t actually seem to work on windows. It gets as far as ‘packaging’ and then nothing happens. It leaves behind a small, non-working exe with the same name as the ruby script.
_why
oh yeah: Oh, I have no doubts that there are bugs. Send me the script you tried to bundle.
oh yeah
I tried simple-accordian.rb from the Shoes sample dir.
_why
Looks like the windows build has an older copy of the Ruby extension. I’ve got to run, but a new build should be out in a day or two. Thanks for finding that.
Bluebie
It isn’t working on Mac OS Leopard intel either, frozen progress bar doodad. It does make the .dmg and .exe though, even though there is no progress, however when I mount the DMG and run the .app, shoes opens and asks me which ruby file to run. O_o
Also what about dependancies like pictures and junk? gotta figure those in too! Maybe shoes should be like camping, have appname.rb and a directory named appname, and put all your junk in there. Be easy to do on Mac, but on windows maybe you could shove the directory data in to a zip and write the zipped data in to the exe? Surely windows provides api’s for unzipping stuff, which could be shoved out to a temporary directory. :)
Julik
On Leopard PPC the downloaded app does one jump in the dock and dies.
review:~ julik$ /SimpleAccordion.app/Contents/MacOS/simple-accordion-launch
/SimpleAccordion.app/Contents/MacOS/simple-accordion-launch: line 9: ./cocoa-install: Bad CPU type in executable
FSPathMakeRef(/Applications/Shoes.app) failed with error -43.
Are we PPC oldies with the 4-core number crunchers sent away from the door at the Shoes party?
oh yeah
Bluebie: You can package a .shy (which can include pictures and stuff)
proppy
On Linux, I heard one could use PackageKit to trigger installation of packages in a cross distribution way.
That could be handy for installing shoes and its dependencies, before installing the distributed shoes application.
cmw
I got it figured out on an Intel-Leopard to build the apps. works like charm (even with pics and stuff if you build a shy).
Only there are some flaws I discovered:
- It won’t build any ‘Linux’ package for me
- It freezes after having created the exe and dmg and dies eventually (might be connected to the above)
- It does not include shoes in the exe/dmg if asked to do so
Oh and one minor thing is that I need to dig around to find a way of building the shy since shoes -s won’t work and you don’t have the option to build it in the menu.
shoes-launch -s is the way on Leopard.
jdefontes
Punting on the version dependecies is kinda sucky.
I’ve got a really old version installed. The exe above launches fine but the app itself errors out on “uninitialized constant” or some such. If you’re going to detect that I have Shoes installed and not upgrade me, you could at least tell me that the version I have isn’t compatible with the app I’m trying to run. And then give me the option to upgrade.
tim
woo hoo!
on ubuntu hardy:
( :7693): Gtk- CRITICAL **: gtk_widget_show: assertion `GTK_IS_WIDGET (widget)’ failed
DeeJay
“These are web installers. Using native calls on each platform, they’ll install Shoes if no Shoes is found on the system.”
On Windows, unsurprisingly, the installer fails – silently – if not run with Administrator rights. The short cuts get created, but the ‘Common Files\Shoes\…’ directory tree cannot be built.
But once it’s installed it’s really exciting news!
_why
This hack is only a few days old, so it’s great to finally get some reaction and some bug reports. My complements to all of you.
jdefontes: Okay, good point, I will go with a prompt if it finds a new installer.
cmw
on jdefontes’ post:
perhaps one could also add the version number it is built/tested with like that:
Shoes. app(:version => ’r726’) do … end
Or directly include the version of the builder?
Anyway, kudos to you _why. Awesome Shoes. Shiny!
Girvo
Hi there! Love shoes :)
I built the latest release from source on Ubuntu here, worked like a charm. Only the package manager won’t build the programs for me :(
(<unknown>:13474): Gtk-CRITICAL **: gtk_widget_show: assertion `GTK_IS_WIDGET (widget)' failed
That’s my error.
_why
Hey, Girvo. Yes, this is fixed in commit d1ac0de.
Girvo
Wicked, I’ll test it when I get into work :D
Comments are closed for this entry.