C#: de tekst verkrijgen van een desktop shortcut.

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • MasterTweaker
  • Registratie: Maart 2010
  • Laatst online: 12-09 18:01
Ik ben bezig met een programmaatje waarmee je de positie van alle sohortcuts op je desktop op kan slaan en die shortcuts bij wijzigingen op je desktop ook weer op de juiste locatie kan terugzetten.

Nu had ik dus ergens een stuk code gevonden die de locatie en tekst van alle sortcuts op je desktop kan achterhalen. Het gaat om de volgende code: (MSDN: How can i get desktop's icon's information ?)

code:
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
 private void button1_Click(object sender, EventArgs e)

        {

            // get the handle of the desktop listview

            IntPtr vHandle = FindWindow("Progman", "Program Manager");

            vHandle = FindWindowEx(vHandle, IntPtr.Zero, "SHELLDLL_DefView", null);

            vHandle = FindWindowEx(vHandle, IntPtr.Zero, "SysListView32", "FolderView");

 

            //Get total count of the icons on the desktop

            int vItemCount = SendMessage(vHandle, LVM_GETITEMCOUNT, 0, 0);

            this.label1.Text = vItemCount.ToString();

           

            uint vProcessId;

            GetWindowThreadProcessId(vHandle, out vProcessId);

 

            IntPtr vProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ |

                PROCESS_VM_WRITE, false, vProcessId);

            IntPtr vPointer = VirtualAllocEx(vProcess, IntPtr.Zero, 4096,

                MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);

            try

            {

                for (int j = 0; j < vItemCount; j++)

                {

                    byte[] vBuffer = new byte[256];

                    LVITEM[] vItem = new LVITEM[1];

                    vItem[0].mask = LVIF_TEXT;

                    vItem[0].iItem = j;

                    vItem[0].iSubItem = 0;

                    vItem[0].cchTextMax = vBuffer.Length;

                    vItem[0].pszText = (IntPtr)((int)vPointer + Marshal.SizeOf(typeof(LVITEM)));

                    uint vNumberOfBytesRead = 0;

 

                    WriteProcessMemory(vProcess, vPointer,

                        Marshal.UnsafeAddrOfPinnedArrayElement(vItem, 0),

                        Marshal.SizeOf(typeof(LVITEM)), ref vNumberOfBytesRead);

                    SendMessage(vHandle, LVM_GETITEMW, j, vPointer.ToInt32());

                    ReadProcessMemory(vProcess,

                        (IntPtr)((int)vPointer + Marshal.SizeOf(typeof(LVITEM))),

                        Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer, 0),

                        vBuffer.Length, ref vNumberOfBytesRead);

                 string vText = Encoding.Unicode.GetString(vBuffer, 0,

                        (int)vNumberOfBytesRead);

                    string IconName = vText;


                    //Get icon location

                    SendMessage(vHandle, LVM_GETITEMPOSITION, j, vPointer.ToInt32());

                    Point[] vPoint = new Point[1];

                    ReadProcessMemory(vProcess, vPointer,

                        Marshal.UnsafeAddrOfPinnedArrayElement(vPoint, 0),

                        Marshal.SizeOf(typeof(Point)), ref vNumberOfBytesRead);

                    string IconLocation = vPoint[0].ToString();

 

                    //Insert an item into the ListView

                    this.listView1.Items.Add(new ListViewItem(new
                      string[]{IconName,IconLocation}));

                }

            }

            finally

            {

                VirtualFreeEx(vProcess, vPointer, 0, MEM_RELEASE);

                CloseHandle(vProcess);

            }

 

            this.listView1.AutoResizeColumns(ColumnHeaderAutoResizeStyle.ColumnContent);

        }

    }


Met deze code kan ik wel de locatie van de shortcuts verkrijgen maar de tekst van de shortcut verkrijgen lukt niet. De tekst wordt hier verkregen (zie ook de code hierboven):

code:
1
2
3
 string vText = Encoding.Unicode.GetString(vBuffer, 0,
     (int)vNumberOfBytesRead);
     string IconName = vText;


Tijdens het debuggen zie ik dat de string: vText de volgende waarde heeft:
/0/0/0/0/0/0/0/0 enz.

De juiste tekst wordt dus niet verkregen en er gaat dus iets fout bij de functie: Encoding.Unicode.GetString(.......

Echter weet ik niet precies wat er fout gaat. Iemand een idee?
En weet iemand ook hoe je de locatie (folder path) van een 'desktop shortcut' kan achterhalen? :)

Acties:
  • 0 Henk 'm!

  • BM
  • Registratie: September 2001
  • Laatst online: 20:37

BM

Moderator Spielerij
vText krijgt dus de verkeerde waarde, maar heb je al gekeken wat de inhoud van vBuffer is? Ik vermoed dat je daar verder mee moet kunnen komen.

Xbox
Even the dark has a silver lining | I'm all you can imagine times infinity, times three


Acties:
  • 0 Henk 'm!

  • MasterTweaker
  • Registratie: Maart 2010
  • Laatst online: 12-09 18:01
BM schreef op woensdag 06 mei 2015 @ 17:47:
vText krijgt dus de verkeerde waarde, maar heb je al gekeken wat de inhoud van vBuffer is? Ik vermoed dat je daar verder mee moet kunnen komen.
vBuffer heeft de volgende waardes:
[0] ->0
[1] ->0
[2] ->0
....enz

Tot aan 256 is de waarde nul.

Vbuffer krijgt ook nergens een waarde toegewezen. Of zou dat hier gebeuren?:

code:
1
ReadProcessMemory(vProcess,(IntPtr)((int)vPointer + Marshal.SizeOf(typeof(LVITEM))), Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer, 0), vBuffer.Length, ref vNumberOfBytesRead);


Maar waar het nu precies fout gaat zie ik nog steeds niet. :)

[ Voor 22% gewijzigd door MasterTweaker op 06-05-2015 17:55 ]


Acties:
  • 0 Henk 'm!

  • Mijzelf
  • Registratie: September 2004
  • Niet online
Mogelijk zit het probleem hier: (uit msdn):
If the LVIF_TEXT flag is set in the mask member of the LVITEM structure, the pszText member must point to a valid buffer and the cchTextMax member must be set to the number of characters in that buffer. Applications should not assume that the text will necessarily be placed in the specified buffer. The control may instead change the pszText member of the structure to point to the new text, rather than place it in the buffer.

Verder geef je een array van bytes mee als buffer, die je daarna met die Unicode functie gaat converteren. Maar je gebruikt LVM_GETITEMW, waarmee je specificeert dat je een wide character buffer gebruikt, die je dus niet hoeft te converteren.

En nog iets, als dit een 64 bits OS is, mag je niet zomaar
code:
1
                    SendMessage(vHandle, LVM_GETITEMW, j, vPointer.ToInt32());
Dat zou denk ik 'ToInt64' moeten zijn, maar voor het mooie zou je een functie moeten gebruiken die zichzelf aanpast. ToIntPtr, misschien. Ik ken geen C#

Acties:
  • 0 Henk 'm!

  • MasterTweaker
  • Registratie: Maart 2010
  • Laatst online: 12-09 18:01
Mijzelf schreef op woensdag 06 mei 2015 @ 20:59:
Mogelijk zit het probleem hier: (uit msdn):
If the LVIF_TEXT flag is set in the mask member of the LVITEM structure, the pszText member must point to a valid buffer and the cchTextMax member must be set to the number of characters in that buffer. Applications should not assume that the text will necessarily be placed in the specified buffer. The control may instead change the pszText member of the structure to point to the new text, rather than place it in the buffer.
Ok thnx. Maar heb je enig idee wat ik aan de code dien te veranderen om dit probleem te voorkomen?

Acties:
  • 0 Henk 'm!

  • Mijzelf
  • Registratie: September 2004
  • Niet online
Ik weet niet hoe het in C# moet, kan alleen raden. Je maakt nu een vPointer datablok aan, en kopieert daar de gegenereerde vItem[ 0 ] in, waarbij pszText verwijst naar het geheugen volgend op de (gecopieerde) vItem[ 0 ].
Vervolgens geef je vPointer mee met de SendMessage, en daarna kopeer je het bedoelde tekstbuffer naar vBuffer:
C#:
1
2
3
4
ReadProcessMemory(vProcess,
                        (IntPtr)((int)vPointer + Marshal.SizeOf(typeof(LVITEM))),
                        Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer, 0),
                        vBuffer.Length, ref vNumberOfBytesRead);

Inplaats daarvan zou je niet de geleverde buffer moeten uitlezen, maar de pointer. Misschien zo:
C#:
1
2
3
4
ReadProcessMemory(vProcess,
                        (IntPtr)((LVITEM *)vPointer)->pszText),
                        Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer, 0),
                        (LVITEM *)vPointer)->cchTextMax, ref vNumberOfBytesRead);
Je mag niet uitlezen over de lengte van vBuffer, omdat je niet weer of het sourceheheugen over die lengte leesbaar is.

Acties:
  • 0 Henk 'm!

  • MasterTweaker
  • Registratie: Maart 2010
  • Laatst online: 12-09 18:01
Mijzelf schreef op zaterdag 16 mei 2015 @ 11:47:
Ik weet niet hoe het in C# moet, kan alleen raden. Je maakt nu een vPointer datablok aan, en kopieert daar de gegenereerde vItem[ 0 ] in, waarbij pszText verwijst naar het geheugen volgend op de (gecopieerde) vItem[ 0 ].
Vervolgens geef je vPointer mee met de SendMessage, en daarna kopeer je het bedoelde tekstbuffer naar vBuffer:
C#:
1
2
3
4
ReadProcessMemory(vProcess,
                        (IntPtr)((int)vPointer + Marshal.SizeOf(typeof(LVITEM))),
                        Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer, 0),
                        vBuffer.Length, ref vNumberOfBytesRead);

Inplaats daarvan zou je niet de geleverde buffer moeten uitlezen, maar de pointer. Misschien zo:
C#:
1
2
3
4
ReadProcessMemory(vProcess,
                        (IntPtr)((LVITEM *)vPointer)->pszText),
                        Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer, 0),
                        (LVITEM *)vPointer)->cchTextMax, ref vNumberOfBytesRead);
Je mag niet uitlezen over de lengte van vBuffer, omdat je niet weer of het sourceheheugen over die lengte leesbaar is.
Thnx. Ik heb dat stukje code nu geschreven als:

code:
1
2
3
4
5
6
7
                    unsafe
                    {
                    IntPtr baseaddress = (IntPtr)((LVITEM*)vPointer)->pszText);
                    int nsize = (int)((LVITEM*)vPointer)->cchTextMax);
                    
                    ReadProcessMemory(vProcess, baseaddress, Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer, 0), nsize, ref vNumberOfBytesRead);
       }


Maar zowel pszText als ccTextMax zijn nu rood onderstreept. Ik krijg dan de volgende error melding:

Only assignment, call, increment, decrement, and new object expressions can be used as a statement

Heeft iemand een idee wat ik hier aan kan doen?

Acties:
  • 0 Henk 'm!

  • MasterTweaker
  • Registratie: Maart 2010
  • Laatst online: 12-09 18:01
Het werkt nu toch als ik het als volgt doe:
code:
1
2
3
4
5
6
7
8
9
10
11
  unsafe
                    {
                    IntPtr baseaddress = (IntPtr)((LVITEM*)vPointer)->pszText;
                    int nsize = (int)((LVITEM*)vPointer)->cchTextMax;


                    //ReadProcessMemory(vProcess, (IntPtr)((LVITEM*)vPointer)->pszText, Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer, 0), (int)((LVITEM*)vPointer)->cchTextMax, ref vNumberOfBytesRead);
                    
                        
                    ReadProcessMemory(vProcess, baseaddress, Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer, 0), nsize, ref vNumberOfBytesRead);
                    }


Alleen nu krijg ik de volgende foutmelding als ik de code uitvoer:

" Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

Iemand een idee wat ik hier aan kan doen?

Acties:
  • 0 Henk 'm!

  • efan
  • Registratie: Januari 2001
  • Niet online
en als je via Tools->Options
Debugging->General
"Suppress JIT optimization on module load" uitvinkt?

of vanwege een stukje 64bit wat je gebruikt (intptr?) en vervolgens compiled als 32bit?

[ Voor 30% gewijzigd door efan op 16-05-2015 17:18 ]


Acties:
  • 0 Henk 'm!

  • MasterTweaker
  • Registratie: Maart 2010
  • Laatst online: 12-09 18:01
ido schreef op zaterdag 16 mei 2015 @ 17:17:
en als je via Tools->Options
Debugging->General
"Suppress JIT optimization on module load" uitvinkt?

of vanwege een stukje 64bit wat je gebruikt (intptr?) en vervolgens compiled als 32bit?
Ik krijg dan nog steeds de volgende foutmelding:
" Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
Pagina: 1