-
-
[求助]大家来帮我看一个线程,读内存错误
-
发表于: 2008-5-8 17:03 3794
-
线程单元:
unit ShellChangeNotifierThread;
interface
uses
Windows, SysUtils, Classes, comctrls, CommCtrl, IniFiles;
type
TMyShellChangeThread = class(TThread)
private
FMutex,
FWaitHandle: Integer;
FWatchSubTree: Boolean;
FWaitChanged : Boolean;
//FNotifyOptionFlags: DWORD;
protected
procedure Execute; override;
public
procedure GetDesktopIconPosition;
constructor Create; virtual;
destructor Destroy; override;
end;
var
CS : TRTLCriticalSection; // 临界区
const
MyDesktop : Pchar ='Z:\桌面';
StrVIPSet = 'Z:\VIPSet\VIPSet.ini';
{ 多个线程操作相同的数据时,一般是需要按顺序访问的,否则会引导数据错乱,无法控制数据,变成随机变量。
为解决这个问题,就需要引入互斥变量,让每个线程都按顺序地访问变量。
这样就需要使用EnterCriticalSection和LeaveCriticalSection函数。 }
implementation
//uses Dialogs;
//------------------------------------------------------------------------------
function GetDesktopHand: THandle;
begin
Result:=FindWindow('Progman', nil);
Result:=GetWindow(Result, GW_Child);
Result:=GetWindow(Result, GW_Child);
end;
//------------------------------------------------------------------------------
constructor TMyShellChangeThread.Create;
begin
FreeOnTerminate := True;
//FChangeEvent := ChangeEvent;
FMutex := CreateMutex(nil, True, nil);
//Mutex is used to wake up the thread as it waits for any change notifications.
WaitForSingleObject(FMutex, INFINITE); //Grab the mutex.
FWaitChanged := false;
inherited Create(True);
end;
destructor TMyShellChangeThread.Destroy;
begin
if FWaitHandle <> ERROR_INVALID_HANDLE then
FindCloseChangeNotification(FWaitHandle);
CloseHandle(FMutex);
DeleteCriticalSection(CS);
inherited Destroy;
end;
//------------------------------------------------------------------------------
procedure TMyShellChangeThread.GetDesktopIconPosition;
const
MaxTextLen = 1023;
StrDesktopIconPosition = 'DesktopIconPosition';
var
DeskTopHandle : THandle;
ItemText: array[0..MaxTextLen] of char;
Item: TLvItem;
dwProcessID: DWORD;
hProcess: THandle;
lpTextRemote: Pointer;
lpPositionRemote: Pointer;
lpListItemRemote: Pointer;
lpData: Pointer;
I, J, IntA, vItemCount : Integer;
dwBytesRead, dwBytesWrite: DWORD;
ptPosition : TPoint;
Ini : TIniFile;
IsExit : Boolean;
KeyList: TStringList;
InocPosition : array of Integer;
begin
//Sleep(2000);
IsExit:=False;
I:=0;
repeat
DeskTopHandle:=GetDesktopHand;
if DeskTopHandle = 0 then Sleep(100);
Inc(I);
until (DeskTopHandle > 0) or (I > 50);
GetWindowThreadProcessId(DeskTopHandle, @dwProcessID);
hProcess := OpenProcess(PROCESS_ALL_ACCESS, False, dwProcessID);
if hProcess = 0 then
begin
GetWindowThreadProcessId(DeskTopHandle, @dwProcessID);
hProcess := OpenProcess(PROCESS_ALL_ACCESS, False, dwProcessID);
if hProcess = 0 then Exit; //得不到指定進程的句柄
end;
KeyList:= TStringList.Create;
Ini:=TIniFile.Create(StrVIPSet);
Ini.ReadSection(StrDesktopIconPosition, KeyList);
if KeyList.Count = 0 then Exit;
SetLength(InocPosition, KeyList.Count);
for I := 0 to KeyList.Count -1 do
InocPosition[I]:=Ini.ReadInteger(StrDesktopIconPosition, KeyList[I], 0);
try
lpData := VirtualAllocEx(hProcess, nil, MaxTextLen + 1 + SizeOf(TPoint) + SizeOf(TLvItem), MEM_COMMIT, PAGE_READWRITE);
if not Assigned(lpData) then Exit;
lpTextRemote := lpData;
lpPositionRemote := PChar(lpData) + MaxTextLen + 1;
lpListItemRemote := PChar(lpData) + MaxTextLen + 1 + SizeOf(TPoint);
try
ZeroMemory(@ItemText, MaxTextLen + 1);
WriteProcessMemory(hProcess, lpTextRemote, @ItemText, MaxTextLen + 1, dwBytesWrite);
WriteProcessMemory(hProcess, lpPositionRemote, @ptPosition, SizeOf(TPoint), dwBytesWrite);
ZeroMemory(@Item, SizeOf(TLvItem));
with Item do
begin
mask := LVIF_TEXT;
iItem := 0;
iSubItem := 0;
pszText := lpTextRemote;
cchTextMax := MaxTextLen;
end;
dwBytesWrite := 0;
if not WriteProcessMemory(hProcess, lpListItemRemote, @Item, sizeof(TLvItem), dwBytesWrite) then Exit;
vItemCount := ListView_GetItemCount(DeskTopHandle);
for I:=0 to vItemCount -1 do
begin
IntA:= 0;
SendMessage(DeskTopHandle, LVM_GETITEMTEXT, I, LPARAM(lpListItemRemote));
SendMessage(DeskTopHandle, LVM_GETITEMPOSITION, I, LPARAM(lpPositionRemote));
ReadProcessMemory(hProcess, lpTextRemote, @ItemText, MaxTextLen + 1, dwBytesRead);
ReadProcessMemory(hProcess, lpPositionRemote, @ptPosition, SizeOf(TPoint), dwBytesRead);
for J:= 0 to KeyList.Count -1 do
begin
if KeyList[J] = ItemText then
begin
IntA:= MakeLparam(ptPosition.X, ptPosition.Y);
if InocPosition[J] <> IntA then
begin
Ini.WriteInteger(StrDesktopIconPosition, ItemText, IntA);
InocPosition[J]:=IntA;
//Form_SaveVIPSet.Memo1.Lines.Add(ItemText + ' ' + InttoStr(IntA));
Break;
end;
end;
end; { for J:= 0 to KeyList.Count -1 do }
if IntA = 0 then
begin
IntA:= MakeLparam(ptPosition.X, ptPosition.Y);
Ini.WriteInteger(StrDesktopIconPosition, ItemText, IntA);
KeyList.Add(ItemText);
SetLength(InocPosition, KeyList.Count);
InocPosition[KeyList.Count-1]:=IntA;
//Form_SaveVIPSet.Memo1.Lines.Add(ItemText + ' ' + InttoStr(IntA));
end;
end;
finally
VirtualFreeEx(hProcess, lpData, 0, MEM_RELEASE);
end;
finally
CloseHandle(hProcess);
end;
end;
//------------------------------------------------------------------------------
procedure TMyShellChangeThread.Execute;
var
Obj: DWORD;
Handles: array[0..1] of DWORD;
begin
InitializeCriticalSection(CS);
EnterCriticalSection(CS);
FWaitHandle := FindFirstChangeNotification(MyDesktop, // 要监视的目录
False, // 如果为TRUE,表示监视lpPathName的所有子目录
FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_DIR_NAME or FILE_NOTIFY_CHANGE_SIZE); // 带有前缀FILE_NOTIFY_CHANGE_???前缀的一个或多个常数,它们指定了对象发出信号的条件
LeaveCriticalSection(CS);
if FWaitHandle = ERROR_INVALID_HANDLE then Exit;
while not Terminated do
begin
Handles[0] := FWaitHandle;
Handles[1] := FMutex;
Obj := WaitForMultipleObjects(2, @Handles, False, INFINITE);
case Obj of
WAIT_OBJECT_0:
begin
Synchronize(GetDesktopIconPosition); // FChangeEvent
FindNextChangeNotification(FWaitHandle);
end;
WAIT_OBJECT_0 + 1:
ReleaseMutex(FMutex);
WAIT_FAILED:
Exit;
end;
EnterCriticalSection(CS);
if FWaitChanged then
begin
FWaitHandle := FindFirstChangeNotification(MyDesktop,
False, FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_DIR_NAME or FILE_NOTIFY_CHANGE_SIZE);
FWaitChanged := false;
end;
LeaveCriticalSection(CS);
end;
end;
end.
调用:
uses ShellChangeNotifierThread;
var
MyShellChangeThreadA : TMyShellChangeThread;
begin
MyShellChangeThreadA.Create; // 一运行到这句就读内存出错!!!不知是什么原因!!!
end;
unit ShellChangeNotifierThread;
interface
uses
Windows, SysUtils, Classes, comctrls, CommCtrl, IniFiles;
type
TMyShellChangeThread = class(TThread)
private
FMutex,
FWaitHandle: Integer;
FWatchSubTree: Boolean;
FWaitChanged : Boolean;
//FNotifyOptionFlags: DWORD;
protected
procedure Execute; override;
public
procedure GetDesktopIconPosition;
constructor Create; virtual;
destructor Destroy; override;
end;
var
CS : TRTLCriticalSection; // 临界区
const
MyDesktop : Pchar ='Z:\桌面';
StrVIPSet = 'Z:\VIPSet\VIPSet.ini';
{ 多个线程操作相同的数据时,一般是需要按顺序访问的,否则会引导数据错乱,无法控制数据,变成随机变量。
为解决这个问题,就需要引入互斥变量,让每个线程都按顺序地访问变量。
这样就需要使用EnterCriticalSection和LeaveCriticalSection函数。 }
implementation
//uses Dialogs;
//------------------------------------------------------------------------------
function GetDesktopHand: THandle;
begin
Result:=FindWindow('Progman', nil);
Result:=GetWindow(Result, GW_Child);
Result:=GetWindow(Result, GW_Child);
end;
//------------------------------------------------------------------------------
constructor TMyShellChangeThread.Create;
begin
FreeOnTerminate := True;
//FChangeEvent := ChangeEvent;
FMutex := CreateMutex(nil, True, nil);
//Mutex is used to wake up the thread as it waits for any change notifications.
WaitForSingleObject(FMutex, INFINITE); //Grab the mutex.
FWaitChanged := false;
inherited Create(True);
end;
destructor TMyShellChangeThread.Destroy;
begin
if FWaitHandle <> ERROR_INVALID_HANDLE then
FindCloseChangeNotification(FWaitHandle);
CloseHandle(FMutex);
DeleteCriticalSection(CS);
inherited Destroy;
end;
//------------------------------------------------------------------------------
procedure TMyShellChangeThread.GetDesktopIconPosition;
const
MaxTextLen = 1023;
StrDesktopIconPosition = 'DesktopIconPosition';
var
DeskTopHandle : THandle;
ItemText: array[0..MaxTextLen] of char;
Item: TLvItem;
dwProcessID: DWORD;
hProcess: THandle;
lpTextRemote: Pointer;
lpPositionRemote: Pointer;
lpListItemRemote: Pointer;
lpData: Pointer;
I, J, IntA, vItemCount : Integer;
dwBytesRead, dwBytesWrite: DWORD;
ptPosition : TPoint;
Ini : TIniFile;
IsExit : Boolean;
KeyList: TStringList;
InocPosition : array of Integer;
begin
//Sleep(2000);
IsExit:=False;
I:=0;
repeat
DeskTopHandle:=GetDesktopHand;
if DeskTopHandle = 0 then Sleep(100);
Inc(I);
until (DeskTopHandle > 0) or (I > 50);
GetWindowThreadProcessId(DeskTopHandle, @dwProcessID);
hProcess := OpenProcess(PROCESS_ALL_ACCESS, False, dwProcessID);
if hProcess = 0 then
begin
GetWindowThreadProcessId(DeskTopHandle, @dwProcessID);
hProcess := OpenProcess(PROCESS_ALL_ACCESS, False, dwProcessID);
if hProcess = 0 then Exit; //得不到指定進程的句柄
end;
KeyList:= TStringList.Create;
Ini:=TIniFile.Create(StrVIPSet);
Ini.ReadSection(StrDesktopIconPosition, KeyList);
if KeyList.Count = 0 then Exit;
SetLength(InocPosition, KeyList.Count);
for I := 0 to KeyList.Count -1 do
InocPosition[I]:=Ini.ReadInteger(StrDesktopIconPosition, KeyList[I], 0);
try
lpData := VirtualAllocEx(hProcess, nil, MaxTextLen + 1 + SizeOf(TPoint) + SizeOf(TLvItem), MEM_COMMIT, PAGE_READWRITE);
if not Assigned(lpData) then Exit;
lpTextRemote := lpData;
lpPositionRemote := PChar(lpData) + MaxTextLen + 1;
lpListItemRemote := PChar(lpData) + MaxTextLen + 1 + SizeOf(TPoint);
try
ZeroMemory(@ItemText, MaxTextLen + 1);
WriteProcessMemory(hProcess, lpTextRemote, @ItemText, MaxTextLen + 1, dwBytesWrite);
WriteProcessMemory(hProcess, lpPositionRemote, @ptPosition, SizeOf(TPoint), dwBytesWrite);
ZeroMemory(@Item, SizeOf(TLvItem));
with Item do
begin
mask := LVIF_TEXT;
iItem := 0;
iSubItem := 0;
pszText := lpTextRemote;
cchTextMax := MaxTextLen;
end;
dwBytesWrite := 0;
if not WriteProcessMemory(hProcess, lpListItemRemote, @Item, sizeof(TLvItem), dwBytesWrite) then Exit;
vItemCount := ListView_GetItemCount(DeskTopHandle);
for I:=0 to vItemCount -1 do
begin
IntA:= 0;
SendMessage(DeskTopHandle, LVM_GETITEMTEXT, I, LPARAM(lpListItemRemote));
SendMessage(DeskTopHandle, LVM_GETITEMPOSITION, I, LPARAM(lpPositionRemote));
ReadProcessMemory(hProcess, lpTextRemote, @ItemText, MaxTextLen + 1, dwBytesRead);
ReadProcessMemory(hProcess, lpPositionRemote, @ptPosition, SizeOf(TPoint), dwBytesRead);
for J:= 0 to KeyList.Count -1 do
begin
if KeyList[J] = ItemText then
begin
IntA:= MakeLparam(ptPosition.X, ptPosition.Y);
if InocPosition[J] <> IntA then
begin
Ini.WriteInteger(StrDesktopIconPosition, ItemText, IntA);
InocPosition[J]:=IntA;
//Form_SaveVIPSet.Memo1.Lines.Add(ItemText + ' ' + InttoStr(IntA));
Break;
end;
end;
end; { for J:= 0 to KeyList.Count -1 do }
if IntA = 0 then
begin
IntA:= MakeLparam(ptPosition.X, ptPosition.Y);
Ini.WriteInteger(StrDesktopIconPosition, ItemText, IntA);
KeyList.Add(ItemText);
SetLength(InocPosition, KeyList.Count);
InocPosition[KeyList.Count-1]:=IntA;
//Form_SaveVIPSet.Memo1.Lines.Add(ItemText + ' ' + InttoStr(IntA));
end;
end;
finally
VirtualFreeEx(hProcess, lpData, 0, MEM_RELEASE);
end;
finally
CloseHandle(hProcess);
end;
end;
//------------------------------------------------------------------------------
procedure TMyShellChangeThread.Execute;
var
Obj: DWORD;
Handles: array[0..1] of DWORD;
begin
InitializeCriticalSection(CS);
EnterCriticalSection(CS);
FWaitHandle := FindFirstChangeNotification(MyDesktop, // 要监视的目录
False, // 如果为TRUE,表示监视lpPathName的所有子目录
FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_DIR_NAME or FILE_NOTIFY_CHANGE_SIZE); // 带有前缀FILE_NOTIFY_CHANGE_???前缀的一个或多个常数,它们指定了对象发出信号的条件
LeaveCriticalSection(CS);
if FWaitHandle = ERROR_INVALID_HANDLE then Exit;
while not Terminated do
begin
Handles[0] := FWaitHandle;
Handles[1] := FMutex;
Obj := WaitForMultipleObjects(2, @Handles, False, INFINITE);
case Obj of
WAIT_OBJECT_0:
begin
Synchronize(GetDesktopIconPosition); // FChangeEvent
FindNextChangeNotification(FWaitHandle);
end;
WAIT_OBJECT_0 + 1:
ReleaseMutex(FMutex);
WAIT_FAILED:
Exit;
end;
EnterCriticalSection(CS);
if FWaitChanged then
begin
FWaitHandle := FindFirstChangeNotification(MyDesktop,
False, FILE_NOTIFY_CHANGE_FILE_NAME or FILE_NOTIFY_CHANGE_DIR_NAME or FILE_NOTIFY_CHANGE_SIZE);
FWaitChanged := false;
end;
LeaveCriticalSection(CS);
end;
end;
end.
调用:
uses ShellChangeNotifierThread;
var
MyShellChangeThreadA : TMyShellChangeThread;
begin
MyShellChangeThreadA.Create; // 一运行到这句就读内存出错!!!不知是什么原因!!!
end;
赞赏
他的文章
- [分享] Windows 可视化管理 的前身源代码 1802
- Windows 可视化管理 1.0.8.2 11774
- [分享]从注册表查询USB插拔记录 8693
谁下载
gestapo8
lxj168360
wangbin
phy0077
KernelKiller
zhuwg
好莱坞
SexFenG
hawking
kagayaki
ppanger
whtyy
wzy
大菜一号
救世猪
qdk
bjjacky
ruffy
chinazwe
combojiang
nsfizz
loqich
DragonTop
littlewisp
ptpy
hfyy
wmhnq
psypsypsy
khongninh
AASSMM
hacktrace
鸿鹄
兼一
foxtang
kohis
TWOGUN
hust白客
chnovsky
小花
kxxyyh
smilesxx
xxguguxx
uisky
billchen
内伤
jidewo
yaolibing
fjlhhxs
flysouding
看原图
赞赏
雪币:
留言: