1

I can pin some programs to taskbar on Win7 using PowerShell.

$shell = new-object -com "Shell.Application"  
$folder = $shell.Namespace('C:\Windows')    
$item = $folder.Parsename('notepad.exe')
$verb = $item.Verbs() | ? {$_.Name -eq 'Pin to Tas&kbar'}
if ($verb) {$verb.DoIt()}

How do I modify the above code to pin a program to the Start menu?

Zombo
  • 1
  • 62
  • 391
  • 407
cethint
  • 2,231
  • 8
  • 28
  • 31
  • 1
    Don't. This is the user's decision, not yours. Same with the taskbar, actually. There is no programmatic access to this *on purpose*. – Joey Mar 28 '12 at 08:35
  • Why? Is it prejudicial? Moreover I tried it for start menu. But it does not work. – cethint Mar 28 '12 at 08:48
  • 1
    [Why is there no programmatic access to the Start menu pin list?](http://blogs.msdn.com/b/oldnewthing/archive/2003/09/03/54760.aspx) – Joey Mar 28 '12 at 08:52
  • I have to do it. Because, I want to create a standard developer machine. All machines must be same. Taskbars, start menus... When developers changed their machines, they mustn't have any concord problem in the future – cethint Mar 28 '12 at 08:53
  • 1
    There are ways to do so in Windows images you roll out. IIRC via the System Image Manager and answer files for unattended installation. – Joey Mar 28 '12 at 08:57
  • You can find more info for create/customize/deploy a windows7 image here http://technet.microsoft.com/EN-US/library/ee523217(v=ws.10).aspx – CB. Mar 28 '12 at 10:14
  • @Joey, your comments apply to windows XP. This question is clearly tagged Windows 7. Your link really confused me until I saw it was written in 2003. – NH. Jul 19 '17 at 12:35
  • @NH.: It still applies, though. Pretty much all user interface things that the user should be able to customize have no public, supported API to change them programmatically. That is intentional. – Joey Jul 19 '17 at 12:55

5 Answers5

6

Another way

$sa = new-object -c shell.application
$pn = $sa.namespace($env:windir).parsename('notepad.exe')
$pn.invokeverb('startpin')

Or unpin

$pn.invokeverb('startunpin')
Zombo
  • 1
  • 62
  • 391
  • 407
4

Use the code below

$shell = new-object -com "Shell.Application"  
$folder = $shell.Namespace('C:\Windows')    
$item = $folder.Parsename('notepad.exe')
$verb = $item.Verbs() | ? {$_.Name -eq 'Pin to Start Men&u'}
if ($verb) {$verb.DoIt()}

Note: the change is in the fourth line.

Zombo
  • 1
  • 62
  • 391
  • 407
Cory Smith
  • 49
  • 2
2

The main problem with most of the solution is that they enumerate the verbs on a file, search for the string to perform the action (“Pin to Startmenu” etc.) and then execute it. This does not work if you need to support 30+ languages in your company, except you use external function to search for the localized command (see answer from shtako-verflow).

The answer from Steven Penny is the first that is language neutral and does not need any external code. It uses the verbs stored in the registry HKEY_CLASSES_ROOT\CLSID\{90AA3A4E-1CBA-4233-B8BB-535773D48449} and HKEY_CLASSES_ROOT\CLSID\{a2a9545d-a0c2-42b4-9708-a0b2badd77c8}

Based on this, here’s the code we are now using:

function PinToTaskbar {
         param([Parameter(Mandatory=$true)][string]$FilePath)  
  ExecuteVerb $FilePath "taskbarpin" 
}

function UnpinFromTaskbar {
         param([Parameter(Mandatory=$true)][string]$FilePath)  
  ExecuteVerb $FilePath "taskbarunpin" 
}

function PinToStartmenu {
         param([Parameter(Mandatory=$true)][string]$FilePath)  
 ExecuteVerb $FilePath "startpin" 
}

function UnpinFromStartmenu {
         param([Parameter(Mandatory=$true)][string]$FilePath)  
 ExecuteVerb $FilePath "startunpin" 
}

function ExecuteVerb {  
         param(
            [Parameter(Mandatory=$true)][string]$File,
            [Parameter(Mandatory=$true)][string]$Verb
         ) 

    $path = [System.Environment]::ExpandEnvironmentVariables($File) 
    $basePath = split-path $path -parent   #retrieve only the path File=C:\Windows\notepad.exe -> C:\Windows
    $targetFile = split-path $path -leaf    #retrieve only the file File=C:\Windows\notepad.exe -> notepad.exe

    $shell = new-object -com "Shell.Application"  
    $folder = $shell.Namespace($basePath)        
    if ($folder)
    {
       $item = $folder.Parsename($targetFile) 

       if ($item)
       {
         $item.invokeverb($Verb)
         # "This method does not return a value." (http://msdn.microsoft.com/en-us/library/windows/desktop/bb787816%28v=vs.85%29.aspx)
         # Therefore we have no chance to know if this was successful...
         write-host "Method [$Verb] executed for [$path]"       
       } 
       else
       {
         write-host "Target file [$targetFile] not found, aborting" 
       }             
    }
    else 
    {      
      write-host "Folder [$basePath] not found, aborting" 
    }

}


#PinToTaskbar "%WINDIR%\notepad.exe"
#UnpinFromTaskbar "%WINDIR%\notepad.exe"

PinToStartmenu "%WINDIR%\notepad.exe"
#UnpinFromStartmenu "%WINDIR%\notepad.exe"
Community
  • 1
  • 1
Tex Hex
  • 141
  • 6
1

See the script (international) here : http://gallery.technet.microsoft.com/scriptcenter/b66434f1-4b3f-4a94-8dc3-e406eb30b750

If you want to add an action like Pin to Modern UI interface (Windows 8), at $verbs, add 51201

TheMightyX2Y
  • 1,473
  • 1
  • 16
  • 24
  • Rather than just providing a link, [it would be preferable](http://meta.stackexchange.com/a/8259) to include the essential parts of the answer here, and just provide the link for additional reference. If you're not up to this task, you should consider simply [leaving a comment](http://stackoverflow.com/privileges/comment) on the question instead of posting an answer. – Bernhard Barker Feb 22 '14 at 04:53
0

Steven Penny's second answer above worked well for me. Here are a couple more tidbits.

It's doing COM through PowerShell, so you can do the same thing with pretty much any COM client. For example, here's an AutoHotkey version.

Shell := ComObjCreate("Shell.Application")
Target := Shell.Namespace(EnvGet("WinDir")).ParseName("Notepad.exe")
Target.InvokeVerb("startpin")

VBScript or InnoSetup would look almost the same except for the function used to create the object.

I also found that I have one program that pinned OK, but didn't have the right icon and/or description because of limitations in the compiler. I just made a little 1-line WinForms app that starts the target with Process.Start, and then added the appropriate icon, and the name I wanted in the Start Menu in the Title property in AppInfo.cs.

Wade Hatler
  • 1,785
  • 20
  • 18