PowerShell命令与脚本(15)——注册表

操作注册表的几条重要命令

你可以像导航文件系统那样来访问注册表,PowerShell把文件系统和注册表都当作层次信息系统来处理。
注册表中的键对应于文件系统的目录,但是键对应的值和文件系统中的文件不是非常类似。相反的,它们显示在属性栏,被以键的属性来管理。
下面的表格列出了访问注册表所需的所有命令。
命令
描述
Dir, Get-ChildItem
列出键的内容
Cd, Set-Location
更改当前(键)目录
HKCU:, HKLM:
预定义的两个重要注册表根目录虚拟驱动器
Get-ItemProperty
读取键的值
Set-ItemProperty
设置键的值
New-ItemProperty
给键创建一个新值
Clear-ItemProperty
删除键的值内容
Remove-ItemProperty
删除键的值
New-Item, md
创建一个新键
Remove-Item, Del
删除一个键
Test-Path
验证键是否存在
 
 

“提供程序”文件系统以外的位置

PowerShell拥有一个被叫做“提供程序”的负责特定信息存储的模型化结构。在上一章,你已经使用过了文件系统提供程序,所以如果你想访问注册表,就需要一个替代文件系统的注册表提供者。在其它方面,就和上一章的操作没什么区别了。你可以在注册表中使用你在文件系统中使用过的命令。
 
1、支持的提供程序
Get-PSProvider能获取安装的提供程序列表。下面的例子中,可能没有列出你自定义的列表,因为提供程序可以随后添加。比如,PowerShell默认就没有活动目录的提供程序。
这里你感兴趣的可能只是“Drives”列,它就是用来管理各自驱动器的名称。你也看到了,注册表提供程序挂载了驱动器HKLM:(根目录HKEY_LOCAL_MACHINE)和HKCU:(根目录HKEY_CURRENT_USER)。这些驱动器用起来,很像传统的文件系统驱动器,试试吧:
 
从这个位置,你可以像你在真正的文件系统中做的那样,通过子目录来导航。相同的特殊字符功能也一样,除了”~”符号在注册表中不能识别,并且会产生错误。
 
2、创建提供程序
注册表提供程序提供访问注册表。你可以通过驱动器来定位它们。如果你想查看那些注册表驱动器已经被注册表提供程序使用了,可以通过Get-PSDrive命令,和参数-PSProvider:
这里稍微注意下,你可能会困惑,注册表包含的根节点远不止两个。
事实上HKEY_CLASSES_ROOT根节点不是一个独立的根节点,而是指向HKEY_LOCAL_MACHINE\SOFTWARE\Classes。这意味着你可以以这个路径为起点,来创建一个新的驱动器。
New-PSDrive -name HKCR -PSProvider registry -root HKLM:\SOFTWARE\Classes
现在,你可以去访问这个分支了。事实上,你可以访问上面表格中列出的任意根节点。
 
小技巧:你可以自由地创建任何额外的驱动器,尤其在你有频繁操作某个特定的注册表区域时。
New-PSDrive job1 registry "HKLM:\Software\Microsoft\Windows NT\CurrentVersion" 
dir job1:
 

搜索注册表

使用Dir,你可以像在文件系统中那样来搜索注册表。使用注册表提供程序提供的虚拟驱动器,非常方便。驱动器HKCU:提供了KEY_CURRENT_USER根目录键的。
如果你想像下面那样列出内容,可以使用Format-List:
Dir | Format-List 
Dir | Format-List Name 
Dir | Format-List *
 
1、递归搜索
注册表提供程序不支持任何过滤器,因此你不能在Dir中使用类似于-filter这样的参数。但是参数-recurse,-include和 -exclude还是支持的。在上一章中,我们使用过它来递归地搜索文件系统。这个活在注册表中也可以这么干。比如,你想知道注册表中的那个位置包含了“PowerShell”,可以这样使用:
Dir HKCU:, HKLM: -recurse -include *PowerShell*
上面的命令会搜索HKEY_CURRENT_USER根节点和HKEY_LOCAL_MACHINE根节点。它会找出所有包括”PowerShell”单词的键。因为可能有很多键包含了单词“PowerShell”,所以使用了通配符。这样的搜索操作可能会产生错误信息,因为搜索的过程,也是读取注册表的每个子键的过程,但是部分键值没有访问权限就会报错。如果想从结果中过滤掉这些错误信息,可以使用参数-ErrorAction,并给它指定值为SilentlyContinue:
Dir HKCU:, HKLM: -recurse -include PowerShell -ErrorAction SilentlyContinue
 
2、单个注册表键
Dir获取的每一个注册表键(Microsoft.Win32.Registry 对象)对应下面的属性。
下面的表格列出一个Microsoft.Win32.Registry(注册表键)对象的重要属性:
属性
描述
Name
在注册编辑器中显示的键的路径
Property
当前键的名称
PSChildName
存储在键中的值的名称数组
PSDrive
键的注册表根节点
PSParentPath
父键
PSPath
键的PowerShell路径,使用Dir可以查看该路径下键的内容
PSProvider
提供程序的名称:注册表
SubKeyCount(SKC)
子键个数
ValueCount (VC)
键中的值个数
PSIsContainer
总是为True
 
3、PowerShell怎样寻址注册表
我们来仔细看下分配一个注册表键的属性。比如:下面图中通过注册表编辑器打开的HKLM:\Software\Microsoft\PowerShell\1 键,这里存放的是PowerShell的一些内部设置。
在PowerShell中使用Get-Item访问该键:
果然,Name属性获取的是键的完整名称,更有意思的是这些属性的名称,前面加了‘PS’,它们将注册表键分成多个片段。
 
4、键对应的值
在上图中打开的注册表编辑器中,右边的属性列有三个值,汇报给PowerShell的只有两个值:
貌似一个值丢了。仔细查看属性“Property”可以发现PowerShell记录了哪些值:
这些属性名对应上图中的属性名,唯独(Default)没有出现。也对,在上图中默认值为空。注册表编辑器识别为:“数值未设置”。
如果你要获取这些值的内容,可以将注册表的PS路径传递给Get-ItemProperty
这种方式会把该键对应的所有值自动获取并输出。另外,除了一些常规属性,这些值还包括了PowerShell添加的其他属性。如果你只想获取特定的值:
如果你想获取键的所有值,但是不想包含PowerShell自动添加的属性。可以这样做:
$key = Get-Item HKLM:\Software\Microsoft\PowerShell\1
$values = Get-ItemProperty $key.PSPath
foreach ($value in $key.Property) 
{ 
  $value + "=" + $values.$value
}
小技巧:如果你已经将路径定位到该注册表路径下,还可以使用另外一种方法获取所有值:
 
这里将”.”传递给Get-ItemProperty。当然前提条件是先得CD到目标键的路径下。
 
如果你想输出多个键的多个值,应当使用Dir。Dir的结果可以通过管道传递给ForEach-Object。这样,你就可以一次性获取某个键的所有子键,并且分 别访问它们的属性值。下面的脚本会列出Uninstall的子键,和它们的属性DisplayName与MoreInfoURL.。这也为你提供了一个简约版已安装程序列表:
Dir hklm:\software\microsoft\windows\currentversion\uninstall |
ForEach-Object { 
 Write-Host -ForegroundColor Yellow "Installed Products:" }{
 $values = Get-ItemProperty $_.PSPath;
 "{0:-30} {1:20}" -f $values.DisplayName, $values.MoreInfoURL
 }{Write-Host -ForegroundColor Yellow "Finished!"}
注:上面的脚本写法稍微有点坑爹,其实是ForEach-Object可以接受三个脚本块用于管道的流模式处理,分别代表begin,process和end。
 
5、键的子键
在注册表编辑器中,某个键的子键在PowerShell中可以这样调用:
Dir也能获取子键的名称。需要将PSPath这样的PowerShell路径传递给Dir:
 

创建和删除键值

使用New-item或者md函数来创建注册表键。注册表中的键行为类似文件系统的中的目录。
但是上面的两条命令创建的键是空的:它的默认值为没有设置。如果你想给一个键定义默认值,使用New-Item替代md吧,同时给它指定值的类型-itemType参数),和值的内容-value参数):
如果你想删除刚才测试时创建的三个注册表键,可以像在文件系统中那样,使用Remove-Item,或者短别名Del
下面的表格列出所有支持的注册表值类型(itemType):
ItemType
描述
数据类型
String
一个字符串
REG_SZ
ExpandString
包含环境变量的字符串在执行时可以自动处理
REG_EXPAND_SZ
Binary
二进制值
REG_BINARY
DWord
32位数值
REG_DWORD
MultiString
多行文本
REG_MULTI_SZ
QWord
64位数值
REG_QWORD
 
1、删除键和内容
如果一个键名称包含空格,需要将该键用括号引起来。非常不幸,不能像在文件系统那样一次性创建多个键。因为父键必须存在。这也就为什么下面的脚本会报错:父键和子键均不存在。
md : 指定路径下的注册表项不存在。
必须将上面的语句分成多个语句来执行:
如果尝试删除第一个键,像文件系统中那样,需要确认。因为它包含了非空子键:
当然可以使用-recurse参数来明确指定要删除子键和它的内容:
 
2、设置,更改,和删除键的值
注册表编辑器通过良好的组织结构来区别键和值:左边为键,右边为值。键对应于文件系统中的文件夹,值对应于文件系统中的目录中的文件。所以要添加一个新键,可以使用md,或者最好使用New-Item,方便使用-itemType 和 -value 参数给你新创建的键来赋一个新值。
 
  • 添加新值
很可惜,你如果想给一个键添加值时,文件系统这个比喻似乎不太奏效。因为常规情况下,可以使用Set-Content往文件夹下写文件。但是注册表似乎不买账。
Set-Content : 无法使用接口。此提供程序未实现 IContentCmdletProvider 接口。
取而代之,使用Set-ItemProperty给一个键添加值。
你添加的这个值会在注册表中自动注册为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")
小技巧SetValue()方法只对刚创建的键有效,因为添加新键时,PowerShell会以写权限打开它。但是对于已存在的键使用Get-Item是以只读模式打开,不能在这种情况下使用SetValue()。相反,可以使用Set-ItemProperty
 
  • 读取值
读取注册表的值,是注册表操作中唯一不太清楚的地方了。一般情况下,我们会想既然可以使用Set-ItemProperty添加值,应当就是可以通过Get-ItemProperty读取值。想法是对的,但是这个蛋疼的PowerShell获取的不是一个值,而是包括了额外PowerShell属性的许多值:
注:其原因应当是 PowerShell 对注册表的处理和对文件系统等一样使用的是统一的层次信息模型。
 
所以要获取正确的属性值,还得针对返回的对象,再次指定属性比如:
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)来访问它:
重要:确保删除刚才添加的这些测试键值:
Del HKCU:\Software\Testkey -recurse
Del HKCU:\Software\Test2 -recurse
Del HKCU:\Software\Test3 -recurse
 
3、实例:扩展上下文菜单
注册表中键值用途广泛而丰富。其中就包括了资源管理器的上下文菜单在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文件的键,若没有则创建一个:
if(!(Test-Path("HKCR:\.ps1"))){
New-Item -ItemType String ("HKCR:\.ps1") -value "Powershell"
$keyname = (Get-ItemProperty HKCR:\.ps1)."(default)"
New-Item -Type Directory ("HKCR:\$keyname")
New-Item -Type Directory ("HKCR:\$keyname\shell")
}
else{
$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
 

注册表权限

在上一章中,我们详细的学习了怎样使用PowerShell来控制文件和文件夹的权限。同样的机制也可以在注册表中使用,使用Get-Acl查看键的当前权限:
 
因为注册表权限管理基本和文件系统的权限管理类似,所以你可能需要在给注册表键分配权限前再看看第15章,或者重温一下基础知识。注册表中所需的权限在.NET中的类和与文件系统稍微有点区别。此时需要使用的不再是FilesystemAccessRule,而是RegistryAccessRule,两者的根本区别在于可以设置不同的访问权限。在注册表访问规则(RegistryAccessRule)中,权限的枚举值并不和文件系统访问规则(FilesystemAccessRule)中的枚举值对应:
[System.Enum]::GetNames([System.Security.AccessControl.RegistryRights]
 
1、接管所有权
在尝试更改注册表的权限前,请先测试以确保你是该键的“所有者”。除非你是所有者,才能够撤销可能存在的错误。下面的示例会演示怎样接管一个注册表键(当然你还是得先有权限访问)的所有权。
 
2、设置新的访问权限
下面的步骤会给这个键分配新的权限,让“所有人”组禁止更改此键。
$acl = Get-Acl HKCU:\Software\Testkey
$person = [System.Security.Principal.NTAccount]"Everyone"
$access = [System.Security.AccessControl.RegistryRights]"WriteKey"
$inheritance = [System.Security.AccessControl.InheritanceFlags]"None"
$propagation = [System.Security.AccessControl.PropagationFlags]"None"
$type = [System.Security.AccessControl.AccessControlType]"Deny"
$rule = New-Object System.Security.AccessControl.RegistryAccessRule( `
$person,$access,$inheritance,$propagation,$type)
$acl.AddAccessRule($rule)
Set-Acl HKCU:\Software\Testkey $acl
更改会立刻生效,当你尝试通过注册表编辑器或者在PowerShell中创建子键时,会得到错误信息:
小技巧:你可能会问,为什么连我自己都限制,我是管理员啊,我应当拥有完全的访问权啊。这是因为在访问权限中,“拒绝”的优先权比“允许”高。哪怕你是管理员,你也是人,既然所有人都被拒绝,你自然也会被拒绝,除非你不是人。
 
3、移除一条访问规则
给所有人的访问权限完全是在浪费时间,也经不起考验。怎样删除这条规则呢?你可以使用RemoveAccessRule()方法来移除特定的权限,还可以使用RemoveAccessRuleAll()方法来移除指定用户的在某条规则中的所有权限(包括授权和拒绝),ModifyAccessRule()方法更新已存在的规则,PurgeAccessRules(),异常特定用户的所有权限。
要移除刚才创建的规则,可以这样处理:
$acl = Get-Acl HKCU:\Software\Testkey
$person = [System.Security.Principal.NTAccount]"Everyone"
$access = [System.Security.AccessControl.RegistryRights]"WriteKey"
$inheritance = [System.Security.AccessControl.InheritanceFlags]"None"
$propagation = [System.Security.AccessControl.PropagationFlags]"None"
$type = [System.Security.AccessControl.AccessControlType]"Deny"
$rule = New-Object System.Security.AccessControl.RegistryAccessRule( `
$person,$access,$inheritance,$propagation,$type)
$acl.RemoveAccessRule($rule)
Set-Acl HKCU:\Software\Testkey $acl -force
但是这样移除自己的访问规则后,并不是期望的结果。因为你把自己锁在了门外,因为你不在有权去更新这个键,本来是可以更改自己的安全设置的。此时如果你接管了所有权后。还是可以纠正遇到的这个问题的。此类情况发生后,你可以打开注册表编辑器,定位到这个键,右键鼠标选择权限,打开安全设置对话框,手动删除“所有人”组。
重要:刚才已经看到了,把自己锁在门外有多容易。所以在操作“所有人”这个组时,一定要格外小心。如果可以,尽量不要给这个组分配“拒绝”规则,因为它通常可能引入超出你预期的恶劣影响。
 
4、控制子键的访问
下面的例子,使用“允许”规则,而非“拒绝”规则,可以让世界稍微变得美好一点。在下面的测试键中,只有管理员才能更改这个键的值,而其它闲杂人等,只能读取和创建子键。
md HKCU:\Software\Testkey2
$acl = Get-Acl HKCU:\Software\Testkey2
# 管理员无所不能:
$person = [System.Security.Principal.NTAccount]"Administrators"
$access = [System.Security.AccessControl.RegistryRights]"FullControl"
$inheritance = [System.Security.AccessControl.InheritanceFlags]"None"
$propagation = [System.Security.AccessControl.PropagationFlags]"None"
$type = [System.Security.AccessControl.AccessControlType]"Allow"
$rule = New-Object System.Security.AccessControl.RegistryAccessRule( `
$person,$access,$inheritance,$propagation,$type)
$acl.ResetAccessRule($rule)
# 所有人只能读取和创建子键:
$person = [System.Security.Principal.NTAccount]"Everyone"
$access = [System.Security.AccessControl.RegistryRights]"ReadKey"
$inheritance = [System.Security.AccessControl.InheritanceFlags]"None"
$propagation = [System.Security.AccessControl.PropagationFlags]"None"
$type = [System.Security.AccessControl.AccessControlType]"Allow"
$rule = New-Object System.Security.AccessControl.RegistryAccessRule( `
$person,$access,$inheritance,$propagation,$type)
$acl.ResetAccessRule($rule)
Set-Acl HKCU:\Software\Testkey2 $acl
稍微注意下,这种情况下没有使用AddAccessRule()而是使用ResetAccessRule()添加规则。其结果导致删除了各个用户已存在的权限。尽管如此,结果仍旧不对,因为正常的用户还是可以创建子键和写值。
 
5、揭示继承权
查看键的当前权限,可以弄清为什么上面的设置没有如期生效:
该键包含的权限可不止我们设置的那两条规则,还有其它一些从父键中继承过来的阿猫阿狗规则。如果你想清理掉它们,可以使用SetAccessRuleProtection()方法。
$acl = Get-Acl HKCU:\Software\Testkey2
$acl.SetAccessRuleProtection($true, $false)
Set-Acl HKCU:\Software\Testkey2 $aclacl = Get-Acl HKCU:\Software\Testkey2 $acl.SetAccessRuleProtection($true, $false) Set-Acl HKCU:\Software\Testkey2 $acl
 
现在再回过头来看看,该键的访问规则只有我们明确指定的两条规则,其它继承权限已不复存在。
此时再让普通用户尝试给该键添加子键或者设置值,应当会报错:Set-ItemProperty : 不允许所请求的注册表访问权。
 
6、控制你自己的继承权
继承权是一把双刃剑。你已经从父键中关闭了继承,但是你自己的继承权呢?使用管理员权限打开控制台,能让我们给上面受保护的测试键添加子键。
md HKCU:\Software\Testkey2\Subkey1
md HKCU:\Software\Testkey2\Subkey1\Subkey2
然后看看这些新创建的子键的权限:
其结果是这些权限仍旧没有与你设置的权限对应起来。理由是:对于你的继承权你啥都没设置,如果你想把自己纯正的血统不折不扣的遗传给下一代,请更改设置:
del HKCU:\Software\Testkey2
md HKCU:\Software\Testkey2
$acl = Get-Acl HKCU:\Software\Testkey2
# Admins may do anything:
$person = [System.Security.Principal.NTAccount]"Administrators"
$access = [System.Security.AccessControl.RegistryRights]"FullControl"
$inheritance = [System.Security.AccessControl.InheritanceFlags]`
"ObjectInherit,ContainerInherit"
$propagation = [System.Security.AccessControl.PropagationFlags]"None"
$type = [System.Security.AccessControl.AccessControlType]"Allow"
$rule = New-Object System.Security.AccessControl.RegistryAccessRule( `
$person,$access,$inheritance,$propagation,$type)
 
$acl.ResetAccessRule($rule)
# Everyone may only read and create subkeys:
$person = [System.Security.Principal.NTAccount]"Everyone"
$access = [System.Security.AccessControl.RegistryRights]"ReadKey"
$inheritance = [System.Security.AccessControl.InheritanceFlags]`
"ObjectInherit,ContainerInherit"
$propagation = [System.Security.AccessControl.PropagationFlags]"None"
$type = [System.Security.AccessControl.AccessControlType]"Allow"
$rule = New-Object System.Security.AccessControl.RegistryAccessRule( `
$person,$access,$inheritance,$propagation,$type)
$acl.ResetAccessRule($rule)
Set-Acl HKCU:\Software\Testkey2 $acldel HKCU:\Software\Testkey2 md HKCU:\Software\Testkey2 $acl = Get-Acl HKCU:\Software\Testkey2 # Admins may do anything: $person = [System.Security.Principal.NTAccount]"Administrators" $access = [System.Security.AccessControl.RegistryRights]"FullControl" $inheritance = [System.Security.AccessControl.InheritanceFlags]` "ObjectInherit,ContainerInherit" $propagation = [System.Security.AccessControl.PropagationFlags]"None" $type = [System.Security.AccessControl.AccessControlType]"Allow" $rule = New-Object System.Security.AccessControl.RegistryAccessRule( ` $person,$access,$inheritance,$propagation,$type)   $acl.ResetAccessRule($rule) # Everyone may only read and create subkeys: $person = [System.Security.Principal.NTAccount]"Everyone" $access = [System.Security.AccessControl.RegistryRights]"ReadKey" $inheritance = [System.Security.AccessControl.InheritanceFlags]` "ObjectInherit,ContainerInherit" $propagation = [System.Security.AccessControl.PropagationFlags]"None" $type = [System.Security.AccessControl.AccessControlType]"Allow" $rule = New-Object System.Security.AccessControl.RegistryAccessRule( ` $person,$access,$inheritance,$propagation,$type) $acl.ResetAccessRule($rule) Set-Acl HKCU:\Software\Testkey2 $acl
 

 

posted @ 2021-06-26 21:45  Ulysses~  阅读(917)  评论(0编辑  收藏  举报