扩展右键菜单

PowerShell注册表(四)创建和删除键值 1


PowerShell管理注册表之系列文章:

  1. 操作注册表的几条重要命令
  2. “提供程序”文件系统以外的位置
  3. 搜索注册表
  4. 创建和删除键值
  5. 注册表权限

使用New-item或者md函数来创建注册表键。注册表中的键行为类似文件系统的中的目录。

> New-Item -type Directory HKCU:\Software\Test1

    Hive: HKEY_CURRENT_USER\Software

Name                           Property
----                           --------
Test1

> md HKCU:\Software\Test2

    Hive: HKEY_CURRENT_USER\Software

Name                           Property
----                           --------
Test2

但是上面的两条命令创建的键是空的:它的默认值为没有设置。如果你想给一个键定义默认值,使用New-Item替代md吧,同时给它指定值的类型(-itemType参数),和值的内容(-value参数):

> New-Item -itemType String HKCU:\Software\Test3 -value "一个默认值而已"

    Hive: HKEY_CURRENT_USER\Software

Name                           Property
----                           --------
Test3                          (default) : 一个默认值而已

如果你想删除刚才测试时创建的三个注册表键,可以像在文件系统中那样,使用Remove-Item,或者短别名Del

Remove-Item HKCU:\Software\Test1
Del HKCU:\Software\Test2
Del HKCU:\Software\Test3

下面的表格列出所有支持的注册表值类型(itemType):

ItemType描述数据类型
String一个字符串REG_SZ
ExpandString包含环境变量的字符串在执行时可以自动处理REG_EXPAND_SZ
Binary二进制值REG_BINARY
DWord32位数值REG_DWORD
MultiString多行文本REG_MULTI_SZ
QWord64位数值REG_QWORD

删除键和内容

如果一个键名称包含空格,需要将该键用括号引起来。非常不幸,不能像在文件系统那样一次性创建多个键。因为父键必须存在。这也就为什么下面的脚本会报错:父键和子键均不存在。

> md "HKCU:\Software\First key\Second key"

md : 指定路径下的注册表项不存在。

必须将上面的语句分成多个语句来执行:

> md "HKCU:\Software\First key" | Out-Null
> md "HKCU:\Software\First key\Second key" | Out-Null

如果尝试删除第一个键,像文件系统中那样,需要确认。因为它包含了非空子键:

> Del "HKCU:\Software\First key"

确认
HKCU:\Software\First key 处的项具有子项,并且未指定 Recurse 参数。如果继续,所有子项均将随该项删除。是否确实要继续?
[Y] 是(Y)  [A] 全是(A)  [N] 否(N)  [L] 全否(L)  [S] 挂起(S)  [?] 帮助 (默认值为“Y”): n

当然可以使用-recurse参数来明确指定要删除子键和它的内容:

> Del "HKCU:\Software\First key" -recurse

设置,更改,和删除键的值

注册表编辑器通过良好的组织结构来区别键和值:左边为键,右边为值。键对应于文件系统中的文件夹,值对应于文件系统中的目录中的文件。所以要添加一个新键,可以使用md,或者最好使用New-Item,方便使用-itemType 和 -value 参数给你新创建的键来赋一个新值。

New-Item HKCU:\Software\Testkey -itemType String -value "一代宗师" | 
Out-Null

添加新值

很可惜,你如果想给一个键添加值时,文件系统这个比喻似乎不太奏效。因为常规情况下,可以使用Set-Content往文件夹下写文件。但是注册表似乎不买账。

> Set-Content HKCU:\Software\Testkey\Value1 "Contents"
Set-Content : 无法使用接口。此提供程序未实现 IContentCmdletProvider 接口。

Set-Content : 无法使用接口。此提供程序未实现 IContentCmdletProvider 接口。

取而代之,使用Set-ItemProperty给一个键添加值。

Set-ItemProperty HKCU:\Software\Testkey -name "Blog" -value www.pstips.net

你添加的这个值会在注册表中自动注册为REG_SZ类型。如果你想尝试其它类型,上面的表格中已经列出来了。下面就创建一系列的值作为测试吧:

$testKey ='HKCU:\Software\Testkey'
if ( -not (Test-Path $testKey)) { md $testKey }
New-ItemProperty $testKey -name "Entry2" -value "123" -propertyType dword
New-ItemProperty $testKey Entry3 -value "Windows is in %windir%" -propertyType string
New-ItemProperty $testKey Entry4 -value "Windows is in %windir%" -propertyType expandstring
New-ItemProperty $testKey Entry5 -value "One","Two","Three" -propertyType multistring
New-ItemProperty $testKey Entry6 -value 1,2,3,4,5 -propertyType binary
New-ItemProperty $testKey Entry7 -value 100 -propertyType dword
New-ItemProperty $testKey Entry8 -value 100 -propertyType qword

然后打开注册表编辑器,来对照一下:

向注册表中写入多种类型的值

向注册表中写入多种类型的值

如果你已经拿到了Microsoft.Win32.Registry对象,你还可以通过该对象的SetValue() 和 GetValue()方法来读写值。在你使用New-Item来创建新键时,返回的结果已然是Microsoft.Win32.Registry了。你需要做的无非是把它保存起来,然后按照下面的步骤操作即可:

# 创建一个包含多个值的键:
$key = md HKCU:\Software\Test2
$key.SetValue("Entry1", "123")
$key.SetValue("Entry2", "123", "Dword")
$key.SetValue("Entry3", "%windir%", "ExpandString")
$key.GetValue("Entry3")
 C:\Windows

小技巧:SetValue()方法只对刚创建的键有效,因为添加新键时,PowerShell会以写权限打开它。但是对于已存在的键使用Get-Item是以只读模式打开,不能在这种情况下使用SetValue()。相反,可以使用Set-ItemProperty(参见上文)。

读取值

读取注册表的值,是注册表操作中唯一不太清楚的地方了。一般情况下,我们会想既然可以使用Set-ItemProperty添加值,应当就是可以通过Get-ItemProperty读取值。想法是对的,但是这个蛋疼的PowerShell获取的不是一个值,而是包括了额外PowerShell属性的许多值:

> Get-ItemProperty HKCU:\Software\Testkey Entry3

Entry3       : Windows is in %windir%
PSPath       : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software\Testkey
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software
PSChildName  : Testkey
PSDrive      : HKCU
PSProvider   : Microsoft.PowerShell.Core\Registry

荔非苔注:其原因应当是 PowerShell 对注册表的处理和对文件系统等一样使用的是统一的层次信息模型。

所以要获取正确的属性值,还得针对返回的对象,再次指定属性比如:

> (Get-ItemProperty HKCU:\Software\Testkey Entry3).Entry3
Windows is in %windir%
> (Get-ItemProperty HKCU:\Software\Testkey Entry4).Entry4
Windows is in C:\Windows

Entry4和Entry3有所区别,因为Entry3类型为REG_SZ,普通字符串,是什么就是什么,但是Entry4的类型为REG_EXPAND_SZ,Windows 会在程序读取该值之前自动解析包含在其中的处理环境变量。这就是为什么你看到了真实的Windows系统目录,而非一个生硬的环境变量半成品。

注意:上面读取值的方法还可写为:

(Get-ItemProperty HKCU:\Software\Testkey).Entry4

貌似简练,可读性强。但是事实上,它先得读取所有值,效率稍低。

删除值

使用Remove-ItemProperty删除一个值,下面的指令会删除之前例子中创建的:Entry5

Remove-ItemProperty HKCU:\Software\Testkey Entry5

只会删除Entry5值,不会删除Testkey。

默认项

默认项扮演着一个特殊的角色。它显示在注册表编辑器的右边属性列,名为(默认)。但事实上,该项的属于未命名项:它无名却有值。
默认项并非一定得定义。如果你没有设置,它在注册表中显示为“数值未设置”。正常情况下在使用New-Item和-Value参数添加键,并赋给它默认值。但是也可以直接通过属性名(default)来访问它:

# 添加一个空键
> md HKCU:\Software\Test3

	Hive: HKEY_CURRENT_USER\Software
Name                           Property
----                           --------
Test3

# 验证默认值:
> Get-ItemProperty HKCU:\Software\Test3 "(default)"
Get-ItemProperty : 路径 HKEY_CURRENT_USER\Software\Test3 处不存在属性 (default)。

# 添加默认值:
> New-ItemProperty HKCU:\Software\Test3 "(default)" -value "A value"

(default)    : A value
PSPath       : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software\Test3
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software
PSChildName  : Test3
PSDrive      : HKCU

# 验证添加的默认值:
> Get-ItemProperty HKCU:\Software\Test3 "(default)"

(default)    : A value
PSPath       : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software\Test3
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\Software
PSChildName  : Test3
PSDrive      : HKCU
PSProvider   : Microsoft.PowerShell.Core\Registry

# 读取默认值的内容
> (Get-ItemProperty HKCU:\Software\Test3 "(default)")."(default)"
A value

# 删除默认值:
# 鉴于PowerShell的bug,不能删除默认值
# 只能使用Clear-ItemProperty清空默认值
> Clear-ItemProperty HKCU:\Software\Test3 "(default)"

重要:确保删除刚才添加的这些测试键值:

Del HKCU:\Software\Testkey -recurse
Del HKCU:\Software\Test2 -recurse
Del HKCU:\Software\Test3 -recurse

实例:扩展上下文菜单

注册表中键值用途广泛而丰富。其中就包括了资源管理器的上下文菜单在Windows系统中的设置。在下面的例子中,我们会测试在上下文菜单中针对PowerShell脚本添加三个新的命令项:“执行完停留”,“执行完关闭”,”记事本编辑”。

执行和编辑PowerShell脚本

要继续上面的测试,你先得知道怎样在PowerShell控制台外面运行PowerShell脚本,这方便啦。首先创建一个示例脚本:

Cd $home
# 创建示例脚本
'"向世界人民问好!"' | Out-File test.ps1

如果在PowerShell控制台中,可以使用相对路径或者绝对路径执行它:

.\test.ps1

但是怎样在PowerShell控制台外面执行它呢?启动PowerShell.exe,并且指定参数-NoExit选项,这样就会让脚本处理完毕后,进程不退出,停留在控制台界面上,方便用户查看和评估脚本的结果。在-Command参数后,指定PowerShell支持的命令行,将路径包在单引号中,前面加上调用操作符,为啥要多次一举呢?因为我们不知道,你的脚本路径中是否包含了空格,然后再将命令放在双引号中。

powershell.exe -NoExit -Command "& '.\test.ps1'"

如果你要编辑脚本,命令要简单的多,根据你的选择指定编辑器,然后将脚本路径传递过去:

notepad.exe ".\test.ps1"

上下文菜单的扩展接下来会被写入注册表,当然需要管理员权限:

# 创建HKEY_CLASSES_ROOT快捷方式:
New-PSDrive -Name HKCR -PSProvider registry -root HKEY_CLASSES_ROOT | Out-Null

# 找出关联PS1文件的键:
$keyname = (Get-ItemProperty HKCR:\.ps1)."(default)"

# 添加三个菜单命令:
$psExe= "$pshome\powershell.exe"
New-Item ("HKCR:\$keyname\shell\myexecute1") -value '执行完停留' -type String
New-Item ("HKCR:\$keyname\shell\myexecute1\command") -value "$psExe -NoExit -Command `"& '%L'`"" -type String
New-Item ("HKCR:\$keyname\shell\myexecute2") -value '执行完关闭' -type String
New-Item ("HKCR:\$keyname\shell\myexecute2\command") -value "$psExe -Command `"& '%L'`"" -type String
New-Item ("HKCR:\$keyname\shell\myeditnotepad") -value '记事本编辑' -type String
New-Item ("HKCR:\$keyname\shell\myeditnotepad\command") -value 'notepad.exe "%L"' -type String

# 设置图标
# 如果存在删除它:
if (Test-Path ("HKCR:\$keyname\DefaultIcon")) {
Del ("HKCR:\$keyname\DefaultIcon") }
$icon = '%windir%\System32\WindowsPowerShell\v1.0\powershell.exe,0'
New-Item ("HKCR:\$keyname\DefaultIcon") -value $icon -type ExpandString

执行完在ps1脚本的右键菜单中就会有:

扩展右键菜单

扩展右键菜单

只让别人安装,不给卸载的行为都是耍流氓,所以测试完毕后可以删除:

dir HKCR:\$keyname\shell\my* | Remove-Item -Force

原文链接:Chapter 16. Managing Windows Registry

本文链接: https://www.pstips.net/creating-and-deleting-keys-and-values.html
请尊重原作者和编辑的辛勤劳动,欢迎转载,并注明出处!

关于 Mooser Lee

我是一个Powershell的爱好者,创建了PowerShell中文博客,热衷于Powershell技术的搜集和分享。本站部分内容来源于互联网,不足之处敬请谅解,并欢迎您批评指正。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

一条评论 “PowerShell注册表(四)创建和删除键值