none
Powershell - Method invocation failed because [System.DBNull] does not contain a method named 'op_Addition' RRS feed

  • Question

  • When I run the script below, I get the error message saying "Method invocation failed because [System.DBNull] does not contain a method named 'op_Addition'."

    $dt | where {$_.StartPosition -eq -1} | foreach {$_.StartPosition = if ([regex]::matches($inString,$_.SearchString+$_.EndMark).success -eq 'True') {[regex]::matches($inString,$_.SearchString+$_.EndMark).index[0]} else {$_.StartPosition}}

    $dt is defined as a datatable as follows: $dt = New-Object System.Data.Datatable

    This works when I run the code directly in Windows PowerShell ISE window. When I call it from the command line, I get the error message.

    What am I missing or doing wrong?

    Thanks,

    Emakun.

    • Moved by Bill_Stewart Friday, July 7, 2017 6:27 PM This is not "fix/debug/rewrite my script for me" forum
    Wednesday, May 17, 2017 6:03 PM

All replies

  • First learn how to post code correctly using the code posting tool.

    Next note that you have a syntax error somewhere in the code.

    Here is you code.  Paste into ISE and look at the syntax errors then fix them.  I cannot help as it is not possible to guess at what you are trying to do or why you are using this method.

    $dt | 
    	Where-Object { $_.StartPosition -eq -1 } | 
    	ForEach-Object { 
    		$_.StartPosition = if ([regex]::matches($inString, $_.SearchString + $_.EndMark).success -eq 'True')
    			[regex]::matches($inString, $_.SearchString + $_.EndMark).index[0] 
    		} else { 
    			$_.StartPosition 
    		} 
    	}
    


    \_(ツ)_/

    Wednesday, May 17, 2017 6:21 PM
  • Note that a DataRow has no such property as "StartPosition".

    $dt.Rows[0]|gm


    \_(ツ)_/

    Wednesday, May 17, 2017 6:29 PM
  • First learn how to post code correctly using the code posting tool.

    Next note that you have a syntax error somewhere in the code.

    Here is you code.  Paste into ISE and look at the syntax errors then fix them.  I cannot help as it is not possible to guess at what you are trying to do or why you are using this method.

    $dt | 
    	Where-Object { $_.StartPosition -eq -1 } | 
    	ForEach-Object { 
    		$_.StartPosition = if ([regex]::matches($inString, $_.SearchString + $_.EndMark).success -eq 'True')
    			[regex]::matches($inString, $_.SearchString + $_.EndMark).index[0] 
    		} else { 
    			$_.StartPosition 
    		} 
    	}


    \_(ツ)_/

    My full code is listed below. The objective is to take a string of data, in this case, vCard information, and extract useful information from it using powershell.

    I created the vCard5.csv file from the properties table in https://en.wikipedia.org/wiki/VCard. The file may not contain all the names shown in Wikipedia, but it meets my need for now. As I mention in a previous post, I am getting the vCard information as a single string of data and this code is an attempt to extract useful information from it. This is not a nromal vCard fromat that seperates each section with a new line.

    The only search pattern that gave me a problem is the "N:". I used the following code to resolve this.

    #Fix N: for UsefulData if it exist in the vCard
    if ($dt.Select("FieldName = 'vcName'")[0])
    {
        $dt.Select("FieldName = 'vcName'")[0] |  foreach {$_.UsefulData = if($_.DataValue.Substring(0,2) -eq 'N:') {$_.DataValue.substring(2,$_.DataValue.Length[0]-2)}}
    }

    So far, this code works when I run in from Windows Powershell ISE window. When I call it from the command line as follows "Powershell.exe -File C:\vCard\parseVcard.ps1", I get the error message.

    clear
    
    $dt = New-Object System.Data.Datatable
    
    [void]$dt.Columns.Add("FieldName","string")
    [void]$dt.Columns.Add("SearchString","string")
    [void]$dt.Columns.Add("StartPosition","int32")
    [void]$dt.Columns.Add("EndPosition","int32")
    [void]$dt.Columns.Add("EndMark","string")
    [void]$dt.Columns.Add("DataValue","string")
    [void]$dt.Columns.Add("UsefulData","string")
    
    $csvVCard = "C:\vCard\vCard5.csv"
    
    $reader = New-Object System.IO.StreamReader $csvVCard
    
    #Read the first header line and discard it
    $reader.ReadLine() | Out-Null
    
    # Read in the data, line by line
    while (($line = $reader.ReadLine()) -ne $null)  {
    	[void]$dt.Rows.Add($line.Split($csvdelimiter))
    } 
    
    #Get vCard Data
    $inString = "BEGIN:VCARDVERSION:2.1FN:John SmithN:Smith;JohnTITLE:Event OrganizerTEL;CELL:8005551212TEL;WORK;VOICE:8005551212TEL;HOME;VOICE:18005551212EMAIL;HOME;INTERNET:jjhome@jjsmithco.comEMAIL;WORK;INTERNET:jjsmithco@jjsmithco.comURL:https://www.jjsmith.com/gallery/n-FwMkK/ADR:;;PO Box 1212;Cherry Block;;08111;United StatesORG:JJ Smith Inc, LLCEND:VCARD"
    
    #Set all StartPosition to -1. This will be used in deleting tags that are not in the string
    $dt | foreach {$_.StartPosition = -1}
    
    #Get Start position of all tags in the vCard
    
    #$dt | where {$_.StartPosition -eq -1} | foreach {$_.StartPosition = if ([regex]::matches($inString,$_.SearchString+$_.EndMark).success -eq 'True') {[regex]::matches($inString,$_.SearchString+$_.EndMark).index[0]} else {$_.StartPosition}}
    
    $dt | 
        where {$_.StartPosition -eq -1} | 
            foreach {$_.StartPosition = if ([regex]::matches($inString,$_.SearchString+$_.EndMark).success -eq 'True') 
                {[regex]::matches($inString,$_.SearchString+$_.EndMark).index[0]} 
                    else 
            {$_.StartPosition}}
    
    #Delete tags not in vCard
    $dt.Select("StartPosition = -1").delete()
    
    
    #Set the EndPosition of last record and get the EndPosition of next record into $newEndPos variable
    if ($dt.Select("","StartPosition DESC")[0])
    {
        $dt.Select("","StartPosition DESC")[0]  | foreach {$_.EndPosition = $inString.Length;$newEndPos = $_.StartPosition -1}
    }
    
    #Update remaining EndPosition 
    if ($dt.Select("EndPosition = 0","StartPosition DESC"))
    {
        $dt.Select("EndPosition = 0","StartPosition DESC") | foreach {$_.EndPosition = $newEndPos;$newEndPos = $_.StartPosition -1}
    }
    
    #Set DataValue for END:VCARD
    if ($dt.Select("FieldName = 'EndCard'")[0])
    {
        $dt.Select("FieldName = 'EndCard'")[0]  | foreach {$_.DataValue = $_.SearchString}
    }
    
    #Get String
    if ($dt.Select("FieldName <> 'EndCard'"))
    {
        $dt.Select("FieldName <> 'EndCard'") | foreach {$_.DataValue = $inString.Substring($_.StartPosition,($_.EndPosition - $_.StartPosition)+1)}
    }
    
    #Assign Useful Data
    if ($dt.Select("FieldName not in ('BeginCard','EndCard')"))
    {
        $dt.Select("FieldName not in ('BeginCard','EndCard')") |  foreach {$startPos = [regex]::matches($_.DataValue,$_.SearchString+$_.EndMark).Length[0];$numChar = $_.DataValue.Length - $startPos;$_.UsefulData = $_.DataValue.Substring($startPos,$numChar)}
    }
    
    #Fix N: for UsefulData if it exist in the vCard
    if ($dt.Select("FieldName = 'vcName'")[0])
    {
        $dt.Select("FieldName = 'vcName'")[0] |  foreach {$_.UsefulData = if($_.DataValue.Substring(0,2) -eq 'N:') {$_.DataValue.substring(2,$_.DataValue.Length[0]-2)}}
    }
    
    $dt.Select("","StartPosition") | Format-Table -AutoSize
    
    $reader.DiscardBufferedData()
    $reader.Close()

    Content of vCard5.csv

    FieldName,SearchString,StartPosition,EndPosition,EndMark,DataValue,UsefulData
    HomeEmail,EMAIL;HOME;INTERNET,0,0,:,,
    WorkEmail,EMAIL;WORK;INTERNET,0,0,:,,
    WorkPhoneNumber,TEL;WORK;VOICE,0,0,:,,
    HomePhoneNumber,TEL;HOME;VOICE,0,0,:,,
    OrgDirectory,ORG-DIRECTORY,0,0,:,,
    Profile,PROFILE:VCARD,0,0,,,
    SyncCard,CLIENTPIDMAP,0,0,:,,
    Anniversary,ANNIVERSARY,0,0,:,,
    SortString,SORT-STRING,0,0,:,,
    BeginCard,BEGIN:VCARD,0,0,,,
    Categories,CATEGORIES,0,0,:,,
    BirthPlace,BIRTHPLACE,0,0,(:|;),,
    DeathPlace,DEATHPLACE,0,0,(:|;),,
    ScheduleRequestURL,CALADRURI,0,0,:,,
    DeathDate,DEATHDATE,0,0,:,,
    Expertise,EXPERTISE,0,0,(:|;),,
    EndCard,END:VCARD,0,0,,,
    NickName,NICKNAME,0,0,:,,
    Interest,INTEREST,0,0,(:|;),,
    CellPhoneNumber,TEL;CELL,0,0,:,,
    Related,RELATED,0,0,(:|;),,
    vcVersion,VERSION,0,0,:,,
    CalendarURL,CALURI,0,0,:,,
    Gender,GENDER,0,0,:,,
    Mailer,MAILER,0,0,:,,
    vcNumber,NUMBER,0,0,:,,
    ProductID,PRODID,0,0,:,,
    SourceURL,SOURCE,0,0,:,,
    Agent,AGENT,0,0,:,,
    ClassSensitivity,CLASS,0,0,:,,
    Email,EMAIL,0,0,:,,
    FreeBusyURL,FBURL,0,0,:,,
    MailingLable,LABEL,0,0,(:|;),,
    Photo,PHOTO,0,0,:,,
    Sound,SOUND,0,0,(:|;),,
    Title,TITLE,0,0,:,,
    Hobby,HOBBY,0,0,(:|;),,
    BirthDate,BDAY,0,0,:,,
    IMHandler,IMPP,0,0,:,,
    EntityType,KIND,0,0,:,,
    Language,LANG,0,0,:,,
    Logo,LOGO,0,0,:,,
    vcNote,NOTE,0,0,:,,
    vcRole,ROLE,0,0,:,,
    Address,ADR,0,0,(:|;),,
    GeoLocation,GEO,0,0,:,,
    EncryptionKey,KEY,0,0,:,,
    OrgName,ORG,0,0,:,,
    LastRevised,REV,0,0,:,,
    PhoneNumber,TEL,0,0,:,,
    UniqueID,UID,0,0,:,,
    WebURL,URL,0,0,:,,
    xmlData,XML,0,0,:,,
    FormatedName,FN,0,0,:,,
    TimeZone,TZ,0,0,:,,
    vcName,N,0,0,:\w+?;,,
    

    Wednesday, May 17, 2017 7:52 PM
  • No idea what you are trying to do.  A DataRow has no property called StartPosition.


    \_(ツ)_/

    Wednesday, May 17, 2017 7:59 PM
  • I figured out the issue. While cleaning up my code, I deleted the line that defined the delimiter to split the csv file. Adding the code below before reading in the csv file resolved the issue.

    $csvdelimiter = ","

    Without the delimiter, it was reading in the file as one long string and the rest of the column is null.

    Thanks,

    Emakun

    Thursday, May 18, 2017 1:45 PM