Get the users who are having server access for my server - powershell

We need to extract a report every month for our servers which should report who all are having the server admin access .This will help us remove the people for whom access is no more needed. Its taking lot of time to extract manually and I read on blogs that PowerShell is used to automate such kind of administration jobs.
Other details:
Server - Win 2008 R2
Powershell 1.0
Could any one help me how to I extract this report?

Here's a quick way to enumerate the list of administrators for a server.
$group = [ADSI]"WinNT://./Administrators"
#($group.Invoke("Members")) | foreach {
$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)
}
You can then use an email cmdlet to send it or however you want to send it back to you.
See: http://blogs.technet.com/b/heyscriptingguy/archive/2013/10/27/the-admin-s-first-steps-local-group-membership.aspx

There's no need for ADSI and PSRemoting. Example:
$cComputerNames = #("computer1", "computer2")
$cRows = #()
foreach ($sComputerName in $cComputerNames) {
$cAdminAccounts = Get-WmiObject -ComputerName $sComputerName `
-Class "Win32_GroupUser" `
| Where-Object {
($_.GroupComponent -split '"')[3] -eq "Administrators"
}
foreach ($cAdminAccount in $cAdminAccounts) {
$oRow = New-Object -TypeName PSObject -Property #{
"ComputerName" = $sComputerName
"AccountDomain" = ($cAdminAccount.PartComponent -split '"')[1]
"AccountName" = ($cAdminAccount.PartComponent -split '"')[3]
}
$cRows += $oRow
}
}
$cRows | Export-Csv -Path "admin-accounts.csv" -NoTypeInformation
You can use an associators of ... query to get more detailed info about accounts. See this blog post.

Related

Change a Windows product key remotely with PowerShell

I'm trying to install/activate a MAK key on remote servers. All of them have RemotePS enabled and firewall exception rules in place.
$Results = Invoke-Command -ComputerName Server1 {
$Props = #{ComputerName = $env:ComputerName}
slmgr.vbs /ipk "12345-12345-12345-12345-12345"
$LicStatus = slmgr.vbs /dlv
$Props.Add('LicenseStatus',$LicStatus)
New-Object -TypeName PSObject -Property $Props
}
$Results | Select-Object ComputerName,LicenseStatus
The above does install the MAK key but I don't get any confirmation of this process which is why I've tried adding in the license check option (/dlv) but get nothing returned in the LicenseStatus field. I'm assuming this is because it returns a multi-value maybe!?
Ultimately I'm just trying to get confirmation that the key was installed. There are articles out there about performing this using RemotePS but they all say a notification message is returned for each computer which isn't the case in my experience: https://4sysops.com/archives/change-a-product-key-remotely-with-powershell/
Any ideas how I can check this?
I would call the slmgr.vbs script using Cscript.exe in order to get the results as string array. Otherwise the system will default to using Wscript.exe which is designed to output everything in a messagebox.
Unfortunately, all output of slmgr is localized, so using a regex or something on the LicenseStatus is a no go (on a Dutch NL machine it reads 'Licentiestatus')
What you can do is using switch /dli, because that returns a string array where the last (not empty) value has the status.
Try
$Results = Invoke-Command -ComputerName Server1 {
# install MAK key
$null = cscript.exe "$env:SystemRoot\System32\slmgr.vbs" /ipk "12345-12345-12345-12345-12345"
# test LicenseStatus
$LicStatus = (((cscript.exe "$env:SystemRoot\System32\slmgr.vbs" /dli) |
Where-Object { $_ -match '\S' })[-1] -split ':', 2)[1].Trim()
# return an object
[PsCustomObject]#{
ComputerName = $env:COMPUTERNAME
LicenseStatus = $LicStatus
}
}
$Results

Language independent way to find all the users with admin access to a computer via powershell

I have a powershell script that can find all users, domain and local, that have admin access to the current computer. The script works fine, until you change the language of the computer. I would like to know if there are other ways to go about this. Below is my current script
$strComputer = "."
$computer = [ADSI]("WinNT://" + $strComputer + ",computer")
$Group = $computer.psbase.children.find("Administrators")
$Props = $Group.psbase.invoke("Members") | %{$_.GetType().InvokeMember("Adspath", 'GetProperty', $null, $_, $null)}
If you doa Write-Host $Props you can get an output of all the users formatted as {DOMAIN}/{USERNAME}
Thanks in advance!
You can use the well-known SID of the group to find it. There is some discussion in a blog post here, but that uses VBScript and WMI (winmgmts:\\).
If you want to use WinNT:// like you already are, then this will search through the local groups for the group with the SID S-1-5-32-544, which corresponds to the Administrators group.
$strComputer = "."
$computer = [ADSI]("WinNT://" + $strComputer + ",computer")
$Group = $computer.Children |
Where {
(New-Object System.Security.Principal.SecurityIdentifier $_.objectSid.Value,0).ToString()
-eq "S-1-5-32-544"
} | Select -First 1
That New-Object bit is because the objectSid property is presented as a byte array, so you need to create a SecurityPrincipal object with it to be able to convert it to a string to do the comparison.

How to get server information from VMware

I have access to the VMWare GUI and I can easily export all the columns such as UPtime, IPAddress, Notes, DNS, GuestOs, State, Name and so on.
I want to right a script that can automatically get this information daily. So gar I was only able to get the server name, power state and VMhost. for some reason VMware is making it so hard to extract that information. I used the script below and I thought by adding the columns I mentioned above to this script, I should be able to retireve the data I need. But it doesn't work that way. Can someone please tell me how I can get this information?
Thanks,
Add-PSSnapin vmware.vimautomation.core
Connect-VIServer SERVERNAME
Get-VM|Select Name, VMHost, Id, PowerState
Exit 0
After digging into the system and many hours of research I found the solution. I just wish VMWare would make it easier to retrieve data or at least improve the manual.
The following code creates two files; one with the server information and another one with Uptime information.
Get-VM | select name,VMHost, #{ Name = "IP Addresses"; Expression = { $_.Guest.IPAddress }}, #{ Name = "PowerState"; Expression = { $_.Guest.State }} , #{ Name = "GuestOS"; Expression = { $_.Guest }}, Notes | Export-Csv -Path "HQstat.csv"
Get-Stat -Entity * -Stat sys.uptime.latest -Realtime -MaxSamples 1| Export-Csv -Path "HQtime.csv"
Why not use the views? They have all the information that you need. Code below assumes you are connected to the vCenter.
$vmView = Get-View -ViewType VirtualMachine -Property Name,Config,Guest,Runtime
$hostView = Get-View -ViewType HostSystem -Property Name
$date = Get-Date
Foreach ($vm in $vmView)
{
If ($vm.Runtime.BootTime -ne $null)
{
$dateDiff = $date.Subtract($vmView.Runtime.BootTime)
}
Else
{
$dateDiff = $null
}
foreach ($h in $hostView)
{
If ($vm.Runtime.Host -eq $h.MoRef)
{
$tempHost = $($h.Name)
Break
}
}
$global:Export += #([PSCustomObject]#{
VMName = $($vm.Name)
ID = $($vm.Config.Uuid) #or use $($vm.MoRef)
Host = $tempHost
PowerState = $($vm.Guest.GuestState)
IPAddress = $($vm.Guest.IPAddress)
Notes = $($vm.Config.Annotations)
UptimeMinutes = $($dateDiff.TotalMinutes)
})
$dateDiff = $null
$tempHost = $null
}
$exportFileName = "C:\temp\VMInformation.csv"
$Export | Export-Csv $exportFileName -Force -NoTypeInformation

Trouble executing powershell script on multiple remote machines

I need to generate a list of all users on our network who are members of their workstation's local administrators group. I found a script here https://gallery.technet.microsoft.com/scriptcenter/List-local-group-members-762b48c5#content which was written to list local group members by executing a WMI query through Powershell. I've tested this script and it works well, but I've been trying to modify it to take in a list of computers to check and that's where I've run into trouble. Here's what I've done:
function LocalAdmins
{
param([string]$GroupName = "Administrators")
begin
{
# Get all workstations listed in this text file
$WorkStations = Get-Content -Path C:\useful_lists\testLocal.txt
# Initialize an array to hold the results of the query
$arr = #()
# hash table for storing computer name, member pairings
$hash = #();
}
process
{
foreach ($machine in $WorkStations)
{
$wmi = Get-WmiObject -ComputerName $machine -Query `
"SELECT * FROM Win32_GroupUser WHERE GroupComponent=`"Win32_Group.Domain='$machine',Name='$GroupName'`""
# Parse out the username from each result and append it to the array
if ($wmi -ne $null)
{
foreach($item in $wmi)
{
$arr += ($item.PartComponent.Substring($item.PartComponent.IndexOf(',') + 1).Replace('Name=', '').Replace("`"", ''))
}
}
# Return a hash table comprised of two columns: Computer Name & Members
$hash += #{ComputerName=$machine;Members=$arr}
}
}
end
{
return $hash
}
}
When I ran the unmodified script here's what I got as output:
PS > (Get-LocalGroupMembers -ComputerName "<COMPUTER NAME>" -GroupName "Administrators").Members
ACCOUNTNAME
ACCOUNTNAME
ACCOUNTNAME
PS >
However, when I run the version of this script that I modified I get this:
PS > (LocalAdmins -GroupName "Administrators").Members
PS >
I'm fairly certain that the issue lies either in how I've setup the first foreach loop to run the wmi query or how the results of that query are being stored in the hash table. I'm not sure what I could do differently to fix the issue.
Thanks in advance to anyone who can help!
UPDATE
Per mortenya's suggestion, I edited my test text file to only include one computer in it. Doing so, along with taking out the foreach ($machine in $computers) loop worked as expected producing the following result:
>> LocalAdmins -GroupName "Administrators"
Name Value
---- ----
ComputerName {computerName.domain}
Members {account, account, account, account}
>>
However, going back and trying to get this to work when incorporating multiple machines using the code above (I've updated it since my initial post), I get the following:
>> LocalAdmins -GroupName "Administrators"
Name Value
---- -----
ComputerName computerName1.domain
Members {}
ComputerName computerName2.domain
Members {}
>>
Why is it that with one machine in the list I can get the members of the Administrator group, but adding a second computer to the list makes it so I can not retrieve members from that group on either machine?
So, if you're going to use Begin{}, Process{}, and End{}, use them for what they're meant for, in the Begin{} block, initialize all your arrays and constant varaibles.
Begin {
# Get all workstations listed in this text file
$WorkStations = Get-Content -Path C:\useful_lists\testLocal.txt
# Store the contents of that list in an array
$computers = #()
$hash = #()
}
Outside of that, I did this same thing a few months ago, it's a little messy, but it spit out a list of computers and who was in the Local Administrators group. It was partially to practice some different methods.
$output = 'c:\psresults\ListOfLocalAdministratorsGroup.txt'
$results = New-Object System.Collections.ArrayList
$objSID = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-32-544")
$objgroup = $objSID.Translate( [System.Security.Principal.NTAccount])
$objgroupname = ($objgroup.Value).Split("\")[1]
foreach($server in (Get-ADComputer -Filter *).name)
{
$admins = New-Object System.Collections.ArrayList
$group =[ADSI]"WinNT://$server/$objgroupname"
$members = #($group.psbase.Invoke("Members"))
$members | foreach {
$obj = new-object psobject -Property #{
Server = $Server
Admin = $_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)
}
#$obj
$admins.Add($obj)
}
$results.Add($admins)
}
$results | Out-File $Output
I found the meat of that somewhere and then modified it a bit.
EDIT: I just put this into ISE and it seems to work fine
$machine = "testsrv"
$groupname = "Administrators"
$wmi = Get-WmiObject -ComputerName $machine -Query `
"SELECT * FROM Win32_GroupUser WHERE GroupComponent=`"Win32_Group.Domain='$machine',Name='$GroupName'`""
if ($wmi -ne $null)
{
foreach ($item in $wmi)
{
$arr += ($item.PartComponent.Substring($item.PartComponent.IndexOf(',') + 1).Replace('Name=', '').Replace("`"", ''))
}
}
$hash = #{ComputerName=$machine;Members=$arr}
return $hash
Get it working on one machine, then start trying to add the loops back in.
EDIT 2.0:
I made a .txt file with only computer names in it, not the FQDN, that works fine for me. I can run it and get results using your script with minor modification.
Despite what I'd said about the Begin{} block, the $arr variable will need to be initialized inside the foreach ($machine in $WorkStations) loop. The reason for this is that when the loop runs, it will create the $arr array, add the data we want, insert that data into a global variable, and then clean up the $arr variable. If we make this global, it won't be cleaned up until the function is done, and we will just keep adding to it, which isn't what we actually want in this case.
The problem you're having with getting multiple machines to work is likely how you're building your results table.

How to verify whether a windows server has mountpoint or not using WMI

I am generating a report where I need to find which servers has mountpoints configured on it..
can you help how to get that infor using WMI or powershell.
I mean I need to identify the servers, if mountpoints exists in it.. and also their names....
Get a list of all servers from textfile, AD, etc. and run a foreach loop with something like this:
Get-Wmiobject -query “select name,driveletter,freespace from win32_volume where drivetype=3 AND driveletter=NULL” -computer servername
A quick google search for "windows mount point wmi" would return THIS (source).
Then export the results to CSV, HTML or whatever you need. Your question is lacking a lot of details and any sign of effort from your part, so I can't/won't go any further.
UPDATE: Does this help? It lists mount points(folder paths, not driveletters).
$servers = #("server1","server2","server3","server4","server5")
$servers | % {
$mountpoints = #(Get-WmiObject Win32_MountPoint -ComputerName $_ | Select-Object -ExpandProperty Directory | ? { $_ -match 'Win32_Directory.Name="(\w:\\\\.+)"' }) | % { [regex]::Match($_,'Win32_Directory.Name="(\w:\\\\.+)"').Groups[1].Value -replace '\\\\', '\' }
if($mountpoints.Count -gt 0) {
New-Object psobject -Property #{
Server = $_
MountPoints = $mountpoints
}
}
}
Server MountPoints
------ -----------
{server1} {D:\SSD, C:\Test}