|  | 
7#
 
 
 楼主|
发表于 2018-11-26 10:34:25
|
只看该作者 
| 更新:省略了/i参数和友好名称后,将使用系统默认的文件描述作为锁定名称;有/i参数省略了友好名称,将使用exe文件名作为锁定名称。 源代码:
 
 复制代码#include"stdafx.h"
#include<windows.h>
#include<stdio.h>
#include<ShlObj.h>
#include<Shlwapi.h>
#include<regex>
#include<strsafe.h>
#pragma comment(lib, "Shlwapi.lib")
#pragma comment(lib, "Shell32.lib")
#pragma comment(lib, "Version.lib")
#pragma comment(lib, "Ole32.lib")
int getCurrentPath(LPTSTR);
BOOL isFilenameValid(LPCTSTR);
BOOL createLink(LPCTSTR, LPCTSTR, LPCTSTR);
BOOL pin(int, LPCTSTR);
BOOL unpin(int, LPCTSTR);
int getTarget(LPCTSTR);
BOOL getExe(LPCTSTR, LPTSTR, LPTSTR, LPTSTR);
BOOL getLink(LPCTSTR, LPTSTR);
BOOL getUnloadLink(int, LPCTSTR, LPTSTR);
int getOperation(LPCTSTR);
void processError();
BOOL getDescription(LPCTSTR, LPTSTR);
int myError=-1;
int _tmain(int argc, _TCHAR* argv[])
{
        int target;
        BOOL isPin=TRUE;
        TCHAR exePath[MAX_PATH], arguments[MAX_PATH], linkPath[MAX_PATH], description[MAX_PATH];
        switch(argc){
        case 3:
                target=getTarget(argv[1]);
                if(1==target || 2==target){
                        if(getExe(argv[2], exePath, arguments, description))
                                if(getDescription(exePath, description)){
                                        if(getLink(description, linkPath))myError=0;
                                }
                                else{
                                        if(getLink(PathFindFileName(exePath), linkPath))myError=0;
                                }
                }
                break;
        case 4:
                target=getTarget(argv[1]);
                if(1==target || 2==target){
                        if(getExe(argv[2], exePath, arguments, description))
                                if(getLink(argv[3], linkPath))myError=0;
                }
                else{
                        target=getTarget(argv[2]);
                        if(1==target || 2==target){
                                int operation=getOperation(argv[1]);
                                if(0==operation)break;
                                if(-1==operation){
                                        isPin=FALSE;
                                        if(getUnloadLink(target, argv[3], linkPath))myError=0;
                                }
                                else{
                                        if(getExe(argv[3], exePath, arguments, description))
                                                if(getLink(PathFindFileName(exePath), linkPath))myError=0;
                                }
                        }
                }
                break;
        case 5:
                target=getTarget(argv[2]);
                if(1!=target && 2!=target)break;
                if(1!=getOperation(argv[1]))break;
                if(!getExe(argv[3], exePath, arguments, description))break;
                if(getLink(argv[4], linkPath))myError=0;
        }
        if(!myError)
                if(isPin){
                        createLink(exePath, arguments, linkPath); 
                        pin(target, linkPath); 
                        if(!DeleteFile(linkPath))myError=-4;
                }
                else unpin(target, linkPath);
        processError();
}
int getCurrentPath(LPTSTR buffer)
{
        GetModuleFileName(NULL, buffer, MAX_PATH);
        LPTSTR temp=buffer;
        while('\0'!=*temp++);
        while('\\'!=*--temp);
        *++temp='\0';
        return temp-buffer;
}
BOOL isFilenameValid(LPCTSTR filename){
        int cbMultiByte = WideCharToMultiByte(CP_ACP, 0, filename, -1, NULL, 0, NULL, NULL);
        char *pszText=new char[cbMultiByte];
        WideCharToMultiByte(CP_ACP, 0, filename, -1, pszText, cbMultiByte, NULL, NULL);
        int retVal=std::regex_match(pszText, std::regex("^[^ \\\\/|<>:"?*]+[^\\\\/|<>:"?*]*$"));
        delete pszText;
        return retVal;
}
BOOL createLink(LPCTSTR exePath, LPCTSTR arguments, LPCTSTR linkPath)
{
        CoInitialize(NULL);
    HRESULT hr;
    IShellLink     *pLink;
    IPersistFile   *ppf;
    hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&pLink);
    if (FAILED(hr))return FALSE;
    hr = pLink->QueryInterface(IID_IPersistFile, (void**)&ppf);
    if (FAILED(hr))
    {
        pLink->Release();
        return FALSE;
    }
    pLink->SetPath(exePath);
        pLink->SetArguments(arguments);
        TCHAR buffer[256];
        _tcscpy(buffer, exePath);
        PathRemoveFileSpec(buffer);
        pLink->SetWorkingDirectory(buffer);
    pLink->SetShowCmd(SW_SHOWNORMAL);
    hr = ppf->Save(linkPath, TRUE);
    ppf->Release();
    pLink->Release();
        SHChangeNotify(SHCNE_UPDATEDIR|SHCNE_INTERRUPT, SHCNF_FLUSH | SHCNF_PATH, buffer, 0);
        CoUninitialize();
        return SUCCEEDED(hr);
}
BOOL pin(int target, LPCTSTR link){
        LPCTSTR strTarget=1==target?TEXT("startpin"):TEXT("taskbarpin");
        return (int)ShellExecute(NULL, strTarget, link, NULL, NULL, 0);
}
BOOL unpin(int target, LPCTSTR exe){
        LPCTSTR strTarget=1==target?TEXT("startunpin"):TEXT("taskbarunpin");
        return (int)ShellExecute(NULL, strTarget, exe, NULL, NULL, 0);
}
int getTarget(LPCTSTR argv){
        return _tstoi(argv);
}
int getOperation(LPCTSTR argv){
        if(0==_tcsicmp(argv, TEXT("/i")))return 1;
        if(0==_tcsicmp(argv, TEXT("/u")))return -1;
        return 0;
}
BOOL getExe(LPCTSTR argv, LPTSTR exePath, LPTSTR arguments, LPTSTR description){
        LPTSTR pArguments;
        TCHAR buffer[MAX_PATH];
        _tcscpy(buffer, argv);
        pArguments=PathGetArgs(buffer);
        _tcscpy(arguments, pArguments);
        _tcscpy(exePath, argv);
        PathRemoveArgs(exePath);
        if(PathIsRelative(exePath)){
                getCurrentPath(buffer);
                _tcscat(buffer, exePath);
        }
        else _tcscpy(buffer, exePath);
        PathCanonicalize(exePath, buffer);
        if(!PathFileExists(exePath) || PathIsDirectory(exePath) || !PathMatchSpec(exePath, TEXT("*.exe"))){
                myError=-2;
                return FALSE;
        }
        getDescription(exePath, description);
        return TRUE;
}
BOOL getLink(LPCTSTR argv, LPTSTR linkPath){
    if(!isFilenameValid(argv)){myError=-3; return FALSE;}
        int retVal=GetTempPath(MAX_PATH, linkPath);
        if(retVal>MAX_PATH || 0==retVal){myError=-4; return FALSE;}
        _tcscat(linkPath, argv);
        PathRenameExtension(linkPath, TEXT(".lnk"));
        return TRUE;
}
BOOL getUnloadLink(int target, LPCTSTR argv, LPTSTR linkPath){
        if(!isFilenameValid(argv)){myError=-3; return FALSE;}
        SHGetSpecialFolderPath(NULL, linkPath, CSIDL_APPDATA, FALSE);
        _tcscat(linkPath, TEXT("\\Microsoft\\Internet Explorer\\Quick Launch\\User Pinned\"));
        _tcscat(_tcscat(_tcscat(linkPath, 1==target?TEXT("StartMenu\"):TEXT("TaskBar")), argv), TEXT(".lnk"));
    if(!PathFileExists(linkPath)){myError=-3; return FALSE;}
        return TRUE;
}
void processError(){
        LPCTSTR badUsage=TEXT("用法:\nPINT [/i|/u] <1/2> exePath [friendlyName]"),
                badLink=TEXT("无效的快捷方式名称!"), badExe=TEXT("指定的文件不是可执行程序!"), badTemp=TEXT("临时文件夹错误!");
        switch(myError){
        case -1:_tprintf(badUsage);break;
        case -2:_tprintf(badExe);break;
        case -3:_tprintf(badLink);break;
        case -4:_tprintf(badTemp);break;
        }
        exit(myError);
}
BOOL getDescription(LPCTSTR exePath, LPTSTR description){
        DWORD arg=0;
        LPTSTR result;
        int size=GetFileVersionInfoSize(exePath, &arg);
        arg=FALSE;
        if(size){
                byte *buffer=new byte[size];
                GetFileVersionInfo(exePath, 0, size, buffer);
                HRESULT hr;
                 struct LANGANDCODEPAGE {
                        WORD wLanguage;
                        WORD wCodePage;
                } *lpTranslate;
                UINT cbTranslate, dwBytes;
                VerQueryValue(buffer, TEXT("\\VarFileInfo\\Translation"), (LPVOID*)&lpTranslate, &cbTranslate);
                TCHAR item[50];
                arg=FALSE;
                for(int i = (cbTranslate/sizeof(struct LANGANDCODEPAGE))-1; i>=0 ; i-- ){
                        hr = StringCchPrintf(item, 50, TEXT("\\StringFileInfo\\%04x%04x\\FileDescription"),
                                        lpTranslate[i].wLanguage,
                                        lpTranslate[i].wCodePage);
                        if (FAILED(hr)){delete buffer; return FALSE;}
                        VerQueryValue(buffer, item, (LPVOID *)&result, &dwBytes);
                        _tcscpy(description, result);
                        arg=TRUE;
                }
                delete buffer;
        }
        return arg;
}
 | 
 |