国产一级一区二区_segui88久久综合9999_97久久夜色精品国产_欧美色网一区二区

掃一掃
關注微信公眾號

Web開發中遠程腳本的應用
2007-09-24   網絡

Web開發中遠程腳本的應用

Windows外殼擴展的使用
在Windows下的一些軟件提供了這樣的功能:當安裝了這些軟件之后,當在Windows的Explore中鼠標右鍵單擊文件或者文件夾后,在彈出菜單中就會多出與該軟件操作相關的菜單項,點擊該項就會激活相應的程序對用戶選中的文件進行相應的操作。例如安裝了Winzip之后,當用戶選中一個文件夾后單擊右鍵,在彈出菜單中就會多出一個Add To Zip和一個 Add To xxx.zip的選項,其中xxx為選中的文件夾的名稱。只要單擊上面的兩個菜單項中的一個,就可以方便的壓縮目錄了。這樣的功能稱為Windows外殼擴展(Shell Extensions)
  外殼擴展概述

  下面是與外殼擴展相關的三個重要術語:
  (1)文件對象(File Object)
   文件對象是外殼中的一項,大家最熟識的文件對象是文件和目錄,此外,打印機、控制面板程序、共享網
絡等也都是文件對象。
  (2)文件類(File Class)
文件類是具有某種共同特性的文件對象的集合,比如,擴展名相同的文件屬于同一文件類。
  (3)處理程序(Handler)
   處理程序是具體實現某個外殼擴展的代碼。

  Windows支持七種類型的外殼擴展(稱為Handler),它們相應的作用簡述如下:
  (1)Context menu handlers向特定類型的文件對象增添上下文相關菜單;
  (2)Drag-and-drop handlers用來支持當用戶對某種類型的文件對象進行拖放操作時的OLE數據傳輸;
  (3)Icon handlers用來向某個文件對象提供一個特有的圖標,也可以給某一類文件對象指定圖標;
  (4)Property sheet handlers給文件對象增添屬性頁,屬性頁可以為同一類文件對象所共有,也可以給一個
文件對象指定特有的屬性頁;
  (5)Copy-hook handlers在文件夾對象或者打印機對象被拷貝、移動、刪除和重命名時,就會被系統調用,
通過為Windows增加Copy-hook handlers,可以允許或者禁止其中的某些操作;
  (6)Drop target handlers在一個對象被拖放到另一個對象上時,就會被系統被調用;
  (7)Data object handlers在文件被拖放、拷貝或者粘貼時,就會被系統被調用。

  Windows的所有外殼擴展都是基于COM(Component Object Model) 組件模型的,外殼是通過接口(Interface)來訪問對象的。外殼擴展被設計成32位的進程中服務器程序,并且都是以動態鏈接庫的形式為操作系統提供服務的。因此,如果要對Windows的用戶界面進行擴充的話,則具備寫COM對象的一些知識是十分必要的。

  寫好外殼擴展程序后,必須將它們注冊才能生效。所有的外殼擴展都必須在Windows注冊表的HKEY_CLASSES_ROOTCLSID鍵之下進行注冊。在該鍵下面可以找到許多名字像{0000002F-0000-0000-C000-000000000046}的鍵,這類鍵就是全局唯一類標識符。每一個外殼擴展都必須有一個全局唯一類標識符,Windows正是通過此唯一類標識符來找到外殼擴展處理程序的。在類標識符之下的InProcServer32子鍵下記錄著外殼擴展動態鏈接庫在系統中的位置。與某種文件類型關聯的外殼擴展注冊在相應類型的shellex主鍵下。如果所處的Windows操作系統為Windows NT,則外殼擴展還必須在注冊表中的HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionShellExtensionsApproved主鍵下登記。

  注冊表HKEY_CLASSES_ROOT主鍵下有幾個特殊的子鍵,如*、Folder、Drive以及Printer。如果把外殼擴展注冊在*子鍵下,那么這個外殼擴展將對Windows中所有類型的文件有效;如果把外殼擴展注冊在Folder子鍵下,則對所有目錄有效。

上面提到的在Windows Explore中在鼠標右鍵菜單中添加菜單項(我們成為上下文相關菜單)的操作屬于外殼擴展的第一類,即Context menu handlers向特定類型的文件對象增添上下文相關菜單。要動態地在上下文相關菜單中增添菜單項,可以通過寫Context Menu Handler來實現。
  編寫Context Menu Handler必須實現IShellExtInit和IContextMenu兩個接口。除了IUnknown接口所定義的函數之外,Context Menu Handler還需要用到QueryContextMenu、InvokeCommand和GetCommandString這三個非常重要的成員函數。

  (1)QueryContextMenu函數:每當系統要顯示一個文件對象的上下文相關菜單時,它首先要調用該函數。為了在上下文相關菜單中添加菜單
項,我們在該函數中調用InsertMenu函數。

  (2)InvokeCommand函數:當用戶選定了某個Context Menu Handler登記過的菜單項后,該函數將會被調用,系統將會傳給該函數一個指向
LPCMINVOKECOMMANDINFO結構的指針。在該函數中要執行與所選菜單項相對應的操作。

  (3)GetCommandString函數:當鼠標指針移到一個上下文相關菜單項上時,在當前窗口的狀態條上將會出現與該菜單項相關的幫助信息,此
信息就是系統通過調用該函數獲取的。

下面我通過具體的例程來說明編寫一個比較完整的上下文菜單程序,這個程序是一個文件操作程序,當安裝并注冊了外殼擴展的服務器動態連接庫之后,當選擇一個或者多個文件并單擊鼠標右鍵后,在右鍵菜單中就會多出一個“執行文件操作”的上下文菜單,點擊菜單就會彈出相應的程序執行文件操作。
在整個程序的編寫中,外殼擴展的服務器動態連接庫是有Delphi4.0編寫的,而動態連接庫調用的文件操作程序是由VB6編寫的。下面首先介紹服務器動態連接庫的編寫:
服務器動態連接庫的工程文件內容如下:

library contextmenu;
uses
ComServ,
ContextMenuHandler in 'Unit2.pas';
// contmenu_TLB in 'contmenu_TLB.pas';

exports
DllGetClassObject,
DllCanUnloadNow,
DllRegisterServer,
DllUnregisterServer;

{$R *.TLB}

{$R *.RES}

begin

end.

將工程文件保存為contextmenu.dpr。
服務器動態連接庫的單位文件內容如下:

unit ContextMenuHandler;

interface
uses Windows,ActiveX,ComObj,ShlObj,Classes;

type
TContextMenu = class(TComObject,IShellExtInit,IContextMenu)
private
FFileName: array[0..MAX_PATH] of Char;
protected
function IShellExtInit.Initialize = SEIInitialize; // Avoid compiler warning
function SEIInitialize(pidlFolder: PItemIDList; lpdobj: IDataObject;
hKeyProgID: HKEY): HResult; stdcall;
function QueryContextMenu(Menu: HMENU; indexMenu, idCmdFirst, idCmdLast,
uFlags: UINT): HResult; stdcall;
function InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult; stdcall;
function GetCommandString(idCmd, uType: UINT; pwReserved: PUINT;
pszName: LPSTR; cchMax: UINT): HResult; stdcall;
end;

const

Class_ContextMenu: TGUID = '{19741013-C829-11D1-8233-0020AF3E97A9}';

{全局唯一標識符(GUID)是一個16字節(128為)的值,它唯一地標識一個接口(interface)}
var
FileList:TStringList;
Buffer:array[1..1024]of char;

implementation

uses ComServ, SysUtils, ShellApi, Registry,UnitForm;

function TContextMenu.SEIInitialize(pidlFolder: PItemIDList; lpdobj: IDataObject;
hKeyProgID: HKEY): HResult;
var
StgMedium: TStgMedium;
FormatEtc: TFormatEtc;
FileNumber,i:Integer;
begin
//如果lpdobj等于Nil,則本調用失敗
if (lpdobj = nil) then begin
Result := E_INVALIDARG;
Exit;
end;

//首先初始化并清空FileList以添加文件
FileList:=TStringList.Create;
FileList.Clear;
//初始化剪貼版格式文件
with FormatEtc do begin
cfFormat := CF_HDROP;
ptd := nil;
dwAspect := DVASPECT_CONTENT;
lindex := -1;
tymed := TYMED_HGLOBAL;
end;
Result := lpdobj.GetData(FormatEtc, StgMedium);
if Failed(Result) then Exit;

//首先查詢用戶選中的文件的個數
FileNumber := DragQueryFile(StgMedium.hGlobal,$FFFFFFFF,nil,0);
//循環讀取,將所有用戶選中的文件保存到FileList中
for i:=0 to FileNumber-1 do begin
DragQueryFile(StgMedium.hGlobal, i, FFileName, SizeOf(FFileName));
FileList.Add(FFileName);
Result := NOERROR;
end;

ReleaseStgMedium(StgMedium);
end;

function TContextMenu.QueryContextMenu(Menu: HMENU; indexMenu, idCmdFirst,
idCmdLast, uFlags: UINT): HResult;
begin
Result := 0;
if ((uFlags and $0000000F) = CMF_NORMAL) or
((uFlags and CMF_EXPLORE) <> 0) then begin
// 往Context Menu中加入一個菜單項
InsertMenu(Menu, indexMenu, MF_STRING or MF_BYPOSITION, idCmdFirst,
PChar('執行文件操作'));
// 返回增加菜單項的個數
Result := 1;
end;
end;

function TContextMenu.InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult;
var
// sFile:TFileStream;
charSavePath:array[0..1023]of char;
sSaveFile:String;
i:Integer;
F: TextFile;
FirstLine: string;
begin
// 首先確定該過程是被系統而不是被一個程序所調用
if (HiWord(Integer(lpici.lpVerb)) <> 0) then
begin
Result := E_FAIL;
Exit;
end;
// 確定傳遞的參數的有效性
if (LoWord(lpici.lpVerb) <> 0) then begin
Result := E_INVALIDARG;
Exit;
end;

//建立一個臨時文件保存用戶選中的文件名
GetTempPath(1024,charSavePath);
sSaveFile:=charSavePath+'chen0001.tmp';

AssignFile(F,sSaveFile); { next file in Files property }
ReWrite(F);
//將文件名保存到臨時文件中
for i:= 0 to FileList.Count -1 do begin
FirstLine:=FileList.Strings;
Writeln(F,FirstLine); { Read the first line out of the file }
end;
CloseFile(F);
//調用文件操作程序對用戶選中的文件進行操作
ShellExecute(0,nil,'c:FileOP.exe',PChar(sSaveFile),charSavePath,SW_NORMAL);

Result := NOERROR;
end;



function TContextMenu.GetCommandString(idCmd, uType: UINT; pwReserved: PUINT;
pszName: LPSTR; cchMax: UINT): HRESULT;
begin
if (idCmd = 0) then begin
if (uType = GCS_HELPTEXT) then
{返回該菜單項的幫助信息,此幫助信息將在用戶把鼠標移動到該菜單項時出現在狀態條上。}
StrCopy(pszName, PChar('點擊該菜單項將執行文件操作'));
Result := NOERROR;
end
else
Result := E_INVALIDARG;
end;



type
TContextMenuFactory = class(TComObjectFactory)
public
procedure UpdateRegistry(Register: Boolean); override;
end;



procedure TContextMenuFactory.UpdateRegistry(Register: Boolean);
var
ClassID: string;
begin
if Register then begin
inherited UpdateRegistry(Register);
ClassID := GUIDToString(Class_ContextMenu);
CreateRegKey('*shellex', '', '');
CreateRegKey('*shellexContextMenuHandlers', '', '');
CreateRegKey('*shellexContextMenuHandlersOpenWithWordPad', '', ClassID);

//如果操作系統為Windows NT的話
if (Win32Platform = VER_PLATFORM_WIN32_NT) then
with TRegistry.Create do
try
RootKey := HKEY_LOCAL_MACHINE;
OpenKey('SOFTWAREMicrosoftWindowsCurrentVersionShell Extensions', True);
OpenKey('Approved', True);
WriteString(ClassID, 'Context Menu Shell Extension');
finally
Free;
end;
end
else begin
DeleteRegKey('*shellexContextMenuHandlersFileOpreation');
DeleteRegKey('*shellexContextMenuHandlers');
// DeleteRegKey('*shellex');
inherited UpdateRegistry(Register);
end;
end;



initialization
TContextMenuFactory.Create(ComServer, TContextMenu, Class_ContextMenu,
'', 'Context Menu Shell Extension', ciMultiInstance,tmApartment);

end.

將該單位文件保存為unit2.pas,文件同contextmenu.dpr位于同一個目錄下。
打開Delphi,選菜單中的 file | open project 打開contextmenu.dpr文件,然后選 Project | build contextmenu菜單項編譯連接程序,如果編譯成功的話,會建立一個contextmenu.dll的動態連接庫文件,這個文件就是服務器動態連接庫。

下面來建立文件操作程序。打開VB,建立一個新的工程文件,在Form1中加入一個ListBox控件和三個CommandButton控件,將ListBox的MultiSelect屬性設置為2。然后在Form1的代碼窗口中加入以下代碼:
Option Explicit

Private Type BrowseInfo
hwndOwner As Long
pIDLRoot As Long
pszDisplayName As Long
lpszTitle As Long
ulFlags As Long
lpfnCallback As Long
lParam As Long
iImage As Long
End Type
Private Type SHFILEOPSTRUCT
hwnd As Long
wFunc As Long '對文件的操作指令
pFrom As String '源文件或路徑
pTo As String '目的文件或路徑
fFlags As Integer '操作標志
fAnyOperationsAborted As Long
hNameMappings As Long
lpszProgressTitle As String
End Type

Const FO_COPY = &H2
Const FO_DELETE = &H3
Const FO_MOVE = &H1
Const FO_RENAME = &H4
Const FOF_ALLOWUNDO = &H40
Const BIF_RETURNONLYFSDIRS = 1
Const MAX_PATH = 260

Private Declare Function ShellAbout Lib "shell32.dll" Alias _
"ShellAboutA" (ByVal hwnd As Long, ByVal szApp As _
String, ByVal szOtherStuff As String, ByVal hIcon As Long) _
As Long
Private Declare Sub CoTaskMemFree Lib "ole32.dll" (ByVal hMem As Long)
Private Declare Function lstrcat Lib "kernel32" Alias _
"lstrcatA" (ByVal lpString1 As String, ByVal lpString2 _
As String) As Long
Private Declare Function SHBrowseForFolder Lib "shell32" (lpbi _
As BrowseInfo) As Long
Private Declare Function SHGetPathFromIDList Lib "shell32" _
(ByVal pidList As Long, ByVal lpBuffer As String) As Long
Private Declare Function SHFileOperation Lib "shell32" _
(lpFileOp As SHFILEOPSTRUCT) As Long
Private Declare Function GetWindowsDirectory _
Lib "kernel32" Alias "GetWindowsDirectoryA" _
(ByVal lpBuffer As String, ByVal nSize As _
Long) As Long

Dim DirString As String
Dim sFile As String

Sub UpdateList()
'UpdateList函數檢查列表框中的文件是否存在,如果不存在,就將其
'從文件列表中刪除
Dim bEndList As Boolean
Dim i As Integer

bEndList = True
i = 0
While bEndList
'檢查文件是否存在,如果不存在就刪除
If Dir$(List1.List(i)) = "" Then
List1.RemoveItem (i)
Else '如果文件存在就轉移到下一個列表項
i = i + 1
If i > List1.ListCount - 1 Then
bEndList = False
End If
End If
Wend
Command1.Enabled = False
Command2.Enabled = False
Command3.Enabled = False
End Sub

Function BrowseForFolder(hwndOwner As Long, sPrompt As String) As String
Dim iNull As Integer
Dim lpIDList As Long
Dim lResult As Long
Dim sPath As String
Dim udtBI As BrowseInfo

'初試化udtBI結構
With udtBI
.hwndOwner = hwndOwner
.lpszTitle = lstrcat(sPrompt, "")
.ulFlags = BIF_RETURNONLYFSDIRS
End With

'彈出文件夾查看窗口
lpIDList = SHBrowseForFolder(udtBI)

If lpIDList Then
sPath = String$(MAX_PATH, 0)
lResult = SHGetPathFromIDList(lpIDList, sPath)
Call CoTaskMemFree(lpIDList)
iNull = InStr(sPath, vbNullChar)
If iNull Then sPath = Left$(sPath, iNull - 1)
End If

BrowseForFolder = sPath
End Function

Private Sub Command1_Click() '執行文件拷貝操作
Dim sPath As String
Dim tCopy As SHFILEOPSTRUCT
Dim i As Integer

'選擇拷貝到的文件夾
sPath = BrowseForFolder(Form1.hwnd, "選擇拷貝到的文件夾")
If sPath <> "" Then
With tCopy
.hwnd = Form1.hwnd
.lpszProgressTitle = "正在拷貝"
.pTo = sPath
.fFlags = FOF_ALLOWUNDO
.wFunc = FO_COPY
End With
For i = 0 To List1.ListCount - 1
If List1.Selected(i) Then '如果文件被選中則拷貝文件
tCopy.pFrom = List1.List(i)
SHFileOperation tCopy
End If
Next i
UpdateList
End If
Kill sFile
End Sub

Private Sub Command2_Click() '執行文件移動操作
Dim sPath As String
Dim tCopy As SHFILEOPSTRUCT
Dim i As Integer

'選擇移動到的文件夾
sPath = BrowseForFolder(Form1.hwnd, "選擇轉移到的文件夾")
If sPath <> "" Then
With tCopy
.hwnd = Form1.hwnd
.lpszProgressTitle = "正在移動"
.pTo = sPath
.fFlags = FOF_ALLOWUNDO
.wFunc = FO_MOVE
End With
For i = 0 To List1.ListCount - 1
If List1.Selected(i) Then '如果文件被選中則拷貝文件
tCopy.pFrom = List1.List(i)
SHFileOperation tCopy
End If
Next i
UpdateList
End If
Kill sFile
End Sub

Private Sub Command3_Click() '執行文件刪除操作
Dim sPath As String
Dim tCopy As SHFILEOPSTRUCT
Dim i As Integer

With tCopy
.hwnd = Form1.hwnd
.lpszProgressTitle = "正在刪除"
.pTo = sPath
.fFlags = FOF_ALLOWUNDO
.wFunc = FO_DELETE
End With
For i = 0 To List1.ListCount - 1
If List1.Selected(i) Then
tCopy.pFrom = List1.List(i)
SHFileOperation tCopy
End If
Next i
UpdateList
Kill sFile
End Sub

Private Sub Form_Load()
Dim hFileHandle As Long
Dim TextLine As String

Command1.Caption = "拷貝"
Command2.Caption = "移動"
Command3.Caption = "刪除"
Command1.Enabled = False
Command2.Enabled = False
Command3.Enabled = False

'sFile接受由Windows外殼擴展庫contextmenu.dll傳遞過來的文件參數
sFile = Command$
hFileHandle = FreeFile
Open sFile For Input As hFileHandle
Do While Not EOF(hFileHandle)
Line Input #1, TextLine
If Dir$(TextLine) <> "" Then
List1.AddItem TextLine
End If
Loop
Close hFileHandle
End Sub

Private Sub Form_Unload(Cancel As Integer)
If Dir$(sFile) <> "" Then
Kill sFile
End If
End Sub

Private Sub List1_Click()
If Not Command1.Enabled Then
Command1.Enabled = True
Command2.Enabled = True
Command3.Enabled = True
End If
End Sub
保存文件并將工程文件編譯為FileOP.exe文件,將文件拷貝到C盤根目錄下。然后注冊contextmenu.dll,注冊的方法是,在DOS窗口中進入Windowssystem子目錄,輸入 Regsvr32 x:xxxxxcontextmenu.dll 。其中x:xxxxx為Contextmenu.dll文件所在的驅動器和目錄。如果注冊成功,系統會彈出對話框,顯示 DllRegisterServer in ..xxxcontextmenu.dll Success 提示注冊成功。
注冊成功后,再選擇文件并單擊右鍵,就會發現在彈出菜單中多了一個“執行文件操作”的菜單項,點擊該項,系統就會調用FileOP.exe執行文件操作,在窗口的列表框中會出現用戶選擇的文件名,點擊相應的文件并點擊“拷貝”、“移動”或“刪除”按鈕就可以對列表框中的選中的文件進行相應的操作。
上面介紹的只是Context Menu Handler的應用的一個框架,各位讀者可以根據需要在上面的程序的基礎上做修改,為自己的程序建立上下文菜單擴展。
上面的程序Pascal部分在Delphi4.0下,Basic部分在VB6.0英文版下,在Windows98中文版下編譯運行通過。

熱詞搜索:

上一篇:高層協議POP3與HTTP
下一篇:如何利用OutLook漏洞編寫病毒腳本

分享到: 收藏
主站蜘蛛池模板: 鹤壁市| 泰兴市| 沁源县| 阿荣旗| 台北市| 曲麻莱县| 江北区| 湛江市| 乐至县| 洮南市| 望谟县| 郑州市| 汾阳市| 丹凤县| 西城区| 康平县| 台东市| 宾川县| 石阡县| 咸宁市| 彰武县| 承德县| 新营市| 隆尧县| 沁阳市| 措美县| 镶黄旗| 广饶县| 洛阳市| 望城县| 利辛县| 武城县| 浦城县| 栾川县| 大厂| 邹城市| 出国| 白水县| 江都市| 江安县| 桐庐县|