InvalidOperationException when trying to add XElement to XDocument - vb.net

I'm getting this error when I try to add a XElement to a XDocument:
An exception of type 'System.InvalidOperationException' occurred in
System.Xml.Linq.ni.dll but was not handled in user code
My code is:
Imports System.Xml
Imports System.Xml.Linq
Imports System.IO.IsolatedStorage
Imports System.IO
Public Sub SaveRecord()
Using myIsolatedStorage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication()
Dim doc As XDocument
Using isoStore1 As IsolatedStorageFile = _
IsolatedStorageFile.GetUserStoreForApplication()
Using isoStream1 As IsolatedStorageFileStream = New IsolatedStorageFileStream("file.xml", FileMode.Open, isoStore1)
doc = XDocument.Load(isoStream1)
MessageBox.Show(doc.ToString)
'This gives the right xml-code
doc.Add(New XElement("NewChild", "new content")) 'This is where the error takes place
MessageBox.Show(doc.ToString)
Using isoStore As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication()
Using isoStream As IsolatedStorageFileStream = New IsolatedStorageFileStream("file.xml", FileMode.Create, isoStore)
doc.Save(isoStream)
End Using
End Using
End Using
End Using
End Using
Exit Sub
End Sub
The error shows up when the debugger enters the line doc.Add(New XElement("NewChild", "new content"))
Can anyone explain to me what the cause of this error is and how I can solve it?

You need to add your XElement to your XDocuments root.
doc.Root.Add(New XElement("NewChild", "new content"))
Adding it directly to the doc will make your xml invalid as it will be having two roots because you are adding the XElement after your XDocument instead of to the root.

Related

Extracting `dll` files from the Resources after they been added using CodeDOM in VB.Net

I'v seen a lot of answers here on stackoverflow, but none of them help me with exactly what i need and almost all of them in C# when i need VB, so i hope someone will help me with my problem, which is this :
I have compiled a exe file in vb.net using CodeDOM, and i added two dll file to its resources and that worked just fine and you can even notice that the size of the exe has increase after adding the resources, but when i run the exe file like that My.Resources.Touchless, it gives me an error saying that
"Resources" is not a member of "My".
And what i need is to read these dll files from the compiled exe file and then extract them using File.WriteAllBytes()..., if i didn't try to extract the files from the resources and instead of that i copied them manually to the executable path, the application will work perfectly, so the problem is just with trying to call the dll files from the resources.
Here is some code :
Public Shared Function Compile(ByVal Output As String, ByVal Source As String, ByVal Icon As String, ByVal resources As String) As Boolean
Dim Parameters As New CompilerParameters()
Dim cResults As CompilerResults = Nothing
Dim Compiler As CodeDomProvider = CodeDomProvider.CreateProvider("VB")
Parameters.GenerateExecutable = True
Parameters.TreatWarningsAsErrors = False
Parameters.OutputAssembly = Output
Parameters.MainClass = "MyNamespace.MainWindow"
Parameters.EmbeddedResources.Add(Path.GetTempPath & "TouchlessLib.dll")
Parameters.EmbeddedResources.Add(Path.GetTempPath & "WebCamLib.dll")
Parameters.ReferencedAssemblies.AddRange(New String() {"System.dll", "System.Drawing.dll", "System.Windows.Forms.dll", "System.Management.dll", Path.GetTempPath & "TouchlessLib.dll"})
Parameters.CompilerOptions = "/platform:x86 /target:winexe"
If Not String.IsNullOrEmpty(Icon) Then
File.Copy(Icon, "icon.ico")
Parameters.CompilerOptions += " /win32icon:" & "icon.ico"
End If
cResults = Compiler.CompileAssemblyFromSource(Parameters, Source)
If cResults.Errors.Count > 0 Then
For Each compile_error As CompilerError In cResults.Errors
Dim [error] As CompilerError = compile_error
Console.Beep()
MsgBox("Error: " & [error].ErrorText & vbCr & vbLf & [error].Line)
Next
Return False
End If
If Not (String.IsNullOrEmpty(Icon)) Then
File.Delete("icon.ico")
End If
Return True
End Function
When i call them from the compiled exe file like this :
File.WriteAllBytes(Application.StartupPath & "\TouchlessLib.dll", My.Resources.TouchlessLib)
File.WriteAllBytes(Application.StartupPath & "\WebCamLib.dll", My.Resources.WebCamLib)
... i get the following error message :
"Resources" is not a member of "My".
Try adding this class:
Imports System.Dynamic
Imports System.Reflection
Public Class DynamicResources
Inherits DynamicObject
Public Overrides Function TryGetMember(binder As GetMemberBinder, ByRef result As Object) As Boolean
Dim asm As Assembly = Assembly.GetExecutingAssembly()
Dim resouceNames As String() = asm.GetManifestResourceNames
For Each s As String In resouceNames
Dim name As String = IO.Path.GetFileNameWithoutExtension(s)
Dim Manager As New Resources.ResourceManager(name, asm)
Try
Dim resource = Manager.GetObject(binder.Name)
If Not resource Is Nothing Then
result = resource
Return True
End If
Catch ex As Exception
End Try
Next
Return False
End Function
End Class
You can use it like this:
Dim root as string=Application.StartupPath
File.WriteAllBytes(Path.Combine(root, "TouchlessLib.dll"), DynamicResources.TouchlessLib)
File.WriteAllBytes(Path.Combine(root, "WebCamLib.dll"), DynamicResources.WebCamLib)
The My namespace and any associated functionality is created via auto-generated code. Since your code is now the code generator and not the IDE, you will not have those niceties unless your code provides it.
To extract an embedded resource, you need to include code similar to the following in the source code you are compiling with CodeDOM.
Dim asm As Assembly = Assembly.GetExecutingAssembly()
Dim resouceNames As String() = asm.GetManifestResourceNames
For Each s As String In resouceNames
Dim fi As New FileInfo(s)
Using strm As Stream = asm.GetManifestResourceStream(s)
Using fs As Stream = fi.Create()
strm.CopyTo(fs)
End Using
End Using
Next
Make sure that you also include:
Imports System.Reflection
Imports System.IO
This code retrieves the executing Assembly obtains an array of embedded resource names. It then calls GetManifestResourceStream method to get the named resource as a stream. This stream is copied to a file stream.
Modify the example to suite your needs.
Note that I have not included any error checking/handling in this example. Anything dealing with IO should have some error handling.
Edit:
Based on the comment below, it appears that only a copy/paste type answer will do for the OP.
Dim asm As Assembly = Assembly.GetExecutingAssembly()
Dim resourceName As String
Dim fi As FileInfo
resourceName = "TouchlessLib.dll"
fi = New FileInfo(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, resourceName))
Using strm As Stream = asm.GetManifestResourceStream(resourceName)
Using fs As Stream = fi.Create()
strm.CopyTo(fs)
End Using
End Using

How to create global obects in vb.net

I'm using visual studio 2015.
I'm clearly missing some things...
I want to create a global filestream and stream writer.
Dim wFile As System.IO.FileStream = New FileStream _
("C:\inetpub\wwwroot\SummitMap1Local\Labels\BufferedData.txt", FileMode.Append)
Dim sw As New StreamWriter(wFile)
This works fine. BUT I need to access it globally. Ideally the code would be in its own .aspx file and the wFile and sw objects could be used in a different .aspx file.
Thanks
(odd that I need to edit my original post to add new info)
I am now trying to add a class based on info from MSDN. It's not working. Code -
Imports System
Imports System.IO
Imports System.Text
Public Class test
Public Shared Sub CreateFileStream()
Dim fs As FileStream = New FileStream("C:\inetpub\wwwroot\SummitMap1Local\Labels\BufferedData.txt", FileMode.Append
End Sub
End Class
Then trying to use the class in a function -
Protected Function bufferList(ByVal testData As String) As String
Try
Dim sw As New StreamWriter(fs)
sw.WriteLine(testData)
End Try
End Function
I get an error on 'Dim sw As New StreamWriter(fs)' fs is not declared. It may be inaccessible due to it's protection level
I've tried calling it with test.fs, but test does not have an fs property.

How to use Stream to get String

I have a method in a third-party tool that has the following criteria:
ExportToXML(fileName As String) 'Saves the content to file in a form of XML document
or
ExportToXML(stream As System.IO.Stream) 'Saves the content to stream in a form of XML document
How do I use the call with the stream as the parameter to get the XML as a string?
I have researched and tried several things and just still can't get it..
You can use a MemoryStream as the stream to export the XML to, and then read the MemoryStream back with a StreamReader:
Option Infer On
Imports System.IO
Module Module1
Sub Main()
Dim xmlData As String = ""
Using ms As New MemoryStream
ExportToXML(ms)
ms.Position = 0
Using sr As New StreamReader(ms)
xmlData = sr.ReadToEnd()
End Using
End Using
Console.WriteLine(xmlData)
Console.ReadLine()
End Sub
' a dummy method for testing
Private Sub ExportToXML(ms As MemoryStream)
Dim bytes = Text.Encoding.UTF8.GetBytes("Hello World!")
ms.Write(bytes, 0, bytes.length)
End Sub
End Module
Added: Alternatively, as suggested by Coderer:
Using ms As New MemoryStream
ExportToXML(ms)
xmlData = Text.Encoding.UTF8.GetString(ms.ToArray())
End Using
A small effort at testing did not show any discernible efficiency difference.

Adding headers with iTextSharp in VB.NET

I'm wondering how can I put a header into my PDF file, cause I've tried the tutorials from here:
http://itextsharp.sourceforge.net/tutorial/ch04.html
And it has not worked.
I've done this:
Dim head As New HeaderFooter(New Phrase("This is page: "), False)
head.Border = Rectangle.NO_BORDER
document.Header = head
But VS2008 says that HeaderFooter is not defined (line 1), and Footer it's not a member of "iTextSharp.text.document" (line 3).
I've already included the imports at the beginning of my code and iIdon't have any other problems with the iTextsharps (I mean that it is working apart of the header problem):
Imports iTextSharp.text
Imports iTextSharp.text.pdf
Imports System.Data.SQLite
Imports System.IO
So please, can anyone explain to me how can i set a header for my pages?
Regards
The answer to this question depends on which version of the iTextSharp dll you are using.
If you are using a version lower than 5, this should work
Imports iTextSharp.text.pdf
Imports iTextSharp.text
Module Module1
Sub Main()
Dim pdfWrite As PdfWriter
Dim pdfDoc As New Document()
Dim pdfMemoryStream As New IO.FileStream("tryme.pdf", IO.FileMode.Create)
pdfWrite = PdfWriter.GetInstance(pdfDoc, pdfMemoryStream)
Dim pdfHeader As New HeaderFooter(New Phrase("Im at the head: "), False)
pdfHeader.Border = Rectangle.NO_BORDER
pdfDoc.Header = pdfHeader
pdfDoc.Open()
pdfDoc.Add(New Paragraph("Hello World"))
pdfDoc.NewPage()
pdfDoc.Add(New Paragraph("Hello World Again"))
pdfDoc.Close()
End Sub
End Module
Update
For version 5+ of iTextSharp the HeaderFooter property has been removed from iTextSharp. To add Headers/Footers now you must use PageEvents. The following code demonstrates how to do this (very simply!)
Imports iTextSharp.text.pdf
Imports iTextSharp.text
Imports System.IO
Module Module1
Sub Main()
Dim pdfDoc As New Document()
Dim pdfWrite As PdfWriter = PdfWriter.GetInstance(pdfDoc, New FileStream("tryme2.pdf", FileMode.Create))
Dim ev As New itsEvents
pdfWrite.PageEvent = ev
pdfDoc.Open()
pdfDoc.Add(New Paragraph("Hello World"))
pdfDoc.NewPage()
pdfDoc.Add(New Paragraph("Hello World Again"))
pdfDoc.Close()
End Sub
End Module
Public Class itsEvents
Inherits PdfPageEventHelper
Public Overrides Sub OnStartPage(ByVal writer As iTextSharp.text.pdf.PdfWriter, ByVal document As iTextSharp.text.Document)
Dim ch As New Chunk("This is my Stack Overflow Header on page " & writer.PageNumber)
document.Add(ch)
End Sub
End Class

Getting a list of users on a network domain

I want to get back to get a list of users on a network domain using VB.Net.
I will have the domain name available to me for use.
Thanks in advance.
It might throw an error in the select query.
Please check this:
Did you add a reference to the System.Management assembly to your project? If you haven't, do this:
In VS, click on Project menu > add reference.
On the .Net tab, scroll down until you see System.Management. Click on it to select, then click OK.
Now back in your code, at the very top of your class, put in "Imports System.Management", and you should be all set.
Source:
http://www.vbforums.com/showthread.php?t=560422
It worked for me without any issues. I am able to get all user names for the domain.
Something like this might point you in the right direction, using System.DirectoryServices and System.DirectoryServices.ActiveDirectory:
Private Function GetDomainUsers(ByVal domainDirectoryEntry As DirectoryEntry, ByRef userList As IList) As Integer
Try
userList = New ArrayList()
Using domainDirectoryEntry
Dim ds As New DirectorySearcher(domainDirectoryEntry, "(&(objectCategory=person)(objectClass=user))", New String() {"distinguishedName"})
Using src As SearchResultCollection = ds.FindAll()
For Each sr As SearchResult In src
userList.Add(sr.Properties("distinguishedName")(0))
Next
End Using
End Using
Return userList.Count
Catch generatedExceptionName As Exception
userList = Nothing
Return -1
Finally
domainDirectoryEntry = Nothing
End Try
End Function
Imports System.Management
Imports System.Management.Instrumentation
Sub PrintDomainUsers()
Dim domainName As String = System.Environment.UserDomainName.ToString
Dim userQuery As SelectQuery = New SelectQuery("Win32_UserAccount", "Domain='" & domainName & "'")
Try
Dim userSearch As ManagementObjectSearcher = New ManagementObjectSearcher(userQuery)
For Each domainUser In userSearch.Get
Console.WriteLine(domainUser("Name"))
Next
Catch ex As Exception
Throw ex
End Try
End Sub
This works but how do i filter by a certain group. Im getting THOUSANDS of resutls
Another option would be exploring System.Management and System.Management.Instrumentation.Here is a short snippet of how you pull the users of a particular domain using these namespaces.
Imports System.Management
Imports System.Management.Instrumentation
Sub PrintDomainUsers()
Dim domainName As String = System.Environment.UserDomainName.ToString
Dim userQuery As SelectQuery = New SelectQuery("Win32_UserAccount", "Domain='" & domainName & "'")
Try
Dim userSearch As ManagementObjectSearcher = New ManagementObjectSearcher(userQuery)
For Each domainUser In userSearch.Get
Console.WriteLine(domainUser("Name"))
Next
Catch ex As Exception
Throw ex
End Try
End Sub