How do I prevent script from aborting when text is not present on each page of document?

I've got a Powershell script question.  I have a script that reads in word documents.  The script is looking for the text ''Dictated by:"  Sometimes the document is two and three pages long, but each page may not have "Dictated by:" on it.  I want the script to continue even if that error state is found.  Right now, if it comes across a document that does not have "'Dictated by:'" on every page it aborts and does not complete.  If there are 1,000 documents, it will abort in the middle wherever it found the error and won't continue on.  There's an error that says: "Error Content -

Exception: System.Management.Automation.RuntimeException: You cannot call a method on a null-valued expression. at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception) at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame) at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame) at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)

CategoryInfo: InvalidOperation: (:) [], RuntimeException

StackLocation: at , D:\script\Isaacs-Scripts\scripts\get-doctorcount\get-doctorcount.ps1: line 87"
gbautista34Asked:
Who is Participating?
 
GrahamSkanRetiredCommented:
I don't speak Powershell, but I'm sure that anyone who does would need to see your script,
0
 
gbautista34Author Commented:
Here is the script.  I've changed names to protect the innocent. ;-)

_________________________________________________
Clear-Variable content -erroraction SilentlyContinue
Clear-Variable list -erroraction SilentlyContinue

$documentPaths = New-Object System.Collections.ArrayList
$doctorResults = @{}
$sites = 'cdc','fh','svh','scdc','rdc'
$date = (Get-Date(Get-Date).AddDays(-1) -Format 'yyyy-MM-dd')
$dateTime = (Get-Date(Get-Date).AddDays(-1) -Format 'MM-dd-yyyy.hh.mm')
$csvPath = "D:\script\Isaacs-Scripts\scripts\get-doctorcount\CSVs\$dateTime.csv"
$completeTotal = 0
$errorLog = "D:\script\Isaacs-Scripts\scripts\get-doctorcount\errorlogs\$dateTime.html"
$doctorLog = "D:\script\Isaacs-Scripts\scripts\get-doctorcount\logs\$dateTime.txt"
# array of all doctor names
# to add to it, simply add quotes and a comma (unless its the last in the array)
$doctors = @(
    'namex',
    'namex',
    'namex',
    'namex',
    'namex',
    'namex',
    'namex',
    'namex',
    'namex',
    'namex',
    'namex',
    'namex',
    'namex',
    'namex'
    'namex',
    'namex',
    "namex x. lastname"
)

try {
    # add firstnames to list
    $firstnames = New-Object System.Collections.ArrayList
    foreach ($doctor in $doctors) {
        $docname = ($doctor -split '\s')
        $docname = $docname[0]+$docname[-1][0]
        $firstnames += $docname
    }

    # foreach doctor name, name a new variable called the doctor name
    foreach ($firstname in $firstnames) {
        if (Get-Variable -name $firstname -ErrorAction SilentlyContinue) {
            Remove-Variable $firstname
        }
        New-Variable -Name $firstname -Value @{}
        $drvar = (Get-Variable -Name $firstname -ValueOnly)
        $drvar.add('rdc',(New-Object System.Collections.Arraylist))
        $drvar.add('cdc',(New-Object System.Collections.Arraylist))
        $drvar.add('fh',(New-Object System.Collections.Arraylist))
        $drvar.add('svh',(New-Object System.Collections.Arraylist))
        $drvar.add('scdc',(New-Object System.Collections.Arraylist))
    }

    foreach ($site in $sites) {
        
        # if site is rdc use rdc path
        if ($site -eq 'rdc') {
            $items = gci "D:\reports\dr_reports\archive\$date"
        } else {
            $items = gci "D:\ininbound\$site\archive\$date"
        }

        foreach ($item in $items) {
                    
            $documentPaths += $item.fullname

        }
    }

    foreach ($document in $documentPaths) {
        $content = get-content $document | Where-Object {$_ -match 'Dictated by:'}
        $sitename = $document.split('\')[2]
        if ($sitename -match 'dr_reports') { $sitename = 'rdc' }

        # choose second read if available
        if ($content.count -gt 1) {
            $content = $content[-1]
        }

        $index = $content.IndexOf('Dictated by:')
        $content = $content.Substring($index)

        Write-Host "`r`n"
        Write-Host $document -ForegroundColor Cyan
        Write-Host $content

        foreach ($doctor in $doctors) {
            if ($content -match $doctor) {
                
                # create dyn string to call dr variable
                $docsplit = $doctor.split(' ')
                [string]$tempDrVar = $docsplit[0]+$docsplit[-1][0]

                # call doctor firstname variable
                $doctorVariable = Get-Variable -Name $tempDrVar

                $doctorVariable.value.$sitename += $document

                Write-Host "$document matched $doctor" -ForegroundColor Yellow
                Add-Content -path $doctorLog -value "$doctor found on $document"

            }
        }
    }

    New-Item -Path $csvPath -itemtype file
    Add-Content $csvPath -Value $dateTime
    Add-Content $csvPath -value "DRName,TOTAL,RASLO,CDC,FH,SVH,SCDC"

    foreach ($firstname in $firstnames) {
        $total = 0
        $docVar = Get-Variable -name $firstname -ValueOnly
        $keys = $docVar.keys
        foreach ($key in $keys) {
            $total = $docVar.$key.count + $total
        }
        $completeTotal = $completeTotal + $total
        Add-Content $csvPath -Value "$firstname,$total,$($docVar.rdc.count),$($docVar.cdc.count),$($docVar.fh.count),$($docVar.svh.count),$($docVar.scdc.count)"
    }
    Add-Content $csvPath -Value "Total Doctor Count,$completeTotal"
    Send-MailMessage -From 'sendfrom@ra-slo.com' -to 'sendto@ra-slo.com' -Subject 'Radiologist Daily Read Count' -Body "Radiologist counts for $date" -SmtpServer 'aspmx.l.google.com' -port '25' -Attachments $csvPath    
    
    $sortedContent = Get-Content $doctorLog | Sort-Object
    Set-Content -path $doctorLog -Value $sortedContent

} catch {
    Add-Content $errorlog -Value "<font color = 'red'>Error Content</font> -<br><br>Exception: $($_.Exception)<br><br> CategoryInfo: $($_.CategoryInfo)<br><br> StackLocation: $($_.ScriptStackTrace)<hr>"
    Send-MailMessage -From 'sendfrom@ra-slo.com' -to 'sendto@ra-slo.com' -Subject 'Error found with Doctor Count:' -Body "<font color = 'red'>Error Content</font> -<br><br>Exception: $($_.Exception)<br><br> CategoryInfo: $($_.CategoryInfo)<br><br> StackLocation: $($_.ScriptStackTrace)<hr>" -SmtpServer 'aspmx.l.google.com' -port '25' -BodyAsHtml
}

Open in new window

0
 
GrahamSkanRetiredCommented:
I have put the script into a code snippet box for easier handling.

I can't see how it is stepping through the pages, but It seems likely that the error is occurring on line 85, because $index is set to Null from the previous line. I suppose that Powershell has a test for Null, so you would need the equivalent of
If $index is not null{ 

Open in new window

after line 84
and a block-closing curly bracket after line 107
0
On-Demand: Securing Your Wi-Fi for Summer Travel

Traveling this summer?Check out our on-demand webinar to learn about the importance of Wi-Fi security and 3 easy measures you can start taking immediately to protect your private data while using public Wi-Fi. Follow us today to learn more!

 
oBdACommented:
This i not an issue with $index being null. This is a method call on a null-valued expression.
You removed lines, including the line breaks, so the line number doesn't add up to what's in the error message, but the only relevant method calls are done on $content, in lines 84 and 85.
In other words: $content is null, which means the script chokes on files that do not contain "Dictated by:" at all. Note that this comparison has zero tolerance (case aside). If someone wrote "Dictated  by:" (notice the difference?), or "Dictated by :", "Dictated by ", etc., it will fail.
Replace lines 74-108 with this, and add whatever you want to do when the string is not found at line 36 below, "# String not found"
For a better handling of the matching, you'd need to provide some real-life examples of the search string variations.
    foreach ($document in $documentPaths) {
        If ($content = get-content $document | Where-Object {$_ -match 'Dictated by:'}) {
			$sitename = $document.split('\')[2]
			if ($sitename -match 'dr_reports') { $sitename = 'rdc' }

			# choose second read if available
			if ($content.count -gt 1) {
				$content = $content[-1]
			}

			$index = $content.IndexOf('Dictated by:')
			$content = $content.Substring($index)

			Write-Host "`r`n"
			Write-Host $document -ForegroundColor Cyan
			Write-Host $content

			foreach ($doctor in $doctors) {
				if ($content -match $doctor) {
					
					# create dyn string to call dr variable
					$docsplit = $doctor.split(' ')
					[string]$tempDrVar = $docsplit[0]+$docsplit[-1][0]

					# call doctor firstname variable
					$doctorVariable = Get-Variable -Name $tempDrVar

					$doctorVariable.value.$sitename += $document

					Write-Host "$document matched $doctor" -ForegroundColor Yellow
					Add-Content -path $doctorLog -value "$doctor found on $document"

				}
			}
		} Else {
			# String not found
		}
 

Open in new window

1
 
gbautista34Author Commented:
Thank you.  I am going to test out this updated script portion.  So to add multiple instances can I do something like this
{$_ -match 'Dictated by:', 'Dictated by'}  
How can I account for the variable string 'Dicated by'?  Thanks!
0
 
oBdACommented:
So if a text has several matches, you only want the last one?
Replace lines 74-108 with this:
    foreach ($document in $documentPaths) {
		If ($Match = Select-String -Path $document -Pattern '\A\s*Dictated\s+by\s*:?\s*(.*?)\s*\Z' | Select-Object -Last 1 -ExpandProperty Matches) {
			$content = $Match.Groups[1].Value

 			$sitename = $document.split('\')[2]
			if ($sitename -match 'dr_reports') { $sitename = 'rdc' }

			Write-Host "`r`n"
			Write-Host $document -ForegroundColor Cyan
			Write-Host $content

			foreach ($doctor in $doctors) {
				if ($content -match $doctor) {
					
					# create dyn string to call dr variable
					$docsplit = $doctor.split(' ')
					[string]$tempDrVar = $docsplit[0]+$docsplit[-1][0]

					# call doctor firstname variable
					$doctorVariable = Get-Variable -Name $tempDrVar

					$doctorVariable.value.$sitename += $document

					Write-Host "$document matched $doctor" -ForegroundColor Yellow
					Add-Content -path $doctorLog -value "$doctor found on $document"
				}
			}
		} Else {
			# String not found
		}
    }

Open in new window

0
 
gbautista34Author Commented:
Yikes.  I did something wrong.  I adjusted the script and tested.  Now it sends me an email with one CSV per word document that it reads in.  
It runs through each word document.   There are word documents that have multiple pages; not each page may have "Dictated by:"  AND not all word documents may have the doctors name either.  What am I missing in this code?  Thanks.

----------------------------
# 07.24.2017 - GB Modified lines 113 & 114. Changed receivers to Google distro group sendto@ra-slo.com and commented out previous line.
# 11.29.2017 - Modified to add message in the error log and not stop the script from running.

Clear-Variable content -erroraction SilentlyContinue
Clear-Variable list -erroraction SilentlyContinue

$documentPaths = New-Object System.Collections.ArrayList
$doctorResults = @{}
$sites = 'cdc','fh','svh','scdc','rdc'
$date = (Get-Date(Get-Date).AddDays(-1) -Format 'yyyy-MM-dd')
$dateTime = (Get-Date(Get-Date).AddDays(-1) -Format 'MM-dd-yyyy.hh.mm')
$csvPath = "D:\script\Isaacs-Scripts\scripts\get-doctorcount\CSVs\$dateTime.csv"
$completeTotal = 0
$errorLog = "D:\script\Isaacs-Scripts\scripts\get-doctorcount\errorlogs\$dateTime.html"
$doctorLog = "D:\script\Isaacs-Scripts\scripts\get-doctorcount\logs\$dateTime.txt"
# array of all doctor names
# to add to it, simply add quotes and a comma (unless its the last in the array)
$doctors = @(
    'Timothy L. Auran',
    'William C. Burnette',
    'Harry F. Corbett',
    'Arthur C. Duberg',
    'Stephen R. Holtzman',
    'Kai Kinder',
    'Thomas L. Miller',
    'Linda D. Mulder',
    'Erik M. Olson',
    'Jaywant P. Parmar',
    'Amol A. Patil',
    'William M. Russell',
    'David J. Tuttle',
    'Donna E. Winingham'
    'Erica Vergara',
    'Laura E. Traube',
    "Sonja M. O'Brien"
)

try {
    # add firstnames to list
    $firstnames = New-Object System.Collections.ArrayList
    foreach ($doctor in $doctors) {
        $docname = ($doctor -split '\s')
        $docname = $docname[0]+$docname[-1][0]
        $firstnames += $docname
    }

    # foreach doctor name, name a new variable called the doctor name
    foreach ($firstname in $firstnames) {
        if (Get-Variable -name $firstname -ErrorAction SilentlyContinue) {
            Remove-Variable $firstname
        }
        New-Variable -Name $firstname -Value @{}
        $drvar = (Get-Variable -Name $firstname -ValueOnly)
        $drvar.add('rdc',(New-Object System.Collections.Arraylist))
        $drvar.add('cdc',(New-Object System.Collections.Arraylist))
        $drvar.add('fh',(New-Object System.Collections.Arraylist))
        $drvar.add('svh',(New-Object System.Collections.Arraylist))
        $drvar.add('scdc',(New-Object System.Collections.Arraylist))
    }

    foreach ($site in $sites) {
        
        # if site is rdc use rdc path
        if ($site -eq 'rdc') {
            $items = gci "D:\reports\dr_reports\archive\$date"
        } else {
            $items = gci "D:\ininbound\$site\archive\$date"
        }

        foreach ($item in $items) {
                    
            $documentPaths += $item.fullname

        }
    }

   foreach ($document in $documentPaths) {
        If ($content = get-content $document | Where-Object {$_ -match 'Dictated by:'}) {
			$sitename = $document.split('\')[2]
			if ($sitename -match 'dr_reports') { $sitename = 'rdc' }

			# choose second read if available
			if ($content.count -gt 1) {
				$content = $content[-1]
			}

			$index = $content.IndexOf('Dictated by:')
			$content = $content.Substring($index)

			Write-Host "`r`n"
			Write-Host $document -ForegroundColor Cyan
			Write-Host $content

			foreach ($doctor in $doctors) {
				if ($content -match $doctor) {
					
					# create dyn string to call dr variable
					$docsplit = $doctor.split(' ')
					[string]$tempDrVar = $docsplit[0]+$docsplit[-1][0]

					# call doctor firstname variable
					$doctorVariable = Get-Variable -Name $tempDrVar

					$doctorVariable.value.$sitename += $document

					Write-Host "$document matched $doctor" -ForegroundColor Yellow
					Add-Content -path $doctorLog -value "$doctor found on $document"
            }
        }
    }

    New-Item -Path $csvPath -itemtype file
    Add-Content $csvPath -Value $dateTime
    Add-Content $csvPath -value "DRName,TOTAL,RASLO,CDC,FH,SVH,SCDC"

    foreach ($firstname in $firstnames) {
        $total = 0
        $docVar = Get-Variable -name $firstname -ValueOnly
        $keys = $docVar.keys
        foreach ($key in $keys) {
            $total = $docVar.$key.count + $total
        }
        $completeTotal = $completeTotal + $total
        Add-Content $csvPath -Value "$firstname,$total,$($docVar.rdc.count),$($docVar.cdc.count),$($docVar.fh.count),$($docVar.svh.count),$($docVar.scdc.count)"
    }
    Add-Content $csvPath -Value "Total Doctor Count,$completeTotal"
    Send-MailMessage -From 'reports@ra-slo.com' -to 'radreadcount@ra-slo.com' -Subject 'Radiologist Daily Read Count' -Body "Radiologist counts for $date" -SmtpServer 'aspmx.l.google.com' -port '25' -Attachments $csvPath    
    
    $sortedContent = Get-Content $doctorLog | Sort-Object
    Set-Content -path $doctorLog -Value $sortedContent

} 
}
catch {
    Add-Content $errorlog -Value "<font color = 'red'>Error Content</font> -<br><br>Exception: $($_.Exception)<br><br> CategoryInfo: $($_.CategoryInfo)<br><br> StackLocation: $($_.ScriptStackTrace)<hr>"
    Send-MailMessage -From 'sendfrom@ra-slo.com' -to 'sendto@ra-slo.com' -Subject 'Error found with Doctor Count:' -Body "<font color = 'red'>Error Content</font> -<br><br>Exception: $($_.Exception)<br><br> CategoryInfo: $($_.CategoryInfo)<br><br> StackLocation: $($_.ScriptStackTrace)<hr>" -SmtpServer 'aspmx.l.google.com' -port '25' -BodyAsHtml
}

Open in new window

0
 
gbautista34Author Commented:
Here is a sample of the CSV file

03-05-2018.01.21                                    
DRName      TOTAL      RASLO      CDC      FH      SVH      SCDC
TimothyA      0      0      0      0      0      0
WilliamB      0      0      0      0      0      0
HarryC      0      0      0      0      0      0
ArthurD      0      0      0      0      0      0
StephenH      0      0      0      0      0      0
KaiK      0      0      0      0      0      0
ThomasM      0      0      0      0      0      0
LindaM      0      0      0      0      0      0
ErikO      0      0      0      0      0      0
JaywantP      0      0      0      0      0      0
AmolP      0      0      0      0      0      0
WilliamR      0      0      0      0      0      0
DavidT      0      0      0      0      0      0
DonnaW      0      0      0      0      0      0
EricaV      0      0      0      0      0      0
LauraT      0      0      0      0      0      0
SonjaO      0      0      0      0      0      0
Total Doctor Count      0
0
 
oBdACommented:
The closing curly bracket went AWOL in my code snippet above.
Here's the complete version including the change:
Clear-Variable content -erroraction SilentlyContinue
Clear-Variable list -erroraction SilentlyContinue

$documentPaths = New-Object System.Collections.ArrayList
$doctorResults = @{}
$sites = 'cdc','fh','svh','scdc','rdc'
$date = (Get-Date(Get-Date).AddDays(-1) -Format 'yyyy-MM-dd')
$dateTime = (Get-Date(Get-Date).AddDays(-1) -Format 'MM-dd-yyyy.hh.mm')
$csvPath = "D:\script\Isaacs-Scripts\scripts\get-doctorcount\CSVs\$dateTime.csv"
$completeTotal = 0
$errorLog = "D:\script\Isaacs-Scripts\scripts\get-doctorcount\errorlogs\$dateTime.html"
$doctorLog = "D:\script\Isaacs-Scripts\scripts\get-doctorcount\logs\$dateTime.txt"
# array of all doctor names
# to add to it, simply add quotes and a comma (unless its the last in the array)
$doctors = @(
    'namex',
    'namex',
    'namex',
    'namex',
    'namex',
    'namex',
    'namex',
    'namex',
    'namex',
    'namex',
    'namex',
    'namex',
    'namex',
    'namex'
    'namex',
    'namex',
    "namex x. lastname"
)

try {
    # add firstnames to list
    $firstnames = New-Object System.Collections.ArrayList
    foreach ($doctor in $doctors) {
        $docname = ($doctor -split '\s')
        $docname = $docname[0]+$docname[-1][0]
        $firstnames += $docname
    }

    # foreach doctor name, name a new variable called the doctor name
    foreach ($firstname in $firstnames) {
        if (Get-Variable -name $firstname -ErrorAction SilentlyContinue) {
            Remove-Variable $firstname
        }
        New-Variable -Name $firstname -Value @{}
        $drvar = (Get-Variable -Name $firstname -ValueOnly)
        $drvar.add('rdc',(New-Object System.Collections.Arraylist))
        $drvar.add('cdc',(New-Object System.Collections.Arraylist))
        $drvar.add('fh',(New-Object System.Collections.Arraylist))
        $drvar.add('svh',(New-Object System.Collections.Arraylist))
        $drvar.add('scdc',(New-Object System.Collections.Arraylist))
    }

    foreach ($site in $sites) {
        
        # if site is rdc use rdc path
        if ($site -eq 'rdc') {
            $items = gci "D:\reports\dr_reports\archive\$date"
        } else {
            $items = gci "D:\ininbound\$site\archive\$date"
        }

        foreach ($item in $items) {
                    
            $documentPaths += $item.fullname

        }
    }

    foreach ($document in $documentPaths) {
		If ($Match = Select-String -Path $document -Pattern '\A\s*Dictated\s+by\s*:?\s*(.*?)\s*\Z' | Select-Object -Last 1 -ExpandProperty Matches) {
			$content = $Match.Groups[1].Value

 			$sitename = $document.split('\')[2]
			if ($sitename -match 'dr_reports') { $sitename = 'rdc' }

			Write-Host "`r`n"
			Write-Host $document -ForegroundColor Cyan
			Write-Host $content

			foreach ($doctor in $doctors) {
				if ($content -match $doctor) {
					
					# create dyn string to call dr variable
					$docsplit = $doctor.split(' ')
					[string]$tempDrVar = $docsplit[0]+$docsplit[-1][0]

					# call doctor firstname variable
					$doctorVariable = Get-Variable -Name $tempDrVar

					$doctorVariable.value.$sitename += $document

					Write-Host "$document matched $doctor" -ForegroundColor Yellow
					Add-Content -path $doctorLog -value "$doctor found on $document"
				}
			}
		} Else {
			# String not found
		}
    }

    New-Item -Path $csvPath -itemtype file
    Add-Content $csvPath -Value $dateTime
    Add-Content $csvPath -value "DRName,TOTAL,RASLO,CDC,FH,SVH,SCDC"

    foreach ($firstname in $firstnames) {
        $total = 0
        $docVar = Get-Variable -name $firstname -ValueOnly
        $keys = $docVar.keys
        foreach ($key in $keys) {
            $total = $docVar.$key.count + $total
        }
        $completeTotal = $completeTotal + $total
        Add-Content $csvPath -Value "$firstname,$total,$($docVar.rdc.count),$($docVar.cdc.count),$($docVar.fh.count),$($docVar.svh.count),$($docVar.scdc.count)"
    }
    Add-Content $csvPath -Value "Total Doctor Count,$completeTotal"
    Send-MailMessage -From 'sendfrom@ra-slo.com' -to 'sendto@ra-slo.com' -Subject 'Radiologist Daily Read Count' -Body "Radiologist counts for $date" -SmtpServer 'aspmx.l.google.com' -port '25' -Attachments $csvPath    
    
    $sortedContent = Get-Content $doctorLog | Sort-Object
    Set-Content -path $doctorLog -Value $sortedContent

} catch {
    Add-Content $errorlog -Value "<font color = 'red'>Error Content</font> -<br><br>Exception: $($_.Exception)<br><br> CategoryInfo: $($_.CategoryInfo)<br><br> StackLocation: $($_.ScriptStackTrace)<hr>"
    Send-MailMessage -From 'sendfrom@ra-slo.com' -to 'sendto@ra-slo.com' -Subject 'Error found with Doctor Count:' -Body "<font color = 'red'>Error Content</font> -<br><br>Exception: $($_.Exception)<br><br> CategoryInfo: $($_.CategoryInfo)<br><br> StackLocation: $($_.ScriptStackTrace)<hr>" -SmtpServer 'aspmx.l.google.com' -port '25' -BodyAsHtml
}

Open in new window

1
 
gbautista34Author Commented:
Good news.  I ran it three times and each time it ran fine.  It continued and produced the CSV file, and attached it to the email that it sends.  I did not see any errors.  There were no error logs produced.  There's nothing catching errors. So that means it's finding the data that it's looking for regardless if it's only on one page of a document which is good.  Thank you very very much for your help and time!
0
 
gbautista34Author Commented:
Anyone there?  I could use a little more help.  I've been working on this all am, but I'm not getting it right.    These line of code below:
foreach ($document in $documentPaths) {
            If ($Match = Select-String -Path $document -Pattern '\A\s*Dictated\s+by\s*:?\s*(.*?)\s*\Z' | Select-Object -Last 1 -ExpandProperty Matches) {
                  $content = $Match.Groups[1].Value

Are working, but it's not including some documents.  I did an audit and I found that the documents that it's ignoring have the enter key hit about two or three times, there may be a jpeg inserted before the line with "Dictated by" or there is a table of names.   So table of names, jpeg and enter key seem to screw it up and the script ignores them.  It just does not include them in the CSV report.  I've been looking at the regex switches, trying `r \r `n \n  but I'm not getting it to run.  It keeps aborting.  Help!
0
All Courses

From novice to tech pro — start learning today.