Windows 7 taskbar and startmenu pin

简介: 原文 Windows 7 taskbar and startmenu pin 在Windows 7上,用户可以将自己喜欢的软件“钉”在开始菜单或任务栏,使用起来更加方便。但有时候我们也需要用程序来将这个过程自动化,比如在IT环境里定制客户机,或者我们从一台Win7系统迁移到另一台Win7系统时。

原文 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

目录
相关文章
|
1月前
|
网络安全 虚拟化 Windows
windows 11安装openSSH server 遇到的"kex_exchange_identification: read: Connection reset"问题
windows 11安装openSSH server 遇到的"kex_exchange_identification: read: Connection reset"问题
|
2月前
|
PHP Windows
【Azure App Service for Windows】 PHP应用出现500 : The page cannot be displayed because an internal server error has occurred. 错误
【Azure App Service for Windows】 PHP应用出现500 : The page cannot be displayed because an internal server error has occurred. 错误
|
2月前
|
开发框架 .NET API
Windows Server 2022 安装IIS 报错 访问临时文件夹 C:\WINDOWS\TEMP\3C 读取/写入权限 错误: 0x80070005
Windows Server 2022 安装IIS 报错 访问临时文件夹 C:\WINDOWS\TEMP\3C 读取/写入权限 错误: 0x80070005
86 0
|
2月前
|
Linux Docker Windows
Windows——Docker拉取Windows Server镜像
Windows——Docker拉取Windows Server镜像
111 0
|
3月前
|
弹性计算 持续交付 Docker
阿里云云效产品使用合集之如何部署到阿里云服务器上的 Windows Server 上的 IIS
云效作为一款全面覆盖研发全生命周期管理的云端效能平台,致力于帮助企业实现高效协同、敏捷研发和持续交付。本合集收集整理了用户在使用云效过程中遇到的常见问题,问题涉及项目创建与管理、需求规划与迭代、代码托管与版本控制、自动化测试、持续集成与发布等方面。
|
3月前
|
网络协议 Unix 网络安全
FTP服务器怎么搭建?Windows server搭建FPT服务器
FTP服务器是按照FTP协议提供文件传输服务的计算机。它用于在两台计算机间安全地传输文件,支持用户权限管理和跨平台操作。FTP使用控制连接处理命令,数据连接传输文件,有PORT和PASV模式。要搭建FTP服务器,首先在Windows Server 2008 R2上安装IIS,确保选中FTP服务。接着,创建FTP文件夹作为站点根目录,通过IIS管理器添加FTP站点,配置站点信息、身份验证和权限。测试客户端通过telnet和浏览器访问FTP服务器,确认能成功登录及浏览文件。FTP常用于文件共享和管理,可通过专用工具如FlashFXP上传下载文件。
121 0
FTP服务器怎么搭建?Windows server搭建FPT服务器
|
4月前
|
编解码 安全 网络安全
RealVNC的 VNC server在windows7系统下无法正确运行
在Windows 7上运行旧版VNC Server(如4.1.2)可能存在兼容性问题,但可通过调整配置解决。步骤包括:安装VNC Server,设置兼容性模式(选择Windows XP SP3),启动VNC Server,配置VNC连接参数。若遇到问题,检查防火墙设置,确保系统更新,并考虑升级到新版VNC Server以提高性能和兼容性。
|
3月前
|
前端开发 JavaScript 应用服务中间件
windows server + iis 部署若伊前端vue项目
5,配置url重写规则(重写后端请求) 注:如果没有Application Request Routing Cachefourcloudbdueclaim和URL重写,则是第二部的那两个插件没装上 打开iis,点击计算机->点击Application Request Routing Cache -> 打开功能
183 0
下一篇
无影云桌面