Solved

Calling a shared method for XMLtextWriter

Posted on 2004-09-09
27
359 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
Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

 
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
 
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

Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Creating an analog clock UserControl seems fairly straight forward.  It is, after all, essentially just a circle with several lines in it!  Two common approaches for rendering an analog clock typically involve either manually calculating points with…
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
Microsoft Active Directory, the widely used IT infrastructure, is known for its high risk of credential theft. The best way to test your Active Directory’s vulnerabilities to pass-the-ticket, pass-the-hash, privilege escalation, and malware attacks …
A short tutorial showing how to set up an email signature in Outlook on the Web (previously known as OWA). For free email signatures designs, visit https://www.mail-signatures.com/articles/signature-templates/?sts=6651 If you want to manage em…

776 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