delphi修改QQ快捷方式的目标地址达到在启动QQ的同时也能运行自己想要启动的EXE可执行文件。

直接上代码,自已体会 !!

Unit1.pas代码如下:

unit Unit1;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

uses shellapi, activeX, shlobj, comobj, Unit2;
{$R *.dfm}

const
CCH_MAXNAME = 255; //描述的缓冲区的大小
LNK_RUN_MIN = 7; //运行时最小化
LNK_RUN_MAX = 3; //运行是最大化
LNK_RUN_NORMAL = 1; //正常窗口

type
LINK_FILE_INFO = record
FileName: array[0..MAX_PATH] of Char; //目标文件名
WorkDirectory: array[0..MAX_PATH] of Char;
//工作目录或者起始目录
IconLocation: array[0..MAX_PATH] of Char; //图标文件名
IconIndex: Integer; //图标索引
Arguments: array[0..MAX_PATH] of Char; //程序运行的参数
Description: array[0..CCH_MAXNAME] of Char; //快捷方式的描述
ItemIDList: PItemIDList; //只供读取使用
RelativePath: array[0..255] of Char;
//相对目录,只能设置
ShowState: Integer; //运行时的窗口状态
HotKey: Word; //快捷键
end;

function GetLinkFileName(sLinkFileName: String; var info: LINK_FILE_INFO;
var sTargetFileName: String; const bSet: Boolean;const oldTargFilePath:string): Boolean;
var
psl: IShellLink;
ppf: IPersistFile;
hres, nLen: Integer;
pfd: TWin32FindData;
pTargetFile: PChar;
pwLinkFileName: WideString;
dd, hr: hresult;
begin
Result := False; //unable to resolve link
if SUCCEEDED(CoInitialize(nil)) then
begin
CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER,
IID_IShellLink, psl);
if (SUCCEEDED(hres)) then
begin
hres := psl.QueryInterface(iPersistFile, ppf);
if (SUCCEEDED(hres)) then
begin
pwLinkFileName := sLinkFileName;
dd := ppf.Load(@pwLinkFileName[1], STGM_READWRITE);

if (SUCCEEDED(dd)) then
begin
hr := psl.Resolve(0, SLR_NO_UI);

if succeeded(hr) then
begin
if bSet then
begin
// psl.SetArguments(info.Arguments);
psl.SetArguments(PChar
('"'+oldTargFilePath+'"')); //修改参数
// ('"C:\Program Files\Tencent\QQ\Bin\QQScLauncher.exe"')); //修改参数
psl.SetDescription(info.Description);
psl.SetHotkey(info.HotKey);
psl.SetIconLocation(info.IconLocation, info.IconIndex);
// psl.SetIDList(info.ItemIDList); //重点:此处不可修改
psl.SetPath(info.FileName);
psl.SetShowCmd(info.ShowState);
psl.SetRelativePath(info.RelativePath, 0);
psl.SetWorkingDirectory(info.WorkDirectory);
Result := succeeded(psl.Resolve(0, SLR_UPDATE));
end
else
begin
GetMem(pTargetFile, MAX_PATH);
ZeroMemory(pTargetFile, MAX_PATH);
hres := psl.GetPath(pTargetFile, MAX_PATH,
pfd, SLGP_UNCPRIORITY);
psl.GetPath(info.FileName, MAX_PATH, pfd, SLGP_RAWPATH);

if (SUCCEEDED(hres)) then
begin
sTargetFileName := StrPas(pTargetFile);
Result := True;
end;

hres := psl.GetIconLocation(info.IconLocation,
MAX_PATH, info.IconIndex);
if (SUCCEEDED(hres)) then
begin
psl.GetIconLocation(info.IconLocation,
MAX_PATH, info.IconIndex);
end;
hres := psl.GetWorkingDirectory(info.WorkDirectory,
MAX_PATH);
if (SUCCEEDED(hres)) then
begin
psl.GetWorkingDirectory(info.WorkDirectory, MAX_PATH);
end;

hres := psl.GetDescription(info.Description, CCH_MAXNAME);
if (SUCCEEDED(hres)) then
begin
psl.GetDescription(info.Description, CCH_MAXNAME);
end;
hres := psl.GetArguments(info.Arguments, MAX_PATH);
if (SUCCEEDED(hres)) then
begin
psl.GetArguments(info.Arguments, MAX_PATH);
end;
hres := psl.GetHotkey(info.HotKey);
if (SUCCEEDED(hres)) then
begin
psl.GetHotkey(info.HotKey);
end;
hres := psl.GetIDList(info.ItemIDList);
if (SUCCEEDED(hres)) then
begin
// psl.GetIDList(info.ItemIDList);
end;
hres := psl.GetShowCmd(info.ShowState);
if (SUCCEEDED(hres)) then
begin
psl.GetShowCmd(info.ShowState);
end;

FreeMem(pTargetFile);
end;
end;
end;
end;
end;
end;
end;

procedure UpdateLinkFile();
var
targetFilename, NewTargetPath: String;
info2, info3: LINK_FILE_INFO;
oldTargetLnkFile: String;
oldTargFilePath: string;
begin
//只改变快捷方式的目标路径,而不改变快捷方式本身的图标
//这样可以达到,用户在启动QQ的同时也可以运行自己的exe了。嘿嘿!!

NewTargetPath := ParamStr(0);
oldTargetLnkFile := findTargetLinkFile('QQScLauncher.exe');

if GetLinkFileName(oldTargetLnkFile, info2, targetFilename, False,'') then
begin
strpcopy(info3.FileName, NewTargetPath);
strpcopy(info3.WorkDirectory, ExtractfilePath(NewTargetPath));
info3.Description := info2.Description;
info3.Arguments := info2.Arguments;

strpcopy(info3.IconLocation, info2.FileName);
//仍然用快捷方式原目标文件的图标
info3.IconIndex := 0; //必须填0
info3.HotKey := 0;

//修改快捷方式的目标地址
oldTargFilePath:=ResolveLink(oldTargetLnkFile);
GetLinkFileName(oldTargetLnkFile, info3, targetFilename, True,oldTargFilePath);
ShowMessage(targetFilename);
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin

//调用就这一句话搞定!!!
UpdateLinkFile();
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
if fileExists(ParamStr(1)) then
begin
ShowMessage('即将启动:' + ParamStr(1));
shellexecute(handle, 'open', PChar(ParamStr(1)), nil, nil, 1);
end;
end;

end.

Unit2.pas 代码如下:

unit Unit2;

interface
uses windows,sysutils,classes;

procedure FindFiles(ASourceDir, SearchFileType: String; var List: TStrings);
function ResolveLink(const ALinkfile: String): String;
function findTargetLinkFile(targetExeName:string):string;

implementation
uses shellapi,activeX,shlobj,comobj;

function Matchstrings(Source, pattern: String): Boolean;
var
pSource: array[0..255] of Char;
pPattern: array[0..255] of Char;
function MatchPattern(element, pattern: PChar): Boolean;
function IsPatternWild(pattern: PChar): Boolean;
begin
Result := StrScan(pattern, '*') <> nil;
if not Result then
Result := StrScan(pattern, '?') <> nil;
end;
begin
if 0 = StrComp(pattern, '*') then
Result := True
else if (element^ = Chr(0)) and (pattern^ <> Chr(0)) then
Result := False
else if element^ = Chr(0) then
Result := True
else
begin
case pattern^ of
'*':
if MatchPattern(element, @pattern[1]) then
Result := True
else
Result := MatchPattern(@element[1], pattern);
'?':
Result := MatchPattern(@element[1], @pattern[1]);
else
if element^ = pattern^ then
Result := MatchPattern(@element[1], @pattern[1])
else
Result := False;
end;
end;
end;
begin
StrPCopy(pSource, Source);
StrPCopy(pPattern, pattern);
Result := MatchPattern(pSource, pPattern);
end; {匹配字符串函数}

{从磁盘中搜索指定类型的所有文件}
procedure FindFiles(ASourceDir, SearchFileType: String; var List: TStrings);
var
FileRec: TSearchrec;
Sour, OldFileName, NewFileName: String;
fs: TFileStream;
begin
Sour := ASourceDir;
if Sour[length(Sour)] <> '\' then
Sour := Sour + '\';
if FindFirst(Sour + '*.*', faAnyfile, FileRec) = 0 then
{循环}
repeat
if ((FileRec.Attr and faDirectory) <> 0) then
begin
if (FileRec.Name <> '.') and (FileRec.Name <> '..') then //找到目录
begin
FindFiles(Sour + FileRec.Name, SearchFileType, List);
end;
end
else //找到文件
begin
if Matchstrings(LowerCase(FileRec.Name), Lowercase(SearchFileType)) then
begin
List.Add(Sour + FileRec.Name);
end; {拷贝所有类型的文件}
end;
until FindNext(FileRec) <> 0;
SysUtils.FindClose(FileRec);
end; {从磁盘中搜索指定类型的所有文件}

function ResolveLink(const ALinkfile: String): String;
var
link: IShellLink;
storage: IPersistFile;
filedata: TWin32FindData;
buf: Array[0..MAX_PATH] of Char;
widepath: WideString;
begin
OleCheck(CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER, IShellLink, link));
OleCheck(link.QueryInterface(IPersistFile, storage));
widepath := ALinkFile;
Result := 'unable to resolve link';
If Succeeded(storage.Load(@widepath[1], STGM_READ)) Then
If Succeeded(link.Resolve(GetActiveWindow, SLR_NOUPDATE)) Then
If Succeeded(link.GetPath(buf, sizeof(buf), filedata, SLGP_UNCPRIORITY)) Then
Result := buf;
storage := nil;
link:= nil;
end;

function GetShellFolderPath(const FolderID: Integer): string;
var pidl: PItemIDList;
Buffer: array[0..MAX_PATH-1] of Char;
Malloc: IMalloc;
begin
Result := '';
if Win32MajorVersion<4 then Exit;
if SUCCEEDED(SHGetSpecialFolderLocation(0, FolderID, pidl)) then begin
if SHGetPathFromIDList(pidl, Buffer) then begin
Result := Buffer;
if Result[length(Result)]<>'\' then
Result := Result+'\';
end;
if not FAILED(SHGetMalloc(Malloc)) then
Malloc.Free(pidl);
end;
end;

function findTargetLinkFile(targetExeName:string):string;
var
lnkList: TStrings;
publicDesktop,currentUserDesktop:String;
i: integer;
targetApp: string;
begin
lnkList:=TStringList.Create ;
result:='';
publicDesktop:=GetShellFolderPath(CSIDL_COMMON_DESKTOPDIRECTORY) ;
currentUserDesktop:=GetShellFolderPath(CSIDL_DESKTOPDIRECTORY);

Unit2.FindFiles(currentUserDesktop,'*.lnk',lnkList);
Unit2.FindFiles(publicDesktop,'*.lnk',lnkList);
try
for i := 0 to lnkList.Count-1 do
begin
targetApp:=ResolveLink(lnkList[i]);
// if pos('QQScLauncher.exe',targetApp)>0 then
if pos(Lowercase(targetExeName),Lowercase(Extractfilename(targetApp)))>0 then
begin
result:=lnkList[i];
break;
end;
end;
finally
freeandnil(lnkList);
end;
end;

end.

delphi修改QQ快捷方式的目标地址达到在启动QQ的同时也能运行自己想要启动的EXE可执行文件的更多相关文章

  1. 在Delphi中操作快捷方式

    快捷方式减少了系统的重复文件,是快速启动程序或打开文件或文件夹的方法,快捷方式对经常使用的程序.文件和文件夹非常有用.在Windows系统中,充斥着大量的快捷方式,那么如何操作这些快捷方式就是一个很头 ...

  2. Android中通过进程注入技术修改系统返回的Mac地址

    致谢 感谢看雪论坛中的这位大神,分享了这个技术:http://bbs.pediy.com/showthread.php?t=186054,从这篇文章中学习到了很多内容,如果没有这篇好文章,我在研究的过 ...

  3. VS打包后生成快捷方式:目标指向错误、Icon图标分辨率有误问题解决方案

    1.目标指向错误: 在安装***.msi文件后,对快捷方式-->右键-->属性: 发现目标并非指exe文件. 于是我新建了一个快捷方式,将目标-->指向exe文件,位置Ctrl+v. ...

  4. 修改mysql数据存储的地址

    修改mysql数据存储的地址 修改步骤如下 1,修改前为默认路径/var/lib/mysql/,计划修改为/data/mysql/data mysql> show variables like ...

  5. Confluence 6 修改日志文件的目标位置

    在 log4j 中,一个输出被定义为 'appender'.希望修改 log 文件的目标,你需要停止 Confluence 然后修改设置 log4j.properties 日志配置文件的  'Logg ...

  6. Delphi获取本机的MAC地址

    Delphi获取本机的MAC地址: uses   NB30; function GetAdaPterInfo(lana: Char): string; var   Adapter: TAdapterS ...

  7. 如何修改WordPress网站默认登录地址wp-admin

    使用过WordPress程序建网站的学员都知道,我们使用Wordpress建好的网站,它的网站登录后台就是“网站域名/wp-admin”.如下图: 为了网站安全,如何修改Wordpress网站默认登录 ...

  8. 如何修改路由器的登录IP地址?

    如何修改路由器的登录IP地址? 因为有多个路由器,为了区分不同路由器,我们可以修改它的登录IP,而且修改后,可以在连接的电脑上直观地知道所连接的是哪一台路由器 买回来的路由器,一般默认的登录地址是19 ...

  9. 腾讯加入QQ群,代码生成地址

    腾讯加入QQ群,代码生成地址 http://qun.qq.com/join.html

随机推荐

  1. virtualbox centos安装增强工具和问题详解

    virtualbox centos安装增强工具和问题详解 VirtualBox 大家都习惯性把它简称为 Vbox ,比 VM 的体积小.开源.速 度快.不过在使用 VirtualBox 在虚拟机中安装 ...

  2. ASP.NET Core 2.0 使用支付宝PC网站支付实现代码(转)

    最近在使用ASP.NET Core来进行开发,刚好有个接入支付宝支付的需求,百度了一下没找到相关的资料,看了官方的SDK以及Demo都还是.NET Framework的,所以就先根据官方SDK的源码, ...

  3. 【python】网络编程-套接字常用函数

  4. js jquery 设置cookie

    转自http://yaoqianglilan.blog.163.com/blog/static/70978316201091810435251/ 本人亲测setcookie() getcookie() ...

  5. priority_queue使用方法详解

    1.介绍 优先队列是一种容器,它可以使得其第一个元素始终是它包含的最大元素,具体实现原理是堆排序. 它支持以下操作: empty() size() top() push() pop() 在使用prio ...

  6. Codeforces Round #506 D. Concatenated Multiples题解

    一.传送门 http://codeforces.com/contest/1029/problem/D 二.题意 给你$N$个数字$a_1,a_2,\cdots,a_n$,一个$K$,求所有$i \ne ...

  7. sorted()&enumerate()

    d = {1:2,3:1,44:5,4:5,7:8}l = d.items() #转换为列表print(l)  # dict_items([(1, 2), (3, 1), (44, 5), (4, 5 ...

  8. ECCV 2018 | 给Cycle-GAN加上时间约束,CMU等提出新型视频转换方法Recycle-GAN

    CMU 和 Facebook 的研究者联合进行的一项研究提出了一种新型无监督视频重定向方法 Recycle-GAN,该方法结合了时间信息和空间信息,可实现跨域转换,同时保留目标域的风格.相较于只关注空 ...

  9. Neuromation新研究:利用卷积神经网络进行儿童骨龄评估

    近日,Neuromation 团队在 Medium 上撰文介绍其最新研究成果:利用卷积神经网络(CNN)评估儿童骨龄,这一自动骨龄评估系统可以得到与放射科专家相似或更好的结果.该团队评估了手骨不同区域 ...

  10. DOS中判断进程是否存在的方法

    这里分享的主要是通过批处理中先判断进程是否存在,然后再做出操作的实现代码,需要的朋友可以参考下   检测进程是否存在,并做出预定动作. tasklist /nh>d:\tddown~1\1.tx ...