IShellExecuteHook untuk memonitor Windows Explorer

January 23, 2009 at 5:34 pm | Posted in Code Samples, Tutorials | 2 Comments
Tags: , , ,

Oleh Zamrony P. Juhara

Tulisan ini sebenarnya untuk menjawab pertanyaan [Delphindo] menangkap jenis file yang diklik di Windows Explorer yang diajukan member Delphindo. Saya asumsikan paling tidak Anda telah punya sedikit pengetahuan mengenai teknologi Component Object Module (COM) yang dikembangkan oleh Microsoft. Demo artikel ini saya tulis menggunakan Turbo Delphi Explorer yang bisa Anda peroleh gratis. Untuk kompiler Delphi versi lain, caranya hampir sama.

Problem memonitor eksekusi Windows Explorer

Untuk memonitor aktifitas eksekusi program pada Windows Explorer, Anda harus membuat COM server dan membuat implementasi interface IShellExecuteHook. COM server ini selanjutnya Anda daftarkan agar dijalankan tiap kali ShellExecute() atau ShellExecuteEx() dijalankan.

Membuat COM server

Untuk membuat COM server, dari IDE Turbo Delphi Explorer, buatlah sebuah project baru (File->New->Other). Pilih ActiveX Librarydan klik OK (Gambar 1). Turbo Delphi Explorer akan menciptakan project baru bernama Project1. Save project ini misal sebagai shhook.

Anda akan mendapatkan source code seperti Listing 1.

Listing 1

library shhook;

uses
  ComServ;

exports
  DllGetClassObject,
  DllCanUnloadNow,
  DllRegisterServer,
  DllUnregisterServer;

{$R *.RES}

begin
end.
Gambar 1. Dialog untuk menciptakan COM server

Gambar 1. Dialog untuk menciptakan COM server

Implementasi Interface IShellExecuteHook

Sebelum membuat implementasi IShellExecuteHook, kita buat dulu object COM. Klik File->New->Other. Pilih COM Object dan klik OK (Gambar 2). Turbo Delphi akan menampilkan dialog COM Object Wizard (Gambar 3).

Gambar 2. Dialog untuk menciptakan COM Object

Gambar 2. Dialog untuk menciptakan COM Object


Gambar 3. Dialog COM Object Wizard

Gambar 3. Dialog COM Object Wizard

Isi ClassName dengan ShellExecuteHook. Field Description bisa Anda isi dengan deksripsi COM server Anda. Hilangkan tanda centang pada opsi Include Type Library karena kita tidak ingin membuat COM object baru hanya membuat implementasi interface yang sudah ada. Klik OK jika sudah selesai.

Turbo Delphi akan menciptakan file unit baru. Simpan unit ini sebagai ushellhookimpl.pas seperti pada Listing 2. Isi constant Class_ShellExecuteHook pada project Anda akan berbeda dengan yang tertera pada Listing 2. Tidak apa-apa dan memang harus berbeda karena GUID tersebut akan dipakai untuk membedakan satu COM server dengan COM server lain.

Listing 2

unit ushellhookimpl;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses
  Windows, ActiveX, Classes, ComObj;

type
  TShellExecuteHook = class(TComObject)
  protected
  end;

const
  Class_ShellExecuteHook: TGUID =
    '{CBEEEE93-8919-43D2-83EA-78A25B8BE3B2}';

implementation

uses ComServ;

initialization
  TComObjectFactory.Create(ComServer, 
            TShellExecuteHook, 
            Class_ShellExecuteHook,
            'ShellExecuteHook', 
            'Memonitor eksekusi shell', 
            ciMultiInstance, tmApartment);
end.

Sekarang kita buat implementasi IShellExecuteHook. Interface ini dideklarasi di unit shlobj.pas sehingga Anda perlu tambahkan shlobj.pas di klausa uses. Anda tambahkan juga unit shellapi.pas karena kita butuh informasi deklarasi TShellExecuteInfo. Ubah deklarasi TShellExecuteHook menjadi seperti Listing 3.

Listing 3

type
  TShellExecuteHook = class(TComObject,IShellExecuteHook)
  protected
    function Execute(var ShellExecuteInfo: 
                           TShellExecuteInfo): HResult; stdcall;
  end;

Lengkapi implementasi fungsi Execute() dengan fitur Code Completion (Shift+Ctrl+C). Ketikkan kode yang akan dikerjakan ketika ShellExecute() atau ShellExecuteEx() dieksekusi pada metode Execute().

Parameter ShellExecuteInfo berisi informasi program yang dieksekusi, termasuk juga parameter yang digunakan ketika memanggil ShellExecute(). Untuk demo ini, saya hanya peduli pada nama file yang dijalankan. Di sini kita hanya akan menampilkan dialog konfirmasi apakah eksekusi file diijinkan atau tidak. Kita harus mengembalikan nilai 0 (false) bila eksekusi ShellExecute() dihentikan dan sebaliknya 1 (true) bila dilanjutkan.

Listing 4

{ TShellExecuteHook }

function TShellExecuteHook.Execute(
  var ShellExecuteInfo: TShellExecuteInfo): HResult;
var filename:string;
    msgbxResult:integer;
begin
  filename:=shellexecuteInfo.lpFile;

  msgbxResult:=MessageBox(0,
                  PChar('Lanjutkan eksekusi file '+filename+'?'),
                  'Konfirmasi Eksekusi',
                  MB_OKCANCEL or MB_TASKMODAL);
  if msgbxResult=IDOK then
    result:=1
  else
    result:=0;

end;

Mendaftarkan COM Server ke Daftar ShellExecuteHook

Agar COM server Anda dikenali dan dijalankan ketika ShellExecute() atau ShellExecuteEx() dipanggil, Anda perlu mendaftarkan COM server Anda ke Explorer. Caranya adalah dengan membuat entri di registry seperti di bawah ini.

  • HKEY_LOCAL_MACHINE
    • Software

      • Microsoft

        • Windows
          • CurrentVersion
            • Explorer
              • ShellExecuteHooks

Anda harus menambah dan menghapus entri tersebut saat COM server di register/unregister menggunakan RegSvr32.exe. Caranya, turunkan kelas TComObjectFactory dan override metode UpdateRegistry() dengan kode untuk menambah dan menghapus entri registry.

Listing 5

//implementasi turunan TComObjectFactory untuk
//mendaftarkan server shellexecutehook kita
type
  TShellExecuteComObjectFactory = class(TComObjectFactory)
  private
    procedure AddRegEntry(const strGUID:string);
    procedure RemoveRegEntry(const strGUID:string);
  public
    procedure UpdateRegistry(doregister: Boolean); override;
  end;

{ TShellExecuteComObjectFactory }
const
  ShellExecuteHookRegistry = 'SOFTWARE\Microsoft\Windows\'+
                         'CurrentVersion\Explorer\ShellExecuteHooks';

procedure TShellExecuteComObjectFactory.AddRegEntry(
             const strGUID:string);
var areg:TRegistry;
begin
  areg:=TRegistry.Create;
  try
    areg.RootKey:=HKEY_LOCAL_MACHINE;
    if areg.OpenKey(ShellExecuteHookRegistry,true) then
    begin
      areg.WriteString(strGUID,Description);
    end;
  finally
    areg.Free;
  end;
end;

procedure TShellExecuteComObjectFactory.RemoveRegEntry(
     const strGUID:string);
var areg:TRegistry;
begin
  areg:=TRegistry.Create;
  try
    areg.RootKey:=HKEY_LOCAL_MACHINE;
    if areg.OpenKey(ShellExecuteHookRegistry,true) then
    begin
      areg.DeleteValue(strGUID);
    end;
  finally
    areg.Free;
  end;
end;

procedure TShellExecuteComObjectFactory.UpdateRegistry(
                                  doregister: Boolean);
var classID:string;
begin
  classID:=GUIDToString(Class_ShellExecuteHook);
  if doRegister then
    AddRegEntry(classID)
  else
    RemoveRegEntry(classID);

  inherited UpdateRegistry(doregister);
end;

Langkah selanjutnya ubah bagian inisialisasi unit, dari TComObjectFactory menjadi TShellExecuteComObjectFactory, seperti Listing 6.

Listing 6

  TShellExecuteComObjectFactory.Create(ComServer,
         TShellExecuteHook,
         Class_ShellExecuteHook,
         'ShellExecuteHook',
         'Monitor eksekusi shell',
         ciMultiInstance, tmApartment);

Mendaftarkan COM Server

Simpan dan lakukan kompilasi project COM server Anda. Jika sukses Anda akan menemukan file shhook.dll pada direktori project Anda. Daftarkan COM server Anda dengan memanggil RegSvr32.exe (Listing 7). Turbo Delphi Explorer yang gratis memang tidak mengijinkan mendaftarkan COM server dari IDE, jadi Anda harus menjalankannya dari Command Prompt atau Run. Restart Explorer.exe agar konfigurasi registry ShellExecuteHooks yang baru dibaca oleh Explorer.exe.

Listing 7

RegSvr32.exe {folder dimana shhook.dll berada}shhook.dll

Jika tidak ada yang salah, akan ada informasi bahwa COM server Anda sukses didaftarkan. Coba buka sebuah file dokumen, Anda akan mendapatkan konfirmasi untuk melanjutkan atau tidak eksekusi program (Gambar 7).

Gambar 7. Shell execute hook beraksi

Gambar 7. Shell execute hook beraksi

Untuk unregister jalankan RegSvr32.Exe dengan menggunakan parameter /u

Listing 8

RegSvr32.exe /u {folder dimana shhook.dll berada}shhook.dll

Problem IShellExecuteHook pada Windows Vista

Menurut Microsoft:

Shell execute hooks are deprecated as of Windows Vista.

Saya pribadi belum mencoba kode di atas di Windows Vista. Dari beberapa pengalaman orang-orang, sepertinya memang IShellExecuteHook bermasalah di Vista.

Download Demo

Demo aplikasi dapat di download di Demo implementasi interface IShellExecuteHook.

Penutup

Itu saja tips dari saya. Selamat memprogram!

2 Comments »

RSS feed for comments on this post. TrackBack URI

  1. Oh! is there alternative to run this in vista or windows 7?

  2. @Jumper: I think this script try on Win XP. Mr Delphindo said never try on Win Vista.

    Om kontributor Delphindo, bagaimana akses port serial di Turbo Delphi? Kalau di Delphi yg bayar kan bisa pakai Cport dan lain-lain.
    Thanks bantuannya


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.
Entries and comments feeds.

%d bloggers like this: