Back tic in VB.net - vb.net

I am wondering if there is a way to use a back tic in vb.net ?
I am using N1QL to query a Couchbase db and i have a reserved keyword in my couchbase docs which is number. In N1QL you just enclose that word in back tic and that allows you to use reserved keywords.
Dim qRequest = New QueryRequest()
qRequest.Statement("select meta().id as DocId, _id,_type,`number`,cname_text,status,action from Vodex where _type ='cname'")
even so i dont get an error i dont get the desired response from my vb.code

I created a bucket called Vodex with a primary index and one document in it like this:
key: doc1
{
"number": 1
}
I then wrote a small console app. It's been a while since I've written VB.NET, so forgive this clumsy example:
Imports Couchbase
Imports Couchbase.Configuration.Client
Imports Couchbase.N1QL
Module Program
Sub Main(args As String())
Dim clientConfig = New ClientConfiguration()
Dim uris = New List(Of Uri)
uris.Add(New Uri("http://localhost:8091"))
clientConfig.Servers = uris
Dim cluster = New Cluster(clientConfig)
cluster.Authenticate("Administrator", "password")
Dim bucket = cluster.OpenBucket("Vodex")
Dim qRequest = New QueryRequest()
qRequest.Statement("select meta().id As DocId, `number` from Vodex")
Dim results = bucket.Query(Of Foo)(qRequest)
Dim rows = results.Rows
For Each o As Foo In rows
Console.WriteLine(o.DocId)
Console.WriteLine(o.Number)
Next
cluster.Dispose()
End Sub
End Module
Friend Class Foo
Public Property DocId As String
Public Property Number As Integer
End Class
After running that, "doc1" and "1" are printed to console. It seems to work okay, even with backticks. If you're experiencing another issue, it is probably not because of the backticks.

Related

Convert an unknown structure to an untyped Object in VB.NET

I'd like to convert an unknown basic structure to an Object (no type here).
I'm building a library that will be used by many users to extract data from my system but don't want to do a new function for everyone of them. They have to know what will be the result.
In vb, it is possible to create an Object with some properties and use it as it is a regular Class like so:
Dim myObj as New With { .name = "Matt", .age = "28" }
MsgBox( myObj.name & " is now " & myObj.age & " years old.")
So far, so good.
Next step : my user will give me some instructions that I need to extract data from various DBs, and I've no idea of what the result will be.
What I know after the execution is a list of String containing the columns of the result set and, of course a (set of) rows.
And here is the problem of course
My function (for a single row) so far:
Public Function GetData(ByVal instructions as String) as Object ' User is supposed to know what will be inside, instructions is as XML describing DB, table, query, ...
' Do what is needed to retrieve data
' Here I have a variable cols As List(Of String) ' e.g. ("BP", "NAME", "VAT")
Dim o As New With ???
Return o
End Function
What I've tried: build a fake JSon on the fly, and try to Deserialize to Object.
But even if it seems to work, I (and the user) can't access the property as in my top piece of code like:
MsgBox(o.BP)
I know that I could do
Public Function GetData(Of T As {New})(ByVal instructions as String) As T
Dim o As T
' Use some Reflexion to TryInvokeMember of T
Return o
End Function
But I wanted to remove the hassle to create a class to use my code.
Plus, My librairy will be use in a webservice and the class of the user is then unknown.
One approach could be - to use Dictionary(Of String, Object)
Public Function GetData(instructions as String) As Dictionary(Of String, Object)
Dim data = ' Load data
Dim columns As String() = { "BP", "NAME", "VAT" }
Return columns.ToDictionary(
Function(column) column,
Function(column) data.GetByColumnName(column)
)
End Function
` Usage
Dim result = GetDate("instructions: ['BP', 'NAME']")
' Because user knows it is Integer
Dim bpValue = DirectCast(result.Item("BP"), Integer)
Thanks to #GSerg, #Fabio and a few other searches about ExpandoObject, I did it !
Imports System.Dynamic
Dim o As Object = New ExpandoObject()
For Each col In cols
DirectCast(o, IDictionary(Of String, Object)).Add(col, row.GetString(col))
Next

{"Unexpected JSON token when reading DataTable. Expected StartArray, got Integer. Path 'id', line 1, position 9."}

Receiving below error on deserializing json to dataset.
Unexpected JSON token when reading DataTable. Expected StartArray, got Integer. Path 'id', line 1, position 9
Json Retrieved : {"id":130,"type":"general","setup":"test?","punchline":"test."}
My Code
Dim wc As New WebClient
Try
Dim res As String
For i = 0 To 5
res = wc.DownloadString("https://official-joke-api.appspot.com/random_joke")
Dim jObject = JsonConvert.DeserializeObject(res)
Dim ds As New DataSet
ds = JsonConvert.DeserializeObject(Of DataSet)(res)
MsgBox(ds.Tables.Count)
Next
Catch ex As Exception
MsgBox(ex)
End Try
As user Akshay Gaonkar commented, you can give Newtonsoft.Json a class, named, say, Joke, to deserialise with. You can get around the mismatch of uppercase/lowercase initial letter naming conventions by decorating the properties with <JsonProperty("nameInTheJson")>.
Instead of deserializing the data into a datatable inside a dataset, you could keep it simple and create a List(Of Joke).
This is for a console application:
Imports System.Net
Imports Newtonsoft.Json
Module Program
Class Joke
<JsonProperty("id")>
Property Id As Integer
<JsonProperty("type")>
Property Type As String
<JsonProperty("setup")>
Property Setup As String
<JsonProperty("punchline")>
Property Punchline As String
End Class
Sub Main(args As String())
Dim jokes As New List(Of Joke)
Using wc As New WebClient()
For i = 1 To 5
Dim jokeInfo = wc.DownloadString("https://official-joke-api.appspot.com/random_joke")
jokes.Add(JsonConvert.DeserializeObject(Of Joke)(jokeInfo))
Next
End Using
' Alternative which fetches ten jokes in one go - note the use of (Of List(Of Joke))
'Using wc As New WebClient()
' Dim jokeInfo = wc.DownloadString("https://official-joke-api.appspot.com/jokes/ten")
' jokes = JsonConvert.DeserializeObject(Of List(Of Joke))(jokeInfo)
'End Using
For Each jk In jokes
Console.WriteLine($"{jk.Setup}{vbCrLf}{jk.Punchline}{vbCrLf}")
Next
End Sub
End Module
The Using statement is needed because a WebClient should be disposed of after use to clear up system resources. (You could use the equivalent Try...Finally with wc.Dispose() instead.)
The JSON you showed is invalid. Datatable is expecting array of Object , so the JSON should look like below :
[{"id":130,"type":"general","setup":"test?","punchline":"test."}]

Vb.NET Device Unique Identifier Win10

I'm trying to get a Device Unique Identifier in vb.net code. I have tried with
Private Function SystemSerialNumber() As String
Dim value As String = ""
Dim baseBoard As ManagementClass = New ManagementClass("Win32_BaseBoard")
Dim board As ManagementObjectCollection = baseBoard.GetInstances()
If board.Count > 0 Then
value = board(0)("SerialNumber")
If value.Length > 0 Then value = value.Substring(2)
End If
Return value
End Function
Which works on some computers but of the board doesn't have a serial number it returns "Default String" or whatever they put in there. Even tried with Win32_Processor and some have it and others just return "To be filled by O.E.M" lol
Also tried with,
Private Function SystemSerialNumber() As String
Dim value As String
Dim q As New SelectQuery("Win32_bios")
Dim search As New ManagementObjectSearcher(q)
Dim info As New ManagementObject
For Each info In search.Get
value = info("SerialNumber").ToString
Return value
Next
End Function
But its the same some devices have it some don't and just returns default string.
So I'm now trying is:
Private Function SystemSerialNumber() As String
Dim value As String
value = Windows.System.Profile.SystemIdentification.GetSystemIdForPublisher()
End Function
But I'm having trouble referencing to it. I tried Imports Windows.System but it just gives the error it cant be found.
As a side note I'm using this program in tablets with windows10, laptops, and desktops.
UPDATE: I'll be using as suggested by Heinzi. Thanks!
Also changed variable names to be more accurate.
Private Function NetworkAdapterMacAddress() As String
Dim McAddress As String
Dim netadapter As ManagementClass = New ManagementClass("Win32_NetworkAdapterConfiguration")
Dim mo As ManagementObject
Dim adapter As ManagementObjectCollection = netadapter.GetInstances()
For Each mo In adapter
If mo.Item("IPEnabled") = True Then
McAddress = mo.Item("MacAddress").ToString()
Return McAddress
End If
Next
End Function
Well, there is no guaranteed ID that identifies every PC out there uniquely (fortunately, I might add. Privacy is a good thing).
You best bets are probably
the MAC of the network adapter (changes when the network adapter is replaced) or
the Windows Computer SID (changes when Windows is reinstalled).
Oh, and on a philosophical note, you might want to ponder on the Ship of Theseus.

Poor performance on SELECT * FROM Win32_Printer

I'm updating some routines that help identify and store the printers available for a user when they access our application over Citrix. When the printers are created they are flagged with a name like;
In citrix;
PrinterName (from MyTerminalID) in session 209
In RDP;
PrinterName (redirected 209)
run locally we just get the PrinterName
That's all fine but we've switched from using the "system.drawing" method of identifying printers which is somewhat dangerous and identifies every single printer on the citrix node to using the System.Management query SELECT * FROM Win32_Printer
I've modified this with a condition e.g., DeviceID Like '%(from MyTerminalID)%' AND DeviceID LIKE '%in session 123' but the first time I execute the query it can take a number of seconds (15+) before it comes back with the results. One I have the results it's very quick.
Now the question is, how can I make it go faster ?
I'm only interesting in getting the subset of printers that either relate to myTerminalID AND my session or my session (if RDP, but the citrix version is the important bit).
Is the query running like a proper SQL query so will use the condition to reduce the time to run or is it more of a pseudo query where it's going to pull back the whole data set and then apply the filtering.
Is there a way to reduce the amount of data that it needs to go and get (e.g., if I do a SELECT DeviceID rather than a SELECT *).
re-running the query is much faster <1 second. In some ways it doesn't matter if it takes 15+ seconds to pull back the list of printers as that's currently used for set up but there is also another routine that checks if the previously selected printers are still available to the user on the same terminal (even if a different user was the one that set them up). I would also like to try and potentially filter out "non-printers" like the fax etc., and to do that I need to look at some of the detail of the properties.
About your current scenario, you could try to set two policies:
- Use Universal printing only
- Do not auto-create client printers
then force the update of the group policy (client side).
Maybe you want that client and server printers mirror each other, but just for testing. (Note, however, that I've seen much worse than 15 seconds in WMI enumerations in different situations. Note also that I'm no expert in Citrix Sessions/UPS.)
WMI SQL (WQL) is a subset of the ANSI SQL standard. See:
Querying with WQL - WQL (SQL for WMI) Keywords
Of course it returns a set of records (objects) that match the constraints defined in the query. Is it an efficient system? You may hear very different opinions on this matter.
The first query is slower because new objects are created at this time.
If not otherwise instructed, WMI caches these objects for subsequent queries.See EnumerationOptions.Rewindable Property
About filtering the results, see Use the Like Operator to Simplify Your WQL Queries
In the test that I made, I use this filter to rule out "non-printers" printers:
_Query.Condition = "NOT DeviceID LIKE '%fax%' AND NOT DeviceID LIKE '%xps%' AND NOT DeviceID LIKE '%PDF%'"
The following test has been performed on a machine that has 7 printers, 3 of which are "non-printers": Fax, XPS Driver and PDF Driver. The other 4 are "real" printers: 2 are local and 2 are network printers.
QUERY MIN MAX
One Printer: 96ms - 181ms
All Printers: (7) 107ms - 190ms
Filtered: (4) 108ms - 229ms
50 iterations measured using a StopWatch
Dim _SW As Stopwatch = Stopwatch.StartNew()
Dim _Printers As List(Of Printer) = GetSystemPrinters()
Console.WriteLine(_SW.ElapsedMilliseconds.ToString())
This is the code and object used:
Public Function GetSystemPrinters() As List(Of Printer)
Dim _Printers As New List(Of Printer)()
Dim _ConnOptions As New ConnectionOptions()
_ConnOptions.Authentication = AuthenticationLevel.Connect
_ConnOptions.Impersonation = ImpersonationLevel.Impersonate
'If needed => .UserName, .Password, .Authority
_ConnOptions.Timeout = EnumerationOptions.InfiniteTimeout
Dim _Scope As New ManagementScope("\\" + Environment.MachineName + "\root\CIMV2", _ConnOptions)
_Scope.Connect()
Dim _Query As New SelectQuery("SELECT * FROM Win32_Printer") 'Or "SELECT * FROM CIM_Printer"
'Create a filter to rule out some "non-printers"
_Query.Condition = "NOT DeviceID LIKE '%fax%' AND NOT DeviceID LIKE '%xps%' AND NOT DeviceID LIKE '%PDF%'"
Dim _Options As New EnumerationOptions()
_Options.Timeout = EnumerationOptions.InfiniteTimeout
'Forward only query => no caching
_Options.Rewindable = False
'Pseudo-async result
_Options.ReturnImmediately = True
Dim _searcher As New ManagementObjectSearcher(_Scope, _Query, _Options)
For Each _objPrinter As ManagementObject In _searcher.Get()
Dim _Printer As New Printer()
_Printer.PrinterName = _objPrinter.Properties("Name").Value.ToString()
_Printer.PrinterPort = _objPrinter.Properties("PortName").Value.ToString()
_Printer.PrinterDriver = _objPrinter.Properties("DriverName").Value.ToString()
_Printer.PrintProcessor = _objPrinter.Properties("PrintProcessor").Value.ToString()
_Printer.DeviceID = _objPrinter.Properties("DeviceID").Value.ToString()
_Printer.Status = CType(_objPrinter.Properties("PrinterStatus").Value, PrinterStatus)
_Printer.IsLocalPrinter = If(_objPrinter.Properties("Local").Value.ToString() = "True", True, False)
_Printer.IsNetworkPrinter = If(_objPrinter.Properties("Network").Value.ToString() = "True", True, False)
_Printer.IsDefaultPrinter = If(_objPrinter.Properties("Default").Value.ToString() = "True", True, False)
Dim _PrinterProps As New List(Of PrinterProperties)()
For Each _oBJData As PropertyData In _objPrinter.Properties
_PrinterProps.Add(New PrinterProperties() With {
.PropertyName = _oBJData.Name,
.PropertyValue = If(_oBJData.Value IsNot Nothing, _oBJData.Value.ToString(), ""),
.PropertyValueType = _oBJData.Type.ToString(),
.PropertyIsArray = _oBJData.IsArray
})
Next
_Printer.PrinterProperties = _PrinterProps
_Printers.Add(_Printer)
Next
Return _Printers
End Function
Relative Objects:
Public Enum PrinterStatus As Integer
Other = 1
Unknown = 2
Ready = 3
Printing = 4
Warmup = 5
StoppedPrinting = 6
Offline = 7
End Enum
Public Class Printer
Public Property PrinterName() As String
Public Property PrinterPort() As String
Public Property PrinterDriver() As String
Public Property PrintProcessor() As String
Public Property DeviceID() As String
Public Property Status() As PrinterStatus
Public Property IsDefaultPrinter() As Boolean
Public Property IsLocalPrinter() As Boolean
Public Property IsNetworkPrinter() As Boolean
Public Property PrinterProperties() As List(Of PrinterProperties)
End Class
Public Class PrinterProperties
Public Property PropertyName() As String
Public Property PropertyValue() As String
Public Property PropertyValueType() As String
Public Property PropertyIsArray() As Boolean
End Class

Calling System.IO.ReadAllBytes by string name

This post is related to Visual Basic .NET 2010
So, I'm wondering if there's any way to call a function from a library such as System.ReadAllBytes by string name.
I've been trying Assembly.GetExecutingAssembly().CreateInstance and System.Activator.CreateInstance followed by CallByName(), but none of them seemed to work.
Example of how I tried it:
Dim Inst As Object = Activator.CreateInstance("System.IO", False, New Object() {})
Dim Obj As Byte() = DirectCast(CallByName(Inst, "ReadAllBytes", CallType.Method, new object() {"C:\file.exe"}), Byte())
Help is (as always) much appreciated
It is System.IO.File.ReadAllBytes(), you missed the "File" part. Which is a Shared method, the CallByName statement is not flexible enough to permit calling such methods. You will need to use the more universal Reflection that's available in .NET. Which looks like this for your specific example, spelled out for clarity:
Imports System.Reflection
Module Module1
Sub Main()
Dim type = GetType(System.IO.File)
Dim method = type.GetMethod("ReadAllBytes")
Dim result = method.Invoke(Nothing, New Object() {"c:\temp\test.bin"})
Dim bytes = DirectCast(result, Byte())
End Sub
End Module