ishelllink设置all user


如何用Shell实现程序组快捷方式的添加
作者 bood E-mail地址 boodweb@263.net
关键词:Shell函数 COM

(一)前言
曾经在《电脑编程与维护》看到过一篇用DDE实现在程序组添加项目的方法,但是MSDN上明确指出应该用更加先进的Shell函数来实现,因此笔者在MSDN上仔细查找,终于在一篇名为“SHORTCUT: A SampleThat Manipulates Shortcuts”的文章中发现了这种方法。由于笔者初学COM不久,若有不当之处,请一定指出,感激不尽!

(二)预备知识
Windows的程序组中的内容,实际上就是一个特定目录下的一些文件夹和文件(一般在c:\Windows\Start Menu\Programs目录下,我们可以用Shell函数SHGetSpecialFolderPath以CSIDL_PROGRAMS参数获得程序组的存放目录),Windows根据这些内容动态创建开始菜单和其下的子菜单。其中的文件夹代表一个弹出菜单,而文件则是快捷方式(.lnk文件),因此要在程序组建立快捷方式,实际上就是要在这个特定目录下新建一些.lnk文件,所幸Windows为我们提供了这样的接口。(当然,你要自己研究.lnk的文件结构然后自己一个字节一个字节的填,我也不反对)这些接口函数就是所谓的Shell函数的一部分。
Shell函数实际上就是一些Windows内置COM对象接口的函数,因此要使用他们,就应当知道一些有关COM的细节,您可以看看潘爱民的《COM原理与应用》。而我们要用的接口是IShellLink(用来设置要建立的快捷方式的一些信息)以及IPersistFile(用来以文件形式保存快捷方式)接口(均属于ShellLink对象),首先我们可以用CoCreateInstance库函数创建一个名为ShellLink的COM对象,同时得到其中一个接口指针,再用QueryInterface查询另外一个接口。详细实现以及接口函数的使用请看下面的代码。

(三)代码
这是我的实现,注意由于用了COM库函数,事先要调用CoInitialize()初始化,而在程序退出前要调用CoUninitialize()

//bAdd=1表示添加快捷方式,bAdd=0表示删除此快捷方式
//此例中快捷方式名称为“自动运行.lnk”,创建在启动组内
BOOL CTestDlg::SetAutoRun(BOOL bAdd)
{
HRESULT hres;
IShellLink *psl;//IShellLink接口指针
BOOL bRet=FALSE;
char pszDesPath[MAX_PATH];//创建的目标路径
char pszShortcutFile[MAX_PATH];//创建的源文件

::GetModuleFileName(NULL,pszShortcutFile,MAX_PATH);//得到本程序路径
SHGetSpecialFolderPath(m_hWnd,pszDesPath,CSIDL_PROGRAMS,0);//程序组路径
strcat(pszDesPath,"\\启动\\自动运行.lnk");//启动组
if(!bAdd)
return DeleteFile(pszDesPath);

hres = CoCreateInstance (CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
IID_IShellLink, (void **)&psl);//得到CLSID_ShellLink标识的COM对象的IShellLink接口
if (!SUCCEEDED(hres)) goto error;
IPersistFile *ppf;//IPersistFile接口指针

//查询IPersistFile接口以进行快捷方式的存储操作
hres = psl->QueryInterface (IID_IPersistFile, (void **)&ppf);
if (!SUCCEEDED (hres)) goto error;
WORD wsz [MAX_PATH]; //Unicode字符串的缓冲地址
//为适应COM标准一定要用Unicode

//设置源文件地址
hres = psl->SetPath (pszShortcutFile);

if (! SUCCEEDED (hres)) goto error;

//设置参数
hres = psl->SetArguments("/ArgumentsHere");
if (! SUCCEEDED (hres)) goto error;

//设置快捷方式的描述
hres = psl->SetDescription ("Shortcut to ScreenColor");

if (! SUCCEEDED (hres)) goto error;

//将ANSI字符串转换为Unicode字符串
MultiByteToWideChar (CP_ACP, 0, pszDesPath, -1, wsz, MAX_PATH);

//调用Save方法进行存储
hres = ppf->Save (wsz, TRUE);

if (! SUCCEEDED (hres)) goto error;

bRet=TRUE;

error:
//释放接口
ppf->Release ();
psl->Release ();

return TRUE;
}


SHGetSpecialFolderPath(m_hWnd,pszDesPath,CSIDL_PROGRAMS,0)获得的路径是:"C:\Documents and Settings\Administrator\「开始」菜单\程序", 我需要的路径是"C:\Documents and Settings\All Users\「开始」菜单\程序"怎办? 我不想认为的对字符串操作


#define CSIDL_COMMON_STARTMENU 0x0016 // All Users\Start Menu #define CSIDL_COMMON_PROGRAMS 0X0017 // All Users\Programs #define CSIDL_COMMON_STARTUP 0x0018 // All Users\Startup #define CSIDL_COMMON_DESKTOPDIRECTORY 0x0019 // All Users\Desktop SHGetSpecialFolderLocation 参数改变一下就是All User 的目录了 具体参数参看shlobj.h 里面

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

//根据zswang和"超级猛料"部分函数改编
  //比放到注册表里麻烦多了
  function GetSpecialFolderDir(const folderid:integer): String;
  var
    pidl: pItemIDList;
    buffer: array[0..255] of char;
  begin
  //取指定的文件夹项目表
  //CSIDL_STARTUP:启动
    SHGetSpecialFolderLocation(application.Handle , folderid, pidl);
    SHGetPathFromIDList(pidl, buffer); //转换成文件系统的路径
    Result:=strpas(buffer);
  end;

  function CreateShellLink(mPath: string; mWorkingDirectory: string;
    mFileName: WideString): Boolean; { 返回创建快捷方式是否成功 }
  var
    vShellLink: IShellLink;
    vPersistFile: IPersistFile;
    vUnKnown: IUnKnown;
  begin
    Result := True;
    try
      vUnKnown := CreateComObject(CLSID_ShellLink);
      vShellLink := vUnKnown as IShellLink;
      vPersistFile := vUnKnown as IPersistFile;
      vShellLink.SetPath(PChar(mPath));
      vShellLink.SetWorkingDirectory(PChar(mWorkingDirectory));
      if ExtractFileExt(mFileName) <> '.lnk' then
        mFileName := mFileName + '.lnk';
      vPersistFile.Save(PWChar(mFileName), False);
    except
      Result := False;
    end;
  end;

  function CreateLinkToStartUp(AppName, WorkingDirectory, 
    LinkFileName: String; CurrentUser: Boolean = True): Boolean;
  begin
    if CurrentUser then //CurrentUser
      Result := CreateShellLink(AppName, WorkingDirectory,
        GetSpecialFolderDir(CSIDL_STARTUP) + '' + LinkFileName)
    else//All User
      Result := CreateShellLink(AppName, WorkingDirectory,
        GetSpecialFolderDir(CSIDL_COMMON_STARTUP) + '' + LinkFileName); 
  end;
  //创建到当前用户的[启动]里,CreateLinkToStartUp中最后一个参数设置为True
  //创建到所有用户的启动里,CreateLinkToStartUp中最后一个参数设置为False
  //创建到别的用户里,可以修改一下,不过。。。这样做不好吧。。。

 

***********************************************************8

  1. // AUTORUNDlg.cpp : implementation file   
  2. //   
  3.    
  4. #include "stdafx.h"   
  5. #include "AUTORUN.h"   
  6. #include "AUTORUNDlg.h"   
  7. #include <shlobj.h>   
  8.    
  9. #ifdef _DEBUG   
  10. #define new DEBUG_NEW   
  11. #undef THIS_FILE   
  12. static char THIS_FILE[] = __FILE__;   
  13. #endif   
  14.    
  15. /////////////////////////////////////////////////////////////////////////////   
  16. // CAUTORUNDlg dialog   
  17.    
  18. CAUTORUNDlg::CAUTORUNDlg(CWnd* pParent /*=NULL*/)   
  19.     : CDialog(CAUTORUNDlg::IDD, pParent)   
  20. {   
  21.    
  22.     //{{AFX_DATA_INIT(CAUTORUNDlg)   
  23.     m_run = _T("");   
  24.     m_user = _T("");   
  25.     //}}AFX_DATA_INIT   
  26.     // Note that LoadIcon does not require a subsequent DestroyIcon in Win32   
  27.     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);   
  28. }   
  29.    
  30. void CAUTORUNDlg::DoDataExchange(CDataExchange* pDX)   
  31. {   
  32.     CDialog::DoDataExchange(pDX);   
  33.     //{{AFX_DATA_MAP(CAUTORUNDlg)   
  34.     DDX_Text(pDX, IDC_RUNEDIT, m_run);   
  35.     DDX_Text(pDX, IDC_USEREDIT, m_user);   
  36.     //}}AFX_DATA_MAP   
  37. }   
  38.    
  39. BEGIN_MESSAGE_MAP(CAUTORUNDlg, CDialog)   
  40.     //{{AFX_MSG_MAP(CAUTORUNDlg)   
  41.     ON_WM_PAINT()   
  42.     ON_WM_QUERYDRAGICON()   
  43.     ON_BN_CLICKED(IDC_OK1, OnOk)   
  44.     ON_BN_CLICKED(IDC_CANCEL, OnCancel)   
  45.     ON_BN_CLICKED(IDC_BUTTON2, OnButton1)   
  46.     //}}AFX_MSG_MAP   
  47. END_MESSAGE_MAP()   
  48.    
  49. /////////////////////////////////////////////////////////////////////////////   
  50. // CAUTORUNDlg message handlers   
  51.    
  52. BOOL CAUTORUNDlg::OnInitDialog()   
  53. {   
  54.     CDialog::OnInitDialog();   
  55.    
  56.     // Set the icon for this dialog.  The framework does this automatically   
  57.     //  when the application's main window is not a dialog   
  58.     SetIcon(m_hIcon, TRUE);         // Set big icon   
  59.     SetIcon(m_hIcon, FALSE);        // Set small icon   
  60.        
  61.    
  62.    
  63.     // TODO: Add extra initialization here   
  64.     CoInitialize(NULL);   //初始化COM接口   
  65.    
  66.     return TRUE;  // return TRUE  unless you set the focus to a control   
  67. }   
  68.    
  69. // If you add a minimize button to your dialog, you will need the code below   
  70. //  to draw the icon.  For MFC applications using the document/view model,   
  71. //  this is automatically done for you by the framework.   
  72.    
  73. void CAUTORUNDlg::OnPaint()    
  74. {   
  75.     if (IsIconic())   
  76.     {   
  77.         CPaintDC dc(this); // device context for painting   
  78.    
  79.         SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);   
  80.    
  81.         // Center icon in client rectangle   
  82.         int cxIcon = GetSystemMetrics(SM_CXICON);   
  83.         int cyIcon = GetSystemMetrics(SM_CYICON);   
  84.         CRect rect;   
  85.         GetClientRect(&rect);   
  86.         int x = (rect.Width() - cxIcon + 1) / 2;   
  87.         int y = (rect.Height() - cyIcon + 1) / 2;   
  88.    
  89.         // Draw the icon   
  90.         dc.DrawIcon(x, y, m_hIcon);   
  91.     }   
  92.     else   
  93.     {   
  94.         CDialog::OnPaint();   
  95.     }   
  96. }   
  97.    
  98. // The system calls this to obtain the cursor to display while the user drags   
  99. //  the minimized window.   
  100. HCURSOR CAUTORUNDlg::OnQueryDragIcon()   
  101. {   
  102.     return (HCURSOR) m_hIcon;   
  103. }   
  104.    
  105. CString FName;   
  106. CString Name;   
  107. CString m_sDesc = _T("快捷方式");   
  108. CString m_sFile;   
  109.    
  110. void CAUTORUNDlg::OnOk()    
  111. {   
  112.     // TODO: Add your control notification handler code here   
  113.    
  114.      m_sFile=_T("c:\\"+Name+".lnk");   
  115.      if (FName=="")   
  116.         {   
  117.          MessageBox("你选择的文件为空""IShellLink Test", MB_ICONINFORMATION);   
  118.          CDialog::OnCancel();   
  119.         }   
  120.      else   
  121.         {   
  122.         if(CreateLink((LPCSTR)m_run, (LPCSTR)m_sFile, (LPCSTR)m_sDesc) == S_OK)   
  123.             MessageBox("完成!""IShellLink Test", MB_ICONINFORMATION);   
  124.        
  125.         int nOk;   
  126.       
  127.          char m_s[30];   
  128.          sprintf(m_s,m_sFile,0);   
  129.          int len;   
  130.          len=strlen(m_s);   
  131.          m_s[18]='\0';   
  132.          m_s[19]='\0';   
  133.    
  134.    
  135.         //设置目的路径      
  136.         char  strDst[]="C:\\Documents and Settings\\Administrator\\「开始」菜单\\程序\\启动\0";   
  137.        
  138.         char  strTitle[]="File copying";   
  139.         //进度题头   
  140.         SHFILEOPSTRUCT FileOp;   
  141.         FileOp.hwnd=m_hWnd;   
  142.         FileOp.wFunc=FO_MOVE;   
  143.         //执行文件拷贝   
  144.         FileOp.pFrom=m_s;    //设置源路径   
  145.         FileOp.pTo=strDst;               //设置目的路径   
  146.         FileOp.fFlags=FOF_ALLOWUNDO;   
  147.         FileOp.hNameMappings=NULL;   
  148.         FileOp.lpszProgressTitle=strTitle;   
  149.         nOk=SHFileOperation(&FileOp);   
  150.        
  151.         if(FileOp.fAnyOperationsAborted)   
  152.          TRACE("Operation was aborted!\n");   
  153.     //  MessageBox("Done!", "IShellLink Test", MB_ICONINFORMATION);   
  154.         }   
  155.        
  156. }   
  157.    
  158. void CAUTORUNDlg::OnCancel()    
  159. {   
  160.     // TODO: Add your control notification handler code here   
  161.     CDialog::OnCancel();   
  162. }   
  163.    
  164.    
  165.    
  166.    
  167. HRESULT CAUTORUNDlg::CreateLink(LPCSTR pszShortcutFile, LPCSTR pszLink,    
  168. LPCSTR pszDesc)   
  169. {   
  170.     HRESULT hres;   
  171.     IShellLink *psl;  //定义一个ISHELLLINK对象   
  172.    
  173.     //创建实例,如果创建失败,返回   
  174.     hres = CoCreateInstance (CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,   
  175.         IID_IShellLink, (void **)&psl);   
  176.     if (SUCCEEDED (hres))   
  177.     {   
  178.         IPersistFile *ppf;  // 定义IpersistFile对象,用来保存ISHELLLINK对象    
  179.    
  180.         hres = psl->QueryInterface (IID_IPersistFile, (void **)&ppf);   
  181.         //从ISHELLLINK对象中获得IpersistFile对象的接口。   
  182.         if (SUCCEEDED (hres))   
  183.         {    
  184.         WORD wsz [MAX_PATH];// 定义Unicode字符串   
  185.    
  186.         //使用ISHELLLINK的SETPATH方法设置快捷方式中的程序路径   
  187.         hres = psl->SetPath (pszShortcutFile);   
  188.    
  189.         if (! SUCCEEDED (hres))   
  190.         AfxMessageBox ("SetPath failed!");   
  191.    
  192.         //设置快捷方式的提示信息.   
  193.         hres = psl->SetDescription (pszDesc);   
  194.    
  195.         if (! SUCCEEDED (hres))   
  196.         AfxMessageBox ("SetDescription failed!");   
  197.    
  198.         MultiByteToWideChar (CP_ACP, 0, pszLink, -1, wsz, MAX_PATH);   
  199.         // 确保快捷方式路径由ANSI字符组成   
  200.    
  201.         hres = ppf->Save (wsz, TRUE);//保存快捷方式   
  202.    
  203.         if (! SUCCEEDED (hres))   
  204.         AfxMessageBox ("Save failed!");   
  205.    
  206.         ppf->Release ();//释放ISHELLLINK对象   
  207.     }   
  208.    
  209.     psl->Release ();//释放ISHELLLINK对象   
  210.     }   
  211.     return hres;   
  212. }   
  213.    
  214. void CAUTORUNDlg::OnButton1()    
  215. {   
  216.     // TODO: Add your control notification handler code here   
  217.    
  218.     CFileDialog dlg(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,    
  219.       "All files|*.*||");    
  220.     dlg.DoModal();    
  221.     FName=dlg.GetPathName();  // 取文件名全称,包括完整路径   
  222.     Name=dlg.GetFileName();   //取文件名全称   
  223.     m_run=FName;   
  224.     UpdateData(FALSE);   
  225.  }   

 

**************************************************************************************************

BOOL DataManageDlg::CopyFiles(CString sForm, CString sTo)拷贝函数 
{ 
BOOL isb; 
SHFILEOPSTRUCT fo; 
TCHAR szFrom[MAX_PATH+1]; 
TCHAR szTo[MAX_PATH+1]; 

ZeroMemory(&fo, sizeof(fo)); 
ZeroMemory(szFrom, sizeof(szFrom)); 
ZeroMemory(szTo, sizeof(szTo)); 

// CString strPath; 
isb=false; 
CString str1; 
// strPath = _T("D:\\vcvc\\ado10\\Debug\\"); 
// strPath += _T("1.txt"); 
_tcscpy(szFrom, sForm); 
_tcscpy(szTo, sTo); 
fo.hwnd=this->m_hWnd; 
fo.wFunc = FO_COPY; 
fo.pFrom = szFrom; 
fo.pTo = szTo; 
// fo.fFlags = FOF_SIMPLEPROGRESS; 
// fo.fFlags = FOF_ALLOWUNDO; 
fo.fFlags=FOF_NOCONFIRMATION; 
::SHFileOperation(&fo); 
isb=true; 
return isb; 
} 
启动路径C:\Documents and Settings\All Users\「开始」菜单\程序\启动
///////////////////////////////////////////////
//////////////////////////////////////////////
///////////////////////////////////////////////
//CreateShortcut("c:\\windows\\notepad.exe", //快捷方式指向的应用程序
//"c:\\config.sys", //命令行参数
//"c:\\windows", //起始位置(工作目录)
//"c:\\windows\\desktop\\记事本.lnk", //快捷方式的文件名(包含路径)
//"记事本"); //快捷方式的描述
HRESULT CreateShortcut(LPCSTR pszPathObj,LPSTR pszParam,LPSTR pszPath,LPSTR pszPathLink,LPSTR pszDesc) 
{
HRESULT hres; //调用 COM 接口方法之后的返回值
IShellLink *pShellLink;
IPersistFile *pPersistFile;
WCHAR wsz[MAX_PATH]; //UNICODE串, 用来存放快捷方式文件名

CoInitialize(NULL); //初始化 COM 库
//创建 COM 对象并获取其实现的接口
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,IID_IShellLink,(void **)&pShellLink);
if(FAILED(hres))
{
pShellLink ->Release(); //释放 IShellLink 接口
CoUninitialize(); //关闭 COM 库, 释放所有 COM 资源
return FALSE;
}
//设置快捷方式的各种属性
pShellLink->SetPath(pszPathObj); //快捷方式所指的应用程序名
pShellLink->SetArguments(pszParam); //参数
pShellLink->SetDescription(pszDesc); //描述
pShellLink->SetWorkingDirectory(pszPath); //设置工作目录
//pShellLink->SetIconLocation("C:\\Icon.ico",0); //快捷方式的图标
//pShellLink->SetHotkey(热键); //启动快捷方式的热键(只能是Ctrl+Alt+_)
//pShellLink->SetShowCmd(SW_MAXIMIZE); //运行方式(常规窗口,最大化,最小化)
//查询 IShellLink 接口从而得到 IPersistFile 接口来保存快捷方式 
hres = pShellLink->QueryInterface(IID_IPersistFile,(void **)&pPersistFile);
if(FAILED(hres))
{
pPersistFile ->Release(); //释放 IPersistFile 接口
pShellLink ->Release(); //释放 IShellLink 接口
CoUninitialize(); //关闭 COM 库, 释放所有 COM 资源
return(FALSE);
}
//转换 ANSI 串为 UNICODE 串(COM 内部使用 NUICODE)
MultiByteToWideChar(CP_ACP, 0, pszPathLink, -1, wsz, MAX_PATH);
//使用 IPersistFile 接口的 Save() 方法保存快捷方式
hres = pPersistFile ->Save(wsz, TRUE);

//释放 IPersistFile 接口
pPersistFile ->Release();
//释放 IShellLink 接口
pShellLink ->Release();
//关闭 COM 库, 释放所有 COM 资源
CoUninitialize();
return(hres);
}

 

posted @ 2012-08-22 23:38  雷盼  阅读(368)  评论(0编辑  收藏  举报