tisdagen den 31:e juli 2007

Helikopterspel, och mer

HelicoptergameJag satt och idlade vid min dator idag (lider fortfarande av att vara oförmögen att slösurfa) och kom att tänka på en gammal klassiker, "Fly the Copter"-spelet (Flash) som jag och bland andra min bror nötte för några år sedan (shit, det var nog ganska många år sedan faktiskt). Sökte lite och hittade bland annat här. Testa! Grym känsla.

Kom sedan även ihåg var jag först sett spelet - i en skruvad "webbdagbok" kallad "South Coast Diaries". Sökte efter den med och den finns kvar! Rekommenderad läsning, stundtals riktigt störd och rolig, vad jag minns. Här är adressen.

Sommarsemestern är slut

Idag är sista dagen på min semester, åtminstone för sommaren. I början kändes det skumt att vara ledig, att jag faktiskt jobbat ihop till ledighet och får lön när jag typ är i Luleå och slappar, men jag vande mig rätt snabbt. Nu har jag söndagsångest i kvadrat, ingen sådär påtaglig lust att börja jobba igen imorgon. Läste i en tidning att man ska dela upp semestern i småbitar så att det aldrig känns som att man är helt ledig, så undviker man tillbaka-på-jobbet-ångesten. Vad är det för blåbär som hittat på det? Jag vill ju totalt glömma bort att jag har ett jobb och bara vara ledig. Sommarlov! Som när jag var student! That's the shit.

Känner för övrigt i denna stund att mitt lilla tangentbord som jag haft några år nu faktiskt inte är så skönt. Tröga tangenter som sitter lite för tÃtt och med en konstig layout och så låter det skitmycket. Me wants något i denna stil istället...

söndagen den 8:e juli 2007

WebBrowser-kontrollen i .NET 2.0

Jag tänkte att jag skulle dela med mig av några erfarenheter från mitt senaste miniprojekt som involverade WebBrowser-kontrollen i .NET 2.0. Ett par observationer som kan underlätta för andra som tänker använda kontrollen (eftersom dokumentationen på nätet inte är sådär otroligt utförlig):
  • Eventet DocumentCompleted uppstår varje gång ett dokument är färdigladdat och renderat, vilket innebär att det triggas lika många gånger som det finns frames (eller iframes) på sidan. Om man har kod i eventhanteraren som ska manipulera eller tolka innehållet i det laddade dokumentet är det därför viktigt att man håller koll på vilket dokument det är man tar emot. Detta gör man enklast via WebBrowserDocumentCompletedEventArgs.Url.
  • I .NET 2.0 krävs FullTrust-permissionset:et för att ett program ska få använda en WebBrowser-kontroll. Vad jag förstår så har detta justerats i 3.0 genom introducerandet av System.Security.Permissions.WebBrowserPermission, vilket naturligtvis är mycket bättre eftersom det då går att tagga ned lite på rättigheterna för programmet i övrigt.
  • När man ska undersöka DOM-trädet eller HTML-koden för ett laddat dokument som innehåller frames/iframes så är det inte alltid som de element man söker efter finns med, även om de syns i browserfönstret. Jag tror att detta har att göra med hur IE (för det är dess motor som används) uppdaterar DOM-trädet för dynamiskt innehåll, eller något liknande. Däremot, om man vet vilken frame som de eftersökta elementen finns i så kan man leta sig fram till dem genom browser.Document.Window.Frames[frameIndex].Document. Detta HtmlDocument har metoder som exempelvis GetElementById som funkar, under förutsättning att det aktuella frame-dokumentet är laddat fullständigt. (Här har jag antagit att instansen av WebBrowser-kontrollen heter browser och att index för den intressanta framen är lagrat i frameIndex. Jag misstänker dock att förpopulerade samlingar som HmtlDocument.Links och liknande inte uppdateras korrekt för de olika frame-dokumenten. Vet inte varför, och jag kan inte med hundra procents säkerhet säga att det är på det sättet, men jag stötte på det ett par gånger i alla fall (varför jag använde HtmlDocument.GetElementsByTagName istället).
  • När du navigerar med din WebBrowser så laddas dokumenten asynkront, vilket är bra - det vore ju tråkigt om programmet slutade svara bara för att en webbsida tog lång tid på sig att ladda.
  • Om du behöver fylla i formulärfält, klicka på knappar eller på något annat sätt härma en verklig användares handlingar så kan du manipulera DOM-trädet precis som du skulle gjort med Javascript. Metoden HtmlElement.InvokeMember används för att trigga events på element i dokumentet (exempelvis "click" på knappar/länkar).
Hoppas det hjälper!

LunarBlogGrabber 0.5

LunarStormGrabber-screenshot
Uppdatering: LunarBlogGrabber har ersatts av Lunarspindeln. Läs mer och ladda ner »

För att sammanfatta ett par tidigare inlägg: Jag har saknat ett vettigt sätt att spara ner de dagboksinlägg (eller numera "blogginlägg") som jag tidigare skrivit på communityn Lunarstorm. Lunarstorm erbjuder ingen sådan funktionalitet och det är tråkigt/jobbigt att manuellt sitta och klicka igenom alla inlägg, klippa ut titel, datum och text och spara till någon slags lokal fil. Därför har jag under de senaste dagarna skrivit ihop ett litet program som gör detta åt mig. Från Lunarblogg till RSS-fil på några minuter, tadaa! Vad kan man då göra med en RSS-fil? Exempelvis importera sina inlägg till en Wordpress-baserad blogg (som denna). Troligen importera till många andra bloggmotorer också. Titta på i en RSS-läsare/feedläsare. Eller bara spara på sin dator för skojs skull.

Jag har döpt programmet till något så fantasifullt som LunarBlogGrabber. Varför ett engelskt namn på ett program som bara kan tillämpas i Sverige och troligen bara kommer att användas av svenskar? Jag kom inte på något bra svenskt namn. Hursomhelst! Programmet laddar du hem här:
LunarBlogGrabber 0.53

En liten friskrivningsklausul:

  • Vad jag vet kan programmet inte skada dig eller din dator, men om så ändå skulle ske så är det faktiskt inte mitt fel. All användning sker på egen risk.

  • Programmet är så vitt jag vet fritt från virus, men kolla ändå för säkerhets skull när du laddat ner det.

  • Det är inte den snabbaste, snyggaste eller mest responsiva och felfria mjukvaran som skrivits, men jag hoppas att det kan vara till nytta ändå.

  • Om Lunarstorm ändrar vissa delar av sin sidkod så kommer programmet med stor sannolikhet att sluta fungera.


Kända problem/brister/etc:

  • När man importerar inlägg så blir datumet rätt, men inte det exakta klockslaget.

  • Om något går snett i kommunikationen med Lunarstorm så får man, med något enstaka undantag, inget snyggt felmeddelande.

  • HTML-kod i inläggens texter bevaras icke - endast ren text.

  • Eftersom programmet använder en WebBrowser-komponent måste det köras med fullständiga rättigheter, vilket är default för nedladdade .NET-program i Windows XP. Hade ju varit trevligt att kunna köra med lite hårdare restriktioner, men...tough shit.

  • Vissa typer av citattecken (ni vet de där sneda, som inte är de vanliga man använder) (och kanske fler specialtecken) visas inte korrekt i den exporterade texten.

Forts: Exportera "blogg" från Lunarstorm

Okej, jag kunde inte hålla mig, var tvungen att göra ett försök till implementation av Lunar-blogg-export. Såhär gick det till:

Jag kom ihåg att det finns en .NET-kontroll som heter WebBrowser som är en wrapper runt Internet Explorers motor och presentation. Bara att dra och släppa den på WinForm-designytan och man har ett browserfönster som kan navigera runt på webben. Smidigt.

Vad jag däremot inte kände till var att man programmatiskt kan komma åt det HTML-dokument som browsern laddat, komplett med DOM-träd och allt. Detta betyder att man exempelvis kan klättra sig fram till specifika noder och manipulera dem "live". Aha - jag kunde alltså låta browsern navigera till Lunarstorms startsida och (när den väl laddat) fylla i mina användaruppgifter samt "klicka" på Logga in-knappen helt automatiskt. Första hindret avklarat: att få programmet att logga in på Lunarstorm förklädd till mig själv.

Sedan då? Som jag nämnde i min förra post använder sig Lunarstormsajten av ett UserID vilket är en sträng med jox som identifierar mig som inloggad användare. Detta behöver man eftersom det är en komponent i vissa undersidors adresser, exempelvis den egna Lunarbloggens. Efter att ha studerat HTML-koden på sidan som dyker upp efter man har loggat in hittade jag ett ställe där UserID:et används i ett Javascriptblock. Bara att plocka ut med regular expressions. Andra hindret övervunnet: att hitta och hämta mitt eget UserID.

Nu kunde jag låta browsern navigera till Lunarbloggens huvudsida, där de 25 senaste blogginläggen visas. Måste ha PostID för varje inlägg (en sträng som identifierar varje inlägg) för att kunna gå till respektive inläggs egna sida. Borde bara vara att gå igenom alla länkar på listsidan och plocka ut PostID med en matchning men så enkelt var det inte!

Det visade sig att WebBrowser-kontrollen har lite svårt för att uppdatera sitt DOM-träd korrekt när en sida använder frames. Jag inspekterar DOM-trädet då eventet DocumentCompleted inträffar, alltså då browsern har laddat färdigt det aktuella dokumentet. Men detta träd innehåller aldrig noderna i de nestade iframe-elementen! Attans. Vad göra? Sova. Tänka. Och sedan: hämta en referens till det aktuella fönstret i browsern och stega igenom alla frames. Genom att titta efter huvudframens namn ("lunar_main", som det ser ut nu) kan programmet avgöra när rätt frame hittats.

En intressant insikt: även om man hittat rätt frame och plockat fram dess dokument (programmatiskt) så är inte dokumentets elementlistor uppdaterade. Exempelvis innehåller propertyn Links inte sina egna länkar, utan huvuddokumentets. Däremot funkar det fint att klättra i DOM-trädet och på det sättet hitta de noder man söker (exempelvis genom metoder som GetElementById() och GetElementsByName()).

Resultat: programmet kunde nu, med hjälp av några schyssta regular expression-matchningar, extrahera PostID för de 25 senaste blogginläggen. Sweet! Tredje hindret alltså besegrat.

Övriga listsidor var enkla: bara att låta programmet klicka sig fram och samla in PostID-information så länge det finns en "Nästa"-knapp på sidan. Plockade samtidigt titel och datum från listorna. Hade alltså nu en fullständig lista över alla blogginlägg. Dessutom snyggt sorterade i fallande ordning efter datum.

Nästa moment: att låta användaren välja vilka av de funna inläggen som ska exporteras. En smal sak. När användaren gjort sitt val går programmet igenom listan och laddar den sida som visar varje inläggs innehåll. Där kan texten läsas ut ganska lätt, eftersom Lunarcrew varit vänliga nog att sätta den i en tabellrad med ett vettigt ID.

Sista steget är att spara de inlästa inläggen till en XML-fil som validerar mot någon RSS-standard. Jag valde RSS 2.0.

Och slutresultatet? Ett nätt litet .NET 2.0-program, inte helt testat och inte garanterat stabilt, men det har funkat för mig. Du hittar det här: http://blogg.fjeldstad.se/2007/07/lunarbloggrabber-05_9761.html

torsdagen den 5:e juli 2007

Exportera "blogg" från Lunarstorm

 Utdrag ur Lunarbloggen

Jag har ett gammalt Lunarstormkonto som jag i princip aldrig använder - jag loggar in någon gång då och då för att se om jag mot förmodan fått några meddelanden eller gästboksinlägg (vilket väl händer någon gång per år, eller så). Anledningen till att jag överhuvudtaget har kvar kontot är att jag under min gymnasietid skrev en del publik dagbok där, och de inläggen har fortfarande ett nostalgiskt värde. Det skulle vara schysst att kunna exportera dem till ett XML-baserat format för att spara dem på datorn, så att jag till slut kan låta Lunarkontot gå i graven. Tyvärr finns ingen sådan funktion inbyggd på Lunarstorm - kanske just för att man inte på något lätt sätt ska kunna migrera till en annan bloggmotor.

Jag funderar allvarligt på att yxa ihop något slags verktyg som hjälper till att spara ner mina dagboksinlägg. Det finns dock ett par randvillkor:
Inloggningsbiten är nog den klurigaste, åtminstone som jag ser det. Vet inte riktigt hur jag ska lyckas "lura" Lunarstorm att mitt verktyg (hur det nu kommer te sig) är jag, den registrerade användaren. När jag väl lyckats med det borde resten vara på sin höjd smärtfyllt - stega igenom HTML-koden, plocka ut postID:s till inläggen från en lista som spänner över ett godtyckligt antal sidor, ladda varje inläggs HTML-sida och spara ner dess innehåll till något bra format.

Jag återkommer om och i så fall när jag gått vidare med detta. Det har, så att säga, inte jättehög prioritet. Så länge: om någon har tips på hur jag kan åstadkomma det jag vill, skriv i så fall en kommentar!

20% MCPD: Enterprise Applications Developer

I morse skrev jag det första provet av fem på vägen mot min MCPD: Enterprise Applications Developer-certifiering och klarade det! Det kändes riktigt svettigt ett tag och jag trodde nog att det skulle bli väldigt på gränsen, men det visade sig i slutändan ha gått betydligt bättre än jag trott. Helt klart kluriga frågor, tur att jag är lite klurig jag med...

onsdagen den 4:e juli 2007

Anders, civilingenjör!

Examensbevis

W00t! Idag fick jag mitt examensbevis, vilket betyder att jag är helt, fullständigt och totalt färdig civilingenjör! Känns lite skumt, inte var det väl så himla länge sedan jag klev in på Studentbo i Norrköping för att hämta nycklarna till mitt korridorsrum...?