如何使用 PowerShell 脚本更改 Windows 7 中的主题?

如何使用 PowerShell 脚本更改 Windows 7 中的主题?

我想要一个可以更改 Windows 7 当前主题的脚本。我找到了存储该脚本的注册表项,但我显然需要采取进一步的措施才能让 Windows 加载该主题。我该怎么办?

这是我正在尝试使用的脚本,但它不起作用(注册表已更新,但主题未更改):

######################################
# Change theme by updating registry. #
######################################

# Define argument which defines which theme to apply. 
param ( [string] $theme = $(Read-Host -prompt "Theme") )

# Define the themes we know about.
$knownThemes = @{ "myTheme" = "mytheme.theme"; "alien" = "oem.theme" }

# Identify paths to user themes.
$userThemes = " C:\Users\yoda\AppData\Local\Microsoft\Windows\"

# Get name of theme file, based on theme provided
$themeFile = $knownThemes["$theme"]

# Build path to theme and set registry.
$newThemePath = "$userThemes$themeFile"
$regPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Themes\"
Set-ItemProperty -path $regPath -name CurrentTheme -value $newThemePath

# Update system with this info...this isn't working!
rundll32.exe user32.dll, UpdatePerUserSystemParameters

答案1

看看 Stack Overflow 上的问题如何以编程方式更改当前 Windows 主题?处理同样的问题。似乎大多数评论者都认为你根本不应该这样做(你可以选择忽略他们)。其他建议可以轻松转换为 PowerShell 脚本 - 只需调用适当的 API 函数即可。

答案2

我已经用此代码解决了该问题(在 Windows 7 64 位中测试)

# definition de la fonction native Windows permettant le test d'activation d'Aero
$def = @"

    [DllImport("dwmapi.dll", PreserveSig = false)]
    public static extern bool DwmIsCompositionEnabled();

"@
# chargement de la fonction native dans un namespace personnel
Add-Type -Namespace MaifCode -Name Aero -MemberDefinition $def


# fonction qui check si Aero est desactive ou non
function Check-Is-Aero{
    [CmdletBinding()]
    param()
    Write-Verbose "[$([DateTime]::Now)] ==> Test de la presence du mode Aero pour la session utilisateur $env:USERNAME"
    if([MaifCode.Aero]::DwmIsCompositionEnabled()){
        Write-Verbose "[$([DateTime]::Now)] ==> Aero actif pour la session utilisateur $env:USERNAME"
        return $true
    }else{
        Write-Verbose "[$([DateTime]::Now)] ==> Aero inactif pour la session utilisateur $env:USERNAME"
        return $false
    }
}

# fonction qui test si Aero est actif et le desactive dans ce cas
function Disable-Aero{
    [CmdletBinding()]
    param()
    # test si aero actif
    If(Check-Is-Aero) {
        Write-Verbose "[$([DateTime]::Now)] ==> Tentative de desactivation du mode Aero pour la session utilisateur $env:USERNAME"
        # desactivation du mode aero en passant sur le them par defaut
        try{
            Start-Process -Wait -FilePath "rundll32.exe" -ArgumentList "$env:SystemRoot\system32\shell32.dll,Control_RunDLL $env:SystemRoot\system32\desk.cpl desk,@Themes /Action:OpenTheme /file:""C:\Windows\Resources\Ease of Access Themes\basic.theme"""
        }
        catch [exception]
        {
            # si erreur alors on sort et on affiche le message d'erreur
            Write-Error "Erreur dans l'execution de la desactivation du mode Aero : $error"
            exit -1
        }
        Write-Verbose "[$([DateTime]::Now)] ==> Desactivation du mode Aero pour la session utilisateur $env:USERNAME terminee"
    }else{
        Write-Verbose "[$([DateTime]::Now)] ==> sortie du script sans action"
    }
}

# execution du code de desactivation
Disable-Aero -Verbose
# on sort
exit 0

答案3

要直接回答 OP 的问题,您可以使用以下内容。我在结尾处添加了一些关于关闭机制的评论,如果您搜索此问题,您会发现它们的行为并不像脚本新手所认为的那样。

我还稍微改进了最先进的技术,因为解决方案是纯 powershell(尽管调用了 com 对象),并且关闭窗口之前的延迟会根据桌面的状态自行配置。

#the path to the theme we want to apply
$ThemePath = "C:\Windows\Resources\Ease of Access Themes\classic.theme"

#the name of the desktop customization window (Written for windows 7, change for your flavor)
$CustomizationWindowName = "Personalization"

$myWScriptShell = New-Object -ComObject Wscript.Shell #wscriptshell com object to interact with the system
$myShellApplication = New-Object -ComObject Shell.Application #shellapplication com object to access window names

#execute the theme change
$myWScriptShell.Run("rundll32.exe %SystemRoot%\system32\shell32.dll,Control_RunDLL %SystemRoot%\system32\desk.cpl desk,@Themes /Action:OpenTheme /file:""$ThemePath""")

#this while block continuously searches for the 
#customization window which will be left behind based on it's name
:search while($true) 
{
    #enumerate the open windows
    foreach($window in $myShellApplication.Windows())
    {
        #check each window to see if it's the one of interest
        #when we find the window, break from the outer 
        #"search" loop to execute the remainder of the script
        if($window.LocationName -eq $CustomizationWindowName){break search} 
    }
}

#activate the customization window (in case it's in the background,
#and to be sure we send the keys to the right window)
$myWScriptShell.AppActivate($CustomizationWindowName)

#This is alt+F+C, intended for file->Close. 
#Presumably pulled from another (perhaps office?) script
#In the common literature, this line actually did the close, #the last line was essentially doing nothing
#$myWScriptShell.SendKeys("%FC") #commented as extraneous

#In the common literature, this was just {F4}, which doesn't work without the % for "alt". 
#The prior line actually did the work.
$myWScriptShell.SendKeys("%{F4}") 

相关内容