Windows Audit Policy/Registry Key Command Check To Only Apply On Domain Controllers - windows

I am trying to craft a command that would run against all of my Windows machines to check if the "Audit Distribution Group Management" audit policy setting is set to "Success and Failure". I would only like to apply this check to Domain Controller servers and for any other server type to echo out something like "NoCheckRequired", is this possible?
I tried to create an if-else statement on PowerShell for this, but it was not successful.

I tried to use the "wmic.exe ComputerSystem get DomainRole" command to find out the type of machine, values 4 / 5 mean DC server from my understanding, and using an IF statement, I tried to match those values and check if the group policy audit settings were set and for any other values returned other than 4 / 5
wmic.exe ComputerSystem get DomainRole outputs the property name on a separate line before outputting the actual value, so comparing to the number 4 (as an example) will not work.
Instead, use the Get-CimInstance cmdlet:
$CS = Get-CimInstance Win32_ComputerSystem
if($CS.DomainRole -in 4,5){
# We're on a Domain Controller
}
elseif($CS.DomainRole -in 1,3) {
# We're on a Domain member
}
else {
# We're on a workgroup machine
}

Get-ADComputer -Filter 'primarygroupid -eq "516"'
Will filter the Domain controller

Related

Trying to write a powershell script that shows all locked files with computer names instead of IP address

The task given was to create a way for our staff to see who has the file open that they want to use, as Windows says it is either locked and doesn't name the person who has it locked, or it displays the person who made the file but not the person who currently has it open.
I can look it up in Computer Management on the fileserver, but were are hoping to speed up this for the end users.
I've written this powershell script on our fileserver and it works perfectly, I have this running every 5 minutes in Task Scheduler with administrative permissions:
get-smbopenfile -ClientUserName * |select clientcomputername,clientusername,path | Out-File -Encoding utf8 "S:\LockedFiles.txt" -width 300
The output looks like this:
clientcomputername clientusername path
------------------ -------------- ----
IPADDRESS DOMAIN\USERNAME S:\FOLDER\FILE.FILEEXTENSION
What I really want to do now is get the computer name rather than the IP address, just in case staff are logged into multiple machines at the same time.
I wondered if ClusterNodeName or PSComputerName would provide this, but the returned data is always blank.
I thought about this and below is one option (the first line is pseudocode), but as I see it that would mean recursively altering the piped data or reading in piped data, which I'm not even sure how to do.
$ipaddress = IPADDRESS
$Workstation = [System.Net.Dns]::GetHostByName($ipaddress)
Write-Host $Workstation.HostName
Anyone have any ideas on how I can do this? Is there a better way?
I assume you're looking to add a new property to your output object that has the resolved DNS Name from the IP Address found in the ClientComputerName property. For this you use Resolve-DnsName to attempt the name resolution and a Try Catch in case it fails to capture the exception message. For the export I would recommend you to use Export-Csv.
Get-SmbOpenFile -ClientUserName * | ForEach-Object {
$dnsName = try {
(Resolve-DnsName $_.ClientComputerName -ErrorAction Stop).NameHost
}
catch {
[ComponentModel.Win32Exception]::new($_.Exception.NativeErrorCode).Message
}
[pscustomobject]#{
ClientIpAddress = $_.ClientComputerName
ResolvedHostName = $dnsName
ClientUserName = $_.ClientUserName
Path = $_.Path
}
} | Export-Csv "S:\LockedFiles.csv" -Encoding utf8 -NoTypeInformation

Adding values from multiple computers with custom headers in a single csv

I need to accomplish the scenario below and for that I have to create a couple of powershell scripts to accomplish it.
The environment: Windows servers and Windows clients
Scenario
1- Create a script to be run in a specific time every day (with Task Scheduler) on windows clients. This script will push the current computer's hostname and IP address to a csv file with a specific headers (let's call these "Hostnames" and "IP Address"). These header shouldn't be changed as these scripts run from multiple computers at that time and all computers' data should be appended to each header, not overwrite them as this operation continues.
2- From a server, (after 15 mins) as fetching this "computer" list (csv), there should be a ping check for each of them using their IP addresses. If pings are successful on these remote computers, it should say "This computer is up" next to the each computer name and its IP address. If pings are unsuccessful, it should say "This computer is down" next to the each computer name and its IP address. Above these "status" information, there should be another header (let's say "IsAlive"). This header should be added to the csv as well.
So with this setup, I could be able to learn which computers are UP at a specific time and after I trigger some actions them, I could be able to learn if they're still up or down.
To be honest, I couldn't take a long way for it. I started to write a script about the first step but I couldn't combine the headers with values adding under them.
$header="Hostname"
$outputfile="\\10.10.10.40\reports\upcomputers.csv"
Add-Content $outputfile -Value $header
$hostname >> $outputfile
If I use this script (even if with one header), it's adding "NULL" after each alphabet of hostname and it doesn't append the other hostname under the "Hostname" header.
Additionally, I have no idea where to start adding the third header (IsAlive) and add each Test-NetConnection query's output as checking their IP addresses. I request you to show me a way to start with this section as well.
Finally, my output should be like that;
For the first step;
For the second step;
Thank you for your help and information
Stated on the main body of the request
Stage 2:
The easy way of doing this using PSCustomobject. Please find the sample code below:
$outputcsv = "C:\PowerShell\pingstatus.csv"
$hostlist = import-csv "C:\PowerShell\hostlist.csv"
$result = foreach($line in $hostlist){
$pingtest = Test-Connection -ComputerName $line.Hostname -Quiet -Count 1 -ErrorAction SilentlyContinue
if($pingtest) {
$OutputMessage = "This computer is up"
}
else {
$OutputMessage = "This computer is down"
}
[pscustomobject][ordered]#{
HostName = $line.Hostname
IPAddress = $line.IPaddress
IsAlive = $OutputMessage
}
}
$result | Export-csv -Path $outputcsv -NoTypeInformation
The Hostname and IPAddress input will be taken as input.
Note: Your input csv file should contain Hostname IPaddress as header.
Stage1:
why not?
$outputfile="\\10.10.10.40\reports\upcomputers.csv"
$serverDetails = [PSCustomObject]#{
Hostname = "$env:COMPUTERNAME"
IPAddress = (Get-WmiObject -Class Win32_NetworkAdapterConfiguration | where {$_.DHCPEnabled -ne $null -and $_.DefaultIPGateway -ne $null}).IPAddress | Select-Object -First 1
}
$serverDetails | Export-csv $outputfile -Append -NoTypeInformation
There are multiple ways to get IP address a computer, I used Get-WMIObject. You may use other simple ways like Test-Connection or Get-NetIPAddress.
To learn more: Please see
[PsCustomObject]: https://learn.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-pscustomobject?view=powershell-7.3

How to format CCM_UserAffinity output to tyoe Microsoft.PowerShell.Commands.LocalPrincipal

I am trying to create a deployment script which adds freshly deployed workstation primary users to local admin group. I utilized CCM_userAffinity class to obtain username, however - Add-LocalGroupMember does not accept its output.
Ive tried creating task sequence variable to pass into powershell script which adds to group with no success either. Preferably the solution would be integrated within deployment TS, however due to no success i have reverted to ps package deployment.
$computer = "LocalHost"
$namespace = "root\ccm\Policy\Machine"
$query = "ConsoleUser"
$PrimaryUser = Get-WmiObject -class CCM_UserAffinity -computername $computer -namespace $namespace | select-object $query | format-wide
i expected the output from -class CCM_UserAffinity to be accepted by Add-LocalGroupMember, however i get this instead -
Add-LocalGroupMember : Cannot bind parameter 'Member'. Cannot convert the "Microsoft.PowerShell.Commands.Internal.Format.FormatStartData" value of type
"Microsoft.PowerShell.Commands.Internal.Format.FormatStartData" to type "Microsoft.PowerShell.Commands.LocalPrincipal".
As you plan on using the value you retrieve and not displaying it there is no need to use something like "format-wide" which only makes the output human readable and is the reason for your FormatStartData datatype.
You can just use :
$PrimaryUser = (Get-WmiObject -class CCM_UserAffinity -computername $computer -namespace $namespace).ConsoleUser
which returns a string and that is taken by the -Member argument of Add-LocalGroupMember
One thing to keep in mind is that in theory there can be more than one ConsoleUser per machine. So the ConsoleUser might be an Array or not. If you can guarantee that there is always only one user in your environment per machine (at the point where the ts runs) you can just use it as is. Otherwise you would have to specify which user you want to use and I can of course not tell you what a good rule for that for your environment would be.
Also I hope you checked that the WMI class CCM_UserAffinity is already populated at the stage where you want to run this script, I could not tell you if this is the case.

Add a user to a domain group and set the user privileges to certain folder

I have a user in my workplace domain, I want to add him to a specific domain group then assign him some privileges on a specific folder.
I wonder how this can be done using command line or a more automated process than doing it step by step as I do this quite often.
I'm using AD on Windows 10
Looks like dsmod group can be used but I don't know how.
If I have a user with username userh01 in domain mydom how I can add him automatically to group mydomgroup1?
I've tried this command:
dsmod group "mydomgroup1" -addmbr "userh01"
but I get this error
dsmod failed:Value for 'Target object for this command' has incorrect format.
Any advice?
Maybe using powershell to add memeber to a domain group is an alternative way.
here below th script for example
Add-ADGroupMember -Identity "Groupmane" -Memebers "Username to add"
Add-ADGroupMember -Identity "mymdomgroup1" -Memebers "userh01"
ps:you may need to import active diretory modul. before using Add-ADGroupMeber parameter use this command 'Import-Module ActiveDirectory' at begining
for different syntax and detailed description to add-adgroupmember parameter follow this link
https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/ee617210(v=technet.10)

List Last Windows Password Change For All Users On A Non-Domain System

I have found an answer to this question for systems that are attached to an AD domain controller. However, this question is for standalone systems where there is no possibility of attaching to a domain controller. Essentially, air-gapped systems.
Short and sweet: Is there a way to list the last time each user changed their Windows password for a non-domain, air-gapped system (either Windows 7 or 10) all at once either as a batch file or PowerShell script?
I know that net user {username} | find /I "Password last set" will do it for them one at a time. However, that would be tedious to run multiple times per machine and we have over 60 systems of this type. So I'm looking for a way to do this in one fell swoop, if possible.
As a caveat, we don't have the option of installing the activedirectory module in PowerShell for this. Also, since the majority of the systems are Windows 7, we don't have access to the Bash command line tools that would be available in Windows 10.
Any and all help with regard to this is appreciated.
Here's one way using the ADSI WinNT provider:
$computerName = [Net.Dns]::GetHostName() # i.e., local computer
$computer = [ADSI] "WinNT://$computerName,Computer"
$childObjects = $computer.Children
foreach ( $childObject in $childObjects ) {
if ( $childObject.Class -eq "User" ) {
if ( $childObject.PasswordAge[0] -gt 0 ) {
$pwdLastSet = (Get-Date).AddSeconds(-$childObject.PasswordAge[0])
}
else {
$pwdLastSet = $null
}
$childObject | Select-Object `
#{Name="AdsPath"; Expression={$_.AdsPath}},
#{Name="PasswordLastSet"; Expression={$pwdLastSet}}
}
}

Resources