I am writing an MVC application that will export data to a CSV file. I have some data pulled via a Linq query, and the query pulls all the correct records, but the data is not being completely written to the stream. I get partial or no data at all when I check the stream before it is returned to the user.
The FileHelpers Class
Imports FileHelpers
<DelimitedRecord(",")> _
Public Class AssetSearchFileHelper
<FieldOrder(1), FieldQuoted()> _
Public AssetNumber As String
<FieldOrder(2), FieldQuoted()> _
Public AssetDescription As String
<FieldOrder(3), FieldQuoted()> _
Public SerialNumber As String
<FieldOrder(4), FieldQuoted()> _
Public ClassName As String
<FieldOrder(5), FieldQuoted()> _
Public ManufacturerName As String
<FieldOrder(6), FieldQuoted()> _
Public ModelName As String
<FieldOrder(7), FieldQuoted()> _
Public LocationName As String
<FieldOrder(8), FieldQuoted()> _
Public AssignedTo As String
End Class
The code that creates the stream and then writes to it.
Dim asfhTemp As List(Of AssetSearchFileHelper) = (From a In lstFilteredAssets
Select New AssetSearchFileHelper With { _
.AssetNumber = a.AssetNumber, _
.AssetDescription = a.AssetDescription, _
.SerialNumber = a.SerialNumber, _
.ClassName = a.ClassName, _
.ManufacturerName = a.ManufacturerName, _
.ModelName = a.ModelName, _
.LocationName = a.LocationName, _
.AssignedTo = a.UserFullName}).ToList()
Dim dle As New DelimitedFileEngine(GetType(AssetSearchFileHelper))
Dim mStream As New MemoryStream
dle.HeaderText = """Asset #"",""Type"",""Serial #"",""Class"",""Make"",""Model"",""Location"",""Assigned To"""
Dim sw As New StreamWriter(mStream)
dle.WriteStream(sw, asfhTemp)
mStream.Position = 0
You need to Close or Flush the stream, internally .net don't write to the stream right away, it just buffer the info and write it when buffer is full or when stream is close just add this line
mStream.Close()
or with
mStream.Flush()
After the WriteStream
Just had this problem myself. The solution is to set the AutoFlush property on the StreamWriter object to true. The following should work:
Dim sw As New StreamWriter(mStream)
sw.AutoFlush = True
Related
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
lblSystemSerialNumbers.Text = SystemSerialNumber()
lblCpuIds.Text = CpuId()
End Sub
Private Function SystemSerialNumber() As String
' Get the Windows Management Instrumentation object.
Dim wmi As Object = GetObject("WinMgmts:")
' Get the "base boards" (mother boards).
Dim serial_numbers As String = ""
Dim mother_boards As Object = wmi.InstancesOf("Win32_BaseBoard")
For Each board As Object In mother_boards
serial_numbers &= ", " & board.SerialNumber
Next board
If serial_numbers.Length > 0 Then serial_numbers = serial_numbers.Substring(2)
Return serial_numbers
End Function
Private Function CpuId() As String
Dim computer As String = "."
Dim wmi As Object = GetObject("winmgmts:" & _
"{impersonationLevel=impersonate}!\\" & _
computer & "\root\cimv2")
Dim processors As Object = wmi.ExecQuery("Select * from Win32_Processor")
Dim cpu_ids As String = ""
For Each cpu As Object In processors
cpu_ids = cpu_ids & ", " & cpu.ProcessorId
Next cpu
If cpu_ids.Length > 0 Then cpu_ids = cpu_ids.Substring(2)
Return cpu_ids
End Function
End Class
This code will retrieve the CPU id and the motherboard id. How do I ensure that this will work even when option strict is on.
Why this could be a problem?
Well, let's see. The type of wmi is Object. That wmi do not necessarily support methods like InstancesOf, and SerialNumber
So how can we pull this out?
I think object that we got from GetObject is not just pure object. I think we should ctype or direct cast it to a more appropriate type. That more appropriate type will support methods like InstancesOf, SerialNumber, etc.
However what are the appropriate types?
You could use the ManagementObjectSearcher from the WMI classes hosted inside the System.Management.dll assembly.
(And you need to add the appropriate reference).
In this way you could write the SystemSerialNumber as
Private Function SystemSerialNumber(computer As String) As String
Dim wmi = New ManagementObjectSearcher(computer & "\root\cimv2", "select * from Win32_BaseBoard")
Dim boards = New List(Of String)()
For Each board In wmi.Get()
Dim temp = board.Properties("SerialNumber").Value?.ToString()
If Not String.IsNullOrEmpty(temp) Then
boards.Add(temp)
End If
Next board
Return String.Join(", ", boards)
End Function
The CpuId function is a bit more complex because you want to set the Impersonate flags but it is still possible to write a method around the NET wrapper classes for WMI interfaces
Private Function CpuId(computer As String) As String
Dim cpu = New List(Of String)()
Dim options = New ConnectionOptions()
options.Impersonation = System.Management.ImpersonationLevel.Impersonate
Dim scope = New ManagementScope(computer & "\root\cimv2", options)
scope.Connect()
Dim query = New ObjectQuery("Select * from Win32_Processor")
Dim wmi = New ManagementObjectSearcher(scope, query)
For Each m As ManagementObject In wmi.Get()
Dim temp = m.Properties("ProcessorId").Value?.ToString()
If Not String.IsNullOrEmpty(temp) Then
cpu.Add(temp)
End If
Next
Return String.Join(", ", cpu)
End Function
I wrote a dll in Visual Basic on Visual Studio 2013 (what it does is irrelevant now):
Namespace TextFiles
Public Class ConfigTextFiles
'Library of functions to handle configuration text files holding pairs of parm-name, param-value.
'Param-name and Param-value are separated by the Delimiter property, or "=" if not set.
Shared strDelimiter As String
Shared intRowsCount As Integer
Public Shared Function getParamValue(ByVal strFileLocation As String, ByVal strFileName As String, ByVal strParamName As String) As String
'Return the value of a specific parameter within the text file
'Return an empty string if param-name is not found
'Return vbNullChar if file was not found
Dim TextLine() As String
Dim strFullFileName As String
If Right(strFileLocation, 1) = "\" Then
strFullFileName = strFileLocation & strFileName
Else
strFullFileName = strFileLocation & "\" & strFileName
End If
getParamValue = ""
If System.IO.File.Exists(strFullFileName) = True Then
If (IsNothing(strDelimiter)) Then strDelimiter = "="
Dim objReader As New System.IO.StreamReader(strFullFileName)
Do While objReader.Peek() <> -1
TextLine = Split(objReader.ReadLine(), strDelimiter)
If (Trim(strParamName) = Trim(TextLine(0))) Then
getParamValue = Trim(TextLine(1))
Exit Do
End If
Loop
objReader = Nothing
Else
MsgBox("File Does Not Exist: " & strFullFileName, MsgBoxStyle.OkOnly, "File Open Error")
getParamValue = vbNullChar
End If
End Function
End Class
End Namespace
This DLL is called: SisConfigTextFiles.dll and is stored in the folder of the executing (calling) (exe) file.
I want to explicitly link to it at runtime, from another Visual Basic application:
Public Class Initializing
Public Const CONFIG_FILE_NAME As String = "AppConfig.ini"
Public Shared Function getConfigParam(ParamName As String) As String
'Load external dll
Dim asm As Assembly = Assembly.Load("SisConfigTextFiles")
Dim type As Type = asm.GetType("TextFiles.ConfigTextFiles")
' Create an instance of a Type by calling Activator.CreateInstance
Dim dynamicObject As Object = Activator.CreateInstance(type)
Dim appPath As String = My.Application.Info.DirectoryPath
getConfigParam = ""
Dim returnValue = DirectCast(type.InvokeMember("getParamValue", _
BindingFlags.InvokeMethod Or BindingFlags.Static, _
Nothing, dynamicObject, {appPath, CONFIG_FILE_NAME, ParamName}), String)
getConfigParam = returnValue
End Function
End Class
However, I keep getting this runtime error:
System.ArgumentNullException: Value cannot be null.
Parameter name: type
Why is "type" Null? How can I straighten this out?
Thanks!
You are almost there but this line isnt valid:
asm.GetType("TextFiles.ConfigTextFiles")
It should be
asm.GetType("SisConfigTextFiles.TextFiles.ConfigTextFiles")
You can see the available types in the Assembly.ExportedTypes property.
Following Sam's advice, here's the fully working code that invokes a method in a DLL with late (run-time) binding:
Imports System.Reflection
Public Class Initializing
Public Const CONFIG_FILE_NAME As String = "AppConfig.ini"
Public Shared Sub Config_Init()
End Sub
Public Shared Function getConfigParam(ParamName As String) As String
'Load external dll
Dim asm As Assembly = Assembly.Load("SisConfigTextFiles")
Dim type As Type = asm.GetType("SisConfigTextFiles.TextFiles.ConfigTextFiles")
' Create an instance of a Type by calling Activator.CreateInstance
Dim dynamicObject As Object = Activator.CreateInstance(type)
Dim appPath As String = My.Application.Info.DirectoryPath
getConfigParam = ""
'Invoking a function "setParamValue" in the dll
Dim returnValue = DirectCast(type.InvokeMember("getParamValue", _
BindingFlags.InvokeMethod Or BindingFlags.Static Or BindingFlags.Public, _
Nothing, dynamicObject, {appPath, CONFIG_FILE_NAME, ParamName}), String)
getConfigParam = returnValue
End Function
End Class
Public Shared Function GetDataSet() As IEnumerable(Of SerialData)
Dim sCon As New SQLConnect
Dim strsql As String
Dim p As New Control
sCon.sqlAdp = New SqlDataAdapter
strsql = "select serialid," & _
" serialno," & _
" serialdesc," & _
" b.materialname," & _
" b.drawing," & _
" a.workorder," & _
" isnull((select top 1 patno from patternmaster where patid = a.patid),'Not Defined') as patno," & _
" case when a.activeflag = 1 then 'True' else 'False' end as activeflag" & _
" from serialmaster a," & _
" materialmaster b" & _
" where 1 = 1" & _
" and a.materialid = b.materialid" & _
" and b.activeflag = 1"
sCon.sqlCmd.CommandText = strsql
sCon.sqlAdp.SelectCommand = sCon.sqlCmd
sCon.sqlAdp.Fill(sCon.DS, "Listing")
Dim dtTable As DataTable
dtTable = sCon.DS.Tables("Listing")
' For Each row As DataRow In dtTable.Rows
' Return dtTable.AsEnumerable().[Select](Function(row) New With { _
' Key .serialid = row("serialid"), _
' Key .serialno = row("serialno"), _
' Key .serialdesc = row("serialdesc"), _
' Key .materialname = row("materialname"), _
' Key .drawing = row("drawing"), _
' Key .workorder = row("workorder"), _
' Key .patno = row("patno") _
'})
' Next
For Each row As DataRow In dtTable.Rows
p.serialid.Add(row("serialid"))
p.serialno.Add(row("serialno"))
p.serialdesc.Add(row("serialdesc"))
p.materialname.Add(row("materialname"))
p.drawing.Add(row("drawing"))
p.workorder.Add(row("workorder"))
p.patno.Add(row("patno"))
Next
Return p
End Function
Control class:
Public Class Control
Public serialid As New Generic.List(Of String)
Public serialno As New Generic.List(Of String)
Public serialdesc As New Generic.List(Of String)
Public materialname As New Generic.List(Of String)
Public drawing As New Generic.List(Of String)
Public workorder As New Generic.List(Of String)
Public patno As New Generic.List(Of String)
Public result As New Generic.List(Of String)
End Class
ServerSidePro class:
Public Class ServerSidePro
Implements System.Web.IHttpHandler
Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
Dim d As New Control
' Those parameters are sent by the plugin
Dim iDisplayLength = Integer.Parse(context.Request("iDisplayLength"))
Dim iDisplayStart = Integer.Parse(context.Request("iDisplayStart"))
Dim iSortCol = Integer.Parse(context.Request("iSortCol_0"))
Dim iSortDir = context.Request("sSortDir_0")
'Fetch the data from a repository (in my case in-memory)
'Dim p = SerialData.GetDataSet()
Dim p = DirectCast(SerialData.GetDataSet(), IEnumerable(Of SerialData))
' prepare an anonymous object for JSON serialization
Dim aaData2 = p.select(Function(h) New With {h.serialid, h.serialno, h.serialdesc, _
h.materialname, h.drawing, h.workorder, h.patno}).Skip(iDisplayStart).Take(iDisplayLength)
Dim str As New List(Of String())
For Each item In aaData2
Dim arr As String() = New String(6) {item.serialid, item.serialno, item.serialdesc, _
item.materialname, item.drawing, item.workorder, item.patno}
str.Add(arr)
Next
Dim result = New With { _
Key .iTotalRecords = p.Count(), _
Key .iTotalDisplayRecords = p.Count(), _
Key .aaData = str
}
Dim serializer As New JavaScriptSerializer()
Dim json = serializer.Serialize(result)
context.Response.ContentType = "application/json"
context.Response.ClearHeaders()
context.Response.Write(json)
context.Response.End()
'Return d
End Sub
ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class
How to return dataset from this function it is giving error Unable to cast object of type 'Control' to type 'System.Collections.Generic.IEnumerable'.
Easiest way is to use a List() object. I would restructure your class
Public Class Control
Public LControl As New List(Of Control)
Public serialid As String
Public serialno As String
Public serialdesc As String
Public materialname As String
Public drawing As String
Public workorder As String
Public patno As String
Public result As String
End Class
Dim ShowImgWebClient = New WebClient
Dim ImageInBytes As Byte() = ShowImgWebClient.DownloadData("http://ex.domain.com/index.php?checksum=" & lblCheckSum.Text.ToString())
Dim ImageStream As New MemoryStream(ImageInBytes)
Dim CaptchaImg As Image = New Bitmap(ImageStream)
ptbCaptcha.Image = CaptchaImg
I'm use this code for get online captcha to my picturebox name ptbCaptcha.
but when request this image my program show error Parameter is not Valid.
Why this ? and How to make it work ?
This is not the proper way to use MemoryStream.
Here is the example taken from microsoft website :
Imports System
Imports System.IO
Imports System.Text
Module MemStream
Sub Main()
Dim count As Integer
Dim byteArray As Byte()
Dim charArray As Char()
Dim uniEncoding As New UnicodeEncoding()
' Create the data to write to the stream.
Dim firstString As Byte() = _
uniEncoding.GetBytes("Invalid file path characters are: ")
Dim secondString As Byte() = _
uniEncoding.GetBytes(Path.GetInvalidPathChars())
Dim memStream As New MemoryStream(100)
Try
' Write the first string to the stream.
memStream.Write(firstString, 0 , firstString.Length)
' Write the second string to the stream, byte by byte.
count = 0
While(count < secondString.Length)
memStream.WriteByte(secondString(count))
count += 1
End While
' Write the stream properties to the console.
Console.WriteLine( _
"Capacity = {0}, Length = {1}, Position = {2}", _
memStream.Capacity.ToString(), _
memStream.Length.ToString(), _
memStream.Position.ToString())
' Set the stream position to the beginning of the stream.
memStream.Seek(0, SeekOrigin.Begin)
' Read the first 20 bytes from the stream.
byteArray = _
New Byte(CType(memStream.Length, Integer)){}
count = memStream.Read(byteArray, 0, 20)
' Read the remaining Bytes, Byte by Byte.
While(count < memStream.Length)
byteArray(count) = _
Convert.ToByte(memStream.ReadByte())
count += 1
End While
' Decode the Byte array into a Char array
' and write it to the console.
charArray = _
New Char(uniEncoding.GetCharCount( _
byteArray, 0, count)){}
uniEncoding.GetDecoder().GetChars( _
byteArray, 0, count, charArray, 0)
Console.WriteLine(charArray)
Finally
memStream.Close()
End Try
End Sub
End Module
See MemoryStream for more information.
I'm working on an WindowsPhone 8 app that stores and reads it's data from its IsolatedStorage.
I'm using Visual Basic.NET and LINQ to XML.
There's no problem with loading/saving the data, but I've got a serious issue with replacing an XElement with [***XElementListName*].FirstOrDefault().ReplaceWith([NewXElementName])**.
It throws an System.AccessViolationException, but only if it's supposed to find and replace the data bound to the FIRST item in a LongListSelector, also the first of that element in the XML file. Editing any other item works fine thou.
Here's the code from the routine that is supposed to replace the data.
Dim Accounts = From el In XMLData.<accounts>.<account> Where _
el.Attribute("title").Value = oiTitle And _
el.Attribute("uname").Value = oiName And _
el.Attribute("pass").Value = oiPass And _
el.Attribute("site").Value = oiSite And _
el.Attribute("description").Value = oiDesc _
Select el
Dim acc As XElement = Accounts.FirstOrDefault()
If acc.Equals(Nothing) Then
MessageBox.Show("Error while saving edited account. Account not found.", "Account not found", MessageBoxButton.OK)
Exit Sub
End If
Dim tmpstr As String = acc.Attribute("title").Value + _
acc.Attribute("uname").Value + _
acc.Attribute("pass").Value + _
acc.Attribute("site").Value + _
acc.Attribute("description").Value
'Does this during debug to confirm that the replace is performed on the correct item.
MessageBox.Show(tmpstr, "Info about first item", MessageBoxButton.OK)
acc.Attribute("title").SetValue(NewInfo.Title)
acc.Attribute("uname").SetValue(NewInfo.Username)
acc.Attribute("pass").SetValue(NewInfo.Password)
acc.Attribute("site").SetValue(NewInfo.Site)
acc.Attribute("description").SetValue(NewInfo.Description)
' This code throws the exception when performing on the first item from the LongListSelector
Accounts.FirstOrDefault().ReplaceWith(acc)
I've searched and tried to figure it out by looking at the LINQ to XML documentation, but it lacks usable examples. Also checked this: How can I update/replace an element of an XElement from a string?
So, does anyone sit on any knowledge I could use to solve this?
If there's some code you'd like to see, just tell me, it's pretty ugly though.
EDIT: Omitted the Accounts.FirstOrDefault().ReplaceWith(acc) line, and it works just fine. Saves everything as it should. Also rewrote some code, here's the new one, and all the related code in that sub.
Public Sub EditAccount(ByVal OldInfo As AccountViewModel, ByVal NewInfo As AccountViewModel)
Dim IsStore As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication()
Dim File As New IsolatedStorageFileStream("Data.xml", FileMode.Open, IsStore)
Dim XMLData As XElement = XElement.Load(File)
Dim oiTitle As String = OldInfo.Title
Dim oiName As String = OldInfo.Username
Dim oiPass As String = OldInfo.Password
Dim oiSite As String = OldInfo.Site
Dim oiDesc As String = OldInfo.Description
Try
Dim Accounts = From e In XMLData.<accounts>.<account> Where ( _
e.Attribute("title").Value = oiTitle And _
e.Attribute("uname").Value = oiName And _
e.Attribute("pass").Value = oiPass And _
e.Attribute("site").Value = oiSite And _
e.Attribute("description").Value = oiDesc)
Select e Take 1
Dim Account As XElement = Accounts.FirstOrDefault()
If Account.Equals(Nothing) Then
MessageBox.Show("Error while saving edited account. Account not found.", "Account not found", MessageBoxButton.OK)
Exit Sub
End If
Dim tmpstr As String = Account.Attribute("title").Value + _
Account.Attribute("uname").Value + _
Account.Attribute("pass").Value + _
Account.Attribute("site").Value + _
Account.Attribute("description").Value
'MessageBox.Show(tmpstr, "Info about first item", MessageBoxButton.OK)
Account.Attribute("title").SetValue(NewInfo.Title)
Account.Attribute("uname").SetValue(NewInfo.Username)
Account.Attribute("pass").SetValue(NewInfo.Password)
Account.Attribute("site").SetValue(NewInfo.Site)
Account.Attribute("description").SetValue(NewInfo.Description)
File.Close()
IsStore.DeleteFile("Data.xml")
File = New IsolatedStorageFileStream("Data.xml", FileMode.Create, IsStore)
XMLData.Save(File)
File.Close()
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
Me.LoadData()
End Sub
Omitted the Accounts.FirstOrDefault().ReplaceWith(acc) line, and it works just fine. Saves everything as it should. Also rewrote some code, here's the new one, and all the related code in that sub.
Public Sub EditAccount(ByVal OldInfo As AccountViewModel, ByVal NewInfo As AccountViewModel)
Dim IsStore As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication()
Dim File As New IsolatedStorageFileStream("Data.xml", FileMode.Open, IsStore)
Dim XMLData As XElement = XElement.Load(File)
Dim oiTitle As String = OldInfo.Title
Dim oiName As String = OldInfo.Username
Dim oiPass As String = OldInfo.Password
Dim oiSite As String = OldInfo.Site
Dim oiDesc As String = OldInfo.Description
Try
Dim Accounts = From e In XMLData.<accounts>.<account> Where ( _
e.Attribute("title").Value = oiTitle And _
e.Attribute("uname").Value = oiName And _
e.Attribute("pass").Value = oiPass And _
e.Attribute("site").Value = oiSite And _
e.Attribute("description").Value = oiDesc)
Select e Take 1
Dim Account As XElement = Accounts.FirstOrDefault()
If Account.Equals(Nothing) Then
MessageBox.Show("Error while saving edited account. Account not found.", "Account not found", MessageBoxButton.OK)
Exit Sub
End If
Dim tmpstr As String = Account.Attribute("title").Value + _
Account.Attribute("uname").Value + _
Account.Attribute("pass").Value + _
Account.Attribute("site").Value + _
Account.Attribute("description").Value
'MessageBox.Show(tmpstr, "Info about first item", MessageBoxButton.OK)
Account.Attribute("title").SetValue(NewInfo.Title)
Account.Attribute("uname").SetValue(NewInfo.Username)
Account.Attribute("pass").SetValue(NewInfo.Password)
Account.Attribute("site").SetValue(NewInfo.Site)
Account.Attribute("description").SetValue(NewInfo.Description)
File.Close()
IsStore.DeleteFile("Data.xml")
File = New IsolatedStorageFileStream("Data.xml", FileMode.Create, IsStore)
XMLData.Save(File)
File.Close()
Catch ex As Exception
MessageBox.Show(ex.ToString)
End Try
Me.LoadData()
End Sub