Accuracy of root/CIMV2/Security/MicrosoftVolumeEncryption VS. manage-bde.exe? - powershell

I am trying to determine the accuracy of reporting from 2 seemingly difference sources (using powershell on Windows devices):
Method1
manage-bde.exe -computername $hostname -status
Returns something like 100% encrypted and partition size
Method 2
if($encryption_check_all = Get-WMIObject -ComputerName $hostname -Namespace "root/CIMV2/Security/MicrosoftVolumeEncryption" -query "SELECT * FROM Win32_EncryptableVolume WHERE DriveLetter='C:'" | Select-Object *){
$encryption_check = $encryption_check_all.ProtectionStatus
if ($encryption_check -eq "1"){$encryption_status = "Encrypted" ; $encryption_value = 200 }
if ($encryption_check -eq "0"){$encryption_status = "No Encryption Found" ; $encryption_value = 200 }
else{}
Returns a value of "1" or "0". 0 meaning partition not encrypted, partially encrypted, or keys in plain text. BOTH snippets "work" as far as the code goes, BUT they return conflicting results. Does anyone have experience or validation for either method? Im having a device return with method 1 as a "0" but bde.exe says it is 100% encrypted. Does this for sure mean that keys are present in plain text or is there other nuances im unaware of? Any clarity is greatly appreciated.
Also if anyone is aware of data source from bde.exe. Is this just an exe to regurgitate AD bitlocker key recovery? I believe the WMI namespace call actually checks on device on partition- more accurate? THANKS!

Related

NIC Order in PowerShell

I have a script where it will provide the NIC binding order like below. But is there anyway so that I can write a condition if binding order is vEthernet*,storage then
Add-Content $report "<td bgcolor= 'Aquamarine' height='25' align=center><B>$ServicesResult1</B></td>"
else
Add-Content $report "<td bgcolor= 'Yellow' height='25' align=center><B>$ServicesResult1</B></td>"
$result1 = Invoke-Command -ComputerName slcae212 -ScriptBlock {
Function Get-BindOrder {
$Binding = (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Linkage").Bind
$Return = New-Object PSobject
$BindingOrder = #()
foreach ($Bind in $Binding) {
$DeviceId = $Bind.Split("\")[2]
$Adapter = (Get-WmiObject Win32_Networkadapter | Where {$_.GUID -eq $DeviceId }).NetConnectionId
$BindingOrder += $Adapter
}
$BindingOrder
} #EndFunction
CLS
Get-BindOrder
}
$adapteresult1= $result1 -join ","
Output:
vEthernet (10.211.21.0_20),,storage,Ethernet 5,Ethernet 4,Ethernet 2,Ethernet 6,,
Im not sure where in your you need it but you can use a regex to check that:
vEthernet[^,]+?,storage
Now you can use that in an if statement using the -match operator:
if ($yourBinding -match 'vEthernet[^,]+?,,storage')
{
# do something
}
else
{
# do something else
}
With all respect, I don't think that you are on the correct way with programming this. I presume that you eventually want to reorder the "HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Linkage").Bind and put that back in the registry. (Years ago I have had similar request and at created a VBScript for that.)
In your script, your currently trying to deal with the adapter names to redefine the order of the original bindingorder but the relation between the $DeviceID and the $Adapter name is completely lost in you current approach.
Instead of doing string manipulation it is better, faster and more native to PowerShell to work with objects in the form of an array or in this case even a HashTable or 'PSCustomObject' where you keep a related between the $DeviceID and the $Adapter name. I would like to point out here that you could possible have multiple vEthernet adpaters and that some $adapter names are apparently empty (there is nothing between two commas ...,,...), but AFAIK that doesn't imply that you just can drop the $DeviceID (without adapter name) from the binding order...
I think there is a good example for your request written here:
https://seawin.org/2016/06/04/setting-binding-and-route-registry-entries/
Notes:
Your binding order could potential change on the fly e.g. if a user create a VPN connection or starts a VM, this probably means that you can not just run your fix at startup or logon but depending on the actual problem, you might have to fix it as it happens by setting a NotificationQuery event on the specific HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\Linkage registry key.
Changing the binding order (on the fly) has a significant impact on the Operating System processes, besides that you CPU will raise, network connection are being reset and could be unavailable for a while. Therefor I advice you to check/flag whether the binding order really changed (where required) and only rewrite it when necessarily.
I doubt whether the known issues related to the binding order are the same for every Operating Systems. Meaning, if you are going to deploy this to multiple OS versions, I would investigate the actual problem you dealing which, also applies to the concerned Operating System.

The server has returned the following error: invalid enumeration context

When I run First part it works fine, however, the Second option (which I want to use) does not work and is giving me an error:
Error getting objects: The server has returned the following error:
invalid enumeration context
I Tried following this article.
I tried result page size with different values but it does not work either. I checked the second Cmdlet with Measure-Command and it is taking 17 minutes to fetch AD objects and time out time is mentioned in the ADWS server is 30 minutes.
Could you please help me to understand what is wrong? We do not want to user the first option; we want to import all account irrespective date and time.
I want to remove date filter which I am using in the first option and wanted to to get ad object in a script without mentioning days and should fetch all records old and the new one. Please help experts here :)
First
$from = ((Get-Date).AddDays(-100)).date
$to = ((Get-Date).AddDays(0)).date
$A = #(Get-ADUser -Filter { whenCreated -ge $from -and whenCreated -le $to } -Properties * -Server $DomainController)
Second
$A = #(Get-ADUser -Filter '*' -Properties * -Server $DomainController)

Setting a DateTime to $null/empty using PowerShell and the SCSM cmdlets

I'm currently trying to sync additional attributes from the AD (Active Directory) for user objects in SCSM (System Center Service Manager) using a PowerShell script.
The extension I wrote for this, includes an attribute for the expiration date of a AD user account (DateTime value, named DateTimeAttribute in the example) if the user account doesn't expire it should be empty/null.
Using Import-SCSMInstance, which should be similar to a CSV import, it kind of works by passing "null" for the field. The problem is that Import-SCSMInstance seems to be quite unreliable and it doesn't offer any kind of information of why it works or doesn't work. Using Update-SCSMClassInstance seems to work a lot better but I can't figure out a way to clear the field using this and even using [DateTime]::MinValue will result in an error, stating that it's an invalid value.
So would anyone have an idea on how to clear the value using Update-SCSMClassInstance or figure out why Import-SCSMInstance might or might not work?
A simple example for this could look like the following:
$server = "<ServerName>"
$extensionGuid = "<GUID>"
Import-Module 'C:\Program Files\System Center 2012 R2\Service Manager\Powershell\System.Center.Service.Manager.psd1'
New-SCManagementGroupConnection -ComputerName $server
$extensionClass = Get-SCSMClass -Id $extensionGuid
$scsmUserObject = Get-SCSMClassInstance -Class $extensionClass -Filter 'UserName -eq "<User>"'
# Error
$scsmUserObject.DateTimeAttribute = ""
# Works but fails on Update-SCSMClassInstance
$scsmUserObject.DateTimeAttribute = $null
$scsmUserObject.DateTimeAttribute = [DateTime]::MinValue
# Works
$scsmUserObject.DateTimeAttribute = "01-01-1970"
Update-SCSMClassInstance -Instance $scsmUserObject
It seems that you can't clear a date once it's filled. When you write $null, it sets the date to 1-1-0001 01:00:00, which is an invalid date causing the update-scsmclassinstance to fail.
What we have set as a user's AD property when we don't want something to expire, is 2999-12-31 (yyyy-MM-dd). Perhaps this could help, although it's not directly what you asked for...
Also, you can use the pipeline to update a property in SCSM:
Get-SCSMClassInstance -Class $extensionClass -Filter 'UserName -eq "<User>"' | % {$_.DateTimeAttribute = <date>; $_} | update-scsmclassinstance
It doesn't look like it's currently possible to clear custom date attributes using the PowerShell cmdlets.

POWERSHELL - The member's SID could not be resolved

Hello im working with Active Directory Group and Users and i wanna check and set proper Users/Groups from AD to machines. Problem is when i iterate over Local Users/Groups on some machine and there is old Users/Group that no longer exists in AD POWERSHELL will stop working and will throw exception.
An error (1332) occurred while enumerating the group membership. The member's SID could not be resolved.
I know what causes this problem but i dont know how to work around it. The main issue here is that its not even possible to iterate over whole array of users if one is no longer valid. Only solution to this is manualy delete those invalid users.
I even saw some reports to Microsoft that this behaviour is wrong and should be fixed but nothing was done about it.
Anyone here encountered this issue?
Thank you for your help.
$ctype = [System.DirectoryServices.AccountManagement.ContextType]::Machine
$computer = "PC name"
$groupName = "Administrators"
$context = New-Object -TypeName System.DirectoryServices.AccountManagement.PrincipalContext -ArgumentList $ctype, $computer
$idtype = [System.DirectoryServices.AccountManagement.IdentityType]::SamAccountName
$groupData = [System.DirectoryServices.AccountManagement.GroupPrincipal]::FindByIdentity($context, $idtype, $groupName)
$groupData.Members | select #{N='Server'; E={$computer}}, #{N='Domain'; E={$_.Context.Name}},#{N='Group'; E={$groupName}} , #{N='Account Name/Group'; E={$_.SamAccountName}}
Here is example of code that im using for iterating over Local users/groups on some PC.
Can You post the code that you are using, and the full error. Im guessing there is a workaround, but without seeing your code I can't see what could be wrong. If a terminating error is thrown it will stop the script or function from running further (with some gotchas, and exceptions), there are many ways of working around this
Also could you post the full error.
You will probably need to set the $erroractionpreference to silentlycontinue. And then review the $error variable to check the errors, but again I am only speculating.

returning and referencing remote powershell variable results

I'm very new to powershell so looking some assistance. I am trying to run remote powershell script to check health of or VDI enviroment using Citrix Commandlets. (I am implementing the script on Microsoft orchestrator .Net Activity). So I have the following code:
#2012 VDI Desktop check
$vdims = "MyCitrixPowershellSDKServer"
function vdidesktopcheck
{
asnp Citrix*
$result = Get-BrokerDesktop -InMaintenanceMode $True -DesktopGroupName Unidesk
$result
}
$output = invoke-command -computer $vdims -scriptblock ${function:vdidesktopcheck}
$machinename = $output.machinename
$machinename
$state = $output.RegistrationState
$state
So when I use orchestrator to expose the variables $machinename, $state - I get the 'last' result from the involked Get-BrokerDesktop query. However Get-Brokerdesktop query may have multiple machines returned so I am hoping to be able to reference each of the machines that match the query output. Thats the basic requirement - what I am hoping to be able to do is further refine the basic Get-BrokerDesktop query to be able to count the number on machines output to say > 3 (ie more than 3 machines in MaintMode is unacceptable) and also check that the MachineName property is not equal to a particular value, ie the 3 test machine names in the environment which may be expected to be in MaintenanceMode.
Hope this makes sense, if not I'll try and elaborate. Any help much appreciated!!
One of the limitations of Orchestrator is that you can only pass strings across the data bus, and you need to pass an array of objects. You need to serialize the object array to a string. One way to do that is to convert the array to json, then use convertfrom-json when you get it back to get an object array to work with.
Don't have a SCORCH server handy to test with, so this isn't tested at all.
$vdims = "MyCitrixPowershellSDKServer"
function vdidesktopcheck
{
asnp Citrix*
$result = Get-BrokerDesktop -InMaintenanceMode $True -DesktopGroupName Unidesk
$result
}
$output = invoke-command -computer $vdims -scriptblock ${function:vdidesktopcheck} |
select machinename,RegistrationState | ConvertTo-Json
$Output