Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 540
  • Last Modified:

CallByName Help?

Can someone help me figure this out here.

I am trying to pass some parameters to a CallByName return as the parameters to a function that it should be calling

The function I am trying to run is called Test, and is simply the following:
    Public Shared Function Test(ByVal str As String) As String
        Return str.ToString()
    End Function

The problem I am having is that it should be returning what is passed to it as a parameter, (which is simply the string "This Is A Test"), but nothing is getting displayed to me.

Here's the class doing the work:
 
Imports System.Web
Imports System.Text.RegularExpressions
Imports System.Text
Imports System.Threading
Imports System.Threading.Tasks

Namespace ZipCM

    Public Class Tokenator
        Implements System.IDisposable

        Private objXml As XDocument
        Private _IT As Type = Nothing
        Private _Token() As Object
        Private _TokenQuery() As Object
        Private _Template As String

        Public Sub New(ByVal Template As String)
            objXml = XDocument.Load(HttpContext.Current.Server.MapPath("/Scripts/Tokens.config"))
            Dim _TokenRE As New Regex("\#\#([^&\n]*?)(&.*?)?\#\#")
            Dim _RCt As Long = 0
            Dim _TokenMatches As MatchCollection = _TokenRE.Matches(Template)
            Dim _T(_TokenMatches.Count - 1) As String
            Dim _TQ(_TokenMatches.Count - 1) As String
            For i As Integer = 0 To _TokenMatches.Count - 1
                _T(i) = _TokenMatches(i).Groups(1).Value
                _TQ(i) = _TokenMatches(i).Groups(2).Value
            Next
            _Token = _T
            _TokenQuery = _TQ
            _Template = Template
            Erase _T : Erase _TQ
        End Sub

        ''' <summary>
        ''' Process out tokens
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function Tokenator() As String
            Dim tmpI As Long
            For i As Long = 0 To _Token.GetUpperBound(0)
                tmpI = i
                Dim _Qry = (From n In objXml...<Token>.AsParallel().WithExecutionMode(ParallelExecutionMode.ForceParallelism) _
                           Where n.@active = 1 And n.<Name>.Value.Contains(_Token(tmpI)) _
                            Select n.<Name>, n.<Namespace>, n.<Class>, n.<Property>, n.<Method>, StrValue = n.<String>).ToList()
                If _Qry.Count > 0 Then
                    For Each r In _Qry
                        If Security.Required(_TokenQuery(i)) Then
                            'Process the QueryStrings attached to the tokens
                            Dim _TmpTok = Invoker(r.Method.Value, r.Namespace.Value, r.Class.Value, r.Property.Value, r.StrValue.Value, New Object() {_TokenQuery(i)}) & ":::" & tmpI
                            _Template = _Template.Replace(r.Name.Value.Replace("##", String.Empty), _TmpTok).Replace(_TokenQuery(i), String.Empty)
                        Else
                            Dim _TmpTok = Invoker(r.Method.Value, r.Namespace.Value, r.Class.Value, r.Property.Value, r.StrValue.Value) & ":::" & tmpI
                            _Template = _Template.Replace(r.Name.Value.Replace("##", String.Empty), _TmpTok)
                        End If
                    Next
                End If
            Next
            Return _Template.Replace("##", String.Empty)
        End Function

        ''' <summary>
        ''' Invoke everything
        ''' </summary>
        ''' <param name="MethodName"></param>
        ''' <param name="NamespaceName"></param>
        ''' <param name="ClassName"></param>
        ''' <param name="PropertyName"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Private Function Invoker(ByVal MethodName As String, Optional ByVal NamespaceName As String = Nothing, Optional ByVal ClassName As String = Nothing, Optional ByVal PropertyName As String = Nothing, Optional ByVal StringValue As String = Nothing, Optional ByVal Params() As Object = Nothing) As String
            If (Len(PropertyName) > 0) Then
                If (Len(ClassName) > 0) Then
                    If Not (Len(NamespaceName) > 0) Then
                        _IT = Type.GetType(ClassName, True, True)
                    Else
                        _IT = Type.GetType(NamespaceName & "." & ClassName, True, True)
                    End If
                Else
                    _IT = Type.GetType(Me.ToString, True, True)
                End If
                Return CallByName(Activator.CreateInstance(_IT), PropertyName, CallType.Get)
            ElseIf Len(StringValue) > 0 Then
                Return StringValue
            Else
                If (Len(ClassName) > 0) Then
                    If Not (Len(NamespaceName) > 0) Then
                        _IT = Type.GetType(ClassName, True, True)
                    Else
                        _IT = Type.GetType(NamespaceName & "." & ClassName, True, True)
                    End If
                Else
                    _IT = Type.GetType(Me.ToString, True, True)
                End If
                If IsNothing(Params) Then
                    Return CallByName(Activator.CreateInstance(_IT), MethodName, CallType.Get)
                Else
                    Return CallByName(Activator.CreateInstance(_IT), MethodName, CallType.Get, Params)
                End If
            End If
        End Function

#Region "IDisposable Support"
        Private disposedValue As Boolean ' To detect redundant calls

        ' IDisposable
        Protected Overridable Sub Dispose(ByVal disposing As Boolean)
            If Not Me.disposedValue Then
                If disposing Then
                    ' TODO: dispose managed state (managed objects).
                End If
                Erase _Token
                Erase _TokenQuery
                _Template = String.Empty
                objXml = Nothing
                ' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
                ' TODO: set large fields to null.
            End If
            Me.disposedValue = True
        End Sub

        ' This code added by Visual Basic to correctly implement the disposable pattern.
        Public Sub Dispose() Implements IDisposable.Dispose
            ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
            Dispose(True)
            GC.SuppressFinalize(Me)
        End Sub

#End Region

    End Class

End Namespace

Open in new window

0
kevp75
Asked:
kevp75
  • 20
  • 11
2 Solutions
 
Carl TawnSystems and Integration DeveloperCommented:
CallType.Get refers to a property get accessor. What you need is CallType.Method.
0
 
kevp75Author Commented:
no luck.   Changed it to Method, and still nothing is returned
0
 
Guy Hengel [angelIII / a3]Billing EngineerCommented:
why not use the CallByName function directly?
http://msdn.microsoft.com/en-us/library/chsc1tx6%28v=vs.71%29.aspx
0
Free Backup Tool for VMware and Hyper-V

Restore full virtual machine or individual guest files from 19 common file systems directly from the backup file. Schedule VM backups with PowerShell scripts. Set desired time, lean back and let the script to notify you via email upon completion.  

 
Carl TawnSystems and Integration DeveloperCommented:
This is the over-simplified test version i am using, which works, so the logic is sound.
    Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click

        Dim _IT As Type
        _IT = Type.GetType("WebApplicationVB.WebForm1", True, True)

        Dim s As String = CallByName(Activator.CreateInstance(_IT), "DoSomething", CallType.Method, New Object() {"Hello World"})

    End Sub

    Public Shared Function DoSomething(ByVal str As String) As String
        Return str
    End Function

Open in new window

Is it retrieving the Type into _IT correctly?
0
 
kevp75Author Commented:
Yes.  Type is retrieving correctly
0
 
Carl TawnSystems and Integration DeveloperCommented:
Ok. So if it is getting the type correctly, and not throwing any exceptions, then I guess the next place to look is at the param() that you should be passing to the method.

If it isn't throwing an exception then presumably it is finding the method. Do you have a breakpoint in your method so you can see if it is being hit?
0
 
kevp75Author Commented:
hmm...  my issue appears to be deeper than this.

Once I replace the New Object() {_TokenQuery(i)} with the New Object() {"Hello World"}

I get the Hello World.
0
 
kevp75Author Commented:
but...when I set the breakpoint on that line...  it shows me the value of _TokenQuery(i)...
0
 
kevp75Author Commented:
@angelIII   I would, but I need to be able to fireoff stuff from any namespace.class.method, etc...
0
 
Carl TawnSystems and Integration DeveloperCommented:
OK. I've expanded my test scenario a little to sort of replicate your arrays:
        Dim _T(1) As String
        _T(0) = "Hello World"

        Dim _Token() As Object
        _Token = _T

        Dim _IT As Type
        _IT = Type.GetType("WebApplicationVB.WebForm1", True, True)

        Dim s As String = CallByName(Activator.CreateInstance(_IT), "DoSomething", CallType.Method, New Object() {_Token(0)})

Open in new window

And I am still getting "Hello World" back. Which may point to an issue with the way you are populating the "_Token" array.
0
 
kevp75Author Commented:
well.   _Token populates fine, and at the same time _TokenQuery populates.

so they have equal bounds.

I have verified, that I can get the value of _TokenQuery(i), that is until it hits Line 51 (above).  once it hits that it disappears
0
 
kevp75Author Commented:
screenshot screen
0
 
Carl TawnSystems and Integration DeveloperCommented:
Does it work ok if you pass a hard-coded value instead of _TokenQuery(i)?
0
 
kevp75Author Commented:
Yes.

If I hardcode in New Object() {"Hello World"}

It passes.   I would normally say that the array is not being filled right, however, when I set a break point to the line before the CallByName, and simply assign the _TokenQuery(i) to a variable, I can see the value that it should be passing. (as in the screenshot above).

Could it be because some of the values in the _TokenQuery() array are empty strings?...  I populate both _Token and _TokenQuery at the same time to make sure the indexes (spelling) line up right.
0
 
Carl TawnSystems and Integration DeveloperCommented:
I wouldn't have thought so. Null/Nothing might cause a problem, but I can't see any reason why an empty string should. So, if you assign it to a variable, and pass that variable to CallByName does it work ok?
0
 
kevp75Author Commented:
Still nothing.  I am even making sure now that the empty _TokenQuery is ""

I assign it to a variable, the variable gets populated, but nothing comes from it once it hits CallByName
0
 
Carl TawnSystems and Integration DeveloperCommented:
Do you have a sample of what your Tokens.config files contains? That way I can replicate precisely what you have.
0
 
kevp75Author Commented:
sure:
 
<?xml version="1.0"?>
<Tokens>
  <Token active="1">
    <Name><![CDATA[##TEST1##]]></Name>
    <Namespace>ZipCM</Namespace>
    <Class>Settings</Class>
    <Property><![CDATA[SiteID]]></Property>
    <Method><![CDATA[]]></Method>
    <String><![CDATA[]]></String>
  </Token>
  <Token active="1">
    <Name><![CDATA[##TEST2##]]></Name>
    <Namespace>ZipCM</Namespace>
    <Class>SiteMap</Class>
    <Property><![CDATA[]]></Property>
    <Method><![CDATA[SiteMapXml]]></Method>
    <String><![CDATA[]]></String>
  </Token>
  <Token active="1">
    <Name><![CDATA[##TEST3##]]></Name>
    <Namespace>ZipCM</Namespace>
    <Class>Settings</Class>
    <Property><![CDATA[SitePath]]></Property>
    <Method><![CDATA[]]></Method>
    <String><![CDATA[]]></String>
  </Token>
  <Token active="1">
    <Name><![CDATA[##TEST4##]]></Name>
    <Namespace></Namespace>
    <Class>Common</Class>
    <Property><![CDATA[]]></Property>
    <Method><![CDATA[Test]]></Method>
    <String><![CDATA[]]></String>
  </Token>
  <Token active="1">
    <Name><![CDATA[##TEST5##]]></Name>
    <Namespace></Namespace>
    <Class></Class>
    <Property><![CDATA[]]></Property>
    <Method><![CDATA[]]></Method>
    <String><![CDATA[This is just a simple string replacement]]></String>
  </Token>
</Tokens>

Open in new window

0
 
Carl TawnSystems and Integration DeveloperCommented:
Forgot one vital part. Do you have a sample of what "template" will contain?
0
 
kevp75Author Commented:
:)  sure:

 
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim _Template = "<div>" & _
                            "    <h1>##TEST1&ID=123&bob=yahoo&email=oioiujij##</h1>" & _
                            "    <h1>##TEST2##</h1>" & _
                            "    <h1>##TEST3##</h1>" & _
                            "    <h1>##TEST4&ID=123&a=1&b=2&c=3&d=4##</h1>" & _
                            "    <h1>##TEST5##</h1>" & _
                            "</div>"

        Using objTok As New ZipCM.Tokenator(_Template)
            With objTok
                Response.Write(.Tokenator())
            End With
        End Using
    End Sub

Open in new window

0
 
Carl TawnSystems and Integration DeveloperCommented:
Hmm, weird, it seems to be working fine for me. In so much as it returns "&ID=123&bob=yahoo&email=oioiujij" from the method call.
0
 
kevp75Author Commented:
can you post your code so I can see how it differs from mine?
0
 
Carl TawnSystems and Integration DeveloperCommented:
Class:
Imports System.Linq

Namespace ZipCM

    Public Class Tokenator
        Implements System.IDisposable

        Private objXml As XDocument
        Private _IT As Type = Nothing
        Private _Token() As Object
        Private _TokenQuery() As Object
        Private _Template As String

        Public Sub New(ByVal Template As String)
            objXml = XDocument.Load(HttpContext.Current.Server.MapPath("/Scripts/Tokens.config"))
            Dim _TokenRE As New Regex("\#\#([^&\n]*?)(&.*?)?\#\#")
            Dim _RCt As Long = 0
            Dim _TokenMatches As MatchCollection = _TokenRE.Matches(Template)
            Dim _T(_TokenMatches.Count - 1) As String
            Dim _TQ(_TokenMatches.Count - 1) As String
            For i As Integer = 0 To _TokenMatches.Count - 1
                _T(i) = _TokenMatches(i).Groups(1).Value
                _TQ(i) = _TokenMatches(i).Groups(2).Value
            Next
            _Token = _T
            _TokenQuery = _TQ
            _Template = Template
            Erase _T : Erase _TQ
        End Sub

        ''' <summary>
        ''' Process out tokens
        ''' </summary>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function Tokenator() As String
            Dim tmpI As Long
            For i As Long = 0 To _Token.GetUpperBound(0)
                tmpI = i
                Dim _Qry = (From n In objXml...<Token>.AsParallel().WithExecutionMode(ParallelExecutionMode.ForceParallelism) _
                           Where n.@active = 1 And n.<Name>.Value.Contains(_Token(tmpI)) _
                            Select n.<Name>, n.<Namespace>, n.<Class>, n.<Property>, n.<Method>, StrValue = n.<String>).ToList()
                If _Qry.Count > 0 Then
                    For Each r In _Qry
                        Dim _TmpTok = Invoker(r.Method.Value, r.Namespace.Value, r.Class.Value, r.Property.Value, r.StrValue.Value, New Object() {_TokenQuery(i)}) & ":::" & tmpI
                        _Template = _Template.Replace(r.Name.Value.Replace("##", String.Empty), _TmpTok).Replace(_TokenQuery(i), String.Empty)
                    Next
                End If
            Next
            Return _Template.Replace("##", String.Empty)
        End Function

        ''' <summary>
        ''' Invoke everything
        ''' </summary>
        ''' <param name="MethodName"></param>
        ''' <param name="NamespaceName"></param>
        ''' <param name="ClassName"></param>
        ''' <param name="PropertyName"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Private Function Invoker(ByVal MethodName As String, Optional ByVal NamespaceName As String = Nothing, Optional ByVal ClassName As String = Nothing, Optional ByVal PropertyName As String = Nothing, Optional ByVal StringValue As String = Nothing, Optional ByVal Params() As Object = Nothing) As String
            If (Len(PropertyName) > 0) Then
                If (Len(ClassName) > 0) Then
                    If Not (Len(NamespaceName) > 0) Then
                        _IT = Type.GetType(ClassName, True, True)
                    Else
                        _IT = Type.GetType(NamespaceName & "." & ClassName, True, True)
                    End If
                Else
                    _IT = Type.GetType(Me.ToString, True, True)
                End If
                Return CallByName(Activator.CreateInstance(_IT), PropertyName, CallType.Get)
            ElseIf Len(StringValue) > 0 Then
                Return StringValue
            Else
                If (Len(ClassName) > 0) Then
                    If Not (Len(NamespaceName) > 0) Then
                        _IT = Type.GetType(ClassName, True, True)
                    Else
                        _IT = Type.GetType(NamespaceName & "." & ClassName, True, True)
                    End If
                Else
                    _IT = Type.GetType(Me.ToString, True, True)
                End If
                If IsNothing(Params) Then
                    Return CallByName(Activator.CreateInstance(_IT), MethodName, CallType.Get)
                Else
                    Return CallByName(Activator.CreateInstance(_IT), MethodName, CallType.Get, Params)
                End If
            End If
        End Function

#Region "IDisposable Support"
        Private disposedValue As Boolean ' To detect redundant calls

        ' IDisposable
        Protected Overridable Sub Dispose(ByVal disposing As Boolean)
            If Not Me.disposedValue Then
                If disposing Then
                    ' TODO: dispose managed state (managed objects).
                End If
                Erase _Token
                Erase _TokenQuery
                _Template = String.Empty
                objXml = Nothing
                ' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
                ' TODO: set large fields to null.
            End If
            Me.disposedValue = True
        End Sub

        ' This code added by Visual Basic to correctly implement the disposable pattern.
        Public Sub Dispose() Implements IDisposable.Dispose
            ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
            Dispose(True)
            GC.SuppressFinalize(Me)
        End Sub

#End Region

    End Class
End Namespace

Open in new window

Page with dummy method:
Imports System.Data
Imports System.Data.OleDb
Imports System.Linq

Public Class _Default
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        Dim _Template = "<div>" & _
                            "    <h1>##TEST1&ID=123&bob=yahoo&email=oioiujij##</h1>" & _
                            "    <h1>##TEST2##</h1>" & _
                            "    <h1>##TEST3##</h1>" & _
                            "    <h1>##TEST4&ID=123&a=1&b=2&c=3&d=4##</h1>" & _
                            "    <h1>##TEST5##</h1>" & _
                            "</div>"

        Using objTok As New ZipCM.Tokenator(_Template)
            With objTok
                Response.Write(.Tokenator())
            End With
        End Using
    
    End Sub

    Public Function DoStuff(ByVal value As String) As String
        Return value & "modified"
    End Function

End Class

Open in new window

Tokens file:
<?xml version="1.0" encoding="utf-8" ?>
<Tokens>
  <Token active="1">
    <Name><![CDATA[##TEST1##]]></Name>
    <Namespace>WebApplication1</Namespace>
    <Class>_Default</Class>
    <Property><![CDATA[]]></Property>
    <Method><![CDATA[DoStuff]]></Method>
    <String><![CDATA[]]></String>
  </Token>
  <Token active="1">
    <Name><![CDATA[##TEST2##]]></Name>
    <Namespace>WebApplication1</Namespace>
    <Class>_Default</Class>
    <Property><![CDATA[]]></Property>
    <Method><![CDATA[DoStuff]]></Method>
    <String><![CDATA[]]></String>
  </Token>
  <Token active="1">
    <Name><![CDATA[##TEST3##]]></Name>
    <Namespace>WebApplication1</Namespace>
    <Class>_Default</Class>
    <Property><![CDATA[]]></Property>
    <Method><![CDATA[DoStuff]]></Method>
    <String><![CDATA[]]></String>
  </Token>
  <Token active="1">
    <Name><![CDATA[##TEST4##]]></Name>
    <Namespace>WebApplication1</Namespace>
    <Class>_Default</Class>
    <Property><![CDATA[]]></Property>
    <Method><![CDATA[DoStuff]]></Method>
    <String><![CDATA[]]></String>
  </Token>
  <Token active="1">
    <Name><![CDATA[##TEST5##]]></Name>
    <Namespace>WebApplication1</Namespace>
    <Class>_Default</Class>
    <Property><![CDATA[]]></Property>
    <Method><![CDATA[DoStuff]]></Method>
    <String><![CDATA[This is just a simple string replacement]]></String>
  </Token>
</Tokens>

Open in new window

0
 
kevp75Author Commented:
The only thing I can see different is that my Method "Test" comes from a class library...
0
 
Carl TawnSystems and Integration DeveloperCommented:
I'd try populating the _TokenQuery() array manually and making sure it has values, and try it with that. If you're sure it is calling the method correctly, but not passing parameters, then I thin you'll have to resort to replacing the dynamic parts with static values to isolate the problem.

The only other thing I can thing is that maybe the parallel part is causing the array to be populated out of sequence. That's only a wild guess though because i can't see any reason why it should.
0
 
kevp75Author Commented:
well...  the whole point is so it's dynamic...  but for this purpose I will try that manually.
0
 
kevp75Author Commented:
ok.  It works if I do this:

            For i As Integer = 0 To _TokenMatches.Count - 1
                _T(i) = _TokenMatches(i).Groups(1).Value
                _TQ(0) = "&email=bob@yahoo.com"
                _TQ(3) = "&a=123"
                'If _TokenMatches(i).Groups(2).Value IsNot Nothing Then
                '    _TQ(i) = "&email=bob@yahoo.com" '_TokenMatches(i).Groups(2).Value
                'Else
                '    _TQ(i) = ""
                'End If
            Next
0
 
kevp75Author Commented:
ready for this one.    It DOES NOT, and I repeat DOES NOT pull the data from the hardcoded _TQ, instead it now does the replacing correctly as it should from the token.config file....

make sense outta that one?   :(
0
 
kevp75Author Commented:
to reiterate...  this:
 
Public Sub New(ByVal Template As String)
            objXml = XDocument.Load(HttpContext.Current.Server.MapPath("/Scripts/Tokens.config"))
            Dim _TokenRE As New Regex("\#\#([^&\n]*?)(&.*?)?\#\#")
            Dim _RCt As Long = 0
            Dim _TokenMatches As MatchCollection = _TokenRE.Matches(Template)
            Dim _T(_TokenMatches.Count - 1) As String
            Dim _TQ(_TokenMatches.Count - 1) As String
            For i As Integer = 0 To _TokenMatches.Count - 1
                _T(i) = _TokenMatches(i).Groups(1).Value
                _TQ(0) = "&email=bob@yahoo.com"
                _TQ(3) = "&a=123"
                'If _TokenMatches(i).Groups(2).Value IsNot Nothing Then
                '    _TQ(i) = "&email=bob@yahoo.com" '_TokenMatches(i).Groups(2).Value
                'Else
                '    _TQ(i) = ""
                'End If
            Next
            _Token = _T
            _TokenQuery = _TQ
            _Template = Template
            Erase _T : Erase _TQ
        End Sub

Open in new window


does not return the values assigned....  it now returns the values attached to the tokens in the _Template variable
0
 
kevp75Author Commented:
so, I am extremely confused now.  When I hard code (0), etc to a value... doesn;t matter what the value is, it will grab the correct query from the token.config...  but when I try to dynamically fill it, the whole thing bombs out...

        Public Sub New(ByVal Template As String)
            objXml = XDocument.Load(HttpContext.Current.Server.MapPath("/Scripts/Tokens.config"))
            Dim _TokenRE As New Regex("(?<=##)([^&\n]*?)(&.*?)?(?=##)")
            Dim _RCt As Long = 0
            Dim _TokenMatches As MatchCollection = _TokenRE.Matches(Template)
            Dim _T(_TokenMatches.Count - 1) As String
            Dim _TQ(_TokenMatches.Count - 1) As String
            For i As Integer = 0 To _TokenMatches.Count - 1
                _T(i) = _TokenMatches(i).Groups(1).Value
                '_TQ(0) = " "
                '_TQ(3) = " "
                '_TQ(4) = " "
                If Not (Security.Required(_TokenMatches(i).Groups(2).Value)) Then
                    _TQ(i) = " "
                Else
                    _TQ(i) = Nothing
                End If
            Next
            _Token = _T
            _TokenQuery = _TQ
            _Template = Template
            Erase _T : Erase _TQ
        End Sub

0
 
kevp75Author Commented:
sorry.   the regex is wrong in the post above this.  it should read: \#\#([^&\n]*?)(&.*?)?\#\#
0
 
kevp75Author Commented:
got it.

I was checking if the match on the second group would produce a nothing, but I should have also included a check for an empty string, once I added that in to populate the _TQ array, it works

Thanks for the help with this one.!!!
0

Featured Post

NFR key for Veeam Agent for Linux

Veeam is happy to provide a free NFR license for one year.  It allows for the non‑production use and valid for five workstations and two servers. Veeam Agent for Linux is a simple backup tool for your Linux installations, both on‑premises and in the public cloud.

  • 20
  • 11
Tackle projects and never again get stuck behind a technical roadblock.
Join Now