如何使用 Powershell 更改我的电脑桌面图标?

How to Change the My Computer Desktop Icon Using Powershell?

我正在尝试学习一些 Shell-脚本,因为最近自动化测试似乎越来越流行。

我对 Powershell 的掌握很笼统。我目前的目标是更改“我的电脑”桌面图标。

Microsoft Windows 10 操作系统的一些东西我还没有使用 Powershell 接触过。我希望也许一些比我多产的作家能够帮助我实现这个目标。

我刚刚测试了两个片段,令人惊讶的是 运行 第一次尝试就成功了。

第一个可能被称为 Create_Shortcut.PS1 并为命令行预处理系统创建一个桌面图标,其中批处理文件可能是 运行.

# Creates the command-line desktop icon.

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

$TargetFile = "C:\Windows\System32\Cmd.Exe"

$ShortcutFile = "\ISXPFV01.hd00.example.com\us_qv2_dem_user_data_pool_nra$\EE65037.HD00\Desktop\Command-Line.Lnk"

$WScriptShell = New-Object -COMObject WScript.Shell

$Shortcut = $WScriptShell.CreateShortcut($ShortcutFile)

$Shortcut.TargetPath = $TargetFile

$Shortcut.Save()

第二个可能被称为 Rename_My_Computer.PS1,它重命名了“我的电脑”桌面图标。

# Changes the My Computer desktop icon name from "This PC" to "VSDC0365".

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

$My_Computer = 17

$Shell = New-Object -COMObject Shell.Application

$NSComputer = $Shell.Namespace($My_Computer)

$NSComputer.Self.Name = $Env:COMPUTERNAME

对于 Powershell 比我更有经验的人来说,我感兴趣的东西可能会被证明是极其简单的。我需要通过指定路径来更改“我的电脑”桌面图标。

由于我还没有达到这个目标,非常感谢任何关于这个问题的帮助。

感谢阅读。

@Theo 的精彩评论后更新:

一个新的令人惊讶的工作片段,设法生成“我的电脑”桌面图标:

# HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel\
# {20D04FE0-3AEA-1069-A2D8-08002B30309D}
# 0 = show
# 1 = hide

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

$Path = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel"

$Name = "{20D04FE0-3AEA-1069-A2D8-08002B30309D}"

$Exist = "Get-ItemProperty -Path $Path -Name $Name"

if ($Exist)
{
    Set-ItemProperty -Path $Path -Name $Name -Value 0
}
Else
{
    New-ItemProperty -Path $Path -Name $Name -Value 0
}

现在,我所要做的就是以某种方式以编程方式按 F5 以刷新桌面视图,以某种方式设置他在评论中提到的设置。

与刷新相关的另一个更新:

刷新桌面视图的另一个令人惊讶的工作片段:

# Refresh Desktop Ability

$Definition = @'

    [System.Runtime.InteropServices.DllImport("Shell32.dll")]

    private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2);

    public static void Refresh() {
        SHChangeNotify(0x8000000, 0x1000, IntPtr.Zero, IntPtr.Zero);
    }
'@

Add-Type -MemberDefinition $Definition -Namespace WinAPI -Name Explorer

# Refresh desktop icons
[WinAPI.Explorer]::Refresh()

现在剩下的就是在刷新之前以某种方式更改“我的电脑”桌面图标。

与获取该注册表项的所有权相关的更新:

棘手的东西。我不知道它会变得如此复杂。

目前,它失败并出现以下错误消息:

PS Y:\> Y:\Digitization\Powershell\The_My_Computer_Desktop_Icon\Change_Registry_Key.PS1
True
Exception calling "OpenSubKey" with "3" argument(s): "Requested registry access is not allowed."
At Y:\Digitization\Powershell\The_My_Computer_Desktop_Icon\Change_Registry_Key.PS1:139 char:1
+ $RegKey = [Microsoft.Win32.Registry]::ClassesRoot.OpenSubKey(         ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : SecurityException

这是 Change_Registry_Key.PS1 文件的内容:

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

Function Enable-Privilege {
  Param(
  ## The privilege to adjust.
  [ValidateSet(
      "SeAssignPrimaryTokenPrivilege"
    , "SeAuditPrivilege"
    , "SeBackupPrivilege"
    , "SeChangeNotifyPrivilege"
    , "SeCreateGlobalPrivilege"
    , "SeCreatePagefilePrivilege"
    , "SeCreatePermanentPrivilege"
    , "SeCreateSymbolicLinkPrivilege"
    , "SeCreateTokenPrivilege"
    , "SeDebugPrivilege"
    , "SeEnableDelegationPrivilege"
    , "SeImpersonatePrivilege"
    , "SeIncreaseBasePriorityPrivilege"
    , "SeIncreaseQuotaPrivilege"
    , "SeIncreaseWorkingSetPrivilege"
    , "SeLoadDriverPrivilege"
    , "SeLockMemoryPrivilege"
    , "SeMachineAccountPrivilege"
    , "SeManageVolumePrivilege"
    , "SeProfileSingleProcessPrivilege"
    , "SeRelabelPrivilege"
    , "SeRemoteShutdownPrivilege"
    , "SeRestorePrivilege"
    , "SeSecurityPrivilege"
    , "SeShutdownPrivilege"
    , "SeSyncAgentPrivilege"
    , "SeSystemEnvironmentPrivilege"
    , "SeSystemProfilePrivilege"
    , "SeSystemtimePrivilege"
    , "SeTakeOwnershipPrivilege"
    , "SeTcbPrivilege"
    , "SeTimeZonePrivilege"
    , "SeTrustedCredManAccessPrivilege"
    , "SeUndockPrivilege"
    , "SeUnsolicitedInputPrivilege")]
    $Privilege
    ## The process on which to adjust the privilege. Defaults to the current process.
  , $ProcessId = $Pid
    ## Switch to disable the privilege, rather than enable it.
  , [Switch] $Disable
  )

  $Definition = @'
    using System;
    using System.Runtime.InteropServices;

    public class AdjPriv
    {
       [DllImport(  "advapi32.dll"
                  , ExactSpelling = true
                  , SetLastError = true)]

       internal static extern bool AdjustTokenPrivileges(  IntPtr htok
                                                         , bool disall
                                                         , ref TokPriv1Luid newst
                                                         , int len
                                                         , IntPtr prev
                                                         , IntPtr relen);

       [DllImport(  "advapi32.dll"
                  , ExactSpelling = true
                  , SetLastError = true)]

       internal static extern bool OpenProcessToken(  IntPtr h
                                                    , int acc
                                                    , ref IntPtr phtok);

       [DllImport(  "advapi32.dll"
                  , SetLastError = true)]

       internal static extern bool LookupPrivilegeValue(  string host
                                                        , string name
                                                        , ref long pluid);

       [StructLayout(  LayoutKind.Sequential
                     , Pack = 1)]

       internal struct TokPriv1Luid
       {
          public int Count;
          public long Luid;
          public int Attr;
       }

       internal const int SE_PRIVILEGE_ENABLED    = 0x00000002;
       internal const int SE_PRIVILEGE_DISABLED   = 0x00000000;
       internal const int TOKEN_QUERY             = 0x00000008;
       internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;

       public static bool EnablePrivilege(  long processHandle
                                          , string privilege
                                          , bool disable)
       {
           bool retVal;
           TokPriv1Luid tp;
           IntPtr hproc = new IntPtr(processHandle);
           IntPtr htok = IntPtr.Zero;
           retVal = OpenProcessToken(  hproc
                                     , TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY
                                     , ref htok);
           tp.Count = 1;
           tp.Luid = 0;
           if(disable)
           {
               tp.Attr = SE_PRIVILEGE_DISABLED;
           }
           else
           {
               tp.Attr = SE_PRIVILEGE_ENABLED;
           }
           retVal = LookupPrivilegeValue(  null
                                         , privilege
                                         , ref tp.Luid);
           retVal = AdjustTokenPrivileges(  htok
                                          , false
                                          , ref tp
                                          , 0
                                          , IntPtr.Zero
                                          , IntPtr.Zero);
           return retVal;
    }
  }
'@

$ProcessHandle = (Get-Process -Id $ProcessId).Handle
$Type = Add-Type $Definition -PassThru
$Type[0]::EnablePrivilege($processHandle, $Privilege, $Disable)
}

Enable-Privilege SeTakeOwnershipPrivilege

# Change Owner to the local Administrators group.
$RegKey = [Microsoft.Win32.Registry]::ClassesRoot.OpenSubKey(               `
            "CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}"                  `
          , [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree  `
          , [System.Security.AccessControl.RegistryRights]::TakeOwnership)
$RegACL = $RegKey.GetAccessControl()
$RegACL.SetOwner([System.Security.Principal.NTAccount]"Administrators")
$RegKey.SetAccessControl($RegACL)

# Change Permissions for the local Administrators group.
$RegKey = [Microsoft.Win32.Registry]::ClassesRoot.OpenSubKey(               `
            "CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}"                  `
          , [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree  `
          , [System.Security.AccessControl.RegistryRights]::ChangePermissions)
$RegACL = $RegKey.GetAccessControl()
$RegRule = New-Object System.Security.AccessControl.RegistryAccessRule(     `
             "Administrators"                                               `
           , "FullControl"                                                  `
           , "ContainerInherit"                                             `
           , "None"                                                         `
           , "Allow")
$RegACL.SetAccessRule($RegRule)
$RegKey.SetAccessControl($RegACL)

与获取该注册表项所有权的另一次尝试相关的更新:

这是另一个片段的内容,称为 Change_Registry_Key.2.PS1:

#Define HKCR
New-PSDrive -Name       HKCR7              `
            -PSProvider Registry           `
            -Root       HKEY_CLASSES_ROOT

#Set $Path HKCR Key Path
$Path = "HKCR:\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}"

#Set $Path Permissions
$ACL = Get-ACL $Path

$Rule = New-Object System.Security.AccessControl.RegistryAccessRule ( `
            "<domain>\<username>"                                     `
          , "FullControl"                                             `
          , "Allow")

$ACL.SetAccessRule($Rule)

$ACL | Set-ACL -Path $path

#Set HKCR 'Attributes' Key Value
Set-ItemProperty -Path   $Path        `
                 -Name   Attributes   `
                 -Value  b0940064

这些是控制台区域中出现的错误:

PS Y:\> Y:\Digitization\Powershell\The_My_Computer_Desktop_Icon\Change_Registry_Key.2.PS1

Name           Used (GB)     Free (GB) Provider      Root                           
----           ---------     --------- --------      ----                           
HKCR7                                  Registry      HKEY_CLASSES_ROOT              
Exception calling "SetAccessRule" with "1" argument(s): "Some or all identity refere
nces could not be translated."
At Y:\Digitization\Powershell\The_My_Computer_Desktop_Icon\Change_Registry_Key.2.PS1
:17 char:1
+ $ACL.SetAccessRule($Rule)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : IdentityNotMappedException
 
Set-ACL : Requested registry access is not allowed.
At Y:\Digitization\Powershell\The_My_Computer_Desktop_Icon\Change_Registry_Key.2.PS1
:19 char:8
+ $ACL | Set-ACL -Path $path
+        ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : PermissionDenied: (HKEY_CLASSES_RO...8-08002B30309D}: 
   String) [Set-Acl], SecurityException
    + FullyQualifiedErrorId : System.Security.SecurityException,Microsoft.PowerShel 
   l.Commands.SetAclCommand
 
Set-ItemProperty : Requested registry access is not allowed.
At Y:\Digitization\Powershell\The_My_Computer_Desktop_Icon\Change_Registry_Key.2.PS1
:22 char:1
+ Set-ItemProperty -Path   $Path        `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : PermissionDenied: (HKEY_CLASSES_RO...8-08002B30309D}: 
   String) [Set-ItemProperty], SecurityException
    + FullyQualifiedErrorId : System.Security.SecurityException,Microsoft.PowerShel 
   l.Commands.SetItemPropertyCommand

关于@Theo 重命名我的电脑桌面图标的第二个版本的更新:

这个版本还不适用于我。

它的测试很简单:

虽然我希望我的电脑桌面图标重命名回 Work-Laptop,但它的名称仍然固定为 Fifi

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

#Requires -RunAsAdministrator

Function Enable-Privilege {
    [CmdletBinding(  ConfirmImpact         = 'low'
                   , SupportsShouldProcess = $false)]
    [OutputType('System.Boolean')]
    Param(
        [Parameter(  Mandatory = $true
                   , Position  = 0)]
        [ValidateSet(  "SeAssignPrimaryTokenPrivilege"
                     , "SeAuditPrivilege"
                     , "SeBackupPrivilege"
                     , "SeChangeNotifyPrivilege"
                     , "SeCreateGlobalPrivilege"
                     , "SeCreatePagefilePrivilege"
                     , "SeCreatePermanentPrivilege"
                     , "SeCreateSymbolicLinkPrivilege"
                     , "SeCreateTokenPrivilege"
                     , "SeDebugPrivilege"
                     , "SeEnableDelegationPrivilege"
                     , "SeImpersonatePrivilege"
                     , "SeIncreaseBasePriorityPrivilege"
                     , "SeIncreaseQuotaPrivilege"
                     , "SeIncreaseWorkingSetPrivilege"
                     , "SeLoadDriverPrivilege"
                     , "SeLockMemoryPrivilege"
                     , "SeMachineAccountPrivilege"
                     , "SeManageVolumePrivilege"
                     , "SeProfileSingleProcessPrivilege"
                     , "SeRelabelPrivilege"
                     , "SeRemoteShutdownPrivilege"
                     , "SeRestorePrivilege"
                     , "SeSecurityPrivilege"
                     , "SeShutdownPrivilege"
                     , "SeSyncAgentPrivilege"
                     , "SeSystemEnvironmentPrivilege"
                     , "SeSystemProfilePrivilege"
                     , "SeSystemtimePrivilege"
                     , "SeTakeOwnershipPrivilege"
                     , "SeTcbPrivilege"
                     , "SeTimeZonePrivilege"
                     , "SeTrustedCredManAccessPrivilege"
                     , "SeUndockPrivilege"
                     , "SeUnsolicitedInputPrivilege")]
        [String]$Privilege

      , [Parameter(Position = 1)]
        $ProcessId = $PID

      , [switch]$Disable
        )


        Add-Type -TypeDefinition @'
using System;
using System.Runtime.InteropServices;

public class Privilege {
    [DllImport(  "advapi32.dll"
               , ExactSpelling = true
               , SetLastError  = true)]

    internal static extern bool AdjustTokenPrivileges(
         IntPtr htok
       , bool   disall
       , ref    TokPriv1Luid newst
       , int    len
       , IntPtr prev
       , IntPtr relen);

    [DllImport(  "advapi32.dll"
               , ExactSpelling = true
               , SetLastError  = true)]

    internal static extern bool OpenProcessToken(  IntPtr h
                                                 , int    acc
                                                 , ref    IntPtr phtok);

    [DllImport(  "advapi32.dll"
               , SetLastError = true)]

    internal static extern bool LookupPrivilegeValue(  string host
                                                     , string name
                                                     , ref    long pluid);

    [StructLayout(  LayoutKind.Sequential
                  , Pack = 1)]

    internal struct TokPriv1Luid {
        public int  Count;
        public long Luid;
        public int  Attr;
    }

    internal const int SE_PRIVILEGE_ENABLED    = 0x00000002;
    internal const int SE_PRIVILEGE_DISABLED   = 0x00000000;
    internal const int TOKEN_QUERY             = 0x00000008;
    internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;

    public static bool EnablePrivilege(  long   processHandle
                                       , string privilege
                                       , bool   disable) {
        bool         retVal;
        TokPriv1Luid tp;
        IntPtr       hproc = new IntPtr(processHandle);
        IntPtr       htok  = IntPtr.Zero;
        retVal = OpenProcessToken(  hproc
                                  , TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY
                                  , ref htok);
        tp.Count = 1;
        tp.Luid  = 0;
        if(disable) {
            tp.Attr = SE_PRIVILEGE_DISABLED;
        }
        else {
            tp.Attr = SE_PRIVILEGE_ENABLED;
        }
        retVal = LookupPrivilegeValue(  null
                                      , privilege
                                      , ref tp.Luid);
        retVal = AdjustTokenPrivileges(  htok
                                       , false
                                       , ref tp
                                       , 0
                                       , IntPtr.Zero
                                       , IntPtr.Zero);
        return retVal;
    }
}
'@

    try {
        $proc   = Get-Process -Id $ProcessId -ErrorAction Stop
        $name   = $proc.ProcessName
        $handle = $proc.Handle
        $action = if ($Disable) { 'Disabling' } else { 'Enabling' }
        Write-Verbose (  "{0} privilege '{1}' for process {2}" -f $action `
                       , $Privilege                                       `
                       , $name)
        [Privilege]::EnablePrivilege(  $handle         `
                                     , $Privilege      `
                                     , [bool]$Disable)
    }
    catch {
        throw
    }
}

################################################################
# Step 1: Give the current process the SeTakeOwnershipPrivilege.
################################################################

    $null = Enable-Privilege -Privilege SeTakeOwnershipPrivilege -Verbose

##############################################################
# Step 2: change Owner to the local Administrators group
##############################################################

# Better not use the string "Administrators", because this
# might have a different name in other cultures.
#
# $RegACL.SetOwner([System.Security.Principal.NTAccount]"Administrators")
#
# Use the Well-Known SID instead.
# Local Administrators Group.
$Administrators = `
   [System.Security.Principal.SecurityIdentifier]::new('S-1-5-32-544')

$RegKey = [Microsoft.Win32.Registry]::ClassesRoot.OpenSubKey(        `
     "CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}"                  `
   , [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree  `
   , [System.Security.AccessControl.RegistryRights]::TakeOwnership)

$RegACL = $RegKey.GetAccessControl()
$RegACL.SetOwner($Administrators)
$RegKey.SetAccessControl($RegACL)

##############################################################
# Step 3:  Give the Local Administrators Group Full Control.
##############################################################

# Refresh the A.C.L.
$RegACL = $RegKey.GetAccessControl()

# Test if there is a Deny rule in the ACL
# for Administrators and, if so, remove that rule.
$RegACL.GetAccessRules(                                     `
         $true                                              `
       , $true                                              `
       , [System.Security.Principal.SecurityIdentifier]) |  `
    Where-Object {                                          `
             $_.AccessControlType -eq 'Deny'                `
        -and $_.IdentityReference -eq $Administrators.Value `
    } |                                                     `
    ForEach-Object { $null = $RegAcl.RemoveAccessRule($_) }

# Create a new rule allowing the Administrators Full Control.
$RegRule = [System.Security.AccessControl.RegistryAccessRule]::new( `
             $Administrators                                        `
           , 'FullControl'                                          `
           , 'ContainerInherit'                                     `
           , 'None'                                                 `
           , 'Allow')
$RegACL.SetAccessRule($RegRule)
$RegKey.SetAccessControl($RegACL)

# Close the Registry Key.
$RegKey.Close()


##############################################################
# Step 4: Change the 'LocalizedString' property
# in the registry to suit your needs.
##############################################################
#
# With PowerShell 5, you need to use
# `Registry::HKEY_CLASSES_ROOT\..` syntax in order to be able
# to set the registry Type for the value
# with parameter '-Type'.
# As of PowerShell 7, the '-Type' parameter is included.

$RegPath = `
 'Registry::HKEY_CLASSES_ROOT\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}'
Set-ItemProperty -Path  $RegPath          `
                 -Name  'LocalizedString' `
                 -Value "%ComputerName%"  `
                 -Type  ExpandString      `
                 -Force

我在控制台得到的是下面的文字:

PS C:\WINDOWS\system32> C:\Users\MihaiDobrescu\OneDrive\Documents_Facturi_-_Bank_Services\Digitization\Powershell\Change_Registry_Key.3.PS1 -RunAsAdministrator
VERBOSE: Enabling privilege 'SeTakeOwnershipPrivilege' for process powershell_ise

PS C:\WINDOWS\system32>

更新: 最终版本,里面有美丽汤的所有成分。

再次感谢@Theo,他实际上调试了整个混乱。

注意: 该片段甚至在虚拟机内部也能正常工作,因为它不需要 运行 作为管理员,因为没有所有权为了解决这个问题,整个太阳系都采取了行动。

# How to test:
#
# 1. Rename the My Computer Desktop Icon to "Fifi".
# 2. Remove the My Computer Desktop Icon from the Desktop View.
# 3. Run this snippet.
# 4. Observe how the My Computer Desktop Icon is produced on the Desktop View,
#    with the name "Tele-Ordinator" and with a very emotional Desktop Icon.

# Allow the execution of snippets.

Set-ExecutionPolicy               `
    -ExecutionPolicy RemoteSigned `
    -Scope           CurrentUser

# Produce the My Computer Desktop Icon on the Desktop View.

# HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel\
# {20D04FE0-3AEA-1069-A2D8-08002B30309D}
# 0 = show
# 1 = hide

$Path = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel"

$Name = "{20D04FE0-3AEA-1069-A2D8-08002B30309D}"

$Exist = "Get-ItemProperty -Path $Path -Name $Name"

if ($Exist)
{
    Set-ItemProperty     `
        -Path  $Path     `
        -Name  $Name     `
        -Value 0
}
Else
{
    New-ItemProperty     `
        -Path  $Path     `
        -Name  $Name     `
        -Value 0
}

# Rename the My Computer Desktop Icon from "This PC" to "Tele-Ordinator".

$My_Computer = 17

$Shell = New-Object -COMObject Shell.Application

$NSComputer = $Shell.Namespace($My_Computer)

$NSComputer.Self.Name = "Tele-Ordinator"

# Change the My Computer Desktop Icon.

$RegPath =                                                                                                                                    `
    'Registry::HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\DefaultIcon'

if (!(Test-Path -Path $RegPath))
{
    $null = New-Item             `
                -Path   $RegPath `
                -Force
}

Set-ItemProperty                                                               `
    -Path  $RegPath                                                            `
    -Name  '(Default)'                                                         `
    -Value 'Y:\Digitization\Icons\Robsonbillponte-Happy-Holidays-Pictures.ICO' `
    -Type  ExpandString                                                        `
    -Force

# Refresh the Desktop View.

$Definition = @'

    [System.Runtime.InteropServices.DllImport("Shell32.dll")]

    private static extern int SHChangeNotify(
          int    eventId
        , int    flags
        , IntPtr item1
        , IntPtr item2);

    public static void Refresh()
    {
        SHChangeNotify(
          0x8000000
        , 0x1000
        , IntPtr.Zero
        , IntPtr.Zero);
    }
'@

Add-Type                          `
    -MemberDefinition $Definition `
    -Namespace        WinAPI      `
    -Name             Explorer

[WinAPI.Explorer]::Refresh()

另一个最终更新,用于设置和运行使用 Microsoft Windows 批处理文件预处理系统自动执行上述自动化的批处理文件:

这只是一个名为 Change_Desktop_Icons.BAT 的简短片段。

ChDir %SystemRoot%\System32\WindowsPowerShell\v1.0\

%SystemRoot%\System32\WindowsPowerShell\v1.0\PowerShell.Exe Y:\Digitization\PowerShell\The_My_Computer_Desktop_Icon\Change_Desktop_Icon.PS1

Pause

这是它的输出,双击它自己的桌面图标。

'\ISXPFV01.hd00.example.com\us_qv2_dem_user_data_pool_nra$\EE65037.HD00\Desktop'
CMD.EXE was started with the above path as the current directory.
UNC paths are not supported.  Defaulting to Windows directory.

C:\Windows>ChDir C:\WINDOWS\System32\WindowsPowerShell\v1.0\

C:\Windows\System32\WindowsPowerShell\v1.0>C:\WINDOWS\System32\WindowsPowerShell\v1.0\PowerShell.Exe Y:\Digitization\PowerShell\The_My_Computer_Desktop_Icon\Change_Desktop_Icon.PS1

C:\Windows\System32\WindowsPowerShell\v1.0>Pause
Press any key to continue . . .

如评论所述,更改 'Computer' 图标标题非常麻烦..

下面的代码适用于 Windows 10 Pro 使用 PowerShell 5.1

您需要 运行 作为管理员

#Requires -RunAsAdministrator

function Enable-Privilege {
    [CmdletBinding(ConfirmImpact = 'low', SupportsShouldProcess = $false)]  
    [OutputType('System.Boolean')]
    Param(
        [Parameter(Mandatory = $true, Position = 0)]
        [ValidateSet(
            "SeAssignPrimaryTokenPrivilege", "SeAuditPrivilege", "SeBackupPrivilege", "SeChangeNotifyPrivilege", 
            "SeCreateGlobalPrivilege", "SeCreatePagefilePrivilege", "SeCreatePermanentPrivilege", 
            "SeCreateSymbolicLinkPrivilege", "SeCreateTokenPrivilege", "SeDebugPrivilege", "SeEnableDelegationPrivilege", 
            "SeImpersonatePrivilege", "SeIncreaseBasePriorityPrivilege", "SeIncreaseQuotaPrivilege", 
            "SeIncreaseWorkingSetPrivilege", "SeLoadDriverPrivilege", "SeLockMemoryPrivilege", 
            "SeMachineAccountPrivilege", "SeManageVolumePrivilege", "SeProfileSingleProcessPrivilege", 
            "SeRelabelPrivilege", "SeRemoteShutdownPrivilege", "SeRestorePrivilege", "SeSecurityPrivilege", 
            "SeShutdownPrivilege", "SeSyncAgentPrivilege", "SeSystemEnvironmentPrivilege", "SeSystemProfilePrivilege", 
            "SeSystemtimePrivilege", "SeTakeOwnershipPrivilege", "SeTcbPrivilege", "SeTimeZonePrivilege", 
            "SeTrustedCredManAccessPrivilege", "SeUndockPrivilege", "SeUnsolicitedInputPrivilege")]
        [String]$Privilege,

        [Parameter(Position = 1)]
        $ProcessId = $PID,

        [switch]$Disable
        )


        Add-Type -TypeDefinition @'
using System;
using System.Runtime.InteropServices;

public class Privilege {
    [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
    internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall, ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);

    [DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
    internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);

    [DllImport("advapi32.dll", SetLastError = true)]
    internal static extern bool LookupPrivilegeValue(string host, string name, ref long pluid);

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    internal struct TokPriv1Luid {
        public int Count;
        public long Luid;
        public int Attr;
    }

    internal const int SE_PRIVILEGE_ENABLED    = 0x00000002;
    internal const int SE_PRIVILEGE_DISABLED   = 0x00000000;
    internal const int TOKEN_QUERY             = 0x00000008;
    internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;

    public static bool EnablePrivilege(long processHandle, string privilege, bool disable) {
        bool retVal;
        TokPriv1Luid tp;
        IntPtr hproc = new IntPtr(processHandle);
        IntPtr htok = IntPtr.Zero;
        retVal = OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, ref htok);
        tp.Count = 1;
        tp.Luid = 0;
        if(disable) { tp.Attr = SE_PRIVILEGE_DISABLED; }
        else { tp.Attr = SE_PRIVILEGE_ENABLED; }
        retVal = LookupPrivilegeValue(null, privilege, ref tp.Luid);
        retVal = AdjustTokenPrivileges(htok, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
        return retVal;
    }
}
'@

    try {
        $proc   = Get-Process -Id $ProcessId -ErrorAction Stop
        $name   = $proc.ProcessName
        $handle = $proc.Handle
        $action = if ($Disable) { 'Disabling' } else { 'Enabling' }
        Write-Verbose ("{0} privilege '{1}' for process {2}" -f $action, $Privilege, $name)
        [Privilege]::EnablePrivilege($handle, $Privilege, [bool]$Disable)
    }
    catch {
        throw
    }
}

function Grant-FullControl ([string]$SubKey, [switch]$BreakInheritance) {
    # helper function to grant registry FullControl for Administrators on a certain subkey

    # better not use the string "Administrators", because this might have a different name in other cultures
    # $RegACL.SetOwner([System.Security.Principal.NTAccount]"Administrators")
    # use the Well-Known SID instead
    $Administrators = [System.Security.Principal.SecurityIdentifier]::new('S-1-5-32-544')   # local Administrators group

    $RegKey = [Microsoft.Win32.Registry]::ClassesRoot.OpenSubKey($SubKey,
                                                                 [Microsoft.Win32.RegistryKeyPermissionCheck]::ReadWriteSubTree,
                                                                 [System.Security.AccessControl.RegistryRights]::TakeOwnership)

    $RegACL = $RegKey.GetAccessControl()
    if ($BreakInheritance) {
        # break inheritance, but keep permissions
        $RegACL.SetAccessRuleProtection($true, $true)
    }

    $RegACL.SetOwner($Administrators)
    $RegKey.SetAccessControl($RegACL)

    # refresh the ACL
    $RegACL = $RegKey.GetAccessControl()

    # test if there is a Deny rule in the ACL for Administrators and if so remove that rule
    $RegACL.GetAccessRules($true, $true, [System.Security.Principal.SecurityIdentifier]) |
        Where-Object { $_.AccessControlType -eq 'Deny' -and $_.IdentityReference -eq $Administrators.Value } |
        ForEach-Object { $null = $RegAcl.RemoveAccessRule($_) }

    # ceate a new rule allowing the Administrators FullControl
    $RegRule =[System.Security.AccessControl.RegistryAccessRule]::new($Administrators,
                                                                      'FullControl',
                                                                      'ContainerInherit',  # ContainerInherit, ObjectInherit
                                                                      'None',              # InheritOnly 
                                                                      'Allow')
    $RegACL.SetAccessRule($RegRule)
    $RegKey.SetAccessControl($RegACL)

    # close the registry key
    $RegKey.Close()
}

##################################################################################
# Step 1: give the current process the SeTakeOwnershipPrivilege
##################################################################################

$null = Enable-Privilege -Privilege SeTakeOwnershipPrivilege -Verbose

##################################################################################
# Step 2: change Key Owner to the local Administrators group and grant FullControl
##################################################################################

# first give Administrators full control on key "CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}"
Grant-FullControl -SubKey "CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}" -BreakInheritance

##################################################################################
# Step 3: change the 'LocalizedString' property in the registry to suit your needs
##################################################################################

# with PowerShell 5 you need to use `Registry::HKEY_CLASSES_ROOT\..` syntax in order to be able
# to set the registry Type for the value with parameter '-Type'.
# As of PowerShell 7 the '-Type' parameter is included

$regPath = 'Registry::HKEY_CLASSES_ROOT\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}'
Set-ItemProperty -Path $regPath -Name 'LocalizedString' -Value "%ComputerName%" -Type ExpandString -Force

##################################################################################
# Step 4: OPTIONAL. Change the Computer icon for NEW user logins
##################################################################################

# give  Administrators full control on subkey "CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\DefaultIcon"
# now, we do not need to break the inheritance as we needed for the root key
Grant-FullControl -SubKey "CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\DefaultIcon"

$regPath = 'Registry::HKEY_CLASSES_ROOT\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\DefaultIcon'
Set-ItemProperty -Path $regPath -Name '(Default)' -Value '%SystemRoot%\System32\imageres.dll,-149' -Type ExpandString -Force

##################################################################################
# Step 5: Change the Computer icon for the CURRENT user
##################################################################################

$regPath = 'Registry::HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\DefaultIcon'
Set-ItemProperty -Path $regPath -Name '(Default)' -Value '%SystemRoot%\System32\imageres.dll,-149' -Type ExpandString -Force

这一切之后,桌面还没有显示计算机名。您需要在桌面上按 F5,或者使用找到的代码刷新桌面。


要更改图标本身,您需要更改注册表路径中的默认值

HKEY_CLASSES_ROOT\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\DefaultIcon 

用于将来的新登录,或注册表路径

HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\DefaultIcon

对于当前用户。

默认指向%SystemRoot%\System32\imageres.dll,-109,即提取第一个图标。来自 imageres.dll 的 109。 在那个dll中。有大约 343 个图标,因此您可以选择使用同一资源中的另一个图标,或者从另一个现有的 dll 中获取一个。 (例如,您可以使用 nirsoft 的 IconsExtract)。

我还没有测试这个,但也应该可以让它指向你自己的图标的完整路径和文件名,比如 %SystemDrive%\MyComputerIcon.ico

例如,这将更新图标以使用 imageres.dll 图标编号。 149

$regPath = 'Registry::HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\DefaultIcon'
Set-ItemProperty -Path $regPath -Name '(Default)' -Value '%SystemRoot%\System32\imageres.dll,-149' -Type ExpandString -Force

看起来像这样