【发布时间】:2015-05-21 09:19:12
【问题描述】:
我正在尝试制作一个程序,它可以记住桌面图标的位置并将它们恢复到正确的位置。
现在我在使用这段代码时遇到了一些实际问题(我在这里得到了这段代码:https://social.msdn.microsoft.com/Forums/windows/en-US/d7df8a4d-fc0f-4b62-80c9-7768756456e6/how-can-i-get-desktops-icons-information-):
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);
}
这段C#代码应该可以获取所有桌面图标的文字和药水。问题是我无法使用此代码获得正确的文本。在此处检索桌面图标的文本:
string vText = Encoding.Unicode.GetString(vBuffer, 0, (int)vNumberOfBytesRead);
string IconName = vText;
不知何故,此处未正确检索文本。 vBuffer 在它的所有 256 个字节中都没有任何值。
所以现在我想出了一个使用指针的解决方案,并像这样重写了上面的代码:
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());
unsafe
{
// IntPtr baseaddress = n;
int nsize = (int)((LVITEM*)vPointer)->cchTextMax;
IntPtr baseaddress = (IntPtr)((LVITEM*)vPointer)->pszText;
ReadProcessMemory(vProcess, baseaddress, Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer, 0), nsize, 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);
}
}
现在的问题是,当我运行我的代码时,出现以下错误:
“试图读取或写入受保护的内存。这通常表明其他内存已损坏”
所以这似乎也不起作用。有人知道我如何成功获取每个桌面项目的文本吗? 而且我以前从未使用过指针,所以我想我可能做错了什么。有人看到上面的代码出了什么问题吗?
【问题讨论】:
-
请记住,由于桌面实际上是多个目录的组合,因此桌面上可以有多个名称完全相同的项目。
-
是的,我牢记这一点,但上面的代码实际上检索了公共用户地图和私人用户地图中的所有桌面图标,因此不存在问题。不过谢谢你的提及。
-
是的,但我想说的是,如果您仅根据图标名称记住图标的放置位置,那么如果有两个同名图标,您肯定会遇到问题吗?
-
是的,我知道,但我在代码的另一部分处理了这个问题。
-
有人知道如何解决这个问题吗?
标签: c# windows desktop shortcut