设为首页 收藏本站
查看: 1173|回复: 0

Windows 7 taskbar and startmenu pin

[复制链接]

尚未签到

发表于 2015-5-10 16:58:06 | 显示全部楼层 |阅读模式
  在Windows 7上,用户可以将自己喜欢的软件“钉”在开始菜单或任务栏,使用起来更加方便。但有时候我们也需要用程序来将这个过程自动化,比如在IT环境里定制客户机,或者我们从一台Win7系统迁移到另一台Win7系统时。
  怎么知道已有哪些软件被“钉”在开始菜单或任务栏:
  当软件“钉”在开始菜单或任务栏后,系统会在"%appdata%\microsoft\internet explorer\Quick Launch\User Pinned"下的"StartMenu"和"TaskBar"目录内创建软件的链接。我们只要看这两个目录下分别有哪些有效链接就可以知道开始菜单和任务栏分别钉有哪些软件。对于每一个链接,我们可以知道它链接了那个程序,然后在目标系统上,我们就可以将这个程序钉在开始菜单或任务栏上(目标系统上也要有这个程序)。
  如何把软件“钉”在开始菜单或任务栏:
  需要注意的是只能将链接钉在开始菜单或任务栏,而且链接必须指向可执行程序,所以我们需要先为目标程序创建一个链接,然后调用ShellExecute,将链接钉住,钉完后这个链接可以删掉。任务栏上钉与解除时传递给ShellExecute的lpOperation参数是taskbarpin/taskbarunpin,而开始菜单的lpOperation参数是startpin/startunpin。
  示例,将IE钉在任务栏上:
  1. 在桌面上为IE创建链接IE.lnk
  2. ShellExecute(NULL, "taskbarpin", "c:\users\username\Desktop\IE.lnk", NULL, NULL, 0)
  以上有一个限制,就是不知道在任务栏上链接的顺序。
  
  Windows XP 任务栏的遍历
  2009-05-04 9:26
  这里的方法可以找到XP下的任务栏,并对任务栏进行遍历,在其他系统上就需要相应的改动了。这里是先找到ToolbarWindow32这个窗口,然后再用通用的遍历Toolbar的方法查找各个按钮;这里有一点特别的是,要用到跨进程缓冲区(因为任务栏和遍历程序不是在同一个进程)。   
    在XP下有一个“分组相似任务栏按钮”特性,如果有一个新的进程窗口要在任务栏上显示,则系统会创建两个按钮,一个按钮有BTNS_DROPDOWN style,默认隐藏,在任务分组后显示(这个style指定它显示一个箭头图标);另一个按钮就是通常我们看到的任务栏按钮。   
    struct TBBUTTONDATA是从网上找到的,没有在微软的文档中发现,但在XP上验证是有效的。   
    在遍历按钮,SendMessage的时候,要注意是Zero-based index 还是 Command ID,现在一些网上的资料范例在需要传Command ID的时候传Zero-based index做参数,这是错误的。   
HWND GetTaskButtonHost(HWND hShellTrayWnd)   
{   
    HWND hWnd = FindWindowEx(hShellTrayWnd, NULL, _T("ReBarWindow32"), NULL);   
    if (hWnd == NULL)   
        return FALSE;   
    hWnd = FindWindowEx(hWnd, NULL, _T("MSTaskSwWClass"), NULL);   
    if (hWnd == NULL)   
        return FALSE;   
    hWnd = FindWindowEx(hWnd, NULL, _T("ToolbarWindow32"), NULL);   
    return hWnd;   
}   
//MSDN: To continue enumeration, the callback function must return TRUE; to stop enumeration, it must return FALSE.   
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)   
{   
    TCHAR strClsName[MAX_PATH+1] = _T("");   
    GetClassName(hwnd, strClsName, MAX_PATH+1);   
    if (_tcsicmp(strClsName, _T("Shell_TrayWnd")) == 0)   
    {   
        HWND hShellTrayWnd = GetTaskButtonHost(hwnd);   
        if (hShellTrayWnd)   
        {   
            HWND *pHwnd = (HWND *)lParam;   
            *pHwnd = hShellTrayWnd;   
            return FALSE;   
        }   
    }   
    return TRUE;   
}   
struct TBBUTTONDATA   
{   
    HWND hwnd; //the handle of the window on the taskbar   
    UINT uID;   
    UINT uCallbackMessage;   
    DWORD Reserved[2];   
    HICON hIcon;   
};   
//This solution works on XP.   
void EnumTasks()   
{   
    HWND hWnd = NULL;   
    EnumWindows(EnumWindowsProc, (LPARAM)&hWnd);   
    if (hWnd == NULL)   
        return;   
    DWORD dwProcID = 0;   
    GetWindowThreadProcessId(hWnd, &dwProcID);   
    HANDLE hProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, dwProcID);   
    if (hProcess == NULL)   
        return;   
    LPTSTR pProcBuf = NULL; //pointer to the buffer allocated in another process   
    TBBUTTON tbb;   
    TBBUTTONDATA tbbData;   
    TCHAR strCaption[MAX_PATH+1] = _T("");   
    pProcBuf = (LPTSTR)VirtualAllocEx(hProcess, NULL, sizeof(strCaption), MEM_COMMIT, PAGE_READWRITE);   
    if (pProcBuf == NULL)   
    {   
        CloseHandle(hProcess);   
        return;   
    }   
    DWORD nTaskCount = ::SendMessage(hWnd, TB_BUTTONCOUNT, 0, 0);   
    for (DWORD i = 0; i < nTaskCount; i++)   
    {   
        ZeroMemory(&tbb, sizeof(TBBUTTON));   
        WriteProcessMemory(hProcess, pProcBuf, &tbb, sizeof(TBBUTTON), NULL);   
        SendMessage(hWnd, TB_GETBUTTON, i/*Zero-based index*/, (LPARAM)pProcBuf);   
        ReadProcessMemory(hProcess, pProcBuf, &tbb, sizeof(TBBUTTON), NULL);   
        //Group similar task-bar buttons(a feature of Windows): if the top-level window is   
        //shown on task-bar, Windows will create another dropdown button for each process.   
        if (tbb.fsStyle & BTNS_DROPDOWN)   
            continue;   
        ReadProcessMemory(hProcess, (LPCVOID)tbb.dwData, &tbbData, sizeof(TBBUTTONDATA), NULL);   
        DWORD nDesireLen = SendMessage(hWnd, TB_GETBUTTONTEXT, tbb.idCommand, 0); //length not including null terminator   
        if (nDesireLen >= sizeof(strCaption))   
            continue;   
        ZeroMemory(strCaption, sizeof(strCaption));   
        WriteProcessMemory(hProcess, pProcBuf, strCaption, sizeof(strCaption), NULL);   
        SendMessage(hWnd, TB_GETBUTTONTEXT, tbb.idCommand, (LPARAM)pProcBuf);   
        ReadProcessMemory(hProcess, pProcBuf, strCaption, sizeof(strCaption), NULL);   
        OutputDebugInfo(L&quot;%s\n&quot;, strCaption);   
    }   
    VirtualFreeEx(hProcess, pProcBuf, 0, MEM_RELEASE);   
    CloseHandle(hProcess);   
}
  
  前一篇Windows XP 任务栏的遍历介绍了在XP下遍历任务栏的方法,可以精确遍历出任务栏的按钮;这篇博客介绍一种通用的遍历任务栏的方法(不仅限于XP),但可能结果不是太精确。   
对于什么样的窗口才会在任务栏上创建按钮,MSDN上的说法是:
  The Shell creates a button on the taskbar whenever an application creates a window that isn't owned. To ensure that the window button is placed on the taskbar, create an unowned window with the WS_EX_APPWINDOW extended style. To prevent the window button from being placed on the taskbar, create the unowned window with the WS_EX_TOOLWINDOW extended style. As an alternative, you can create a hidden window and make this hidden window the owner of your visible window.
  做了一些测试,总结的结果是:
  1、如果窗口没有被其他窗口拥有(GetWindow(hwnd, GW_OWNER) == 0),那么默认情况下它会在任务栏中创建按钮,除非:
  a). 窗口被隐藏了
  或者:
  b). 窗口有WS_EX_TOOLWINDOW风格,且没有WS_EX_APPWINDOW风格
  2、如果窗口被其他窗口拥有,默认不会在任务栏创建按钮,除非:
  a). 窗口可见,且有WS_EX_APPWINDOW风格
  从1、2点可以得出结论,如果窗口可见,有WS_EX_APPWINDOW和WS_EX_TOOLWINDOW风格,那么,这个窗口是一个Tool window,且在任务栏上有按钮。
  范例:
  BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)   
{   
    LONG lExStyle = ::GetWindowLong(hwnd, GWL_EXSTYLE);   
    if (::IsWindowVisible(hwnd) &&   
        ( (lExStyle & WS_EX_APPWINDOW) ||   
          (GetWindow(hwnd, GW_OWNER) == NULL && (lExStyle & WS_EX_TOOLWINDOW) == 0) )   
        )   
    {   
        TCHAR strTitle[MAX_PATH+1] = _T(&quot;&quot;);   
        GetWindowText(hwnd, strTitle, MAX_PATH+1);   
        OutputDebugInfo(L&quot;%s\n&quot;, strTitle);   
    }   
    return TRUE;   
}   
EnumWindows(EnumWindowsProc, NULL);
  
  
  
  
  Vista UAC : 以管理员权限运行程序
  2009-04-25 20:21
  在Windows Vista启用UAC后,程序启动后默认没有管理员权限,
  即使当前的用户属于管理员组。如果要使程序获得管理员权限,还需要一些额外的工作。可以从两个角度来看待:   
一、从程序用户的角度:   
1、用鼠标右击某个应用程序(例如cmd.exe), 再选择&quot;Run As Administrator&quot;(在旧版本里是&quot;Run Elevated&quot;)来以管理员权限运行它   
2、在程序(或其快捷方式)的属性Compatibility中选择Run this program as an administrator来运行   
3、在程序的安装目录,添加一个Manifest文件,使程序以管理员权限运行   
   
   
   
   
   
   
   
   
   
4、有编程经验的用户也可以写脚本来运行程序,如:   
objShell = new ActiveXObject(&quot;Shell.Application&quot;);   
objShell.ShellExecute(app, args, &quot;&quot;, &quot;runas&quot;);   
C#示例:   
ProcessStartInfo startInfo = new ProcessStartInfo();   
startInfo.FileName = &quot;cmd.exe&quot;;   
startInfo.Arguments = &quot;/c c:\\test\\script.cmd&quot;;   
startInfo.UseShellExecute = true;   
startInfo.Verb = &quot;RunAs&quot;;   
Process process = new Process();   
process.StartInfo = startInfo;   
process.Start();
  C/C++, 可调用ShellExecute或ShellExecuteEx, 把lpOperation/lpVerb设成&quot;RunAs&quot;就可以
  二、从开发人员角度:   
1、在应用程序RC中加入MANIFEST类型资源.   
   
   
   
   
   
   
   
   
   
2、以上几种方法都使得程序刚运行就要求管理员权限,要在程序运行中动态要求管理员权限则可以使用COM Elevation Moniker。可参考:http://msdn2.microsoft.com/en-us/library/ms679687.aspx

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-65599-1-1.html 上篇帖子: 一起学Windows Phone 7开发(八.BingMap控件) 下篇帖子: 一名苹果开发者的 Windows Phone 7 使用报告:第三方程序和开发环境对比
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表