超赞的Visual Studio命令提示符和PowerShell图标覆盖
[原文发表地址] Awesome Visual Studio Command Prompt and PowerShell icons with Overlays
[原文发表时间]2010-08-18 17:00
一般来说,我并不属于“图标一族”。我的意思是说,我并没有收集图标,或者把系统上的图标换成自定义炫酷图标。不过,今天我注意到自己在使用Visual Studio 命令提示符(拥有正确路径和环境设置的命令提示符),还有常规PowerShell,以及PowerShell“VSVars32”设置提示符(再重申一下,就是有正确环境设置的PowerShell)。他们的图标都不尽相同。
看来是个恰好的机会来编辑一些新的图标,改变一下我的世界了。搜索,并下载了我所知道的最有趣的免费图标编辑器,叫做IcoFX。我鼓励你们去资助他们,因为他们在全世界范围内提供了一个很棒的服务。我在cmd.exe,devenv.exe和powershell.exe上用过他们的提取命令。
免责声明: 我想我这么做的确触犯了各种国际条例或者其他规定。当Ninjas跑进来说“你不能用我们的图标来取乐。”的时候,我会否认写过这篇博文。请支持我。我只是自寻其乐而已。并不是微软什么的官方产品,你也不能说这是官方的。你是谁!?不要再说我了。Jimmy不在这儿。别再打来了。
另外: 这是我还未触及的部分。看上去VS2010图标编辑器在alpha通道部分仍然有问题。其实我一直对整个产品感到反感,不过既然我不是那个团队中的一员,我就得花功夫去深究一些细节问题了。我倒是希望在VS中把这些全解决掉。
好了,现在我把所有的图标都加载到了IcoFX。我会把它们都编辑一下,并在所有可获方案中做出最优的图标,尽管从技术上来说我的Windows 7任务栏和桌面只需要32x32的图标。
稍稍编辑和调整大小。说真的,这个图标编辑器 真的是一种享受。开始做吧!
我把这些保存为vscommand.ico和vspowershell.ico,现在,我桌面上就有这两个很好看的图标了。
我把“Visual Studio命令提示符”贴到任务栏上,如下图所示:
我还给系统菜单做了一个小的图标,因为这是我的一贯做法。
好了,多棒啊。
不过,在PowerShell中,我有时候会通过运行添加在Microsoft.PowerShell_profile.ps1中的自定义PowerShell VSVars脚本来转换我的VSVars。还记得Chris Tavares里的这个脚本吗?
1: function Get-Batchfile ($file) {
2: $cmd = "`"$file`" & set"
3: cmd /c $cmd | Foreach-Object {
4: $p, $v = $_.split('=')
5: Set-Item -path env:$p -value $v
6: }
7: }
8:
9: function VsVars32($version = "10.0")
10: {
11: $key = "HKLM:SOFTWARE\Microsoft\VisualStudio\" + $version
12: $VsKey = get-ItemProperty $key
13: $VsInstallPath = [System.IO.Path]::GetDirectoryName($VsKey.InstallDir)
14: $VsToolsDir = [System.IO.Path]::GetDirectoryName($VsInstallPath)
15: $VsToolsDir = [System.IO.Path]::Combine($VsToolsDir, "Tools")
16: $BatchFile = [System.IO.Path]::Combine($VsToolsDir, "vsvars32.bat")
17: Get-Batchfile $BatchFile
18: [System.Console]::Title = "Visual Studio " + $version + " Windows Powershell"
19: //add a call to set-consoleicon as seen below...hm...!
20: }
为什么不断然处之,和Aaron Lerch's为“改变Windows PowerShell控制台图标”而写的脚本合并起来呢?这样的话,当我调用“vsvars32”时,我会同时改变我PowerShell的图标。
以下是Aaron的脚本,做过一些变更,使其成为点源函数,还进行了一些修改。这能快速改变系统菜单图标,不过不会更新任务栏或者ALT-TAB。我也不确定这能否实现。
1: ##############################################################################
2: ## Script: Set-ConsoleIcon.ps1
3: ## By: Aaron Lerch, tiny tiny mods by Hanselman
4: ## Website: www.aaronlerch.com/blog
5: ## Set the icon of the current console window to the specified icon
6: ## Dot-Source first, like . .\set-consoleicon.ps1
7: ## Usage: Set-ConsoleIcon [string]
8: ## PS:1 > Set-ConsoleIcon "C:\Icons\special_powershell_icon.ico"
9: ##############################################################################
10:
11: $WM_SETICON = 0x80
12: $ICON_SMALL = 0
13:
14: function Set-ConsoleIcon
15: {
16: param(
17: [string] $iconFile
18: )
19:
20: [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") | out-null
21: $iconFile
22: # Verify the file exists
23: if ([System.IO.File]::Exists($iconFile) -eq $TRUE)
24: {
25: $icon = new-object System.Drawing.Icon($iconFile)
26:
27: if ($icon -ne $null)
28: {
29: $consoleHandle = GetConsoleWindow
30: SendMessage $consoleHandle $WM_SETICON $ICON_SMALL $icon.Handle
31: }
32: }
33: else
34: {
35: Write-Host "Icon file not found"
36: }
37: }
38:
39:
40: ## Invoke a Win32 P/Invoke call.
41: ## From: Lee Holmes
42: ## https://www.leeholmes.com/blog/GetTheOwnerOfAProcessInPowerShellPInvokeAndRefOutParameters.aspx
43: function Invoke-Win32([string] $dllName, [Type] $returnType,
44: [string] $methodName, [Type[]] $parameterTypes, [Object[]] $parameters)
45: {
46: ## Begin to build the dynamic assembly
47: $domain = [AppDomain]::CurrentDomain
48: $name = New-Object Reflection.AssemblyName 'PInvokeAssembly'
49: $assembly = $domain.DefineDynamicAssembly($name, 'Run')
50: $module = $assembly.DefineDynamicModule('PInvokeModule')
51: $type = $module.DefineType('PInvokeType', "Public,BeforeFieldInit")
52:
53: ## Go through all of the parameters passed to us. As we do this,
54: ## we clone the user's inputs into another array that we will use for
55: ## the P/Invoke call.
56: $inputParameters = @()
57: $refParameters = @()
58:
59: for($counter = 1; $counter -le $parameterTypes.Length; $counter++)
60: {
61: ## If an item is a PSReference, then the user
62: ## wants an [out] parameter.
63: if($parameterTypes[$counter - 1] -eq [Ref])
64: {
65: ## Remember which parameters are used for [Out] parameters
66: $refParameters += $counter
67:
68: ## On the cloned array, we replace the PSReference type with the
69: ## .Net reference type that represents the value of the PSReference,
70: ## and the value with the value held by the PSReference.
71: $parameterTypes[$counter - 1] =
72: $parameters[$counter - 1].Value.GetType().MakeByRefType()
73: $inputParameters += $parameters[$counter - 1].Value
74: }
75: else
76: {
77: ## Otherwise, just add their actual parameter to the
78: ## input array.
79: $inputParameters += $parameters[$counter - 1]
80: }
81: }
82:
83: ## Define the actual P/Invoke method, adding the [Out]
84: ## attribute for any parameters that were originally [Ref]
85: ## parameters.
86: $method = $type.DefineMethod($methodName, 'Public,HideBySig,Static,PinvokeImpl',
87: $returnType, $parameterTypes)
88: foreach($refParameter in $refParameters)
89: {
90: $method.DefineParameter($refParameter, "Out", $null)
91: }
92:
93: ## Apply the P/Invoke constructor
94: $ctor = [Runtime.InteropServices.DllImportAttribute].GetConstructor([string])
95: $attr = New-Object Reflection.Emit.CustomAttributeBuilder $ctor, $dllName
96: $method.SetCustomAttribute($attr)
97:
98: ## Create the temporary type, and invoke the method.
99: $realType = $type.CreateType()
100: $realType.InvokeMember($methodName, 'Public,Static,InvokeMethod', $null, $null,
101: $inputParameters)
102:
103: ## Finally, go through all of the reference parameters, and update the
104: ## values of the PSReference objects that the user passed in.
105: foreach($refParameter in $refParameters)
106: {
107: $parameters[$refParameter - 1].Value = $inputParameters[$refParameter - 1]
108: }
109: }
110:
111: function SendMessage([IntPtr] $hWnd, [Int32] $message, [Int32] $wParam, [Int32] $lParam)
112: {
113: $parameterTypes = [IntPtr], [Int32], [Int32], [Int32]
114: $parameters = $hWnd, $message, $wParam, $lParam
115:
116: Invoke-Win32 "user32.dll" ([Int32]) "SendMessage" $parameterTypes $parameters
117: }
118:
119: function GetConsoleWindow()
120: {
121: Invoke-Win32 "kernel32" ([IntPtr]) "GetConsoleWindow"
122: }
用PowerShell“类型扩展”功能来为System.Console做“.Icon”属性一定也很有趣。那样我就会运行 [System.Console]::Icon = "something.ico" , 不过我把这个任务留给读者们来练习。
记住,我们不会只说不做。
Comments
- Anonymous
December 14, 2011
超赞!