Tag Archives: Troubleshooting

Find user session on all active servers

If you want to find a session on all active servers in the domain you can make use of the command quser /server:whatever. This displays the session details from that server. This is handy if some administrator has locked his account because of old sessions on some server. There’re alternative ways to find this. I made a post awhile back. See it here.

IPMO ActiveDirectory

$Username = "SAMACCOUNTNAME"
$List2 = @()

$List = Get-ADComputer -Properties passwordlastset,operatingsystem -Filter * | ?{$_.PasswordLastSet -gt (Get-Date).Adddays(-30) -and $_.OperatingSystem -match "Server"}

Foreach ($item in $list){
	[String]$Server = $item.Name
	$Result =@( (quser /server:$Server) -replace '\s{2,}',','|ConvertFrom-Csv)
		Foreach ($object in $result){
			If ($Object.UserName -Match $Username){$Output = ($Server + ";" + $Object.UserName + ";" + $Object.State)
			$List2 += $Output
		}
	}
} 

Filtering and Arraying 101 Powershell

So I try to teach my colleagues a bit more about Powershell from time to time. I have advised them a bit about how they can filter values to meet their requirements. Our architect wanted an export of all user accounts. When I simply exported all AD users in the domain he said that the amount of users is way too large. He asked me how this happend and where all those users are coming from? I wanted to give him an export of all enabled users in ActiveDirectory per OU. Actually I just wanted to show him the amount of users per OU. So I made a little script that does that job. However this is an excellent opportunity for someone to start working with Powershell. So I’ve written a little 101 about how they should start.

Step 1

Import the module ActiveDirectory.

IPMO ActiveDirectory

Step 2

You want to know in what OU a user is situated. Maybe the CMDlet Get-ADUser returns this value. By running the command Get-ADUser SAMACCOUNTNAME -Properties * you’ll get all the available properties. To display the methods and functions you can also use this command, in correspondence with the CMDlet Get-Member (Alias GM). You’ll have to run:

Get-ADUser SAMACCOUNTNAME -Properties * | GM

This prints all available methods,functions,properties and so forth. If you see a property, that is name something like, parent or OU you’ll be lucky. Unfortunately in Powershell 1,2 and 3 there isn’t such a property. So you have to find other ways to get the parent OU.

Step 3

Many CMDlets can be used against the registry, file systems, certificate stores or the Active Directory. In this case you’ll still have to know the containing OU. So probably the best way is to use the CanonicalName which contains this information. However that would kill all the fun. In this example DistinguishedName will have to do it. This obviously displays the containing OU. To save the DistinguishedName in a string run:

$Result = (Get-ADUser SAMACCOUNTNAME).DistinguishedName

Step 4

The DistinguishedName contains the CN of a user. You want to filter that out of the string. But how do you do that? Again use GM to see if you can convert the value to it’s parent or the get what is possible with the value.  To do so run the command:

$Result | GM

You can replace the CN as text. This can be really really tricky. To do so run the command in step 3 without the .DistinguishedName property behind it. Next run the command:

$Result.DistinguishedName.Replace(("CN="+$Result.Name+","),'')

There is no right or wrong if the result is the same and it meets your goals. That is an important lesson to learn.

Step 5

To select an item use the CMDlet Get-Item (Alias GI). This CMDlet will let you select any file, folder or object in the registry,file system, certificate store or AD. Actually you can use it against any mounted PSdrive. We still want to know the containing OU. So in this case we will look up the DistinguishedName in the AD. Again use GM to find out what is possible with the output. To do so run:

GI "AD:\$Result" | GM

Step 6

As you can see the property PSParentPath exists. Maybe this displays the required output? Run the command:

(GI AD:\$Result).PSParentPath

Step 7

That output is not how you want it to be. The type is displayed. To be as clean as possible you will have to replace that part of the line. You can use the Replace method like this:

(GI AD:\$Result).PSParentPath.Replace("Microsoft.ActiveDirectory.Management\ActiveDirectory:://RootDSE/",'')

Step 8

To come back to the objective, we’ll have to export all enabled users. There are two ways to accomplish this.

$List = Get-ADUser -Filter * | ? {$_.Enabled -eq $True}

Or

$List = Get-ADUser -Filter {Enabled -eq $True}

Which one is better? The correct answer would be none. The result is what counts. The best thing is running the command that you can remember or that works best for you. In terms of performance the second command would be better. Try this:

(Measure-Command -Expression {$list = Get-ADUser -Filter * | ?{$_.Enabled -eq $True}}).TotalSeconds

(Measure-Command -Expression {$list = Get-ADUser -Filter {Enabled -eq $true}}).TotalSeconds

Step 9

Next you can form a “script” to collect all DistinguishedNames and replace the unwanted text. To do so run:

Foreach ($item in $List){$Result = (GI AD:\$item).PSParentPath.Replace("Microsoft.ActiveDirectory.Management\ActiveDirectory:://RootDSE/",'')
AC -Value $Result -Path ".\Output.csv"}

Step 10

We have a list called Output.csv. The only thing we have to do now is to count the number of occurrences. This is not necessary the best way to do it. You can save this output in an array if you like.  Below there are examples of many different ways to solve this problem. Below is an example of the last bit of a script.

$List2 = GC ".\Output.csv"
$Uniquelist = $list2 | Sort -Unique
Foreach ($UniqueItem in $Uniquelist){
[int]$Count = 0
Foreach ($Item in $list2){If ($Item -eq $UniqueItem){$Count++}}
$Outinfo = "$UniqueItem" + ";" + "$Count"
AC -Value $outinfo -Path ".\Counted OUs.csv"
}

There are lots of ways to get to your destination. I have generated a number of scripts to do this task.

Script 1

IPMO ActiveDirectory
$list = Get-ADUser -Filter * | ? {$_.Enabled -eq $True}
Foreach ($item in $List){$Result = (GI AD:\$item).psparentPath.Replace("Microsoft.ActiveDirectory.Management\ActiveDirectory:://RootDSE/",'')
AC -Value $Result -Path ".\Output.csv"}
$List2 = GC ".\Output.csv"
$Uniquelist = $list2 | Sort -Unique
Foreach ($UniqueItem in $Uniquelist){
[int]$Count = 0
Foreach ($Item in $list2){If ($Item -eq $UniqueItem){$Count++}}
$Outinfo = "$UniqueItem" + ";" + "$Count"
AC -Value $outinfo -Path ".\Counted OUs.csv"
}

This script generated two output files. A part of statics values is replaced.

Script 2

IPMO ActiveDirectory
$list = Get-ADUser -Filter * | ? {$_.Enabled -eq $True}
Foreach ($item in $list){$Result = $item.distinguishedName.Replace(("CN="+$item.Name+","),'')
AC -Value $Result -Path ".\Output.csv"}
$List2 = GC ".\Output.csv"
$Uniquelist = $list2 | Sort -Unique
Foreach ($UniqueItem in $Uniquelist){
[int]$Count = 0
Foreach ($Item in $list2){If ($Item -eq $UniqueItem){$Count++}}
$Outinfo = "$UniqueItem" + ";" + "$Count"
AC -Value $outinfo -Path ".\Counted OUs.csv"
}

This script contains a replace of dynamic content. You have to be very careful using such a replace. We have CN’s with a value like Berg, Steven van den. That comma is precisely the problem. To display a comma in the DistinguishedName a break is inserted. So the actual value is CN=Berg\, Steven van den,. Based on the specified condition this does not apply. Meaning that you will have inconsistent results. In script 3 this is corrected.

Script 3

IPMO ActiveDirectory
$list = Get-ADUser -Filter {Enabled -eq $True}
$List2 = @()
Foreach ($item in $list){$Result = $item.distinguishedName.Replace('\','').Replace(("CN="+$item.Name+","),'')
$List2 += $Result}
$Uniquelist = $list2 | Sort -Unique
Foreach ($UniqueItem in $Uniquelist){
[int]$Count = 0
Foreach ($Item in $list2){If ($Item -eq $UniqueItem){$Count++}}
$Outinfo = "$UniqueItem" + ";" + "$Count"
AC -Value $outinfo -Path ".\Counted OUs.csv"
}

Here the conditions are met. I have also included an empty array at the line 3. Next all values are added to that array. So only the correct file is exported. Be aware that is you do a double ” after the replace of the special character you’ll need a double backslash. In this case something like .Replace(“\\”,””). The backslash means a break stating a special character.

Even though this script delivers the correct output, I would still advise you to refrain from replacing dynamic content unless you are really sure that every condition is met and that you not filter out too much.

Script 4

IPMO ActiveDirectory
$list = (Get-ADUser -Filter {Enabled -eq $True}).DistinguishedName | %{(GI "AD:\$_").PSParentPath.Replace("Microsoft.ActiveDirectory.Management\ActiveDirectory:://RootDSE/",'')}
$Uniquelist = $list | Sort -Unique
Foreach ($UniqueItem in $Uniquelist){
[int]$Count = 0
Foreach ($Item in $list2){If ($Item -eq $UniqueItem){$Count++}}
$Outinfo = "$UniqueItem" + ";" + "$Count"
AC -Value $outinfo -Path ".\Counted OUs.csv"
}

Script 1 uses the CMDlet Get-Item (Alias GI) to collect the parent OU. In script 1 this is done in separate commands. You can combine this in one line let the example above. I have done this by using the CMDlet Foreach-Object (Alias %).

Script 5

IPMO ActiveDirectory
$list = (Get-ADUser -Filter {Enabled -eq $True}).DistinguishedName | %{(GI "AD:\$_").PSParentPath.Replace("Microsoft.ActiveDirectory.Management\ActiveDirectory:://RootDSE/",'')}
Foreach ($UniqueItem in ($List | Sort -Unique)){
[int]$Count = 0
Foreach ($Item in $list){If ($Item -eq $UniqueItem){$Count++}}
$Outinfo = "$UniqueItem" + ";" + "$Count"
AC -Value $outinfo -Path ".\Counted OUs.csv"
}

Unlike script 4 in shorted the script even further by not generation a separate unique item list.

Script 6

IPMO ActiveDirectory
$list = (Get-ADUser -Filter {Enabled -eq $True}).DistinguishedName | %{(GI "AD:\$_").PSParentPath.Replace("Microsoft.ActiveDirectory.Management\ActiveDirectory:://RootDSE/",'')}
Foreach ($UniqueItem in ($List | Sort -Unique)){
[int]$Count = 0
Foreach ($Item in $list){If ($Item -eq $UniqueItem){$Count++}}
AC -Value ("$UniqueItem" + ";" + "$Count") -Path ".\Counted OUs.csv"
}

The output string is combined in one line.

Script 7

IPMO ActiveDirectory
Get-ADUser -Filter {Enabled -eq $True} | % {($_).distinguishedName.Replace('\','').Replace(("CN="+$_.Name+","),'')} | Group | Select Name,Count | epcsv ".\Counted OUs.csv" -Delimiter ";" -NoTypeInformation

This example is even prettier. Nearly a oneliner. To count we use the Group-Object (Alias Group) te count the number of occurrences. Next we Select the fields we want. Followed by exporting the data by Export-CSV (Alias epcsv). This can be done with that other command aswel.

Script 8

IPMO ActiveDirectory
(Get-ADUser -Filter {Enabled -eq $True}).DistinguishedName | %{(GI "AD:\$_").PSParentPath.Replace("Microsoft.ActiveDirectory.Management\ActiveDirectory:://RootDSE/",'')} | Group | Select Name,Count | epcsv ".\Counted OUs.csv" -Delimiter ";" -NoTypeInformation

In this case you have few ways to select the data. Like these:

IPMO ActiveDirectory
Get-ADUser -Filter {Enabled -eq $True} | %{(GI AD:\$_).PSParentPath.Replace("Microsoft.ActiveDirectory.Management\ActiveDirectory:://RootDSE/",'')} | Group | Select Name,Count | epcsv ".\Counted OUs.csv" -Delimiter ";" -NoTypeInformation

Or

IPMO ActiveDirectory
Get-ADUser -Filter {Enabled -eq $True} | %{(GI AD:\$_).PSParentPath.Replace("Microsoft.ActiveDirectory.Management\ActiveDirectory:://RootDSE/",'')} | Group |  % { AC -Value ("$($_.Name)" + ";" + "$($_.Count)") -Path ".\Counted OUs.csv"}

Or

IPMO ActiveDirectory
Get-ADUser -Filter {Enabled -eq $True} | %{(GI AD:\$_).PSParentPath.Replace("Microsoft.ActiveDirectory.Management\ActiveDirectory:://RootDSE/",'')} | Group  | % { AC -Value ($($_.Name) + ";" +  ($($_).Group.Count)) -Path ".\Counted OUs.csv"}

Except one, these scripts all generate the same output. Know that there are many more ways to get the same output. Again the best method is the one you can remember and you feel comfortable using. If you like oneliners you’ll prefer script 8. If you like to have an overview of what is happening you’ll prefer script 1. Based on your skills in scripting/Powershell you’ll choose anything in between.

You could also have selected CanonicalName. This would have been a lot easier as it doesn’t contain any breaking (\). Another advantage would be that you can sort alphabetically. Since DistinguishedName is formed from the deepest to the highest level is it only possible to sort based on the last OU. Normally you would want to have this export correspond with the hierarchy of Active Directory. This is only possible with CanonicalName. CanonicalName is built up from highest in the hierarchy to the lowest container.

Reference table

Alias CMDlet
IPMO  Import-Module
 GM  Get-Member
 GI  Get-Item
 ?  Where-Object
AC  Add-Content
 GC  Get-Content
 Sort Sort-Object
 % Foreach-Object
 Group  Group-Object
 Select  Select-Object
epcsv  Export-CSV

I hope you’ve had fun!

Find old share names in files on Apps share

A client was talking about how he couldn’t quit sharing a certain share in his Citrix environment. There were to many connections still to that share. So I suggested that I could help him by making a script that looks for certain values in .ini, .log, .cmd, .bat, .cfg, .config etc files. You can adjust this to your own preference.

I did a check of the drive mapping G:\. Please note that a lot of log files contain Logging: which matches G:. That is why I did a match on G:\. In Powershell the ‘\’ character  is an expression followed by a special character which in this case will be \. That is why you need a double slash.

$Locatie = "\\ShareName" 
$Exportfile = ".\Exportfile.csv"
$List = gci $Locatie -Recurse | Where {$_.Extension -match ".ini" -or $_.Extension -match ".cfg" -or $_.Extension -match ".config" -or $_.Extension -match ".inc" -or $_.Extension -match ".bat" -or $_.Extension -match ".cmd" -or $_.Extension -match ".log" -or $_.Extension -match ".txt"}
Foreach ($item in $list){$Content = Get-Content $item.fullname
$Pad = $item.fullname
If ($Content -match "G:\\"){Add-Content -Value  "Er is een verwijzing naar G:\ gevonden in: $Pad" -Path $Exportfile}
If ($Content -match "G:/"){Add-Content -Value  "Er is een verwijzing naar G:/ gevonden in: $Pad" -Path $Exportfile}
If ($Content -match "ServerName1"){Add-Content -Value  "Er is een verwijzing naar ServerName1 gevonden in: $Pad" -Path $Exportfile}
If ($Content -match "ServerName2"){Add-Content -Value  "Er is een verwijzing naar ServerName2 gevonden in: $Pad" -Path $Exportfile}
If ($Content -match "ServerName3"){Add-Content -Value  "Er is een verwijzing naar ServerName3 gevonden in: $Pad" -Path $Exportfile}
If ($Content -match "ServerName4"){Add-Content -Value  "Er is een verwijzing naar ServerName4 gevonden in: $Pad" -Path $Exportfile}
If ($Content -match "ServerName5"){Add-Content -Value  "Er is een verwijzing naar ServerName5 gevonden in: $Pad" -Path $Exportfile}
If ($Content -match "ServerName6"){Add-Content -Value  "Er is een verwijzing naar ServerName6 gevonden in: $Pad" -Path $Exportfile}}

App-v 5 and Citrix Provisioning

An administrator here came to me and asked me about how to Powershell around a problem with the App-V 5.0 Client Cache directory. The implementation configured is that App-V uses a folder on the D disk. This disk is dedicated. It is not on the distributed Vdisk. When the server reboots the cache becomes corrupted and the App-V service does not start. A sync is necessary in order to start the App-V 5.0 service. I made a script that clears a few reg values, deletes the App-v Client Connection Groups, App-V Client Packages, the AppV folder in Programdata and the entire folder on the D disk.

I handed over the script to the administrator and asked him to create a scheduled task that run at system startup. The reason for  running the script this way, is that creating a GPO that run a Powershell script will not statisfy the required security context. The SYSTEM account doesn’t have enought permissions to complete the script. PSRemoting will not work either. When running the script on another server with the Invoke-Command -Scriptblock {} fails. This is probably due to a bug in App-V. The account has enough rights and UAC is disabled. Yet all attempts fail. Please review the script before implementing

 

<#Script Variables#>
$ServiceName = "AppVClient"
$ProgramDataAppV = "C:\ProgramData\Microsoft\AppV"
$AppVData = "D:\App-V 5.0"

<#Regvalues#>
$Regvalues=@()
$Regvalues +=@{Regvalue="HKLM:\SOFTWARE\Microsoft\AppV\Client\PackageGroups"}
$Regvalues +=@{Regvalue="HKLM:\SOFTWARE\Microsoft\AppV\Client\Packages"}
$Regvalues +=@{Regvalue="HKLM:\SOFTWARE\Microsoft\AppV\Client\Streaming\Packages"}

#Service stoppen om Program Data te verwijderen.
$State = Get-Service $ServiceName
If ($State.status -NotMatch "Stopped"){Stop-Service $ServiceName
Start-Sleep -s 5}
Remove-Item $ProgramDataAppV -force -recurse

#Verwijderen van de Registersleutels
Foreach ($item in $Regvalues){If ((Test-Path $item.Regvalue) -ne $True){Remove-item $item.regvalue -force -Recurse}}

#Service Starten om initiele synch uit te voeren zodat de D schijf wordt vrijgegeven.
$State = Get-Service $ServiceName
If ($State.status -Match "Stopped"){Start-Service $ServiceName
Start-Sleep -s 5}
Get-AppvPublishingServer | Sync-AppvPublishingServer

#Service Stoppen om Packages en AppvClientConnectionGroup te verwijderen.
$State = Get-Service $ServiceName
If ($State.status -NotMatch "Stopped"){
Write-Host Stoppen
Stop-Service $ServiceName
Start-Sleep -s 5}
Get-AppvClientConnectionGroup -all | Remove-AppvClientConnectionGroup
Get-AppvClientPackage -all | Remove-AppvClientPackage
Start-Sleep -s 10

#Service stoppen om App-v folder op de D schijf te verwijderen.
If ($State.status -NotMatch "Stopped"){Stop-Service $ServiceName
Start-Sleep -s 5}
Remove-Item $AppVData -Force -Recurse
Start-Sleep -s 10

#Check of de folder ook daadwerkelijk verwijderd is.
If ((Test-Path $AppVData) -eq $True){

#Proberen de D schijf leeg te krijgen door eerst te synchen
Get-AppvPublishingServer | Sync-AppvPublishingServer
Start-Sleep -s 5
$State = Get-Service $ServiceName
If ($State.status -NotMatch "Stopped"){Stop-Service $ServiceName
Start-Sleep -s 5}
Get-AppvClientConnectionGroup -all | Remove-AppvClientConnectionGroup
Get-AppvClientPackage -all | Remove-AppvClientPackage
Start-Sleep -s 10
Remove-Item $AppVData -Force -Recurse

#Laatste check op de D schijf om te kijken of de folder nu daadwerkelijk weg is.
If ((Test-Path $AppVData) -eq $True){
$Outinfo = "De App-V Data op de D Schijf is na twee pogingen niet succesvol verwijderd. Bekijk het logboek."
Add-Content -Value $Outinfo -Path "C:\ScriptFout.txt"
$Outinfo = Get-Date
Add-Content -Value $Outinfo -Path "C:\ScriptFout.txt"
}}

#Laatste Sync uitvoeren
Get-AppvPublishingServer | Sync-AppvPublishingServer

Remove old definitions

Symantec Endpoint Protection has a tendency to preserve definitions that are no longer needed. I’ve written a powershell script in three variations.

First is a powershell script that deletes any folders in the Virusdef above the count of 3. So if there are 4 folders with definitions it will delete the oldest.

$Servers =@( Import-CSV ".\Server.csv")
Foreach ($Server in $Servers){$Folders =@( gci "\\$Server\C$\Program Files\Common Files\Symantec Shared\VirusDefs" | Where {$_.PsIsContainer -and $_.Name -notmatch "Binhub" -and $_.Name -notmatch "Texthub"} | Sort CreationTime -Descending | Select -Skip 3})
ForEach ($Folder in $Folders){Remove-Item $Folder -Force -Recurse}

Second is a powershell script that deletes any folder in de Virusdef folder older than 2 days ago. Of course only definition folders not the other two folders.

$Datum = (Get-Date).AddDays(-2)
$Servers = @(Import-CSV ".\Server.csv")
Foreach ($Server in $Servers){gci -Path "\\$Server\C$\Program Files\Common Files\Symantec Shared\VirusDefs" | Where-Object { $_.PSIsContainer -and $_.CreationTime -lt $Datum -and $_.Name -notmatch "Binhub" -and $_.Name -notmatch "Texthub" } | Remove-Item -Force}

The last script is a combination of the above. It will any folder older than two days ago skipping the first. If a server hasn’t updated its definition it will not delete the active  definition.

$Datum = (Get-Date).AddDays(-2)
$Servers = @(Import-CSV ".\Server.csv")
Foreach ($Server in $Servers){gci -Path "\\$Server\C$\Program Files\Common Files\Symantec Shared\VirusDefs" -Recurse -Force | Where-Object { $_.PSIsContainer -and $_.CreationTime -lt $Datum } | Sort CreationTime -Descending | Select -Skip 1| Remove-Item -Force}

All Script require a script.csv file with servers. Just a header with Server. Neighter do you need any delimiters. Just a list with servers

You can replace import-csv with get-content as needed.

Replace text in local TNSNames.ora with Powershell

An administrator came to me today. Recently they had migrated from Oracle 10 to Oracle 11 and from HP UX to ODA (Oracle Database Appliance). Due to the fact that in this organization there are over 2000 databases, some applications wheren’t tested. In some cases application server look at the wrong TNSNames.ora. The request was to replace the text after host for the approriate host. I had the ‘luck’ that this request only included servers.

I created a that resolve his problem. The script contacts the ActiveDirectory for the list of “servers”. Then the script test if that server has an Oracle directory under C:\. Change this if you have Oracle installed under a different folder. Next there’s a check under the Oracle Directory for any folder that match Ora. These folders are included in an array. The next thing that will be checked is, if the TNSNames.ora exists in the usual folder. If that is the case the script continues. If it doesn’t exist the script will continue with the next folder or server.

Then the content of the TNSNames.ora will be loaded into the memory. The script renames the original TNSNames.ora to TNSNames.old. Or if that file is already in use in some other extension. Then all lines in the TNSNames will be check on the existance of few specific words and those words will be replaced with something else. At last the array NewTNSNames will be written to the location.

 

Import-Module ActiveDirectory
$ADComputers = Get-ADComputer -Filter * -Properties * | Where {$_.OperatingSystem -match "Server"}
$Computers =@()
ForEach ($ADComputer in $ADComputers){$ADComputer = $ADComputer.DNSHostName
If((Test-Path "\\$ADComputer\C$\Oracle") -eq $True){$Computers += $ADComputer}}
ForEach ($Computer in $Computers){$Folders =@( gci "\\$Computer\c$\Oracle\Ora*")
ForEach ($Folder in $Folders){If ((Test-Path "$Folder\Network\Admin\TNSNames.ora") -eq $True){$TNSNames = get-content "$Folder\Network\Admin\TNSNames.ora"
If ((Test-Path "$Folder\Network\Admin\TNSNames.old") -eq $False){Rename-item -Path "$Folder\Network\Admin\TNSNames.ora" -NewName "$Folder\Network\Admin\TNSNames.old"}
If ((Test-Path "$Folder\Network\Admin\TNSNames.NaChangeAugustus2014") -eq $False){Rename-item -Path "$Folder\Network\Admin\TNSNames.ora" -NewName "$Folder\Network\Admin\TNSNames.NaChangeAugustus2014"}
$NewTNSNames =@()
ForEach ($Item in $TNSNames){
If ($Item -match "odatst101a"){$NewTNSNames += $Item.replace("odatst101a","RobIsDeBarbecueKoning.local")}
If ($Item -match "odatst101b"){$NewTNSNames += $Item.replace("odatst101b","RobIsDeBarbecueKeizer.local")}
If ($Item -notmatch "odatst101a" -and $Item -notmatch "odatst101b"){$NewTNSNames +=  $Item}}
ForEach ($Item in $NewTNSNames){Add-Content -Value $Item -Path "$Folder\Network\Admin\TNSNames.ora" }}}}

Account locked Out Randomly

A user was reporting that at random his AD Account was locked. He ensured me that he did not type his password wrong. After the first six reset I did not believe him. The user was an Administrator so I asked him if by any chance he installed any service under his name. He did change his password some time ago. We decided to revert to his old password. However the problem still occurred. I looked further into the problem. First searching why his account was locked out. On the first domain controller I ran a command:

Get-EventLog -LogName Security | ?{$_.entrytype -eq "FailureAudit" -and $_.message -match "SAMACCOUNTNAMEOFUSER"}

Change the SAMACCOUNTNAMEOFUSER to the sAMAccountname of the user. Add | FL for a larger output of the error.

This retured a set of four result. Three where at the exact same time one was some time after. The message was Kerberos Authentication Failed. The last time was the time that the user came to me saying his account was locked out again.

At the client address was an IP-address specified. It seemed that the Admin had an inactive session on that server or an scheduled task of some sort. Maybe even a service under his account.

I could not enter a pssession to that specific server. So I used a good old DOS Command:

query user /server:IPOFTHATSERVER

It retured the following output:

OutputQueryUser

This  session was logged on far before he changed his password. Maybe this account tried to log on to the domain with an old ticked which caused the DC to lock his account. Maybe he had an open file which occasionally tried to save with old credentials. It did however solve the problem

Get Inherited Permission

Script reads DFS Location from host. Script reads ADuser from host. Script checks whether DFS location and User specified are correct. Then checks how the user have access to the folder and what NTFS rights the user has.

PS1:

#Load Active Directory modules
Import-Module ActiveDirectory 
Clear-host
$Locatie = Read-Host "Voer de DFS Locatie in in UNC Format bijvoorbeeld:\gemeentenet.localdfsdeelnemerfolder"
While ((Test-Path $Locatie) -ne $true){
write-host "De opgegeven locatie bestaat niet. Voor opnieuw in" -b Black -f Red
$Locatie = Read-Host "Voer de DFS Locatie in in UNC Format bijvoorbeeld:\gemeentenet.localdfsdeelnemerfolder"
While ((Test-Path $Locatie) -ne $true){
	[System.Windows.Forms.MessageBox]::Show("ERROR: $locatie bestaat niet. Het script is beeindigd!")
	write-host De $locatie bestaat niet. Voer het script opnieuw uit! -F Red
	If (!($psISE)){"Press any key to continue...";[void][System.Console]::ReadKey($true)}}}
$User = Read-Host "Voer de User in in sAMaccountname Format bijvoorbeeld:othsbe02"
$testresult = get-aduser $User
If ($testresult -eq $null){
write-host "De opgegeven User bestaat niet. Voor opnieuw in" -b Black -f Red
$User = Read-Host "Voer de User in in sAMaccountname Format bijvoorbeeld:othsbe02"
$testresult = get-aduser $User
if ($testresult -eq $null){
	[System.Windows.Forms.MessageBox]::Show("ERROR: $User bestaat niet. Het script is beëindigd!")
	write-host De $User bestaat niet. Voer het script opnieuw uit! -F Red
	If (!($psISE)){"Press any key to continue...";[void][System.Console]::ReadKey($true)}}}
$Folders = @()
$Folders = get-item $locatie  | where {$_.psiscontainer -eq $true}
$outfile = ".temp.csv"
$Header = "Folder Path;IdentityReference;AccessControlType;IsInherited;InheritanceFlags;PropagationFlags;Filesystemrights"
Add-Content -Value $Header -Path $OutFile 
foreach ($Folder in $Folders){
	$ACLs = get-acl $Folder.fullname | ForEach-Object { $_.Access  }
	Foreach ($ACL in $ACLs){
	$OutInfo = $Folder.Fullname + ";" + $ACL.IdentityReference  + ";" + $ACL.AccessControlType + ";" + $ACL.IsInherited + ";" + $ACL.InheritanceFlags + ";" + $ACL.PropagationFlags + ";" + $ACL.FileSystemRights
	Add-Content -Value $OutInfo -Path $OutFile	
	}}

	$CSVImport = import-csv $outfile -delimiter ";"	
	$list1 = @()
	foreach ($item in $CSVImport){
	$identity = $item.Identityreference.replace("GEMEENTENET","")
	if ($item -match "BUILTIN" -and $item -match "Users"){$identity = $item.Identityreference
	$temp1 = Get-ADGroupmember -identity "Domain Users" -recursive |ForEach-Object {$_.sAMaccountname}}

	if ($item -notmatch "Builtin" -and $item -notmatch "NT AUTHORITY" -and $item -notmatch "CREATOR"){
	$temp1 = Get-ADGroupmember $identity -recursive |ForEach-Object {$_.sAMaccountname} }

	if ($item -match "BUILTINAdministrators"){$identity = $item.Identityreference.replace("BUILTIN","")
	$temp1 = Get-ADGroupmember $identity -recursive |ForEach-Object {$_.sAMaccountname} }
	foreach ($line in $temp1){$list1 += $line + ";" + $identity + ";" + $item.FileSystemRights}
	$result = $list1 |? {$user -contains $_}}

$print = $list1 -match $user
$print | sort -unique
remove-item $outfile

ZIP:

 

Snapmanager for Virtual Infrastructure probleem bij het maken van Quiesced Snapshot

In sommige situaties is het niet mogelijk om een back-up te maken met SMVI van virtuele machines. Er komen dan meldingen zoals:

Failed with the following error:Cannot create a quiesced snapshot because the create snapshot operation exceeded the time limit for holding off I/O in the frozen virtual machine

Of

ERROR - VM :"naam" Will not be backed up since VMware snapshot create operation failed

Dit probleem heeft te maken met de VSS service van de VMware Tools. Quiesced Snapshot hebben VMware tools nodig. Het probleem is op te lossen door de VMware tools te deïnstalleren. Hierna te herstarten en daarna de VMware tools te installeren. De VMware tools moeten dan wel geïnstalleerd worden zonder de VSS service.

Dit is verder besproken in VMware KB 1018194

Exchange HUB servers

Wanneer er een e-mail wordt verzonden in een Microsoft Exchange 2010 organisatie gaat het transport proces als volgt:

Exchange kijkt binnen de Active Directory Site waar het mailtje wordt gesubmit naar een beschikbare HUB Transport server om de e-mail te versturen. De HUB Transport servers accepteren de e-mail als de services draaien. Er wordt niet gekeken naar de mogelijkheid om het mailtje daadwerkelijk te versturen. Als de HUB Transport server een Send connector heeft is dat voldoende. Stel er is geen Send connector toegewezen met als address space * dan kan de HUB server het mailtje niet kwijt. Er is makkelijk in de Exchange console te kijken naar de wachtrij binnen Exchange.

Get-TransportServer | Get-Queue

Er wordt dan een lijst uitgedraaid met de queue’s van alle server binnen de Exchange organisatie. Er is dus ook makkelijk te zien welke server mogelijk een probleem heeft de mail te versturen.

Andere nuttige commando’s zijn:

Overzicht uitdraaien van users op een mailbox server
Get-MailboxDatabase "Mailbox Database Naam" | Get-Mailbox