Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien
Toon posts:

[C#] ListBox item text via sendmessage *

Pagina: 1
Acties:
  • 236 views sinds 30-01-2008
  • Reageer

Verwijderd

Topicstarter
Ik probeer uit een ListBox alle item texten te krijgen. Alleen krijg ik bij de applicatie waarbij ik dit nodig heb rare resultaten terug, terwijl ik uit een willekeurig andere applicatie met dezelfde code juist prima resultaten terug krijg. waar kan het verschil in zitten? |:( Ik ben al uuuuuuuren aan het proberen te achterhalen WAT het probleem is, zodat ik het kan oplossen.

De code die ik gebruik:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Unicode)]
        internal static extern int SendMessage(IntPtr hwnd,
                                               int msg,
                                               IntPtr wParam,
                                               IntPtr lParam);

[DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Unicode)]
        internal static extern int SendMessage(IntPtr hwnd,
                                               int msg,
                                               int wParam,
                                               [MarshalAs(UnmanagedType.LPTStr)] StringBuilder lParam);
        
internal const int
          LB_GETTEXTLEN = 0x0000018A,
          LB_GETTEXT = 0x00000189,
          LB_GETCOUNT = 0x0000018B;

[...]

int listBoxItemCount = SendMessage(listBoxHandle, LB_GETCOUNT, IntPtr.Zero, IntPtr.Zero);

for (int i = 0; i < listBoxItemCount; i++)
{
    int length = SendMessage(listBoxHandle, LB_GETTEXTLEN, IntPtr.Zero, IntPtr.Zero);
    StringBuilder text = new StringBuilder();
    SendMessage(listBoxHandle, LB_GETTEXT, i, text);
}

Het verwijderen van listbox items gaat prima, ook de lengte bevat altijd de correcte waarde. Ik krijg alleen hele rare tekens bij LB_GETTEXT?

Waar moet ik het probleem zoeken? b.v. andere encoding?
Als jullie meer informatie/verschillen willen hebben, bijvoorbeeld informatie uit Spy++, laat het dan even weten.

  • Free rider
  • Registratie: November 2006
  • Laatst online: 27-11 02:21
Ansi/Unicode?
Merk op dat er geen Ansi/Unicode functies bestaan voor SendMessage.

Als een Window is gecreeerd met een Ansi functie (bv. CreateWindowExA) dan communiceert het in Ansi. Is het gecreeerd met een Unicode functie (bv. CreateWindowExW) dan communiceert het in Unicode.

  • SjonnieX
  • Registratie: Juni 2007
  • Laatst online: 15-04 21:57
Waarom gebruik je niet System.Windows.Forms.ListBox?
Misschien moet je nog text.EnsureCapacity(length) oproepen voordat je de text laat vulllen door SendMessage()?

Verwijderd

Topicstarter
Bedankt voor je reply Free rider en SjonnieX, ik ben me er blind op aan het staren, voor een oplossing en waardeer zekers alle hulp.

@Free rider: Ik denk dat mijn applicatie Unicode is, dat verteld spy++ mij namelijk.
Ik had uiteraard al geprobeerd om de CharSet.Unicode op alle andere waarden te zetten, onder andere CharSet.ANSI.

Ik heb ook het volgende geprobeerd:
C#:
1
2
3
4
5
6
int len = SendMessage(listBoxHandle, LB_GETTEXTLEN, IntPtr.Zero, IntPtr.Zero);
IntPtr text = Marshal.AllocHGlobal(len);
byte []itemText = new byte[len];
SendMessage(listBoxHandle, LB_GETTEXT, (IntPtr)i, text);
Marshal.Copy(text, itemText, 0, len);
string s = System.Text.Encoding.Unicode.GetString(itemText);



Ik denk nu dat het met het volgende te maken heeft:
If you create the list box with an owner-drawn style but without the LBS_HASSTRINGS style, the buffer pointed to by the lParam parameter will receive the value associated with the item (the item data). (Bron)
De ListBox bevat de LBS_OWNERDRAWFIXED style in zijn properties... Zou dit inhouden dat een GetText naar zijn eigen formaat verwijst, ipv van naar een string? dat zou iig de rare tekens verklaren.
Alleen dan snap ik alleen nog maar minder van hoe ik de text van de items zou moeten achterhalen... 8)7

@SjonnieX: omdat het niet de listbox van de huidige applicatie is. Ik ben een ander programma aan het aansturen waarvan de API tekort schiet. Ik heb geprobeerd om er een ListBox van te maken met het commando: ListBox lb = (ListBox)ListBox.CreateFromHandle(listBoxHandle), maar dat werkte niet (had ik ook niet verwacht trouwens). Of bedoelde je dat niet?

  • Doctor M.
  • Registratie: September 2004
  • Laatst online: 05:46
Probeer eens LB_GETITEMDATA en kijk wat je daarmee kan terugkrijgen. Zover ik de omschrijving van msdn snap zou deze de waarde teruggeven die bij de LB_ADDSTRING of LB_INSERTSTRING meegegeven is.

http://msdn2.microsoft.com/en-us/library/ms671415.aspx

  • Free rider
  • Registratie: November 2006
  • Laatst online: 27-11 02:21
Als de listbox niet zelf de tekst bevat maar een pointer, weet alleen het programma wat de betekenis van het item is: Windows weet evenmin wat de tekst zal zijn. Het enige wat je kan doen is aan het programma vragen om zelf de inhoud te tekenen, door het een WM_DRAWITEM te sturen.

NB: Ik denk niet dat je een DC naar een ander proces kunt sturen - wellicht moet je een DLL injecten en daarin alles regelen. Je kan dan alle acties op de DC laten loggen door een metafile te gebruiken, en deze later af te draaien.
Dit alles lijkt me de moeite niet waard en kan je beter een plan B bedenken.

Verwijderd

Topicstarter
Als ik met een LB_GETITEMDATA een bericht stuur, krijg ik inderdaad een pointer terug naar een locatie in het geheugen. Dit heb ik gecontroleerd door te kijken met een memory editor naar het geheugen van de applicatie. Daar staat een wide string met de text in het geheugen.
Ziet er veel belovend uit dus...

Maar hoe krijg ik nu de tekst van die locatie als een string terug? ....

als ik dit probeer
C#:
1
2
3
int b = (int)SendMessage(listBoxHandle, LB_GETITEMDATA, i, IntPtr.Zero);
byte[] byteText = new byte[200];
Marshal.Copy((IntPtr)b, byteText, 0, 4);

krijg ik de volgende melding terug
code:
1
2
3
System.AccessViolationException: Poging tot het lezen of schrijven van beveiligd geheugen. Dit duidt er vaak op dat ander geheugen is beschadigd.
   bij System.Runtime.InteropServices.Marshal.CopyToManaged(IntPtr source, Object destination, Int32 startIndex, Int32 length)
   bij System.Runtime.InteropServices.Marshal.Copy(IntPtr source, Byte[] destination, Int32 startIndex, Int32 length)

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Je kunt niet 'zomaar' het geheugen van een ander proces uitlezen ;) Wiedes he? ;)

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Verwijderd

Topicstarter
RobIII schreef op woensdag 25 juli 2007 @ 10:24:
Je kunt niet 'zomaar' het geheugen van een ander proces uitlezen ;) Wiedes he? ;)
Nee, dat had ik ook al beredeneerd... maar ja, nu uiteraard de vraag, hoe krijgen we dat wél voor elkaar? Zal wel niet makkelijk worden ;) dll-injectie waarschijnlijk?

Verwijderd

Topicstarter
HEBBES!!! Eindelijk :D

De extra benodigde code, voor de geinteresseerden:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[DllImport("user32.dll")]
public static extern uint GetWindowThreadProcessId(IntPtr hwnd, out Int32 lpdwProcessId);

[DllImport("Kernel32.dll")]
public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, Int32 dwProcessId);

[DllImport("Kernel32.dll")]
public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] buffer, UInt32 size, ref IntPtr lpNumberOfBytesRead);

[...]

Int32 pid = new Int32();
GetWindowThreadProcessId(listBoxHandle, out pid);
IntPtr hwnd = OpenProcess(PROCESS_VM_READ, false, pid); // PROCESS_VM_READ = 0x0010;
int b = (int)SendMessage(listBoxHandle, LB_GETITEMDATA, i, IntPtr.Zero); // LB_GETITEMDATA = 0x0199
byte[] buffer = new byte[200];
IntPtr nRead = IntPtr.Zero;
bool result = ReadProcessMemory(hwnd, (IntPtr)b, buffer, 200, ref nRead);
string s = System.Text.Encoding.Unicode.GetString(buffer);
s = s.Substring(0, s.IndexOf('\0')-1);


Wat een gemartel was dat zeg, om wat tekst uit een listbox te krijgen :P

  • Alex
  • Registratie: Juli 2001
  • Laatst online: 10-11 17:17
Als ik dit zie dan komen er 3 dingen in mij op:
1. Als ik dit zo zie vraga ik me eigenlijk af of je weet wat je doet en ook door hebt wat dit doet met het systeem?
2. Onderhoud van de code? Ooit aan gedacht dat dit aangepast moet gaan worden door een collega/opvolger?
3. Hoort dit niet thuis op thedailywtf.com? ;)

Nu ben ik altijd erg pessimistisch hoor...

Deze post is bestemd voor hen die een tegenwoordige tijd kunnen onderscheiden van een toekomstige halfvoorwaardelijke bepaalde subinverte plagiale aanvoegend intentioneel verleden tijd.
- Giphart


  • ATS
  • Registratie: September 2001
  • Laatst online: 28-11 20:56

ATS

Hmmm.... dit ziet er erg vies uit. Zo controleer je op geen enkel moment of je functies die je aanroept wel gelukt zijn! Als het niet lukt, dan heb je een crash te pakken, of erger...

My opinions may have changed, but not the fact that I am right. -- Ashleigh Brilliant


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Alex schreef op woensdag 25 juli 2007 @ 12:30:
Als ik dit zie dan komen er 3 dingen in mij op:
1. Als ik dit zo zie vraga ik me eigenlijk af of je weet wat je doet en ook door hebt wat dit doet met het systeem?
Vertel eens dan? Behalve wat closehandles en checks (die wrsch. voor het voorbeeld zijn weggelaten) zie ik niet iets super-engs? Dit lijkt me een 'proof-of-concept', ik neem aan dat error-handling nog komt.
Alex schreef op woensdag 25 juli 2007 @ 12:30:
2. Onderhoud van de code? Ooit aan gedacht dat dit aangepast moet gaan worden door een collega/opvolger?
Again, ik zie niets super-engs en gewoon wat standaard api-calls. Wat commentaar zou geen kwaad kunnen, maar again is dit mss. nog niet gebeurd (code is 'vers') en/of weggelaten voor het voorbeeld.
Alex schreef op woensdag 25 juli 2007 @ 12:30:
3. Hoort dit niet thuis op thedailywtf.com? ;)
Wat is er dan zo horrible aan? Heb je een betere/mooiere manier?

[ Voor 4% gewijzigd door RobIII op 25-07-2007 12:37 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Verwijderd

Topicstarter
RobIII schreef op woensdag 25 juli 2007 @ 12:37:
[...]

Vertel eens dan? Behalve wat closehandles en checks (die wrsch. voor het voorbeeld zijn weggelaten) zie ik niet iets super-engs? Dit lijkt me een 'proof-of-concept', ik neem aan dat error-handling nog komt.


[...]

Again, ik zie niets super-engs en gewoon wat standaard api-calls. Wat commentaar zou geen kwaad kunnen, maar again is dit mss. nog niet gebeurd (code is 'vers') en/of weggelaten voor het voorbeeld.


[...]

Wat is er dan zo horrible aan? Heb je een betere/mooiere manier?
Je hebt het helemaal door 8) Bedankt voor het ophelderen aan de anderen. Ik had verwacht dat men wel begreep dat dit niet de uiteindelijke code is... :X

Sterker nog, zien jullie ergens bijv i gedefinieerd worden? Inderdaad, gedeeltelijke code ;) Zoals RobIII al aangaf, proof of concept, ondertussen zijn alle variabelen hernoemd naar duidelijke namen, en zijn er error-handling en controles aan toe gevoegd. Ben wel blij dat ik hem al well 'managed' had gemaakt, en de oorspronkelijke unsafe en fixed code blokken er al uit gehaald heb >:)

  • SjonnieX
  • Registratie: Juni 2007
  • Laatst online: 15-04 21:57
ik heb de method nog even opgezocht en hij heet naar mijn mening:
ListBox lb = (ListBox)ListBox.FromHandle(listBoxHandle)

als dit niet werkt, dan zou ik toch de dubbele cast eruithalen:
IntPtr b = (IntPtr)SendMessage(listBoxHandle, LB_GETITEMDATA, i, IntPtr.Zero);
ReadProcessMemory(hwnd, b, buffer, 200, ref nRead)
Pagina: 1