Cannot Call A Method Error

Hello All,

I am attempting to teach myself Powershell by trying to assemble a script for GFI Remote Management to check the iDrive cloud backup service on our servers. So far I have this much put together which seems to do what I want it to do but I am getting an error in the process that is tripping up my reporting.

Here is what i have so far:

$iDriveAcct=Get-Childitem -name C:\ProgramData\IDrive\IBCOMMON\logs\ 
$Computer=Get-Childitem -name C:\ProgramData\IDrive\IBCOMMON\logs\$iDriveAcct\ 
$LogDate=Get-ChildItem -Path C:\ProgramData\IDrive\IBCOMMON\logs\$iDriveAcct\$Computer\*.xml | Sort-Object -Property LastWriteTime | Select-Object -Skip 1 -Last 1 -ExpandProperty LastWriteTime
$LogFile=Get-Item C:\ProgramData\IDrive\IBCOMMON\logs\$iDriveAcct\$computer\*.xml | Sort-Object -Property LastWriteTime | Select-Object -Skip 1 -Last 1 | Get-Content
$BackupStatus = $xdoc.SelectNodes("//status") | % { $_.InnerText } | select -Unique


if ($LogFile -match "Success") {
                               Write-Host "The backup on $LogDate was Successful"
                               Exit 0
                               }
                               elseif ($Logfile -match "Failure") {
                                                                  Write-Host "The backup on $LogDate has FAILED"
                                                                  Exit 1001
                                                                  }
                                                                  elseif ($Logfile -match "Cancelled") {
                                                                                                       Write-Host "The backup on $LogDate was CANCELLED"
                                                                                                       Exit 1001
                                                                                                       }
                                                                                                       else {
                                                                                                            Write-Host "Error, no status found for backup job on $LogDate"
                                                                                                            Exit 1001
                                                                                                            }

And here is the error that I get when I run it:

You cannot call a method on a null-valued expression.
At C:\Users\***\***\GFI - Scripts\iDrive\2017.01.07_iDrive_Testing.ps1:5 char:1
+ $BackupStatus = $xdoc.SelectNodes("//status") | % { $_.InnerText } |  ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull
 
The backup on 11/18/2016 23:19:59 has FAILED

If anyone could give me an idea of the mistake I have made I would really appreciate it!

All best…

Jason

In line 5 you use a variable “$xdoc” but you did not fill it in. At least not in the part of the code you posted here.

Ah, that makes sense! Thanks Olaf.

I see that was a variable from another iteration of the script.

When I took that line out completely I got no error. I dont think it is necessary because by the line preceding it:

$LogFile=Get-Item C:\ProgramData\IDrive\IBCOMMON\logs\$iDriveAcct\$computer\*.xml | Sort-Object -Property LastWriteTime | Select-Object -Skip 1 -Last 1 | Get-Content

it ran the Get-Content which would have loaded the content of the .xml file into memory for the if/then statement that follows can then use to evaluate.

Is this correct?

Thanks again!

Jason

Jason,

actually I did not pay attention to you code before. I just read the error and pointed you there. When I take a closer look to you code I see some room for improvement. :wink:
You first 3 lines look pretty weird to me and I would expect them to produce errors. If I’m right your script should work this way too:

$LogFile = Get-Item C:\ProgramData\IDrive\IBCOMMON\logs*.xml | Sort-Object -Property LastWriteTime | Select-Object -Last 1
$LogFileContent = Get-Content -Path $LogFile
$LogFileDate = $LogFile.LastWriteTime

if ($LogFileContent -match “Success”) {
Write-Host “The backup on $LogDate was Successful”
Exit 0
}
elseif ($LogFileContent -match “Failure”) {
Write-Host “The backup on $LogFileDate has FAILED”
Exit 1001
}
elseif ($LogFileContent -match “Cancelled”) {
Write-Host “The backup on $LogFileDate was CANCELLED”
Exit 1001
}
else {
Write-Host “Error, no status found for backup job on $LogFileDate”
Exit 1001
}


But anyway even if this does what you expect. If your xml files are really xml files and not just text files with fancy extensions you miss the whole point of working with structured data in Powershell. The free XML CookBock written by Dr.T.Weltner might give you an idea of what I mean.
I think you should start to learn the basics of Powershell. I’m sure it will pay off for you in future. Some great points to start from you can find here: Beginner Sites and Tutorials.

Thanks again Olaf,

I am going to go thru that XML CookBook, it looks just like the thing I need for some other parts of the script I would like to add in the future. That was one of the biggest challenges to me was understanding how you can pull data out of the XML file and assign it to variables within the script I could use for reporting, this looks to be the answer.

The way that iDrive places the Log file directory is essentially different on every computer as it uses the account name (email address) and the computer name in the path, this is why the first three lines are a bit wonky. I also discovered thru trial and error that you also had to account for if the account had possibly changed or if it was migrated from another PC/Server which means I could not use the COMPUTERNAME variable reliably. So far that is the best way I have been able to get it to find the right directory pretty reliably.

I really like the simplicity of your if/then statement. This makes much more sense to me as to how it should work. I am having one issue when trying to run it the way you suggested. The line that runs the Get-Content for the $LogFileContent variable throws up an error when it is run. Forgive me if I have changed something in your suggested code, here is what I have after re-writing what I had and using your suggested way:

$iDriveAcct = Get-Childitem -name C:\ProgramData\IDrive\IBCOMMON\logs\ 
$Computer = Get-Childitem -name C:\ProgramData\IDrive\IBCOMMON\logs\$iDriveAcct\ 
$LogFile = Get-Item C:\ProgramData\IDrive\IBCOMMON\logs\$iDriveAcct\$computer\*.xml | Sort-Object -Property LastWriteTime | Select-Object -Skip 1 -Last 1 | Get-Content
$LogFileContent = Get-Content -Path $LogFile
$LogFileDate = $LogFile.LastWriteTime

if ($LogFileContent -match "Success") {
    Write-Host "The backup on $LogDate was Successful"
    Exit 0
}
elseif ($LogFileContent -match "Failure") {
    Write-Host "The backup on $LogFileDate has FAILED"
    Exit 1001
}
elseif ($LogFileContent -match "Cancelled") {
    Write-Host "The backup on $LogFileDate was CANCELLED"
    Exit 1001
}
else {
    Write-Host "Error, no status found for backup job on $LogFileDate"
    Exit 1001
}

I get this error:

PS C:\Users\***> C:\Users\***\***GFI - Scripts\iDrive\Testing\2017.01.08_iDrive_Testing.ps1
Get-Content : Cannot find drive. A drive with the name '2017-01-08 00' does not exist.
At C:\Users\***\***\GFI - Scripts\iDrive\Testing\2017.01.08_iDrive_Testing.ps1:5 char:19
+ $LogFileContent = Get-Content -Path $LogFile
+                   ~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (2017-01-08 00:String) [Get-Content], DriveNotFoundException
    + FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.GetContentComma

I am going to begin to go thru the XML CookBook as well to see if I can figure out where I went wrong with this.

Thanks again for all your help! I really appreciate you taking the time!

All best…

Jason

OK. Just a quick one before I go to bed: Try the following snippet and see if it contains what you expect


$LogFile = Get-Item C:\ProgramData\IDrive\IBCOMMON\logs***.xml | Sort-Object -Property LastWriteTime | Select-Object -Last 1
$LogFileContent = Get-Content -Path $LogFile
$LogFileDate = $LogFile.LastWriteTime

“‘$($LogFile)’”
“‘$($LogFileDate)’”
“‘$($LogFileContent)’”


If I’m right this should give you the name of your logfile enclosed in single quotes, the “lastwritetime” enclosed in single quotes and finaly the content of the xml file you are looking for enclosed in single quotes.

OK, now your error message: You changed my suggestion. You added in line 3 “| Get-Content” and in line 4 use “Get-Content” again. That does not work. That’s why you get the error. And btw. if you use “Select-Object -Last 1” it does not make sense at all that you use “-skip 1”. It’s obsolete.

You really should take the time to learn the basics of Powershell. You don’t even have to read a book you can watch videos.

http://www.microsoftvirtualacademy.com/training-courses/getting-started-with-powershell-3-0-jump-start

http://www.microsoftvirtualacademy.com/training-courses/advanced-tools-scripting-with-powershell-3-0-jump-start

https://www.youtube.com/playlist?list=PL6D474E721138865A

https://www.youtube.com/results?search_query=don+jones+toolmaking

https://www.youtube.com/watch?v=SSJot1ycM70