简体   繁体   中英

Powershell change taskbar icon of running console application

I'm using code from this post over at Microsoft's TechNet to change the icon of my running PowerShell application. This works great for the icon that is displayed in the Powershell window itself, but it doesn't change the Taskbar's icon. I changed the function a bit an hoped that it would also change the icon displayed in the Taskbar.

# Set the icon of the current console window to the specified icon.
#
# AUTHOR:    Aaron Lerch <http://www.aaronlerch.com/blog>
# COPYRIGHT: © 2009 Aaron Lerch
# LINK:      http://gallery.technet.microsoft.com/scriptcenter/9d476461-899f-4c98-9d63-03b99596c2c3
#
# PARAM:
#   -IconFile
#     Absolute path to the icon file.
# RETURN:
#   $null
function Set-ConsoleIcon {
  Param(
    [parameter(Mandatory = $true)] [string] $IconFile
  )

  [System.Reflection.Assembly]::LoadWithPartialName('System.Drawing') | Out-Null

  # Verify the file exists
  if ([System.IO.File]::Exists($iconFile) -eq $true) {
    $ch = Invoke-Win32 'kernel32' ([IntPtr]) 'GetConsoleWindow'
    $i = 0;
    $size = 16;
    while ($i -ne 4) {
      $ico = New-Object System.Drawing.Icon($iconFile, $size, $size)
      if ($ico -ne $null) {
        Send-Message $ch 0x80 $i $ico.Handle | Out-Null
      }
      if ($i -eq 4) {
        break
      }
      $i += 1
      $size += 16
    }
  }
  else {
    Write-Host 'Icon file not found' -ForegroundColor 'Red'
  }
}

I'm providing the icon in the sizes 16 ( wParam 1 ), 32 ( wParam 2 ), 48 ( wParam 3 ), and 64 ( wParam 4 ).

I also tried to change the Icon from my launching C# application (based on this Stackoverflow discussion ) but that didn't work at all.

If you'd like to see the complete code have a look at the following:

An easy alternative is to create a shortcut to the powershell exe. Change the icon of the shortcut to whatever you want.

Then whenever you call your script, use the shortcut instead of the PS exe. So instead of

powershell.exe -ExecutionPolicy Bypass -File D:\scripts\whatever.ps1

Use

D:\scripts\powershell.lnk -ExecutionPolicy Bypass -File D:\scripts\whatever.ps1

The shortcut powershell.lnk can be "C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe" or just powershell.exe without the full path (as long as PATH var is set properly for PS on the system)

You can put the PS shortcut anywhere really, but I would recommend you put it with the script for portability.

Now when you launch the script via the shortcut, the taskbar icon will be whatever you defined it as via the shortcut file.

The only caveat is that your window settings in the shortcut will override the PS window, so you should define how you want it to look in the shortcut properties.

This might not be possible. Here are more details about the "group icon" in the taskbar:

Change icon of group in taskbar (Win7)

Update:

You can change the application ID of your window. Since the icon primarily comes from the application ID, by changing it Explorer doesn't know the default icon anymore and will use the actual window icon. This also ungroups the window from other CMD windows to make the individual icon visible at all. (There's a taskbar animation like for closed/new windows when you do this in an existing console window.) There's an MSDN article, look for "application ID" in it:

https://msdn.microsoft.com/en-us/magazine/dd942846.aspx

Here's the relevant code from it (C++):

#define WINVER 0x601
#define _WIN32_WINNT 0x601
#include <Propvarutil.h>
#include <propkey.h>
#include <Shellapi.h>

PROPVARIANT pv;
InitPropVariantFromString(L"MyAppID", &pv);

IPropertyStore* pps;
VERIFY(SHGetPropertyStoreForWindow(hwnd, IID_PPV_ARGS(&pps)));
VERIFY(pps->SetValue(PKEY_AppUserModel_ID, pv));
VERIFY(pps->Commit());

(Linked libs: shlwapi.lib)

The Windows API Code Pack should also have managed wrapper code for this. Didn't look it up because I currently use this function in a C++ application. But I found other questions about it here.

For your PowerShell script that probably won't help much either. Since it's all native code wrapped with more complex managed code, I think your best bet would be a little native helper tool. I am currently integrating this function into my FlashConsoleWindow tool that can do some more things to console windows like flashing or displaying a taskbar progress state.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM