How to access array elements of SAFEARRAY from MS JScript? - com

A COM object lives in a DLL. Its IDL looks roughly like this:
[
object,
uuid(51EB4046-221E-45EF-BD63-0D31B163647C),
oleautomation,
dual,
pointer_default(unique)
]
interface IOne2OneNode : IDispatch
{
// ...
[propget, id(2), helpstring("property Vector")] HRESULT Vector([out, retval] VARIANT *pVal);
};
The DLL fills in *pVal with a SAFEARRAY of VT_R8 (using COleSafeArray).
I want to access the array elements from a JScript script that is executed with cscript.exe.
I tried node.Vector[1], but it reports
TestIDispatch.wsf(115, 2) runtime error in Microsoft JScript: 'node.Vector' is Null or not an object
(modulo German to English translation errors).
Also, typeof node.Vector reports unknown.
After reading this answer, I tried
var vec = new VBArray(node.Vector).toArray();
but it reports runtime error in Microsoft JScript: VBArray expected.
How can I access the array elements from JScript?

JScript can only process SAFEARRAYs with element type VT_VARIANT. Any other element type is incompatible.
It is correct to convert the returned array using
var vec = new VBArray(node.Vector).toArray();
but the COM server must create an array of VARIANTs, i.e., type code VT_VARIANT; VT_R8 will end up in a type mismatch error.
Found in the responses to this post.

Related

Cannot serialize a string object with Microsoft.Bond

I am using Microsoft.Bond to serialize a class object which works perfectly fine. However, when I try to serialize a simple System.String object, the CompactBinaryWriter writes almost nothing to the output buffer. I am using this code:
string v = "test data";
var outputBuffer = new OutputBuffer();
var writer = new CompactBinaryWriter<OutputBuffer>(outputBuffer);
Serialize.To(writer, v);
var output = outputBuffer.Data;
output in this case is a one element array : {0}, irrespective of the value of v. Can someone point out why this doesn't work?
Bond requires a top-level Bond struct to perform serialization/deserialization.
If only one value needs to be passed/returned, the type bond.Box<T> can be used to quickly wrap a value in a Bond struct. (There's nothing special about bond.Box<T>, except that it ships with Bond.)
Try this:
Serialize.To(writer, Bond.Box.Create(v));
You'll need to deserialize into a bond.Box<string>.
There's an open issue about having better behavior in cases like this.

Populate picture box from eID vb.net

Hi i got form that reads eID card, smart cards
text data reads correctly
picturebox name is picLK
but last statement is a picture
in VB6 and VBA I used
me.pctLK.Picture = ReaderEngine.portrait
ReaderEngine is procedure that reads data from card
when I use command in vb.net I get an error
me.pctLK = ReaderEngine.portrait
reader is reading card, but I got this message
An unhandled exception of type 'System.InvalidCastException' occurred in Project1.exe
Additional information: Unable to cast COM object of type 'stdole.StdPictureClass' to class type 'System.Windows.Forms.PictureBox'. Instances of types that represent COM components cannot be cast to types that do not represent COM components; however they can be cast to interfaces as long as the underlying COM component supports QueryInterface calls for the IID of the interface.
I am new to VB .net
Is there any suggestions?
VB.NET has a helper function in the Microsoft.VisualBasic.Compatibility.VB6.Support module, named IPictureDispToImage, which accepts an StdPictureClass object (which implements IPictureDisp) and returns a .NET System.Drawing.Image object which you can assign to the PictureBox.Image property. Be sure you appropriately dispose of the Image when you're finished with it:
Dim comImage As StdOle.StdPictureClass = ReaderEngine.portrait
If Me.picLK.Image Is Not Nothing Then
Me.picLK.Image.Dispose()
Me.picLK.Image = Nothing
End If
Dim newImage As System.Drawing.Image = Support.IPictureDispToImage( comImage )
Me.picLK.Image = newImage

How do I get the Kind of Elements in an Array using Roslyn

I am trying to get the Type that is iterated through using Roslyn. I can get the fact that the object is defined as String() using
Dim ElementTypeInfo As TypeInfo = SemanticModel.GetTypeInfo(ForEachStatement.Expression)
Dim expressionType As ITypeSymbol = ElementTypeInfo.Type
and in the Visual Studio debugger I can look at expressionType.ElementType and find out it is a String. But when I try to access ElementType in code I get an error saying the ElementType is not a member of ITypeSymbol.
If you know that expressionType is going to be an array, you can cast it to IArrayTypeSymbol. After that, you will be able to access its ElementType:
Dim expressionType = DirectCast(elementTypeInfo.Type, IArrayTypeSymbol)
Dim elementType As ITypeSymbol = expressionType.ElementType

Creating WCF service by determining type at runtime

I am trying to create a WCF service without knowing its type/interface at runtime. To do this, I use ChannelFactory. ChannelFactory is a generic class so I need to use Type.MakeGenericType. The type I pass to MakeGenericType is from a list of interfaces I previously gathered with reflection by searching some assemblies.
Ultimately, I call MethodInfo.Invoke to create the object. The object is created just fine, but I cannot cast it to the proper interface. Upon casting, I receive the following error:
"Unable to cast transparent proxy to type 'Tssc.Services.MyType.IMyType'"
After some experimenting, I have found that the interface/type passed to MakeGenericType seems to be the problem. If I substitute the interface in my list with the actual interface, then everything works fine. I have combed through the two objects and cannot see a difference. When I modify the code to produce both types, comparing them with Equals returns false. It is unclear to me whether Equals is just checking that they are referring to the same object (not) or thety are checking all properties, etc.
Could this have something to do with how I gathered my interfaces (Reflection, saving in a list...)? A comparison of the objects seems to indicate they are equivalent. I printed all properties for both objects and they are the same. Do I need to dig deeper? If so, into where?
// createService() method
//*** tried both of these interfaces, only 2nd works - but they seem to be identical
//Type t = interfaces[i]; // get type from list created above - doesn't work
Type t = typeof(Tssc.Services.MyType.IMyType); // actual type - works OK
// create ChannelFactory type with my type parameter (t)
Type factoryType = typeof(ChannelFactory<>);
factoryType = factoryType.MakeGenericType(new Type[] { t });
// create ChannelFactory<> object with two-param ctor
BasicHttpBinding binding = new BasicHttpBinding();
string address = "blah blah blah";
var factory = Activator.CreateInstance(factoryType, new object[] { binding, address });
// get overload of ChannelFactory<>.CreateChannel with no parameters
MethodInfo method = factoryType.GetMethod("CreateChannel", new Type[] { });
return method.Invoke(factory, null);
//--------------- code that calls code above and uses its return
object ob = createService();
//*** this cast fails
Tssc.Services.MyType.IMyType service = (Tssc.Services.MyType.IMyType)ob;
Ok, I understand whats happening here - the problem is relating to loading the same assembly being effectively loaded twice - once via a reference, and once via the assembly load command. What you need to do is change the place where you load your assembly, and check to see if it already exists in the current AppDomain, like this maybe:
Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.GetName().Name.Equals("ClassLibrary1Name"));
if (assembly == null)
{
assembly = System.Reflection.Assembly.LoadFile("path to your assembly");
}
//do your work here
This way if the assembly is already loaded into memory, it'll use that one.

VB.NET Deserialize JSON to anonymous object using newtonsoft returned error

I would like to deserialize the returned JSON from a service call in VB.NET to an anonymous type but I was having error. It works in C# using dynamic type but i dont know how to do it in VB.
Here is my JSON returned from a web service call:
{"format":"png","height":564,"width":864}
Here is my VB code json above assigned to param text:
Dim testObj = Newtonsoft.Json.JsonConvert.DeserializeObject(text)
But when i tried to access testObj.format, an exception was thrown with message
{"Public member 'format' on type 'JObject' not found."}
I already have added Option Strict Off. I dont want to use an Object/Class to deserialize the JSON. If its in C# assigning this to dynamic type will be working fine.
Can anyone please help? I am not expert in VB but I need to have this running on VB. TIA
Dim js As New System.Web.Script.Serialization.JavaScriptSerializer
Dim testObj = js.Deserialize(source, New Object().GetType())
Then you can access the key(attribute name)/values via:
value=testobj(key)
One more thing, you can access your Newtonsoft key(attribute name)/values through:
value=testObj.item(key)
Dim js As New System.Web.Script.Serialization.JavaScriptSerializer
Dim DeSerialObjEventData = New With {.Prop1 = String.Empty, .Prop2 = String.Empty, .Prop3 = String.Empty}...
Dim testObj = js.DeserializeAnnonomusType(source, DeSerialObjEventData)