PowerShell copy AD objectGUID to ms-ds-consistencyguid - windows

I am trying to resolve a PowerShell problem that has proved to be more complicated than I first thought. When trying to copy the objectGUID of each domain user into the same users ms-ds-consistencyguid the values do not match. Can anybody help?
I have tried this rough method below but the GUID's do not match:
$SGSADUser=get-aduser -filter {samaccountname -eq 'Test10_User'} -Properties objectguid,samaccountname,ms-ds-consistencyguid | Select Samaccountname,Objectguid,ms-ds-consistencyguid
[guid]$SGSADMSDSConsistencyguid = ($SGSADUser.objectguid).ToString()
$SGSADbase64 = [System.Convert]::ToBase64String($SGSADMSDSConsistencyguid.ToByteArray())
set-aduser -Identity 'Test10_User' -replace #{'ms-ds-consistencyguid' = $SGSADbase64}
ObjectGUID
ms-ds-ConsistencyGuid

I just ran through this and when you convert to base 64, the value changes.
Try
set-aduser -Identity 'Test10_User' -replace #{'ms-ds-consistencyguid' = $SGSADMSDSConsistencyguid}
This came out as the correct value when I checked.
Thanks, Tim.

Related

How to get the Get-ADGroup users list from LDAP (PowerShell cmdlet) in windows

How to get AD-group users list from LDAP using PowerShell without username and password.
Get-ADGroup -LDAPFilter (&(objectCategory=group)((cn=Testgrp"))))
I am trying this way but not fixing can anyone please help me out?
Right now I'm able to get the AD-Group info by using the below PowerShell scripts.
Get the group Info:
Get- ADGroupMember -Identify TEST_GRP_NM | select distinguishName | ft
Get-AdUser -filter{Name -like "GROUP_NM"} -Properties *
Get the user info:
Get-AdUser -Server "DOMAIN" -Identify "NTID" -Properties MemberOf
Note: Need to achieve the list of users from the LDAP group without using LDAP username and password
I personnally use this script to crawl through the AD (from another StackOverFlow question)
In case it becomes somehow a broken link:
# Your filter
$Filter = "(&(objectCategory=group)((cn=Testgrp))))"
# The path you want to scan
$RootOU = "OU=AnotherOU,OU=AnOU,DC=etc,DC=Something"
# The scope Base, One-level or Subtree
# The name is explicit enough
$Scope = "subtree"
# Instanciation and configuration of the directory searcher
$Searcher = New-Object System.DirectoryServices.DirectorySearcher
$Searcher.SearchRoot = New-Object System.DirectoryServices.DirectoryEntry("LDAP://$($RootOU)")
$Searcher.Filter = $Filter
$Searcher.SearchScope = $Scope
# Getting results from the AD
# A first pipe to get the member property returning a list of member
# A second pipe to display each member of the list in a line
$Searcher.FindAll() | Foreach-Object {$($_.Properties["member"])} | Foreach-Object {"$($_)`n"}
Hope it helps !

Disable Computers with Powershell

I have a list of 150 computers I would like to disable in active directory with powershell.
So I have a csv file with the computernames and the follwoing script:
Import-Module ActiveDirectory
$computers = import-csv "C:\temp\test.csv"
foreach ($computer in $computers)
{
$computer | disable-adaccount
$computer | move-adobject -targetpath "OU=Disabled computers, DC=domain, DC=com"
}
Following error occures:
Disable-ADAccount : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeli
ne input.
Can someone please help?
Cheers
Try a regular parameter instead of a pipe: disable-adaccount $computer
(If necessary repeat this for the other call)
Also have a look at this question at Technet: Powershell script to disable AD account based on CSV file
Create a txt file called disable.txt and put list of computers that u want to disable on C:\temp location
Run this script:
$Computer = Get-content c:\temp\disable.txt
Foreach ($Computer in $computers) {
Set-ADComputer -Identity $computer -Enabled $false
}
I know this is an old post but I believe it's a type mismatch of Disable-ADAccount expecting a property rather than the whole object for input.
Using the example I added .DistinguishedName to the item passed to Disable-ADAccount and it worked. The input csv would need to have DistinguishedName available to the command though.
{
Disable-ADAccount $StaleComputer.DistinguishedName
Move-ADObject $StaleComputer.DistinguishedName -TargetPath "OU=Disabled Computers, DC=domain, DC=com"
}

Powershell 'Optimize-Volume' Output

I have written a system maintenance script which executes basic functions that retrieve statistics from a host, writes the output to a new PSObject, then finally combines the results and converts it all to a HTML web page.
I do not seem to be able to write the output of Optimize-Volume to the pipeline, I have to use -verbose - why is this? I would like to check the results of the Optimize-Volume cmdlet by looking for the following text which is generated at the end of the -verbose output, depending on the result:-
'It is recommended that you defragment this volume.'
'You do not need to defragment this volume.'
Here is the function:-
function Get-DefragInfo {
$getwmi = Get-WmiObject -Class Win32_volume -Filter "DriveType = 3" | Where-Object {$_.DriveLetter -cne $null} -ErrorAction SilentlyContinue
$letter = $getwmi.DriveLetter -replace ':'
foreach ($drive in $getwmi)
{
$analysis = Optimize-Volume -DriveLetter $letter -Analyze
if ($analysis -like 'It is recommended that you defragment this volume.')
{
$props =[ordered]#{‘Drive Letter’=$letter
'Defrag Recommended?'='Yes'}
}
elseif ($analysis -like 'You do not need to defragment this volume.')
{
$props =#{‘Drive Letter’=$letter
'Defrag Recommended?'='No'}
}
$obj = New-Object -TypeName PSObject -Property $props
Write-Output $obj
}
}
How do I capture the output I need?
Thanks in advance.
In PowerShell 3.0 and onward, you can use the stream redirection operator > to capture the Verbose ouput to a variable:
# Merge stream 4 (Verbose) into standard Output stream
$analysis = &{Optimize-Volume -DriveLetter $letter -Analyze -Verbose} 4>&1
# Check the "Message" property of the very last VerboseRecord in the output
if($analysis[-1].Message -like "*It is recommended*")
{
# defrag
}
else
{
# don't defrag
}
If we Get-Help Optimize-Volume -full we'll see the cmdlet has no output.
Some searching lead me to this Microsoft Scripting Guys article that pointed out using the following to check if Defrag is needed.
(gwmi -Class win32_volume -Filter "DriveLetter = 'C:'").DefragAnalysis()
Knowing this, we can easily make an IF Statement.
$DefragCheck = (gwmi -Class win32_volume -Filter "DriveLetter = 'C:'").DefragAnalysis() |
Select DefragRecommended
IF($DefragCheck){"Defrag recommended"}ELSE{"Defrag is not needed."}
It's helpful to pipe cmdlets to Get-Member in order to see if there are any options available. In the above example, we can pipe gwmi -Class win32_volume -Filter "DriveLetter = 'C:'" to Get-Member and find the DefragAnalysis method, which we use dotted notation to access (wrap the Get-WmiObject in () then use a . and the method name followed by (), it looks confusing until you try it a couple times!)
Thanks, I went for the verbose redirection option and it seems to be working well. My method is not the cleanest way of doing it I understand, but it works for me.
I like the second option also, I'm going to look at using this once the script is complete and functionality is proofed.
Thanks for your help once again.

Powershell, How to get date of last Windows update install or at least checked for an update?

I am trying to find a way of retrieving the date/time of which the last windows update was either installed, or checked for.
So far I have found a function that allows to list recent Windows Updates, but it is far too much data and too bloated for such a simple function. Secondly I have tried to access the registry although I am having no luck in retriving the value I am after.
I am testing this on a Windows 10 Machine although the software will probably reside on Windows Server 2012 R2.
Here is an example of some of the code I have tried:
$key = “SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\Results\Install”
$keytype = [Microsoft.Win32.RegistryHive]::LocalMachine
$RemoteBase = [Microsoft.Win32.RegistryKey]::OpenBaseKey($keytype,"My Machine")
$regKey = $RemoteBase.OpenSubKey($key)
$KeyValue = $regkey.GetValue(”LastSuccessTime”)
$System = (Get-Date -Format "yyyy-MM-dd hh:mm:ss")
Also, just trying the Get-ChildItem
$hello = Get-ChildItem -Path “hkcu:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\”
foreach ($a in $hello) {
$a
}
I've checked in regedit and this key does not exist. Going to the "Windows Update" path shows only App Updates and not Windows updates.
EDIT
I seem to be closer to my goal with this line:
Get-HotFix | Where {$_.InstallDate -gt 30}
However how to I only retrive those of which have been installed in the last 30 days? And this doesnt show many results, even using Select $_.InstallDate
an option :
gwmi win32_quickfixengineering |sort installedon -desc
Another alternative, using the com object Microsoft.Update.Session can be find here : https://p0w3rsh3ll.wordpress.com/2012/10/25/getting-windows-updates-installation-history/
in short :
$Session = New-Object -ComObject Microsoft.Update.Session
$Searcher = $Session.CreateUpdateSearcher()
$HistoryCount = $Searcher.GetTotalHistoryCount()
# http://msdn.microsoft.com/en-us/library/windows/desktop/aa386532%28v=vs.85%29.aspx
$Searcher.QueryHistory(0,$HistoryCount) | ForEach-Object {$_}
Here you have how to know the date and time of the last Windows update in a single line of Powershell:
(New-Object -com "Microsoft.Update.AutoUpdate"). Results | fl
You also have the following script to check it massively in Windows Server:
$ servers = Get-ADComputer -Filter {(OperatingSystem-like "* windows * server *") -and (Enabled -eq "True")} -Properties OperatingSystem | Sort Name | select -Unique Name
foreach ($ server in $ servers) {
write-host $ server.Name
Invoke-Command -ComputerName $ server.Name -ScriptBlock {
(New-Object -com "Microsoft.Update.AutoUpdate"). Results}
}
Extracted from: https://www.sysadmit.com/2019/03/windows-update-ver-fecha-powershell.html
Get-HotFix |?{$_.InstalledOn -gt ((Get-Date).AddDays(-30))}
Using PowerShell, you can get the date of the las Windows update like this:
$lastWindowsUpdate = (Get-Hotfix | Sort-Object -Property InstalledOn -Descending | Select-Object -First 1).InstalledOn

Powershell - Running .ps1 doesn't work, but running it through the console itself does

Before I start, please note I am a beginner at Powershell, so some questions I ask may seem very obvious and stupid to the more experienced.
I have a problem with my script. If I copy paste it into Powershell itself, it works with no problems. However putting it in a .ps1 file, and making it execute with Powershell doesn't work. Can anyone tell me why, and what I can do to make it work using a .ps1? Here's the code:
$Group = import-csv -path C:\Output\Gruppe.csv
$DomainUsers = import-csv -path C:\Output\DomainUsers.csv
$ErrorActionPreference = "SilentlyContinue"
Get-ADGroupMember –identity Test –recursive | select "samaccountname" | Export-csv –path C:\Output\Gruppe.csv -NoTypeInformation
Get-ADUser –Filter * -SearchBase ”ou=Domain Users,dc=sfol,dc=local” | select "samaccountname" | Export-csv –path C:\Output\DomainUsers.csv –NoTypeInformation
Compare-Object $Group $DomainUsers -property samaccountname -IncludeEqual | where-object {$_.SideIndicator -eq "=="} | select "samaccountname" | Export-csv C:\Output\Difference.csv –NoTypeInformation
(Get-Content C:\Output\Difference.csv) | % {$_ -replace '"', ""} | out-file -FilePath C:\Output\Difference.csv -Force -Encoding ascii
$File = "C:\Output\Difference.csv"
$Time = Get-Date
ForEach ($User in (Get-Content $File))
{ Try {
Remove-ADGroupMember -Identity "Test" -Member $User -Confirm:$false -ErrorAction Stop
Add-Content c:\Output\Gruppelog.log -Value "$Time - $User slettet fra gruppen"
}
Catch {
Add-Content c:\Output\Gruppelog.log -Value "$Time - $User medlem kunne ikke blive slettet fra gruppen pga: $($Error[0])"
}
}
I also have another problem I noticed as I am writing this question. What this script does is to print out a userlist from an OU and a group. Then it compares the OU to the group using the two files it printed out, and prints out a new userlist containing only the users that exists in both the OU and the group. Then it uses the new userlist to remove users from the group (so that there is no users that exist in both the OU and group).
This script works well the first time I run it, but if I proceed with re-adding the users to the group, running the script again, sometimes it will only remove some of the users. If I do ctrl+c and CLS after running the script, it works fine. As mentioned, I am a beginner at this, so I'd just like to know why it doesn't work 100% the second time without ctrl+c or cls. Sorry if I am bad at explaining, and I don't expect you to help me with this since it's not a part of the question. But I'd appreciate it if you could.
Kind regards, Shadow
Problem was not having imported the module ActiveDirectory. I thought that when you imported the module once, it would stay for future use in Powershell. This isn't so, so what I did to fix the problem was adding Import-Module ActiveDirectory to the beginning of the code. I still haven't figured out my bonus question, so if anyone can help with that, it'd be great.

Resources