为什么在创建 WMI 实例时出现严重错误?
Why am I getting a Critical Error when creating a WMI Instance?
我有一个脚本,旨在根据转换为字符串的 ACL 输出创建自定义 WMI class 的实例。这最终是通过 WMI class 查询权限。
过程的主要内容是:
[cmdletbinding()]
param([Parameter(ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$True)]$Computer = '.')
$shares = gwmi -Class win32_share -ComputerName $computer | select -ExpandProperty Name
foreach ($share in $shares) {
$acl = $null
#Write-Host $share -ForegroundColor Green
#Write-Host $('-' * $share.Length) -ForegroundColor Green
$objShareSec = Get-WMIObject -Class Win32_LogicalShareSecuritySetting -Filter "name='$Share'" -ComputerName $computer
try {
$SD = $objShareSec.GetSecurityDescriptor().Descriptor
foreach($ace in $SD.DACL){
$UserName = $ace.Trustee.Name
If ($ace.Trustee.Domain -ne $Null) {$UserName = "$($ace.Trustee.Domain)$UserName"}
If ($ace.Trustee.Name -eq $Null) {$UserName = $ace.Trustee.SIDString }
[Array]$ACL += New-Object Security.AccessControl.FileSystemAccessRule($UserName, $ace.AccessMask, $ace.AceType)
for( $i = 1; $i -lt $ACL.Length; $i++)
{
$permission = $ACL[$i] | Out-String
Write-Host "permission for $share is $permission"
Set-WmiInstance -Class TestShare -Puttype CreateOnly -Argument @{Name = $share; Permissions = $permission}
}
} #end foreach ACE
} # end try
catch
{
Write-host "Failed to create or update instance for share $share"
Write-Host ""
}
#$ACL
# Write-Host $('=' * 50)
} # end foreach $share
其中 returns 以下错误:
Set-WmiInstance : Critical error
At ...\GetShares.ps1:35 char:15
+ ... Set-WmiInstance -Class LDLocalShare -Puttype CreateOnly - ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Set-WmiInstance], ManagementException
+ FullyQualifiedErrorId : SetWMIManagementException,Microsoft.PowerShell.Commands.SetWmiInstance
我将 Security.AccessControl.FileSystemAccessRule 转换为字符串的方式似乎存在问题,因为使用下面的代码并提供文字字符串会创建一个没有问题的实例,并具有适当的值:
Set-WmiInstance -Class TestShare -Puttype CreateOnly -Argument @{Name = "TestShare" ; Permissions = "TestPermission"}
我查看了与返回的错误相关的 technet 论坛帖子,但问题似乎总是与尝试创建未创建的 class 的实例有关。 class 肯定在那里。有没有什么方法可以将没有 运行 的 Security.AccessControl.FileSystemAccessRule 转换成这个,或者用不同的方法将该信息存储在自定义 WMI class 的实例中?
编辑:$permission 的示例输出,它被转换为字符串
FileSystemRights : FullControl
AccessControlType : Allow
IdentityReference : Everyone
IsInherited : False
InheritanceFlags : None
PropagationFlags : None
要创建对象,您可以通过 运行以管理员身份执行一次以下代码片段来完成此操作:
$WMI_Class = ""
$WMI_Class = New-Object System.Management.ManagementClass("Root\cimv2", $null, $null)
$WMI_Class.name = 'TestShare'
$WMI_Class.Properties.Add("Name", [System.Management.CimType]::String, $false)
$WMI_Class.Properties["Name"].Qualifiers.Add("key", $true)
$WMI_Class.Properties.Add("Permissions", [System.Management.CimType]::String, $false)
$WMI_Class.Put()
你可以通过创建一个虚拟对象来测试它(也应该是 运行 作为管理员):
Set-WmiInstance -Class TestShare -Puttype CreateOnly -Argument @{Name = 'test';Permissions = 'x'}
那么您的代码应该可以正常工作,只需对 set-wmiinstance 进行以下小改动:
Set-WmiInstance -Class TestShare -Puttype CreateOnly -Argument @{Name = $share;Permissions = $permission.Replace("`r`n","`n")}
但是,我已将共享名称定义为键,并且属性没有写入限定符。因此您以后将无法为同一共享修改对象
我有一个脚本,旨在根据转换为字符串的 ACL 输出创建自定义 WMI class 的实例。这最终是通过 WMI class 查询权限。
过程的主要内容是:
[cmdletbinding()]
param([Parameter(ValueFromPipeline=$True,
ValueFromPipelineByPropertyName=$True)]$Computer = '.')
$shares = gwmi -Class win32_share -ComputerName $computer | select -ExpandProperty Name
foreach ($share in $shares) {
$acl = $null
#Write-Host $share -ForegroundColor Green
#Write-Host $('-' * $share.Length) -ForegroundColor Green
$objShareSec = Get-WMIObject -Class Win32_LogicalShareSecuritySetting -Filter "name='$Share'" -ComputerName $computer
try {
$SD = $objShareSec.GetSecurityDescriptor().Descriptor
foreach($ace in $SD.DACL){
$UserName = $ace.Trustee.Name
If ($ace.Trustee.Domain -ne $Null) {$UserName = "$($ace.Trustee.Domain)$UserName"}
If ($ace.Trustee.Name -eq $Null) {$UserName = $ace.Trustee.SIDString }
[Array]$ACL += New-Object Security.AccessControl.FileSystemAccessRule($UserName, $ace.AccessMask, $ace.AceType)
for( $i = 1; $i -lt $ACL.Length; $i++)
{
$permission = $ACL[$i] | Out-String
Write-Host "permission for $share is $permission"
Set-WmiInstance -Class TestShare -Puttype CreateOnly -Argument @{Name = $share; Permissions = $permission}
}
} #end foreach ACE
} # end try
catch
{
Write-host "Failed to create or update instance for share $share"
Write-Host ""
}
#$ACL
# Write-Host $('=' * 50)
} # end foreach $share
其中 returns 以下错误:
Set-WmiInstance : Critical error
At ...\GetShares.ps1:35 char:15
+ ... Set-WmiInstance -Class LDLocalShare -Puttype CreateOnly - ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Set-WmiInstance], ManagementException
+ FullyQualifiedErrorId : SetWMIManagementException,Microsoft.PowerShell.Commands.SetWmiInstance
我将 Security.AccessControl.FileSystemAccessRule 转换为字符串的方式似乎存在问题,因为使用下面的代码并提供文字字符串会创建一个没有问题的实例,并具有适当的值:
Set-WmiInstance -Class TestShare -Puttype CreateOnly -Argument @{Name = "TestShare" ; Permissions = "TestPermission"}
我查看了与返回的错误相关的 technet 论坛帖子,但问题似乎总是与尝试创建未创建的 class 的实例有关。 class 肯定在那里。有没有什么方法可以将没有 运行 的 Security.AccessControl.FileSystemAccessRule 转换成这个,或者用不同的方法将该信息存储在自定义 WMI class 的实例中?
编辑:$permission 的示例输出,它被转换为字符串
FileSystemRights : FullControl
AccessControlType : Allow
IdentityReference : Everyone
IsInherited : False
InheritanceFlags : None
PropagationFlags : None
要创建对象,您可以通过 运行以管理员身份执行一次以下代码片段来完成此操作:
$WMI_Class = ""
$WMI_Class = New-Object System.Management.ManagementClass("Root\cimv2", $null, $null)
$WMI_Class.name = 'TestShare'
$WMI_Class.Properties.Add("Name", [System.Management.CimType]::String, $false)
$WMI_Class.Properties["Name"].Qualifiers.Add("key", $true)
$WMI_Class.Properties.Add("Permissions", [System.Management.CimType]::String, $false)
$WMI_Class.Put()
你可以通过创建一个虚拟对象来测试它(也应该是 运行 作为管理员):
Set-WmiInstance -Class TestShare -Puttype CreateOnly -Argument @{Name = 'test';Permissions = 'x'}
那么您的代码应该可以正常工作,只需对 set-wmiinstance 进行以下小改动:
Set-WmiInstance -Class TestShare -Puttype CreateOnly -Argument @{Name = $share;Permissions = $permission.Replace("`r`n","`n")}
但是,我已将共享名称定义为键,并且属性没有写入限定符。因此您以后将无法为同一共享修改对象