原创: 用代码实现为程序创建快捷方式的二种方法

作者: 陆岛工作室



本文由陆岛工作室原创,如需转载,请注明转载地址。

有时,我们会编一些小的工具软件, 不需要安装就能直接使用的那种所谓的绿色软件。这种软件不需要安装,但有时我们又需要他能在桌面或 Windows 开始菜单的程序组里能有一个快捷方式。那么就可能需要工具软件本身来直接为程序创建一个桌面或程序组的快捷方式。
在Windows操作系统里,桌面的快捷方式有两种, 一种是以 .lnk 为后缀名的文件快捷方式。另一种是保存在注册表里的快捷方式,如MS Word 的快捷方式。这种方式有定的封密性,可以防止用户修改或删除快捷方式里的内容。这里我将二种方法分别给大家说明一下,并贴出在 DELPHI 中的实现代码。方便有用的朋友直接使用。

//以下代码需要引用的单元文件。
uses Registry, ShlObj, ComObj, ShellAPI, ActiveX;


第一种:快捷方式文件的方法。

函数 CreateLinkFile 通过使用 Windows 的COM对象,调用 CreateComObject(CLSID_ShellLink) 来创建一个子IShellLink的COM接口对象。现使用IPersistFile来保存创建的文件。

IShellLink 与 IPersistFile 在 MSDN 的类描述如下, 如果我们掌握了这两个类,也可以方便地实现快捷方式文件的读取。

 

IShellLink


The IShellLink interface allows Shell links to be created, modified, and resolved.

Methods

IShellLink supports the following methods:

GetArguments Retrieves the command-line arguments associated with a Shell link object.
GetDescription Retrieves the description string for a Shell link object.
GetHotkey Retrieves the hot key for a Shell link object.
GetIconLocation Retrieves the location (path and index) of the icon for a Shell link object.
GetIDList Retrieves the list of item identifiers for a Shell link object.
GetPath Retrieves the path and file name of a Shell link object.
GetShowCmd Retrieves the show (SW_) command for a Shell link object.
GetWorkingDirectory Retrieves the name of the working directory for a Shell link object.
Resolve Resolves a Shell link by searching for the Shell link object and updating the Shell link path and its list of identifiers (if necessary).
SetArguments Sets the command-line arguments associated with a Shell link object.
SetDescription Sets the description string for a Shell link object.
SetHotkey Sets the hot key for a Shell link object.
SetIconLocation Sets the location (path and index) of the icon for a Shell link object.
SetIDList Sets the list of item identifiers for a Shell link object.
SetPath Sets the path and file name of a Shell link object.
SetRelativePath Sets the relative path for a Shell link object.
SetShowCmd Sets the show (SW_) command for a Shell link object.
SetWorkingDirectory Sets the name of the working directory for a Shell link object.

Remarks

Note: The IShellLink interface has an ANSI version (IShellLinkA) and a Unicode version (IShellLinkW). The version that will be used depends on whether you compile for ANSI or Unicode. However, Microsoft® Windows 95 and Microsoft® Windows 98 only support IShellLinkA.

IPersistFile

The IPersistFile interface provides methods that permit an object to be loaded from or saved to a disk file, rather than a storage object or stream. Because the information needed to open a file varies greatly from one application to another, the implementation of IPersistFile::Load on the object must also open its disk file.

The IPersistFile interface inherits its definition from IPersist, so all implementations must also include the GetClassID method of IPersist.

When to Implement

Implement IPersistFile when you want to read or write information from a separate file, which could be of any file format.

This interface should be implemented on any objects that support linking through a file moniker, including the following:

  • Any object that supports links to its files or to pseudo-objects within its files.
  • A container application that supports links to objects within its compound file.

Typically, you implement the IPersistFile interface as part of an aggregate object that includes other interfaces that are appropriate for the type of moniker binding that is supported.

For example, in either of the cases mentioned above, the moniker for the linked object can be a composite moniker. In the first case, a composite moniker identifies the pseudo-object contained within the file. In the second case, a composite moniker identifies the embedded object contained within the compound file. In either case of composite monikers, you must implement the IPersistFile interface as part of the same object on which the IOleItemContainer interface is implemented. Then, when the application for the linked object is run, OLE queries for the IOleItemContainer interface to locate the embedded object or the pseudo-object contained in the file.

As another example, if the moniker is a simple file moniker (i.e., the link is to the entire file), OLE queries for the interface that the initiator of the bind operation requested. Typically, this is one of the compound document interfaces, such as IOleObject, IDataObject, or IPersistStorage.

When to Use

Call methods in the IPersistFile interface to load or save a linked object in a specified file.

When IPersistFile is implemented on an object that supports linking through a file moniker and the application for the linked object is run, OLE calls IPersistFile::Load. Once the file is loaded, OLE calls IPersistFile::QueryInterface to get another interface pointer to the loaded object. The IPersistFile interface is typically part of an aggregate object that offers other interfaces.

In this case, the only IPersistFile method that OLE calls is the Load method to load a file linked to a container, running the application associated with the file. It would also be unusual for applications to call other methods in this case, which support saving an object to a file. Generally, it is left to the end user and the application for the linked object to decide when to save the object. This differs from the situation for an embedded object, in which the container application uses the IPersistStorage interface to provide the storage and to tell the object when to save itself.

Methods in Vtable Order

IUnknown Methods Description
QueryInterface Returns pointers to supported interfaces.
AddRef Increments the reference count.
Release Decrements the reference count.

IPersist Method

Description

GetClassID Returns the class identifier (CLSID) for the component object.

IPersistFile Methods

Description

IsDirty Checks an object for changes since it was last saved to its current file.
Load Opens the specified file and initializes an object from the file contents.
Save Saves the object into the specified file.
SaveCompleted Notifies the object that it can revert from NoScribble mode to Normal mode.
GetCurFile Gets the current name of the file associated with the object.


CreateLinkFile 的实现代码如下,熟悉 DELPHI 的朋友也可以根据 MSDN 中 IShellLink 的说明,实现为快捷方式设置快捷键,窗口运行方式等,CreateLinkFile 只是提供了最基本的快捷方式模式。

{ CreateLinkFile }

procedure CreateLinkFile(SourceFile, ShortCutName, Description: String);
var
  IUnk: IUnknown;
  ShellLink: IShellLink;
  IPFile: IPersistFile;
  tmpShortCutName: string;
  WideStr: WideString;
  i: integer;
begin
  
if SUCCEEDED(CoInitialize(nil)) then   
  
begin
    IUnk :
= CreateComObject(CLSID_ShellLink);
    ShellLink :
= IUnk as IShellLink;
    IPFile  :
= IUnk as IPersistFile;

    
with ShellLink do
    
begin
      SetPath(PChar(SourceFile)); 
//执行程序的文件名
      SetDescription(PChar(Description)); 
//提示说明文本 
      SetWorkingDirectory(PChar(ExtractFilePath(SourceFile))); 
//启动目录
    
end;

    ShortCutName :
= ChangeFileExt(ShortCutName,'.lnk');
    
    
if FileExists(ShortCutName) then //如果文件名存在,就以数据序号来重新命名一个新的文件名
    
begin
      ShortCutName :
= Copy(ShortCutName, 1, Length(ShortCutName) - 4);
      i :
= 1;
      
repeat
        tmpShortCutName :
= ShortCutName +'(' + IntToStr(i)+ ').lnk';
        Inc(i);
      
until not FileExists(tmpShortCutName);
      WideStr :
= tmpShortCutName;
    
end
    
else WideStr := ShortCutName;

    IPFile.Save(PWChar(WideStr),False);
    
    CoUninitialize;
  
end;
end;

 

第二种:通过注册表创建快捷方式的方法。

函数:CreateShortCutOnDeskTop; 这种方法主要是通过写注册表来实现。通过这种方式实现的快捷方式具有一定的封装性。一般用在桌面上的快捷方式。
这种快捷方式必须要有一个GUID,子GUID 可以通过 CoCreateGuid 来取得, 如
var
  FShortCutID: string
  AGuid: TGUID;
begin
  if (CoCreateGuid(AGuid)=S_OK) then
    FShortCutID := GuidToString(AGuid);
end;

CreateShortCutOnDeskTop 的实现代码如下:

 

const
  REG_ROOTRUN_KEY 
= 'Software\Microsoft\Windows\CurrentVersion\Run';
  REG_ROOTRUN_STR 
= '我的快捷方式'//你可以修改这个名称为自己合适的名称

{ CreateShortCutOnDeskTop }

{ 参数说明
  aTitle: 快捷方式名称 
  aInfoTip: 快捷方式提示说明文本 
  aCmdLine: 执行程序文件名
  aIcon: 图标文件
  FShortCutID: 快捷方式的 GUID 必须有
  
}

function CreateShortCutOnDeskTop(aTitle, aInfoTip, aCmdLine, aIcon, FShortCutID: String): Boolean;
var
  FRegFile: TRegIniFile;
  RegStr: String;
  TempKey: HKey;
  Buffer,BufSize,Disposition: Integer;
begin
  FRegFile :
= TRegIniFile.Create('HKEY_LOCAL_MACHINE\');
  RegStr :
= '.DEFAULT\Software\Classes\CLSID\' + FShortCutID;
  FRegFile.RootKey :
= HKEY_USERS;
  FRegFile.CreateKey(RegStr);
  FRegFile.WriteString(RegStr,
'',aTitle);
  RegStr :
= 'Software\Microsoft\Windows\CurrentVersion\explorer\Desktop\NameSpace\'+ FShortCutID;
  FRegFile.RootKey :
= HKEY_LOCAL_MACHINE;
  FRegFile.CreateKey(RegStr);
  FRegFile.WriteString(RegStr,
'',aTitle);
  RegStr :
= 'Software\CLASSES\CLSID\' + FShortCutID;
  FRegFile.CreateKey(RegStr);
  FRegFile.WriteString(RegStr,
'',aTitle);
  FRegFile.WriteString(RegStr,
'InfoTip',aInfoTip);
  FRegFile.CreateKey(RegStr
+'\DefaultIcon');
  FRegFile.WriteString(RegStr
+'\DefaultIcon','',aIcon);
  FRegFile.CreateKey(RegStr
+'\shell\open\command');
  FRegFile.WriteString(RegStr
+'\shell\open\command','',aCmdLine);
  FRegFile.CreateKey(RegStr
+'\ShellFolder');//'Attributes'
  FRegFile.WriteString(RegStr
+'\ShellFolder','Attributes','1000000');
  FRegFile.Free;
  TempKey :
= 0;
  try
    RegCreateKeyEx(HKEY_LOCAL_MACHINE, PChar(RegStr
+'\ShellFolder'), 0nil,
      REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 
nil, TempKey, @Disposition);
    Bufsize :
= Sizeof(Integer);
    Buffer :
= 311{137} {0x20000137}
    
if (RegSetValueEx(TempKey, PChar('Attributes'), 0, REG_DWORD, @Buffer,
      BufSize)
<> ERROR_SUCCESS) then Result := False
    
else Result := True;
  finally
    
//更新桌面显示,将刚创建的快捷方式立即显示出来
    SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 
nilnil);
  
end;
end;

示范:

var
  ShortcutId: string;
  AGuid: TGUID;
begin
  
if (CoCreateGuid(AGuid)=S_OK) then
    ShortcutId :
= GuidToString(AGuid);

  
if ShortcutId<>'' then
    CreateShortCutOnDeskTop(Application.MainForm.Caption, Application.MainForm.Hint,
      Application.ExeName, Application.ExeName, ShortcutId);
end;


posted @ 2008-06-17 16:56  陆岛工作室  阅读(5057)  评论(5编辑  收藏  举报