I need to modify the script below, so I can get the list of AD server and then check for any SSL certificate that is in the server for its validity.
Note: The server may or not may run IIS, which is why I am not sure how to do it properly.
$ComputerName = Get-ADComputer -Filter {Enabled -eq $True} -SearchBase "OU=Servers,OU=Production,DC=Domain,DC=com"
[CmdletBinding()]
param(
[parameter(Mandatory, ValueFromPipeline)][string[]]$ComputerName,
[int]$TCPPort = 443,
[int]$Timeoutms = 3000
)
process {
foreach ($computer in $computerName) {
$port = $TCPPort
write-verbose "$computer`: Connecting on port $port"
[Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
$req = [Net.HttpWebRequest]::Create("https://$computer`:$port/")
$req.Timeout = $Timeoutms
try {$req.GetResponse() | Out-Null} catch {write-error "Couldn't connect to $computer on port $port"; continue}
if (!($req.ServicePoint.Certificate)) {write-error "No Certificate returned on $computer"; continue}
$certinfo = $req.ServicePoint.Certificate
$returnobj = [ordered]#{
ComputerName = $computer;
Port = $port;
Subject = $certinfo.Subject;
Thumbprint = $certinfo.GetCertHashString();
Issuer = $certinfo.Issuer;
SerialNumber = $certinfo.GetSerialNumberString();
Issued = [DateTime]$certinfo.GetEffectiveDateString();
Expires = [DateTime]$certinfo.GetExpirationDateString();
}
new-object PSCustomObject -Property $returnobj
}
}
I'm not sure if you've forgotten to put the function instantiation on top or not, but the following should be the correct format for an advanced function in PowerShell. You can also give the parameter $ComputerName a default value with the Get-ADComputer cmdlet. Try this out to see if this works.
function Get-ADComputerCert {
[CmdletBinding()]
param(
[int]$TCPPort = 443,
[int]$Timeoutms = 3000
)
process {
$ComputerName = (Get-ADComputer -Filter {Enabled -eq $True} -SearchBase "OU=Servers,OU=Production,DC=Domain,DC=com").Name
foreach ($computer in $computerName) {
$port = $TCPPort
write-verbose "$computer`: Connecting on port $port"
[Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
$req = [Net.HttpWebRequest]::Create("https://$computer`:$port/")
$req.Timeout = $Timeoutms
try {$req.GetResponse() | Out-Null} catch {write-error "Couldn't connect to $computer on port $port"; continue}
if (!($req.ServicePoint.Certificate)) {write-error "No Certificate returned on $computer"; continue}
$certinfo = $req.ServicePoint.Certificate
$returnobj = [ordered]#{
ComputerName = $computer;
Port = $port;
Subject = $certinfo.Subject;
Thumbprint = $certinfo.GetCertHashString();
Issuer = $certinfo.Issuer;
SerialNumber = $certinfo.GetSerialNumberString();
Issued = [DateTime]$certinfo.GetEffectiveDateString();
Expires = [DateTime]$certinfo.GetExpirationDateString();
}
new-object PSCustomObject -Property $returnobj
}
}
}
Related
I am trying to obtain the difference in time between each start and stop action in the following output:
User Computer Time Event Action
---- -------- ---- ----- ------
TEST\me TEST-DC-01 27/05/2020 14:45:06 Logoff Stop
TEST\me TEST-DC-01 27/05/2020 14:44:56 Unlock Start
TEST\me TEST-DC-01 27/05/2020 14:44:49 Lock Stop
TEST\me TEST-DC-01 27/05/2020 14:44:40 Reconnect Start
TEST\me TEST-DC-01 27/05/2020 14:43:17 Disconnect Stop
TEST\me TEST-DC-01 27/05/2020 14:43:07 Logon Start
I've been playing with the New-Timespan cmdlet but seem to be going round and round in circles when trying to integrate it with the script (below) which the above output is derived from.
Ideally, I'd like to see the following appended to it:
Total active time: 00:00:29
Can anyone advise on the best approach (either by fully integrating with the existing script or by importing the output in CSV format).
Any guidance most appreciated.
#
# GROUP POLICY (TO ENABLE 480x AND 477x EVENTS):
#
# COMPUTER CONFIGURATION
# - WINDOWS SETTINGS
# - SECURITY SETTINGS
# - ADVANCED AUDIT POLICY CONFIGURATION
# - SYSTEM AUDIT POLICIES - LOCAL GROUP POLICY OBJECT
# - LOGON/LOGOFF
# - AUDIT OTHER LOGON/LOGOFF EVENTS
# - SUCCESS
#
$OU = "OU=Domain Controllers,DC=test,DC=local"
# WHERE TO SEARCH FOR COMPUTERS IN ACTIVE DIRECTORY
$days = "-1"
# HOW MANY DAYS TO SEARCH BACK THROUGH
$directory = "C:\"
# LOCATION OF FAILED CONNECTIONS FILE
$computers = Get-ADComputer -Filter * -SearchBase $OU
$logs = #()
$timestamp = ((Get-Date).ToString("yyyyMMdd_HHmmss"))
$output = ForEach ($computer in $computers){
try{
$logs += get-eventlog `
-LogName system `
-ComputerName $computer.Name `
-After (Get-Date).AddDays($days)
$logs += get-eventlog `
-LogName security `
-ComputerName $computer.Name `
-After (Get-Date).AddDays($days)
$res = #()
ForEach ($log in $logs){
if($log.instanceid -eq 7001){
$type = "Logon"
$user =
try{
(New-Object System.Security.Principal.SecurityIdentifier(
$log.ReplacementStrings[1])).Translate(
[System.Security.Principal.NTAccount]).value
}
catch{
$log.ReplacementStrings[1]
}
$action = "Start"
}
Elseif ($log.instanceid -eq 7002){
$type = "Logoff"
$user =
try{
(New-Object System.Security.Principal.SecurityIdentifier(
$log.ReplacementStrings[1])).Translate(
[System.Security.Principal.NTAccount]).value
}
catch{
$log.ReplacementStrings[1]
}
$action = "Stop"
}
Elseif ($log.instanceid -eq 4800){
$type = "Lock"
$user = $log.ReplacementStrings[2] + "\" +
$log.ReplacementStrings[1]
$action = "Stop"
}
Elseif ($log.instanceid -eq 4801){
$type = "Unlock"
$user = $log.ReplacementStrings[2] + "\" +
$log.ReplacementStrings[1]
$action = "Start"
}
Elseif ($log.instanceid -eq 4778){
$type = "Reconnect"
$user = $log.ReplacementStrings[1] + "\" +
$log.ReplacementStrings[0]
$action = "Start"
}
Elseif ($log.instanceid -eq 4779){
$type = "Disconnect"
$user = $log.ReplacementStrings[1] + "\" +
$log.ReplacementStrings[0]
$action = "Stop"
}
Else {
Continue
}
$hash = [ordered]#{
"User" = $user
"Computer" = $computer.Name
"Time" = $log.TimeWritten
"Event" = $type
"Action" = $action
}
$res += New-Object PSObject -Property $hash
}
$res
}
Catch {
Add-Content -Path "${directory}${timestamp}_failed.txt" $computer.Name
}
}
$TimeDescending = #{
Expression = 'Time'
Descending = $true
}
$EventDescending = #{
Expression = 'Event'
Descending = $true
}
$output |
sort User,Computer,$TimeDescending,$EventDescending |
? User -like "*me" |
ft
You could use the New-TimeSpan cmdlet:
$start = Get-Date
# Do some stuff here
$end = Get-Date
$timeTaken = (New-TimeSpan -Start $start -End $end).TotalSeconds
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 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
}
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