Solved

Calling a shared method for XMLtextWriter

Posted on 2004-09-09
27
353 Views
Last Modified: 2008-02-01
I have the following code in a class name Invoice.  I am trying to call each of the below procedures from my form class by using Invoice.OpenInvoice()... getting an error "Access of a shared member through an instance".  How do I call these shared methods from my form?

Shared Sub OpenInvoices()
'writes XML declaration..start tag called from load event of form
        Dim writer As New XmlTextWriter(Path, Nothing)
        writer.Formatting = Formatting.Indented
        writer.WriteStartDocument()
        writer.WriteStartElement("Invoices")
        writer.Close()
    End Sub

'writes invoice elements for each invoice click event  
 Public Sub WriteInvoice(ByVal writer As XmlTextWriter)
        writer.WriteStartElement("Invoice")
        writer.WriteAttributeString("Customer", sCustomerName)
        writer.WriteElementString("OrderTotal", CStr(dOrderTotal))
        writer.WriteElementString("Discount", CStr(dDiscountAmount))
        writer.WriteElementString("InvoiceTotal", CStr(dInvoiceTotal))
        writer.WriteEndElement()
    End Sub
'writes end tag and closes
    Shared Sub CloseInvoices()
        Dim writer As New XmlTextWriter(Path, Nothing)
        writer.WriteEndElement()
        writer.Close()
    End Sub
0
Comment
Question by:bamoon
  • 13
  • 7
  • 4
27 Comments
 
LVL 5

Expert Comment

by:thenrich
ID: 12019532
try this: instead of 'Invoice.OpenInvoice' Import the class that has OpenInvoice and then just call OpenInvoice from the Form
0
 
LVL 5

Expert Comment

by:thenrich
ID: 12019541
Your trying to Access it through The Instance of Invoice and you don't need too.
0
 

Author Comment

by:bamoon
ID: 12019900
Ok that seemed to clear up that error now I have the error "Object reference not set to an instance of an object" on the line writer.WriteStartElement("Invoice") under WriteInvoice
0
 
LVL 5

Expert Comment

by:thenrich
ID: 12019935
You need to Dimension 'writer'. That function is not shared and therefore does not have writer in it's scope from the shared functions.
0
 

Author Comment

by:bamoon
ID: 12020456
For some reason the program does not seem to be writing my top start element, error message when opening file .."XML document must have a top level element. Error processing resource 'file:..."  I had dimensioned writer in the form class then changed the code to dimension in the Invoice class.  But now this seems now to be a problem in OpenInvoices.
0
 
LVL 4

Expert Comment

by:Javert93
ID: 12021875
Revert all of your code to what you started with and simply mark the WriteInvoice() and CloseInvoice() functions as Shared.
0
 
LVL 5

Expert Comment

by:thenrich
ID: 12025646
Javert93 ,
He'd still need to Dim a writer varibale for the Public Sub WriteInvoice(ByVal writer As XmlTextWriter) sub
0
 

Author Comment

by:bamoon
ID: 12027711
I changed it back and made all methods shared. now on open I get the error message System.IO.IOException: The process can not access the file because it is being used by another process. I have a module level variable Path in the invoice class and dim Path in the form class.

0
 
LVL 5

Expert Comment

by:thenrich
ID: 12027786
you need to put a writer.close in the  Public Sub WriteInvoice(ByVal writer As XmlTextWriter)
0
 

Author Comment

by:bamoon
ID: 12027857
I tried that still the same error.
0
 
LVL 5

Expert Comment

by:thenrich
ID: 12027860
it's very unclear to me what you are trying to even do...
It doesn't make any sense to me.
0
 
LVL 5

Expert Comment

by:thenrich
ID: 12027889
Make everything un-shared intantiate the class and call it by.

Invoice.CloseInvoices
Invoice.WriteInvoice
or
Invoice.OpenInvoices

Why do you even have those subs marked as shared?
0
Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

 
LVL 5

Expert Comment

by:thenrich
ID: 12027966
Once you have a pointer to the writer why not just keep it around:

Imports System.Xml
Public Class Invoice
    Public Function OpenInvoices() As XmlTextWriter
        Try
            'writes XML declaration..start tag called from load event of form
            Dim writer As New XmlTextWriter("Path", Nothing)
            writer.Formatting = Formatting.Indented
            writer.WriteStartDocument()
            writer.WriteStartElement("Invoices")
            writer.Close()
            Return writer
        Catch ex As Exception
            MsgBox(ex.Message)
            Return Nothing
        End Try
    End Function

    'writes invoice elements for each invoice click event  
    Public Function WriteInvoice(ByVal writer As XmlTextWriter) As XmlTextWriter
        Try
            writer.WriteStartElement("Invoice")
            writer.WriteAttributeString("Customer", "sCustomerName")
            writer.WriteElementString("OrderTotal", CStr("dOrderTotal"))
            writer.WriteElementString("Discount", CStr("dDiscountAmount"))
            writer.WriteElementString("InvoiceTotal", CStr("dInvoiceTotal"))
            writer.WriteEndElement()
            Return writer
        Catch ex As Exception
            MsgBox(ex.Message)
            Return Nothing
        End Try
    End Function
    'writes end tag and closes

    Public Function CloseInvoices(ByVal writer As XmlTextWriter) As Boolean
        Try
            writer.WriteEndElement()
            writer.Close()
            Return True
        Catch ex As Exception
            MsgBox(ex.Message)
            Return False
        End Try
    End Function
End Class
0
 
LVL 5

Expert Comment

by:thenrich
ID: 12028067
Works perfectly - take the:
 
writer.Close()

out of the OpenInvoice function and here is what I put in the form to test it:


''' Form test code
    Dim I1 As New Invoice
        I1.CloseInvoices(I1.WriteInvoice(I1.OpenInvoices))
0
 

Author Comment

by:bamoon
ID: 12028150
still getting the execption file being used.
0
 
LVL 5

Expert Comment

by:thenrich
ID: 12028169
I can't help then, I tested the code I posted and it works fine.

0
 
LVL 5

Accepted Solution

by:
thenrich earned 125 total points
ID: 12028181
You either have the file physically open or there is someother pieace of code you are not showing.
0
 
LVL 4

Expert Comment

by:Javert93
ID: 12028752
One of two things will cause the IO exception: either the file is open by another process (or the same process), or you do not have permission to access the file. Try downloading process explorer from http://www.sysinternals.com for the former issue, and check the security permissions on both the file and the directory for the latter issue.
0
 

Author Comment

by:bamoon
ID: 12028971
Here is all of it..the file is on my personal computer so I know it's not being used, and I do have permission to access.

'Invoice Class
Imports Microsoft.VisualBasic

Imports System.Xml

Module mItotal
    Public dInvoiceTotal As Decimal
    Public sCustomerName As String
    Public dOrderTotal As Decimal
    Public dDiscountAmount As Decimal
   
End Module

Public Class Invoice

    Public InvInfo As InvoiceInfo
   

    Public Property CustomerName() As String
        Get
            Return sCustomerName
        End Get
        Set(ByVal value As String)
            sCustomerName = value
        End Set
    End Property

    Public Property OrderTotal() As Decimal
        Get
            Return dOrderTotal
        End Get
        Set(ByVal value As Decimal)
            dOrderTotal = value
        End Set
    End Property

    Public ReadOnly Property DiscountAmount() As Decimal
        Get
            Return dDiscountAmount
        End Get
    End Property

    Public ReadOnly Property InvoiceTotal() As Decimal
        Get
            Return dInvoiceTotal
        End Get
    End Property

    Public Sub AddItem(ByVal UnitPrice As Decimal, _
            ByVal Quantity As Integer)
        dOrderTotal = dOrderTotal + (UnitPrice * Quantity)
        dDiscountAmount = Discount(dOrderTotal)
        dInvoiceTotal = dOrderTotal - dDiscountAmount

    End Sub
    Private Function Discount(ByVal OrderTotal As Decimal) As Decimal
        Dim dDiscountPct As Decimal
        Select Case OrderTotal
            Case Is >= 500
                dDiscountPct = 0.3
            Case Is >= 200
                dDiscountPct = 0.2
            Case Is >= 100
                dDiscountPct = 0.1
            Case Else
                dDiscountPct = 0
        End Select
        Return Math.Round(OrderTotal * dDiscountPct, 2)
    End Function
    Structure InvoiceInfo
        Dim Cust As String
        Dim OTotal As Decimal
        Dim ITotal As Decimal
        Dim DAmt As Decimal
    End Structure
    Public Function OpenInvoices(ByVal Path As String) As XmlTextWriter

        Try
            'writes XML declaration..start tag called from load event of form
            Dim writer As New XmlTextWriter(Path, Nothing)
            writer.Formatting = Formatting.Indented
            writer.WriteStartDocument()
            writer.WriteStartElement("Invoices")
            'writer.Close()
            Return writer
        Catch ex As Exception
            MsgBox(ex.Message)
            Return Nothing
        End Try
    End Function

    'writes invoice elements for each invoice click event  
    Public Function WriteInvoice(ByVal writer As XmlTextWriter) As XmlTextWriter
        Try
            writer.WriteStartElement("Invoice")
            writer.WriteAttributeString("Customer", "sCustomerName")
            writer.WriteElementString("OrderTotal", CStr("dOrderTotal"))
            writer.WriteElementString("Discount", CStr("dDiscountAmount"))
            writer.WriteElementString("InvoiceTotal", CStr("dInvoiceTotal"))
            writer.WriteEndElement()
            Return writer
        Catch ex As Exception
            MsgBox(ex.Message)
            Return Nothing
        End Try
    End Function


    'writes end tag and closes

    Public Function CloseInvoices(ByVal writer As XmlTextWriter) As Boolean
        Try
            writer.WriteEndElement()
            writer.Close()
            Return True
        Catch ex As Exception
            MsgBox(ex.Message)
            Return False
        End Try
    End Function

End Class

'Form Class

Option Explicit On

Imports System.Xml
Module mQ
    Public qInvoice As New Queue
    Public SortedItemList As New SortedList(5)
End Module
Partial Class Invoice_aspx


    Dim Invoice As Invoice
    Dim Path As String = "..\Invoices.xml"
    Dim writer As New XmlTextWriter(Path, Nothing)
   
    Public Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
       
        Invoice = New Invoice()
        txtCustomerName.Focus()
        btnNewInvoice.Enabled = False


        Dim ItemEntry As DictionaryEntry
        If SortedItemList.Count = 0 Then
            SortedItemList.Add(1000, 19.95)
            SortedItemList.Add(2000, 9.95)
            SortedItemList.Add(3000, 29.95)
            SortedItemList.Add(4000, 69.95)
            SortedItemList.Add(5000, 129.95)

            For Each ItemEntry In SortedItemList
                cmbItem.Items.Add(ItemEntry.Key)
            Next
        End If
        Invoice.OpenInvoices(Path)
    End Sub
    Private Sub btnadditem_click(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles btnAddItem.Click
       
        Invoice.AddItem(CDec(txtUnitPrice.Text), CInt(txtQuantity.Text))
        lblOrderTotal.Text = FormatNumber(Invoice.OrderTotal)
        lblDiscountAmount.Text = FormatNumber(Invoice.DiscountAmount)
        lblInvoiceTotal.Text = FormatNumber(Invoice.InvoiceTotal)

        txtUnitPrice.Text = ""
        txtQuantity.Text = ""
        txtUnitPrice.Focus()
        btnNewInvoice.Enabled = True
        InvoiceTotal(iIndex) = CDec(Me.lblInvoiceTotal.Text)
        iIndex += 1
        InvoiceArray.Add(Invoice.InvoiceTotal)


    End Sub

    Private Sub btnNewInvoice_Click(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles btnNewInvoice.Click

        Invoice.CustomerName = txtCustomerName.Text
        MsgBox("Order Total: " & _
                    FormatCurrency(Invoice.OrderTotal) & _
                    ControlChars.CrLf & _
                "Discount Amount: " & _
                    FormatCurrency(Invoice.DiscountAmount) & _
                    ControlChars.CrLf & _
                "Invoice Total: " & _
                    FormatCurrency(Invoice.InvoiceTotal), , _
                "Invoice for Customer " & Invoice.CustomerName)
        Invoice.WriteInvoice(writer)
        Invoice.OrderTotal = 0
        Invoice = New Invoice()
        lblOrderTotal.Text = ""
        lblDiscountAmount.Text = ""
        lblInvoiceTotal.Text = ""
        txtCustomerName.Text = ""
        txtUnitPrice.Text = ""
        txtQuantity.Text = ""
        cmbItem.SelectedItem.Selected = False
        txtCustomerName.Focus()
        btnNewInvoice.Enabled = False
        qInvoice.Enqueue(Invoice.CustomerName & " " & FormatCurrency(Invoice.InvoiceTotal))

    End Sub

    Sub btnExit_Click(ByVal sender As Object, ByVal e As System.EventArgs)
       
        Invoice.CloseInvoices(writer)

    End Sub

    Public Sub cmbItem_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
       
        txtUnitPrice.Text = SortedItemList.Item(CInt(cmbItem.SelectedItem.Value))

    End Sub

   

   
End Class
Module mInvoice
    Public InvoiceTotal(4) As Decimal
    Public iIndex As Integer
    Public dInvoiceTotal As Decimal
    Public InvoiceArray As New ArrayList(4)
End Module
0
 
LVL 4

Expert Comment

by:Javert93
ID: 12029151
This is an ASP.NET application? The most likely problem is that IUSER_<Machine Name> does not have access to the file. You need to explicitly give this account write permissions on the folder and file before you can access it. Under a default installation, anonymous reuqests to a Web Application run under the IUSER_<Machine Name> account, which does not have permission to write to the file system (note that you need to replace <Machine Name> with the name of your computer). Also, watch out for the execute permission (especially if the file is accessible from IIS), because that could allow a remote user to write an executable to the directory and execute it.
0
 
LVL 5

Expert Comment

by:thenrich
ID: 12029427
Yea - he's right. Depending on which OS your using if you right mouse click on the directory you should find a tab to allow you to set ASP.NET permissions.
0
 

Author Comment

by:bamoon
ID: 12029475
How do I give IUSER_ <Maching Name> permission?  The file that is created is not read only.
0
 
LVL 5

Expert Comment

by:thenrich
ID: 12029495
Why does this seem to be the never ending question?
0
 
LVL 4

Assisted Solution

by:Javert93
Javert93 earned 125 total points
ID: 12029644
To set, view, change, or remove file and folder permissions (assuming you are using Windows XP):

    1) Open Windows Explorer, and then locate the file or folder for which you want to set permissions.
    2) Right-click the file or folder, click Properties, and then click the Security tab.
    3) Click Add. In the "select users" dialog box, type the name of the group or user you want to set permissions for and then click OK (in your case, IUSR_<Machine Name>).
    4) Select the "Internet User (IUSR_<Machine Name>)" account from the list.
    5) Check the "Modify", "Read", and "Write" check boxes (all others should be unchecked).
    6) Click OK.

This is the procedure for Windows XP, but you can look in the Windows Help File for the exact procedure if you are using Windows 2000. After you set the folder permissions, you need to go into Internet Services Administrator and check the "Write" check box in the property page for the target folder (DO NOT check execute). That should allow you to write your file.
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

If you're writing a .NET application to connect to an Access .mdb database and use pre-existing queries that require parameters, you've come to the right place! Let's say the pre-existing query(qryCust) in Access takes a Date as a parameter and l…
Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…
This video shows how to remove a single email address from the Outlook 2010 Auto Suggestion memory. NOTE: For Outlook 2016 and 2013 perform the exact same steps. Open a new email: Click the New email button in Outlook. Start typing the address: …

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now