原文 Windows 7 taskbar and startmenu pin

在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"%s\n", 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(""); 
        GetWindowText(hwnd, strTitle, MAX_PATH+1); 
        OutputDebugInfo(L"%s\n", strTitle); 
    } 
    return TRUE; 

EnumWindows(EnumWindowsProc, NULL);

Vista UAC : 以管理员权限运行程序

2009-04-25 20:21

在Windows Vista启用UAC后,程序启动后默认没有管理员权限,

即使当前的用户属于管理员组。如果要使程序获得管理员权限,还需要一些额外的工作。可以从两个角度来看待: 
一、从程序用户的角度: 
1、用鼠标右击某个应用程序(例如cmd.exe), 再选择"Run As Administrator"(在旧版本里是"Run Elevated")来以管理员权限运行它 
2、在程序(或其快捷方式)的属性Compatibility中选择Run this program as an administrator来运行 
3、在程序的安装目录,添加一个Manifest文件,使程序以管理员权限运行 
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestversion="1.0"> 
<trustinfo xmlns="urn:schemas-microsoft-com:asm.v3"> 
<security> 
<requestedprivileges> 
<requestedexecutionlevel level="requireAdministrator" uiaccess="false"> 
</requestedexecutionlevel> 
</requestedprivileges> 
</security> 
</trustinfo> 
4、有编程经验的用户也可以写脚本来运行程序,如: 
objShell = new ActiveXObject("Shell.Application"); 
objShell.ShellExecute(app, args, "", "runas"); 
C#示例: 
ProcessStartInfo startInfo = new ProcessStartInfo(); 
startInfo.FileName = "cmd.exe"; 
startInfo.Arguments = "/c c:\\test\\script.cmd"; 
startInfo.UseShellExecute = true; 
startInfo.Verb = "RunAs"; 
Process process = new Process(); 
process.StartInfo = startInfo; 
process.Start();

C/C++, 可调用ShellExecute或ShellExecuteEx, 把lpOperation/lpVerb设成"RunAs"就可以

二、从开发人员角度: 
1、在应用程序RC中加入MANIFEST类型资源. 
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestversion="1.0"> 
<trustinfo xmlns="urn:schemas-microsoft-com:asm.v3"> 
<security> 
<requestedprivileges> 
<requestedexecutionlevel level="requireAdministrator" uiaccess="false"> 
</requestedexecutionlevel> 
</requestedprivileges> 
</security> 
</trustinfo> 
2、以上几种方法都使得程序刚运行就要求管理员权限,要在程序运行中动态要求管理员权限则可以使用COM Elevation Moniker。可参考:http://msdn2.microsoft.com/en-us/library/ms679687.aspx

Windows 7 taskbar and startmenu pin的更多相关文章

  1. Change the Windows 7 Taskbar Thumbnail and List Mode

    Manually in Registry Editor 1. Open the Start Menu, then type regedit in the search boxand press Ent ...

  2. Scott Hanselman's 2014 Ultimate Developer and Power Users Tool List for Windows -摘自网络

    Everyone collects utilities, and most folks have a list of a few that they feel are indispensable.  ...

  3. Windows 7 Shortcuts (完整兼具分类有序,想我所想,赞!)

    Original Link: http://www.shortcutworld.com/en/win/Windows_7.html Table of Contents: Managing 'Windo ...

  4. Windows Server 2008 R2 小技巧 (转)

    一些 Windows Server 2008 R2 的小技巧,包括启用「God Mode (上帝模式)」.添加「快速启动」工具栏.启用桌面「个性化」服务.停用「密碼複雜性」要求,对老程序员熟悉新版的 ...

  5. .net Framework Class Library(FCL)

    from:http://msdn.microsoft.com/en-us/library/ms229335.aspx 我们平时在VS.net里引用的那些类库就是从这里来的 The .NET Frame ...

  6. win7下Chrome有两个图标的解决方法

    摘抄自:http://www.sevenforums.com/browsers-mail/238406-windows-7-taskbar-creating-double-google-chrome- ...

  7. 卸载oracle删除注册表脚本

    一.前言 在我们操作系统中,有时要卸载oracle数据库,每一次都要去删除win下的注册表,为了方便删除注册表的信息,下面通过一种删除注册表快捷的脚本. 二.脚本信息 Windows Registry ...

  8. MFC程序运行流程

    ->进入入口函数_tWinMain() 程序首先进入文件AppModul.cpp,找到_tWinMain()函数运行,调用其中的AfxWinMain()函数. 由于为了支持UNICODE,C运行 ...

  9. Oracle11g的注册表清理

    每次卸载了oracle总是有一堆注册表没有清理,麻烦,特地在网上找了一个较为完整的,全文复制过来,存自己这里,如下: <<< Windows Registry Editor Vers ...

随机推荐

  1. python第二步,类对象部分

    类创建: class 类名: '类说明' def __init__ (self,参数):#类似php类的构造函数,self不知道什么东东 方法体 实例创建: 变量名 = 类名() #构造函数后的参数, ...

  2. GROUPING SETS、ROLLUP、CUBE

    大家对GROUP BY应该比较熟悉,如果你感觉自己并不完全理解GROUP BY,那么本文不适合你.还记得当初学习SQL的时候,总是理解不了GROUP BY的作用,经过好长时间才终于明白GROUP BY ...

  3. [python]通过urllib2设置代理访问网址

    #!/usr/bin/env pythonimport urllib2 # change followings before useuser = 'foo'passwd = 'bar'proxyser ...

  4. python手记(41)

    python opencv图片融合 #!/usr/bin/env python #-*- coding: utf-8 -*- #code:myhaspl@qq.com import cv2 impor ...

  5. 用newLISP读取Hive的元数据

    思想是通过调用hive -e命令,然后解析返回的结果. 以下的hive.lsp文件是一个样例,提供了读取本地hive数据库名称.表名,表结构和依据hive表的创建语句生成相应的MySQL的创建语句. ...

  6. [Swust OJ 217]--Factor(数论,类素数表)

    题目链接:http://acm.swust.edu.cn/problem/0217/ Time limit(ms): 2000 Memory limit(kb): 65535    Descripti ...

  7. ASP.NET MVC 以Stream 下载文件

     1.0以Stream 下载文件 nl.fileid = Int32.Parse(id); //服务器上对应的id Stream stream = Lawsuit.DownLoad(nl);//服务器 ...

  8. Hibernate MySQL 数据库 使用别名 报 Column * Not Found

    使用Hibernate 查询MySQL数据表的时候报 Column Not Found ,原因是MySQL的驱动不支持别名, 解决方案如下,在连接参数中加上 useOldAliasMetadataBe ...

  9. 独立搭建zookeeper

    1.如果你装了带有zookeeper的Hbase版本,先把hbase-env.sh   export HBASE_MANAGES_ZK=false 设置为false 见下图 2.下载安装zookeep ...

  10. JMS 企业开发流程实现

    关于JMS的一些介绍参见[http://blog.csdn.net/aking21alinjuju/article/details/6051421] [补充] 消息的组成 1. 头(head) 每条J ...