PDA

View Full Version : جلوگیری از تغییر ساعت(لطفا)



Ali_Hashemi
جمعه 06 خرداد 1384, 15:22 عصر
سلام به همه دوستان

امیدوارم کمکم کنید :oops:

من میخوام تا زمانی که برنامه من در حال اجراست شخص نتواند زمان سیستم را تغییر دهد.

حتما باید یه جوری بشه از این کار جلوگیری کرد.
البته میشه ساعت سیستم را غیر فعال کرد و یا پنجره اونو بست قبل از اینکه
طرف فرصت کنه ساعت رو تغییر بده.
اما این اصولی نیست . تازه در این صورت میتونه از طریق پنجره داس این کارو
انجام بده.

من میتونم از طریق WM_TimeChange تغییر رو تشخیص بدم ولی نمیدونم چطور از اون جلوگیری کنم :گیج:

لطفا اگه کسی چیزی در این ارتباط میدونه کمک کنه.
با تشکر از همه

Touska
جمعه 06 خرداد 1384, 15:26 عصر
شما با تشخیص تعویض اون ساعت می تونید زمان را از قبل نگه دارید.

و در صورت تغییر یک پیفام نمایش داده و سپس ساعت را به حالت قبل بر گردانید.

البته به اضافه زمان زمان بعد از بستن پنچره.

موفق باشید :flower:

Ali_Hashemi
جمعه 06 خرداد 1384, 15:54 عصر
بله ولی مشکل اینجاست که این پیغام بعد از تغییر اتفاق میفته

یعنی وقتی بخوام زمان قبلی بدست بیارم - زمان قبلی میشه همین زمانی که تغییر اتفاق میفته

البته شاید بشه با استفاده از صف این کار رو بکنم- آره درسته - فهمیدم! :D

من از یک صف استفاده میکنم و زمان را تا چند ثانیه قبل به صورت بافر ذخیره میکنم
و هنگام تغییر ساعت از زمانهای موجود در صف انتخاب میکنم .

از شما ممنونم - باعث شدید که این فکر به ذهن من خطور کنه!
الان میرم امتحان کنم. اگه جواب داد کدش رو میذارم اینجا !

سالومه
جمعه 06 خرداد 1384, 17:31 عصر
به نظر من جلوگیری کردن از این کار رو می تونید اگر در یک کامپیوتر مشخص ( مثلاً در دانشگاه یا جایی هست ) با استفاده از Permission های سیستم عامل متوقف کنید. اما اگر میخواهید در هنگام اجرای برنامه خودتون (فقط) این کار رو انجام بدین فکر کنم مثال پایین به درد شما بخوره ( البته راه مطمئنی نیست ):

برای این کار دو Timer احتیاج دارید


.
.
.
private
{ Private declarations }
CurrentTime : TSystemTime;
getCurrentTime : boolean;
procedure WMTIMECHANGE(var Message: TWMTIMECHANGE); message WM_TIMECHANGE;
.
.
.

procedure TForm1.FormCreate(Sender: TObject);
begin
getCurrentTime := true;
end;

procedure TForm1.WMTIMECHANGE(var Message: TWMTIMECHANGE);
begin
getCurrentTime := false;
Timer2.Enabled := true;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
if (getCurrentTime) then GetSystemTime(CurrentTime);
end;

procedure TForm1.Timer2Timer(Sender: TObject);
begin
SetSystemTime(CurrentTime);
getCurrentTime := true;
Timer2.Enabled := false;
end;


مطمئن از این نظر نیست که روی بعضی از سیستم ها شما خودتون هم باید Permission تغییر ساعت و تاریخ سیستم رو هم داشته باشید که البته یک مقدار دنبالش باشین این راه رو هم پیدا می کنید.

اما ساده ترین و سریع ترین راهی که به نظر من اومد همین راهی بود که نوشتم براتون

البته این راه درصد خطا هم داره مثلاً اگر کاربر دقیقاً همون زمانی که Timer شما ساعت رو از سیستم می گیره اون رو تغییر بده، قبل از اجرا شدن Message ویندوز تایمر ساعت جاری رو می گیره و به عنوان currentTime ذخیره می کنه و اشتباده انجام میشه!

فقط یادتون باشه عمل تنظیم ساعت رو در داخل Message انجام ندین.

موفق باشین

Inprise
جمعه 06 خرداد 1384, 17:55 عصر
باید توابعی که به تاریخ و ساعت دسترسی دارند Hook ، از اجرای اونها جلوگیری و اشاره گر مربوطه رو به محلی دیگر منتقل کنی ؛ بدین ترتیب اصولا" امکان فراخوانی ساب سیستم تغییر ساعت برای کاربر موجود نخواهد بود و روش کار اهمیتی خاصی نخواهد داشت ( چون بهر ترتیب نهایتا" توابع API مربوطه برای تغییر ساعت فراخوانی میشوند و قبل از اجرا توسط Hook "بازداشت" شده و به محلی دیگر منتقل میشن ) برای کسب اطلاعات بیشتر ، Hook رو روی فروم و البته وب جستجو کن

موفق باشی

سالومه
جمعه 06 خرداد 1384, 19:14 عصر
باید توابعی که به تاریخ و ساعت دسترسی دارند Hook ، از اجرای اونها جلوگیری و اشاره گر مربوطه رو به محلی دیگر منتقل کنی ؛ بدین ترتیب اصولا" امکان فراخوانی ساب سیستم تغییر ساعت برای کاربر موجود نخواهد بود و روش کار اهمیتی خاصی نخواهد داشت ( چون بهر ترتیب نهایتا" توابع API مربوطه برای تغییر ساعت فراخوانی میشوند و قبل از اجرا توسط Hook "بازداشت" شده و به محلی دیگر منتقل میشن ) برای کسب اطلاعات بیشتر ، Hook رو روی فروم و البته وب جستجو کن

موفق باشی

آیا بعد از این کار تغییر ساعت سیستم توسط برنامه ای در داس هم غیر ممکن هست؟

Inprise
جمعه 06 خرداد 1384, 19:51 عصر
وقتی در مورد ویندوز حرف میزنیم چیزی بنام داس وجود نداره . برنامه های کنسول و برنامه های مبتنی بر داس از طریق NTVdm اجرا میشن که وظیفهء معادل سازی اینتراپتها و توابع مربوطه بر عهده اش است ؛ تحت ویندوز دسترسی مستقیم به وقفه هائی که میتونن ساعت سیستم رو تغییر بدن وجود نداره ؛ ( در واقع تحت ویندوز اصولا" API پائین ترین چیزی ست که یک برنامهء سطح کاربرد بهش دسترسی داره ، فلذا بازداشت توابع ، عملی ترین روش کنترل عملکرد سیستم است ؛ در واقع سیستم مجوز و اعطای اختیار ویندوز هم دقیقا بر همین مبنا عمل میکنه ! )

سالومه
جمعه 06 خرداد 1384, 20:00 عصر
ممنون از توضیحتون

Ali_Hashemi
شنبه 07 خرداد 1384, 13:57 عصر
من در برنامه خودم این کار رو تونستم انجام بدم که
تازمانی که برنامه من در حال اجراست کاربر نتونه Task manager رو فعال کنه
با استفاده از Permission ها.

اما در مورد تغییر ساعت نمیدونم از چه Permission استفاده کنم !

راستی کسی میدونه چطور میتونم در مورد Permission های مختلف اطلاعاتی پیدا کنم ؟

Ali_Hashemi
شنبه 07 خرداد 1384, 14:05 عصر
راستی سالومه !

این کدی که شما گفتی یک مشکل داره و اون هم اینه که :
زمانی که در Timer2 زمان رو تغییر بدیم دوباره رویداد WM_timechange اتفاق میفته و دوباره
روز از نو و روزی از نو ... حلقه تکرار میشه

در ضمن نمیدونم چرا وقتی که زمان رو تغییر میدم دوبار رویداد WM_timechange اتفاق میفته.

البته من برای جلوگیری از اون حلقه که گفتم فاصله زمانی بین دو رویداد WM_timechange رو چک میکنم
اگر که فاصله اونا بیشتر از 700 میلی ثانیه بود اونوقت اجازه تغییر رو میدم.
این به خاطر اینه که زمانی که من از برنامه ساعت رو تغییر میدم ، همون زمان هم رویداد WM_timechange
اتفاق میفته . اما زمان بین تغییر من و رویداد WM_timechange کمتر از 700 میلی ثانیه است.

ولی نمیفهمم که چی میشه که هر 10 تا 12 بار یکی دو بار تغییر رو قبول میکنه !

سالومه
شنبه 07 خرداد 1384, 16:06 عصر
راستی سالومه !
این کدی که شما گفتی یک مشکل داره و اون هم اینه که :
زمانی که در Timer2 زمان رو تغییر بدیم دوباره رویداد WM_timechange اتفاق میفته و دوباره
روز از نو و روزی از نو ... حلقه تکرار میشه



برای این مشکل میشه به راحتی از یک Condition استفاده کرد و از طریق یک متغییر Boolean چک کرد که آیا ما خودمون داریم تایم رو تغییر میدیم یا کاربر داره اون کار رو انجام میده. در اینصورت WM_timechange متوجه میشه اما وقتی که کاندیشن ما مثلاً False هست تایمر رو فعال نمی کنه.



.
.
.
private
{ Private declarations }
CurrentTime : TSystemTime;
getCurrentTime : boolean;
changePermission : boolean;
procedure WMTIMECHANGE(var Message: TWMTIMECHANGE); message WM_TIMECHANGE;
.
.
.

procedure TForm1.FormCreate(Sender: TObject);
begin
getCurrentTime := true;
changePermission := true;
Timer2.Enabled := false;
end;

procedure TForm1.WMTIMECHANGE(var Message: TWMTIMECHANGE);
begin
getCurrentTime := false;
if (changePermission) then Timer2.Enabled := true;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
if (getCurrentTime) then GetSystemTime(CurrentTime);
end;

procedure TForm1.Timer2Timer(Sender: TObject);
begin
changePermission := false;
SetSystemTime(CurrentTime);
getCurrentTime := true;
Timer2.Enabled := false;
changePermission := true;
end;



من این کد رو امتحان نکردم و توی Notepad نوشتم اما فکر کنم درست کار کنه.

البته این راهی که من گفتم خیلی پیش و پا افتاده هست و بهترین راه این هست که تایع های تغییر زمان رو Hook کنیم. اما مشکل اون موضوع هم اینه که از طریق داس میشه زمان رو تغییر داد چون اون تایع ها برای ویندوز هستند!

Ali_Hashemi
یک شنبه 08 خرداد 1384, 07:37 صبح
خیلی از شما ممنونم

بله همونطوری که فرمودید درست جواب میده.

ولی نه نمیده !

10 % مواقع جواب میده زمانی که دقیقه رو تغییر بدیم مشکل پیدا میکنه
یک ثانیه میره جلو و یک ثانیه میره عقب !
اما تو تغییر ساعت مشکلی نداره.
به حر حال خیلی متشکرم از وقتی که گذاشتید.

فکر کنم اگه روش شما رو با روش خودم ترکیب کنم جواب بده
یعنی یک لیست از زمان های تا چند ثانیه گذشته رو ذخیره کنم به جای اینکه یک زمان یعنی زمان فعلی رو فقط ذخیره کنم تو متغیر .
:sad2: