In the following script, it will print all the users of the groups. However, the domain name is missing (Some users are in different Windows domain)?
$computer = [ADSI]"WinNT://$server,computer"
$computer.psbase.children | ? {
$_.psbase.schemaClassName -eq 'group'
} | % {
$gn = $_.name.ToString()
write-host $gn
write-host "------"
$group =[ADSI]$_.psbase.Path
$group.psbase.Invoke("Members") | % {
$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)
}
}
Try fetching the SID instead of the name and translate that back to a username:
$computer.psbase.children | ? {
$_.psbase.schemaClassName -eq 'group'
} | % {
$gn = $_.name.ToString()
write-host $gn
write-host "------"
$group =[ADSI]$_.psbase.Path
$group.psbase.Invoke("Members") | % {
$bytes = $_.GetType().InvokeMember('objectSid', 'GetProperty', $null, $_, $null)
$sid = New-Object Security.Principal.SecurityIdentifier ($bytes, 0)
$sid.Translate([Security.Principal.NTAccount])
}
}
The result should include the computer or domain name.
We have a similar issue where there are accounts from different domains on the computers and we need the domain back. Unfortunately the SID fetch doesn't work I think for local accounts and the domains the computer used to be joined to in some cases, so it didn't return all results.
This was the best solution I found for us:
Admin = $_.GetType().InvokeMember("AdsPath", 'GetProperty', $null, $_, $null)
will return results like
WinNT://#domain#/#account#
or WinNT://#domain of computer#/#computer-name#/#account#
for local accounts
$servers= get-content 'C:\temp\work\localadmins\serverlist_in.txt'
$output = 'C:\temp\work\localadmins\serverlist_out.csv'
$results = #()
foreach($server in $servers)
{
$admins = #()
$group =[ADSI]"WinNT://$server/Administrators"
$members = #($group.psbase.Invoke("Members"))
$members | foreach {
$obj = new-object psobject -Property #{
Server = $Server
Admin = $_.GetType().InvokeMember("AdsPath", 'GetProperty', $null, $_, $null)
}
$admins += $obj
}
$results += $admins
}
$results | Export-csv $Output -NoTypeInformation
Related
I'm using this code in 2012 server but unable to run in windows 2008, i'm new to powershell script which tried to search online but unable to find an answer.
The error come from -property, which i tried -properties and pipe before -property also can't.
$OS = Get-WmiObject Win32_OperatingSystem | Select-Object Caption,Version,ServicePackMajorVersion,OSArchitecture,CSName,WindowsDirectory
$HostName = [System.Net.Dns]::GetHostName()
$TargetPath = Get-Location
$ExportPath = $TargetPath.Path + "\" + $HostName + "_" + $OS.Caption + ".csv"
$UserAccount = Get-WmiObject -Class Win32_UserAccount -Filter "LocalAccount='True'"
$NetworkLoginProfile = Get-WmiObject -Class Win32_NetworkLoginProfile
$GroupUser = Get-WmiObject -Class Win32_GroupUser
if (Test-Path $ExportPath)
{
Remove-Item $ExportPath
}
Foreach($Account in $UserAccount){
$Description = $Account.Description
$Description = $Description.replace("`r`n","_")
$Description = $Description.TrimEnd()
$Profile = #{
HostName = $HostName
Domain = $Account.Domain
LocalAccount = $Account.LocalAccount
SID = $Account.SID
Name = $Account.Name
Caption = $Account.Caption
Status = $Account.Status
Disabled = $Account.Disabled
Lockout = $Account.Lockout
FullName = $Account.FullName
Description = $Description
AccountType = $Account.AccountType
PasswordRequired = $Account.PasswordRequired
PasswordExpires = $Account.PasswordExpires
PasswordChangeable = $Account.PasswordChangeable
NumberOfLogons = ""
LastLogon = ""
UserComment = ""
UserId = ""
UserType = ""
Workstations = ""
BadPasswordCount = ""
GroupMemberShip = ""
}
Foreach ($NetworkProfile in $NetworkLoginProfile)
{
If ($Account.Caption -eq $NetworkProfile.Name)
{
$Profile.NumberOfLogons = $NetworkProfile.NumberOfLogons
$Profile.LastLogon = $NetworkProfile.LastLogon
$Profile.UserComment = $NetworkProfile.UserComment
$Profile.UserID = $NetworkProfile.UserId
$Profile.UserType = $NetworkProfile.UserType
$Profile.Workstations = $NetworkProfile.Workstations
$Profile.BadPasswordCount = $NetworkProfile.BadPasswordCount
}
}
$Groups = New-Object System.Collections.ArrayList
Foreach ($User in $GroupUser)
{
$PartComponent = $User.PartComponent
$Index1 = $PartComponent.indexOf("Name=")
$MemberName = $PartComponent.substring($Index1)
$MemberName = $MemberName.substring(6)
$MemberName = $MemberName.subString(0, $MemberName.indexOf("`""))
$Index2 = $PartComponent.indexOf("Domain=")
$MemberDomain = $PartComponent.subString($Index2)
$MemberDomain = $MemberDomain.substring(8)
$MemberDomain = $MemberDomain.substring(0, $MemberDomain.indexOf("`""))
if (($MemberDomain -eq $Account.Domain) -and ($MemberName -eq $Account.Name))
{
$GroupComponent = $User.GroupComponent
$Index3 = $GroupComponent.indexOf("Name=")
$MemberGroup = $GroupComponent.substring($Index3)
$MemberGroup = $MemberGroup.substring(6)
$MemberGroup = $MemberGroup.subString(0, $MemberGroup.indexOf("`""))
if($MemberGroup)
{
$Groups.Add($MemberGroup)
}
}
}
$count = 0
Foreach ($Group in $Groups)
{
$count++
if($count -lt $Groups.Count){
$Profile.GroupMemberShip += $Group + '|'
}
else{
$Profile.GroupMemberShip += $Group
}
}
$Csv = New-Object psobject -Property $Profile
$Csv | Select-Object -Property Hostname,Domain,LocalAccount,SID,Name,Caption,Status,Disabled,Lockout,FullName,Description,AccountType,PasswordRequired,PasswordExpires,PasswordChangeable,NumberOfLogons,LastLogon,UserComment,UserId,UserType,Workstations,BadPasswordCount,GroupMemberShip | Export-Csv $ExportPath -Append -Delimiter ',' -NoTypeInformation
}
Error I receive:
Since it's no longer supported, it's tough to find documentation this far back, but I found mention of New-Object -Property being used in Windows Powershell 2.0. In the comments under your question, you state that you are running Powershell 1.0. I am fairly confident that -Property did not exist on New-Object in v1.0, so you likely need to update your Windows Management Framework to get Powershell 2.0 or later.
Note that 2.0 is no longer supported so I would recommend going with a more recent verison of Windows Powershell, at least 4.0 if not 5.1. If you can, Powershell Core (v6) would give you the most modern Powershell experience, and will work with most Windows Powershell cmdlets on Windows systems if you install the WindowsCompatibility PowerShell module.
I'm using Windows 10 Enterprise 1709 and PowerShell ISE v5. I am trying to get the last write time to the file deployment.properties by checking to see if the testpath holds the file and if it does, write the LastWriteTime of that file. I'm not sure I'm doing this the correct way. Any help showing me how to make this work would be appreciated. I've tried several options but this is the only one that doesn't produce an error. However, the code runs, completes without error but doesn't produce and output. My code is listed below first and then the output I see on the PowerShell ISE screen.
Set-ExecutionPolicy Bypass
$env:COMPUTERNAME = HostName
$DeplPath = "AppData\LocalLow\Sun\Java\Deployment\deployment.properties"
$dateTime = foreach ($User in Get-ChildItem C:\Users -Directory) {
$folderFile = Join-Path $javauser.FullName $DeplPath
if (Test-Path $folderFile) {
$testResult = Get-ChildItem | select -Property fullName, LastWriteTime
} Else {
$testResult = "Not found - deployment.properties"
}
}
$dateTime
Below is the output I get which returns no information.
PS C:\WINDOWS\system32> Set-ExecutionPolicy Bypass
$env:COMPUTERNAME = HostName
$DeplPath = "AppData\LocalLow\Sun\Java\Deployment\deployment.properties"
$dateTime = foreach ($User in Get-ChildItem C:\Users -Directory) {
$filelist = Join-Path $User.FullName $file
if (Test-Path $filelist) {
$testResult = Get-ChildItem $dateTime | select -Property fullName, LastWriteTime
} Else {
$testResult = "Not found - deployment.properties"
}
}
$dateTime
PS C:\WINDOWS\system32>
Newly modified code below
Set-ExecutionPolicy Bypass
$env:COMPUTERNAME = HostName
$DeplPath = "AppData\LocalLow\Sun\Java\Deployment\deployment.properties"
$dateTime = foreach ($User in Get-ChildItem C:\Users -Directory) {
$folderFile = Join-Path $User.FullName $DeplPath
if (Test-Path $folderFile) {
$testResult = Get-ChildItem | select -Property fullName, $DeplPath.LastWriteTime
} Else {
$testResult = "Not found - deployment.properties"
}
[PSCustomObject]#{
"Computer Name" = $env:COMPUTERNAME
"Java User True/False" = $TestResult
"Users" = $user.Name
"Last Write Time" = $testResult.LastWriteTime
}
}
$dateTime
Try this out. Your property select for the get-childitem were mislabeled.
Set-ExecutionPolicy Bypass
$env:COMPUTERNAME = HostName
$DeplPath = "AppData\LocalLow\Sun\Java\Deployment\deployment.properties"
$dateTime = foreach ($User in Get-ChildItem C:\Users -Directory) {
$folderFile = Join-Path $User.FullName $DeplPath
$test = Test-Path $folderFile
if ($test -eq $True) {
$testResult = Get-ChildItem $folderfile | select -Property Name, LastWriteTime
} Else {
$testResult = "Not found - deployment.properties"
}
[PSCustomObject]#{
"Computer Name" = $env:COMPUTERNAME
"Java User True/False" = $TestResult
"Users" = $user.Name
"Last Write Time" = $testResult.LastWriteTime
}
}
$dateTime
I made a PowerShell script to create Active Directory users from a CSV file. For one specific user I get this error
As you can see, the user has been successfully created though. All other users have been made as well. Does anyone know what this error means?
Script:
Import-Module ActiveDirectory
$csv_file = Read-Host -Prompt "Path naar CSV bestand?"
$pwd = Read-Host -Prompt "Password for users?" -AsSecureString
$csv_file = $csv_file.Replace('"','')
$csv_list = Import-Csv $csv_file
$domainname = Get-ADDomain
$domainname = $domainname.DNSRoot
$server = hostname
$usernames = (get-aduser -Filter *).name
$i = 0
foreach ($adUser in $csv_list) {
$department = $adUser.Department
if ($adUser.GivenName) {
$givenname = $adUser.GivenName
}
else {
$givenname = $adUser.FirstName
}
if ($adUser.Surname) {
$surname = $adUser.Surname
}
else {
$surname = $adUser.LastName
}
$username = ("${givenname}.${surname}" -replace (' ','')).ToLower()
if ($username -in $usernames -eq $true) {
$number = 1
}
$variableusername = $username
while ($variableusername -in $usernames -eq $true) {
$number += 1
$variableusername = [string]($username + $number)
}
$username = $variableusername
$usernames += $username
$sam = $username
if ($sam.Length -gt 20) {
$sam = $sam.Substring(0,20)
}
$path = (Get-ADOrganizationalUnit -Filter * | Where-Object -Property Name -eq $department).DistinguishedName | Select-Object -First 1
if ($path -eq $False) {
$department = Read-Host -Prompt "Could not find an OU for user $username in department ${department}. Please specify the correct OU"
$path = (Get-ADOrganizationalUnit -Filter * | Where-Object -Property Name -eq $department).DistinguishedName | Select-Object -First 1
}
$password = $pwd
$email = "${username}#${domainname}"
$title = $adUser.Title
$dpn = "${givenname} ${surname}"
New-ADUser -name $username -path $path -UserPrincipalName "${username}#${domainname}" -GivenName $givenname -Surname $surname -Department $department -AccountPassword $password -EmailAddress $email -ChangePasswordAtLogon $False -Title $title -Enabled $True -Server $server -DisplayName $dpn -SamAccountName $sam
Add-ADGroupMember -Identity "G_${department}" -Members $sam
$i++
Write-Progress -activity "Creating users . . ." -status "Created: $i of $($csv_list.Count)" -percentComplete (($i / $csv_list.Count) * 100)
}
I have a list of users in a CSV File that I want to find out if/when they last logged in. I can get this info for an individual account but I need to write this to a file for several accounts.
The error I'm getting:
At line:5 char:7
import-module activedirectory
Missing = operator after key in hash literal
hash literal was incomplete
My Code:
$resultList = #()
Import-Csv C:\Users\admin\Desktop\SamAccountName.csv -header("SamAccountName") | Foreach-Object{
$user = ([adsisearcher]"(samAccountName=$($_.SamAccountName))").FindOne()
$resultList += New-Object -TypeName PSObject -Property #{
SamAccountName = $_.SamAccountName
Import-Module ActiveDirectory
function Get-ADUserLastLogon([string]$_.userName)
{
$dcs = Get-ADDomainController -Filter {Name -like "*"}
$time = 0
foreach($dc in $dcs)
{
$hostname = $dc.HostName
$user = Get-ADUser $userName | Get-ADObject -Properties lastLogon
if($user.LastLogon -gt $time)
{
$time = $user.LastLogon
}
}
$dt = [DateTime]::FromFileTime($time)
Write-Host $username "last logged on at:" $dt }
Get-ADUserLastLogon -UserName $user
}
}
}
$resultList | export-csv -Path c:\users\admin\desktop\SamAccountName_results.csv -NoTypeInfo
Instead of this:
$user = ([adsisearcher]"(samAccountName=$($_.SamAccountName))").FindOne()
$resultList += New-Object -TypeName PSObject -Property #{
SamAccountName = $_.SamAccountName
Please do this:
$user = ([adsisearcher]"(samAccountName=$($_.SamAccountName))").FindOne()
$resultList += New-Object -TypeName PSObject -Property #{
SamAccountName = $_.SamAccountName
}
Is there a simple way using powershell to show all Local Windows Groups that are active on a machine and the users that are part of those groups? A second part of this question would be if it can be extended to look at more than one machine at a time.
In fact you can with the ADSI type shortcut and the WinNT moniker. Here's an example to list groups and members from your own machine:
$server="."
$computer = [ADSI]"WinNT://$server,computer"
$computer.psbase.children | where { $_.psbase.schemaClassName -eq 'group' } | foreach {
write-host $_.name
write-host "------"
$group =[ADSI]$_.psbase.Path
$group.psbase.Invoke("Members") | foreach {$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)}
write-host
}
Powershell does not have any inherent support for such a feature. However it's easy to wrap the "net localgroup" command with a couple of powershell functions and thus enable it in the pipeline.
Get Local Groups
function Get-LocalGroups() {
net localgroup | ?{ $_ -match "^\*.*" } | %{ $_.SubString(1) };
}
Get Local Group members
function Get-LocalGroupMembers() {
param ([string]$groupName = $(throw "Need a name") )
$lines = net localgroup $groupName
$found = $false
for ($i = 0; $i -lt $lines.Length; $i++ ) {
if ( $found ) {
if ( -not $lines[$i].StartsWith("The command completed")) {
$lines[$i]
}
} elseif ( $lines[$i] -match "^----" ) {
$found = $true;
}
}
}
Below is an improved version of Shay Levy's script which works for local groups with "orphaned" accounts which SIDs can't be resolved.
$server = "$env:COMPUTERNAME"
$computer = [ADSI]"WinNT://$server,computer"
$computer.psbase.children | where { $_.psbase.schemaClassName -eq 'group' } | foreach {
write-host $_.name
write-host "------"
$group =[ADSI]$_.psbase.Path
$group.psbase.Invoke("Members") | foreach {$_."GetType".Invoke().InvokeMember("Name", 'GetProperty', $null, $_, $null)}
write-host
}
Jay Levy's answer turned into a function :)
Function Get-LocalGroupMembers
{
Param(
[string]
$server = "."
)
Try
{
$computer = [ADSI]"WinNT://$( $Server ),computer"
$computer.psbase.children |
where {
$_.psbase.schemaClassName -eq 'group'
} |
ForEach {
$GroupName = $_.Name.ToString()
$group =[ADSI]$_.psbase.Path
$group.psbase.Invoke("Members") |
foreach {
$memberName = $_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null) -replace "WinNT:", ""
$props = #{
"LocalGroup" = $GroupName
"MemberName" = $memberName
}
$obj = New-Object -TypeName psobject -Property $props
Write-Output $obj
} # foreach members
} # foreach group
}
Catch
{
Throw
}
}
To get the local group members
Get-LocalGroupMembers
To get the local group members for another machine
Get-LocalGroupMembers -Server $Computer