Hash Generator 1.1.60.0

What’s new

  • เพิ่ม MD5
  • เพิ่ม CheckBox สำหรับเลือก Uppercase/Lowercase

หน้าตาโปรแกรม

จิ้ม ที่นี่ เพื่อดาวน์โหลด

ระบบขั้นต่ำที่ต้องการคือ Windows XP หากรันไม่ขึ้น ให้ทำการติดตั้ง Microsoft Visual C++ 2010 SP1 Redistributable Package (x86) เสียก่อน หากต้องการ Hash ชนิดอื่นลอง Comment ขอไว้ดู เผื่อทำให้ได้ก็จะทำให้

Categories: Software, Windows Tags: , ,

ประโยชน์ของ DateTimeOffset และการใช้งานเบื้องต้น

ปรกติแล้ว ใน .NET Framework เรามักจะใช้ DateTime ในการจัดเก็บเวลากัน ซึ่ง คลาสนี้จะมีข้อเสียอยู่ คือ มันไม่สามารถเก็บ Timezone ไว้ได้ ทำให้เวลามันไม่อิงที่เวลา UTC เพราะมันเก็บแค่เวลาของพื้นที่นั้นๆ ผลที่ตามมาคือ เราจะไม่สามารถแสดงผลและเปรียบเทียบเวลาได้อย่างถูกต้องในบางสถานการณ์

ตัวอย่างสถานการณ์ที่จะเกิดปัญหา

  1. นาย A อยู่ที่ญี่ปุ่น (UTC +09.00)
  2. นาย B อยู่ที่อังกฤษ (UTC +00.00)
  3. นาย B ส่งข้อความไปให้นาย A โดยข้อมูลที่ถูกส่งไปมีสองอย่างคือ ข้อความ และ เวลาที่ข้อความถูกส่งออกมา สมมุติให้เวลาขณะนั้นของนาย B เป็น 07:00 นาฬิกา และเวลาของนาย A จะเท่ากับ 16:00 นาฬิกา (เอาเวลาของนาย B บวกด้วย 09:00 ซึ่งเป็น Timezone ของนาย A จะได้เวลาปัจจุบันของนาย A สาเหตุที่บวก 09:00 ตรงๆเพราะว่า Timezone ของนาย B เป็น +00:00)
  4. หากใช้ DateTime เก็บเวลา นาย A จะเห็นว่าข้อความมันถูกส่งมาตอน 07.00 นาฬิกาของญี่ปุ่น (ซึ่งขณะนั้นญี่ปุ่นเป็นเวลา 16:00 นาฬิกา) ทั้งๆที่มันพึ่งถูกส่งออกมา !

ปัญหานี้แก้ได้โดยการใช้ DateTimeOffset เมื่อนาย B ส่งข้อความไปให้นาย A พร้อมด้วยเวลาที่ข้อความถูกส่งออกมาโดยใช้ DateTimeOffset เก็บเวลา เมื่อนาย A ได้รับข้อความ จะรู้ทันทีว่านาย B อยู่ Timezone ไหน และจะสามารถปรับการแสดงผลของเวลาได้ถูกต้อง เพราะเวลาที่เก็บใน DateTimeOffset เป็นเวลา UTC +00.00 เสมอ (แต่เวลาแสดงผลจริงมันจะบวก Timezone ให้เราด้วย) ไม่ว่าโปรแกรมจะทำงานอยู่ที่ Timezone ไหนก็ตาม

สิ่งน่ารู้เกี่ยวกับ DateTimeOffset

  • เวลาเปรียบเทียบ มันจะเปรียบเทียบโดยใช้เวลาที่เก็บอยู่อย่างเดียว (ซึ่งก็คือเวลา UTC +00:00) โดยไม่เปรียบเทียบ Timezone ตัวอย่าง
    using System;
    
    namespace TestDateTimeOffset
    {
        class Program
        {
            static void Main(string[] args)
            {
                DateTimeOffset thailand, japan;
    
                thailand = DateTimeOffset.Now;
                japan = thailand.ToOffset(TimeSpan.FromHours(9));
    
                Console.WriteLine("Thailand Time: {0}", thailand);
                Console.WriteLine("   Japan Time: {0}", japan);
    
                if (thailand == japan)
                    Console.WriteLine("This line will be printed.");
            }
        }
    }
    

    ผล

  • เวลาที่ได้จาก DateTimeOffset.Now จะเป็นเวลา UTC +00:00 เสมอ แต่ Timezone ที่ได้จะเป็น Timezone ของเครื่องที่โปรแกรมทำงานอยู่ ทำให้การเปรียบเทียบและการแสดงผลของเวลาที่ได้ถูกต้องตลอด

Compiler และ Linker ของภาษา C สร้างโปรแกรมหนึ่งตัวออกมาได้อย่างไร

2012/02/22 1 comment

ในภาษา C นั้น จะใช้ไฟล์สองชนิด คือ Source File (ที่นามสกุล .c) และ Header File (นามสกุล .h) ในการเก็บ Source Code ซึ่งแตกต่างจากภาษายุคใหม่หลายๆภาษาที่ใช้เพียงไฟล์ชนิดเดียวในการเก็บ Source Code

ระบบการคอมไพล์ของภาษา C นั้น ตัวคอมไพล์เลอร์จะแปลง Source File แต่ละไฟล์ในโปรเจคออกมาเป็น Object File ให้หมดก่อน (หนึ่ง Source File จะได้หนึ่ง Object File) แต่ละไฟล์จะถูกคอมไพล์แบบตัวใครตัวมัน คือ ไม่เกี่ยวข้องกับ Source File ตัวอื่นๆ จากนั้น Linker จะทำการรวม Object File ทั้งหมดเข้าด้วยกันเพื่อสร้าง Executable ที่พร้อมใช้งานขึ้นมา (หรือ Shared Library)

แล้วไอ้ Linker นี่ทำไมต้องมีมันด้วย ทำไมไม่มีแค่คอมไพล์เลอร์ตัวเดียวให้มันจบๆไป? สาเหตุที่ต้องมี Linker ก็เพราะว่า การเขียนโปรเจคใหญ่ๆใน Source File อันเดียวเป็นอะไรที่ไม่ควรทำอย่างยิ่ง ลองนึกสภาพ Code ของระบบปฏิบัติการที่มีเป็นล้านๆบรรทัดถูกเก็บอยู่ใน Source File อันเดียวดู

เมื่อมีการแยก Source File การ Forward declaration ก็ตามมาเพื่อให้ Source File สามารถเรียกใช้งานฟังชั่นที่อยู่ใน Source File อันอื่นได้ การ Forward declaration คือ การประกาศชื่อฟังชั่นล่วงหน้าเพื่อให้คอมไพล์เลอร์รู้ว่าควรจะเรียกฟังชั่นนั้นอย่างไร และฟังชั่นนั้นคืนค่าชนิดไหนกลับมา ซึ่ง Linker จะเป็นตัวจัดการฟังชั่นตัวจริงที่อยู่ใน Source File อันอื่นเอง

อ้าว แล้ว Header File มันมีประโยชน์อย่างไรละ ในเมื่อมันคอมไพล์แค่ Source File อย่างเดียว? สำหรับประโยชน์ของ Header File นั้นจะมีไว้ให้ Source File ใช้ Include เข้าไป เพื่อแยก Code ออกเป็นส่วนๆ เช่น ส่วนที่สามารถใช้งานได้ในหลาย Source File ก็จะถูกแยกออกมาใส่ใน Header File

การ Include นั้น คอมไพล์เลอร์จะใช้การอ่าน Code ในไฟล์ที่ต้องการ Include เข้ามาใส่ใน Source File โดยตรง ไม่มีอะไรลึกลับซับซ้อนนอกเหนือจากนั้น ตัวอย่างเช่น ให้ไฟล์ foo.h มี Code ดังนี้

#ifndef _FOO_H_
#define _FOO_H_

int bar();

#endif // _FOO_H_

และไฟล์ foo.c มี Code ดังนี้

#include "foo.h"

int main(int argc, char *argv[])
{
	return bar();
}

เมื่อคอมไพล์เลอร์ทำการคอมไพล์ไฟล์ foo.c ตัวคอมไพล์เลอร์จะทำการประมวลผล Preprocessor ก่อนการคอมไพล์ Code (พวกที่ขึ้นต้นด้วย # นั่นละ เช่น #include) แล้ว Code ของไฟล์ foo.c ที่คอมไพล์เลอร์เข้าใจจะกลายเป็น

#ifndef _FOO_H_
#define _FOO_H_

int bar();

#endif // _FOO_H_

int main(int argc, char *argv[])
{
	return bar();
}

ไม่งงใช่มั้ย? ส่วนปัญหาที่เหลือๆก็ลองคิดกันดู เช่น ทำไมใน Header File ส่วนมากจะมีไว้ทำ Forward declaration และทำไมใน Header File มันถึงมี #ifdef กับ #define อะไรแปลกๆนั้นบนหัวไฟล์ตลอด และทำไมตัวแปรที่ประกาศใน Header File จะต้องใช้ extern นำหน้าทุกครั้ง ฯลฯ

อาจจะอ่านได้งงไปนิด เพราะผมตั้งใจให้อ่านไปแล้วคิดเองตามไปด้วย ส่วนภาษา C++ ก็ไม่ต่างกัน

virtual จำเป็นหรือไม่สำหรับ Method ที่เป็นตัว Override ของคลาสที่สืบทอดไป

เวลา Override method คนส่วนมากมักจะใช้ virtual บน Method ที่เป็นตัว Override แบบด้านล่าง

class Root
{
public:
	Root()
	{
	}

	virtual ~Root()
	{
	}

	virtual void Bar()
	{
	}
};

class Foo : public Root
{
public:
	Foo()
	{
	}

	virtual ~Foo()
	{
	}

	virtual void Bar()
	{
	}
};

แต่ในความเป็นจริงแล้ว มันไม่มีความจำเป็นเลย Code ด้านล่างนี้ทำงานเหมือนกับ Code ข้างบน

class Root
{
public:
	Root()
	{
	}

	virtual ~Root()
	{
	}

	virtual void Bar()
	{
	}
};

class Foo : public Root
{
public:
	Foo()
	{
	}

	~Foo()
	{
	}

	void Bar()
	{
	}
};

และด้านล่างนี้คือ Code ตัวอย่างพร้อมผลลัพธ์การทำงาน

#include <stdio.h>

class Root
{
public:
	Root()
	{

	}

	virtual ~Root()
	{
		printf("In ~Root()\n");
	}

	virtual void Boo()
	{
		printf("In Root::Boo()\n");
	}

	virtual void Bee()
	{
		printf("In Root::Bee()\n");
	}
};

class Foo : public Root
{
public:
	Foo()
	{

	}

	~Foo()
	{
		printf("In ~Foo()\n");
	}

	void Boo()
	{
		printf("In Foo::Boo()\n");
	}

	virtual void Bee()
	{
		printf("In Foo::Bee()\n");
	}

	virtual void Bam()
	{
		printf("In Foo::Bam()\n");
	}
};

class Bar : public Foo
{
public:
	Bar()
	{

	}

	~Bar()
	{
		printf("In ~Bar()\n");
	}

	void Boo()
	{
		printf("In Bar::Boo()\n");
	}

	void Bam()
	{
		printf("In Bar::Bam()\n");
	}
};

int main(int argc, char *argv[])
{
	Foo *foo = new Bar();
	Root *root = foo;

	foo->Boo();
	foo->Bam();
	root->Bee();

	delete root;

	return 0;
}

ผลลัพธ์

In Bar::Boo()
In Bar::Bam()
In Foo::Bee()
In ~Bar()
In ~Foo()
In ~Root()

ทำไมบางโปรแกรมใน Android ถึงชอบเปิดขึ้นมาเองทั้งๆที่เราไม่ได้เปิด?

เหตุที่ได้เขียนเรื่องนี้ขึ้นมา เพราะเมื่อคืนวันศุกร์ที่ผ่านมา ผมได้ไปเอาเสื้อผ้าที่ฝากไว้กับพี่สาวที่โรงพยาบาลจุฬาลงกรณ์ตอนที่หนีน้ำท่วม แล้วเขามาถามผมว่า “ทำไมโปรแกรมพวกนี้มันชอบเปิดขึ้นมาเองทั้งๆที่ไม่ได้กดเปิดมันเลย พอกด Kill มันก็เปิดขึ้นมาใหม่อีก ปิดยังไงก็ไม่ได้” พร้อมกับเปิด Task Killer ให้ผมดูรายชื่อโปรแกรมที่มันทำงานขึ้นมาเอง บวกกับเห็นคำค้นหาที่มีคนค้นหาเกี่ยวกับเรื่องนี้เข้ามาด้วย ก็เลยตัดสินใจเขียนเรื่องนี้ขึ้นมา

เหตุผลที่โปรแกรมเหล่านั้นมันทำงานขึ้นมาเอง เพราะตัวมันเองเป็นโปรแกรมประเภท Service กล่าวคือ ตัวมันเป็นโปรแกรมที่ต้องการทำงานเบื้องหลังตลอดเวลา เช่น Whatsapp ที่ต้องรอรับข้อความตลอดเวลา

วิธีการป้องกันไม่ให้มันทำงานเบื้องหลังก็มี เช่น ปิดการแจ้งเตือนต่างๆของมัน ปิดการอัพเดตข้อมูลแบบอัตโนมัติของมัน การถอด Widget ออกจากหน้า Home ฯลฯ แต่บางโปรแกรมก็จะไม่สามารถปิดได้ ก็ต้องปล่อยให้มันทำงานไป หรือถอนการติดตั้ง

Hash Generator 1.0.40.0 โปรแกรมสำหรับคำนวน Hash (เช่น SHA-2)

โปรแกรมสำหรับคำนวน Hash จากข้อความ (ตอนนี้มีแค่ SHA-2 256 Bits นะ เพราะเขียนแบบเร่งรีบมาก ขนาดเร่งรีบยังใช้เวลาทั้งวันในการเขียน) เหตุที่ต้องเขียนขึ้นมาใหม่เพราะอยู่ๆก็จำเป็นต้องสร้าง SHA-2 256 Bits แล้วไปหาใน Google ก็เจอแต่แบบบนเว็บ ซึ่งอันตรายมาก เพราะส่วนมากมันจะดักข้อความที่เราเอาไปทำ Hash เพื่อไว้ใช้ทำ Reverse Hash Lookup

หน้าตาโปรแกรม

Main Window (Windows 7 Aero)

จิ้ม ที่นี่ เพื่อดาวน์โหลด

ระบบขั้นต่ำที่ต้องการคือ Windows XP (หรือถ้าเอาไปรันได้ต่ำกว่า XP ก็ไม่ว่ากัน) หากรันไม่ขึ้น ให้ทำการติดตั้ง Microsoft Visual C++ 2010 SP1 Redistributable Package (x86) เสียก่อน หากต้องการ Hash ชนิดอื่นลอง Comment ขอไว้ดู เผื่อทำให้ได้ก็จะทำให้

อ๋อ โปรแกรมนี้เป็น Open Source โดยใช้ Apache License 2.0 นะ ปิด src ไว้แล้วเดียวอาจจะหาว่าแอบดักข้อความทำ Hash ส่งกลับมาให้ผม ถ้าไม่มั่นใจกับ Binary ที่ผมทำก็ตรวจสอบ Code แล้วคอมไพล์เอาเองเด้อ

Categories: Software, Windows Tags: ,

Stock Kernel ของ I9100TDCKK3

อันนี้ผมดั้มจากเครื่องศูนย์ DTAC ที่อัพเดต 2.3.6 ตัวล่าสุดนะคับ ดาวน์โหลดได้จาก ที่นี่

Update

พึ่งจะเห็นว่ามันมีใน http://samsung-updates.com/gt-i9100-galaxy-sii/ แล้ว แต่จากการตรวจสอบ พบว่า Kernel มันเป็นคนละตัวกันกับอันที่ผมดั้มจากเครื่องศูนย์ DTAC