Question

So here's the scope of what I'm trying to do:

Get remote computer information for Windows computers in multiple sites and write the information found to the .Description property of each computer object in Active Directory. If the script can't connect to the remote machine, log that information into a text file and don't make any changes to the computer object that can't be connected to.

In order to time how long the script is taking to run, I have a second script that measures the execution time.

I have this setup as a scheduled task to run the second script (which calls the first) that is executed via a batch file on a Windows 7 Pro virtual machine.

My problem is I believe the script may be running into memory problems based on the information I see in my log. Any help on possible diagnosing the root cause would be appreciated to the extreme. Without further adieu, here's my code for both scripts as well as a sample of the strange log output.

Main Script (script 1):

set-location \\myscriptcomputer\c$\somefolder\PSScripts

enter code here`function Measure-Latest {
    BEGIN { $latestlogon = $null }
    PROCESS {
            if (($_ -ne $null) -and (($latestlogon -eq $null) -or ($_ -gt $latestlogon))) {
                $latestlogon = $_ 
            }
    }
    END { $latestlogon }
}
Function CreateLog {

#Create a log file
    $global:path = "C:\Somefolder\PSScripts\WriteComputerDescriptions"
    $global:LogTime = Get-Date -Format "MM-dd-yyyy_hh-mm-ss"
    $global:LogName = 'CompDescriptions'
    $global:LogFile = 'C:\Somefolder\PSScripts\WriteComputerDescriptions\'+$LogName+$LogTime+'.txt'
    Write-Host "Creating log file" -foregroundcolor yellow
    if([IO.Directory]::Exists($global:path))
    {
        #Do Nothing
    }
    else
    {
        New-Item -ItemType directory -Path C:\Somefolder\PSScripts\WriteComputerDescriptions
    }

    cd C:\Somefolder\PSScripts\WriteComputerDescriptions
    echo "WriteComputerDescriptions Script Log" >> $global:logfile

}

Function WriteDescription {
    Write-Host "Gathering Computer information..." -foregroundcolor yellow
    $UserWorkstations = get-qadcomputer -sizelimit 0 -includeallproperties -searchroot my.domain.com/MyUserWorkstations

    $IPv4Regex = "^(\d{1,3}\.){3}\d{1,3}$"
    foreach ($computerobject in $UserWorkstations) {

    $computerIP = $NULL
    $computerIP2 = $NULL
    $computerIP3 = $NULL
    $computerserial = $NULL
    $computerserial2 = $NULL
    $findlastuser = $NULL
    $findlastuser2 = $NULL
    $lastlogontime = $NULL
    $findlastuserFname = $NULL
    $findlastuserFname2 = $NULL
    $findlastuserLname = $NULL
    $findlastuserLname2 = $NULL
    $fullname = $NULL
    $userlogon = $NULL

    $computerName = $computerobject.name
    $oldcomputerdescription = $computerobject.description
    Write-Host " "
    Write-Host "Testing connection to $computerName ..."

    $testConnection = test-connection -computername $computerName -count 2 -quiet
    Write-Host "Connection is $testconnection"


        if ($testConnection -eq $True) {
            $Connect = $testConnection

        #get IP address(es)
            try {
                $computerIP = get-wmiobject -class win32_networkadapterconfiguration -filter IPEnabled=TRUE -computername $computerName
                $computerIP2 = $computerIP.ipaddress[0]
                $computerIP3 = $computerIP.ipaddress[1]
                Write-Host = $computerIP2
                if ($computerIP3 -match $IPv4Regex){
                    Write-Host = $computerIP3
                    }
                }
             catch [system.exception]{
                $connect = $False
                Write-Host "Could not connect to $computerName. No IP collected."
                }
        #get computer serial
            try {
                $computerSerial = gwmi win32_bios -computername $computerName | select serialnumber
                $computerserial2 = $computerSerial.serialnumber.tostring()
                }
            catch [system.exception]{
                Write-Host "Could not get serial for $computerName."
                $computerSerial = "Unavailable"
                $computerSerial2 = "Unavailable"
                }
        #get username of currently logged in user
            try {
                $findlastUser = gwmi win32_computersystem -computer $computerName | select username
                $findlastuser2 = ($findlastUser.username).replace("mydomain\","")
                }
            catch [system.exception]{
                Write-Host "Could not get username of logged in user on $computerName"
                $findlastUser = "Unavailable"
                $findlastUser2 = "Unavailable"
                }

        #get last logon time of user
            try {
                if($findlastuser2 -ne $NULL -and $findlastuser2 -notlike "Unavailable") {
                    #ignore domain controllers in a datacenter due to connectivity stuff
                    $lastlogontime = get-qadcomputer -computerrole domaincontroller | where { $_.name -notmatch "-COLO"} | foreach {(get-qaduser -service $_.name -samaccountname $findlastuser2).LastLogon } | Measure-Latest
                    }
                }
            catch {
                if ($lastlogontime -eq $NULL -and $findlastuser2 -eq $NULL){
                    Write-Host "Could not find a last logon time"
                    Write-Host "No username available to query"
                    $lastlogontime = "Unavailable"
                    }
                if ($lastlogontime -eq $NULL -and $findlastuser2 -ne $NULL){
                    Write-Host "Could not find a last logon time for user $findlastuser"
                    $lastlogontime = "Unavailable"
                    }
                }

        #search AD for the user identified, select first name
            try {
                $findlastuserFname = get-qaduser $findlastuser2 | select firstname
                $findlastuserFname2 = $findlastuserFname.firstname.tostring()
                }
            catch [system.exception]{
                if ($findlastuserFname2 -eq $NULL) {
                    Write-Host "No first name for user found"
                    }
                }
        #search AD for the user identified, select last name
            try {
                $findlastuserLname = get-qaduser $findlastuser2 | select lastname
                $findlastuserLname2 = $findlastuserLname.lastname
                }
            catch [system.exception] {
                if ($findlastuserLname2 -eq $NULL) {
                    Write-Host "No last name for user found"
                    }
                }       
        #join the first and last names together if both properties are available

            if ($findlastuserFname2 -ne $NULL -and $findlastuserLname2 -ne $NULL){
                $fullname = "$findlastuserFname2" + " $findlastuserLname2"
                }
            elseif ($findlastuserFname2 -eq $NULL -and $findlastuserLname -ne $NULL){
                $fullname = $findlastuserLname2
                }
            elseif ($findlastuserFname2 -ne $NULL -and $findlastuserLname -eq $NULL){
                $fullname = $findlastuserFname2
                }
            else {
                $fullname = "Unavailable"
                }

        #Set the description data format
            #With only 1 IPv4 Address
            if ($computerIP3 -notmatch $IPv4Regex -or $computerIP3 -eq $NULL){
                $newcomputerdescription = "$fullname | $computerIP2 | $computerSerial2 | $lastlogontime"
                }

            #With 2 IPv4 Addresses

            if ($computerIP3 -match $IPv4Regex) {
                $newcomputerdescription = "$fullname | $computerIP2, $computerIP3 | $computerSerial2 | $lastlogontime"
                }

        #If the description data is the same, leave it as it is
            if ($newcomputerdescription -eq $oldcomputerdescription){
                Write-Host " "
                Write-Host "Information for $computerName has not" -foregroundcolor yellow
                Write-Host "changed. No edits were made on this object." -foregroundcolor yellow
                }

            if ($newcomputerdescription -ne $oldcomputerdescription -and $Connect -eq $TRUE) {
                set-qadcomputer -identity $computerName -Description $newcomputerdescription
                Write-Host " "
                Write-Host "Computer description updated for object $computerName" -foregroundcolor yellow
                Write-Host "New host information:"
                Write-Host "$newcomputerdescription"
                }
            }
        else {
            Write-Host "Could not connect to computer $computerName"
            Write-Host "No changes made to description for $computerName"
            $noconnecterror = "Could not connect to computer $computerName"
            $noconnecterror | Out-File $global:logfile -Append -Force
        }
    }
    Write-Host "Processing complete!"
}
CreateLog -erroraction silentlycontinue
WriteDescription -erroraction silentlycontinue
start-sleep -s 3
##END OF SCRIPT

Second Script:

set-location \\myscriptcomputer\c$\somefolder\PSScripts
Add-PSSnapin Quest.ActiveRoles.ADManagement -erroraction SilentlyContinue
$timeoutput = Measure-Command {\\myscriptcomputer\c$\Somefolder\PSScripts\WriteComputerDescriptions.ps1}
cd \\myscriptcomputer\c$\Somefolder\PSScripts\WriteComputerDescriptions
$scriptlog = get-childitem | sort creationtime | select -last 1
$logname = $scriptlog.name
Add-Content c:\somefolder\PSScripts\WriteComputerDescriptions\$logname "`nExecution Time: $timeoutput"
Write-Host "Script complete!"
Start-sleep -s 3
exit

In the results in my environments Active Directory, this works effectively for several hundred objects, but here's a sample of what I see in my log file:

Could not connect to computer computer391 Could not connect to computer computer392 Could not connect to computer computer393 Could not connect to computer computer394 䔊數畣楴湯吠浩㩥ㄠ㨱㘰㈺⸱㜵㤵㐰ഷ

The very last line with the garbled text is what made me think there's a memory-related issue perhaps. If I run my scripts against a container/OU with a much smaller amount of computers, the last line in my log is a time, which is what I would normally expect.

If any seasoned Powershell pros could offer some advice here, I'd really appreciate the help.

Thanks!

Was it helpful?

Solution

I don't know why my comments are not getting added. Anyways, let me just post it here. In order to track the free memory, you just look at its the performance counter.

Here is the powershell command:

Get-Counter -Counter "\Memory\Available MBytes"
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top