OleProcedure() C++ Builder 10.3 - com

I try to select 10 characters in Word document with C++ Builder.
VBA method looks as follows:
Selection.SetRange Start:=0, End:=10
How to correctly pass parameters to C++ Builder method?
I tried several options, but did not succeed.
selection.OleProcedure("SetRange", Start:=0, End:=10)
selection.OleProcedure("SetRange", "Start:=0", "End:=10")
selection.OleProcedure("SetRange", 0, 10)

OleProcedure() does not support named parameters 1. You have to pass the parameter values in the same order that they are declared by the COM object, which in this case is:
expression.SetRange(Start, End)
So selection.OleProcedure("SetRange", 0, 10) should work just fine. If it is not, you need to be more specific about what exactly is not working for you.
1: if you want to use named parameters, you will have to access the variant's held IDispatch interface and call its IDispatch::Invoke() method directly, providing it with a DISPPARAMS struct containing the desired names and values.

Related

What is the Type returned by GetValues in each of the overloaded versions

Module Module1
Enum Colors
Red
Green
Blue
Yellow
End Enum
Sub main()
Dim values = [Enum].GetValues(GetType(Colors)) ' Statement 1
Console.WriteLine(values.GetType) 'O/P: Colors[]
Console.ReadLine()
End Sub
End Module
Values expectedly is of type Colors[]. Now my question is which of the overloaded versions of GetValues is being executed here? To put this in context the basic GetValues method returns an Array type whereas the overloaded version returns TEnum[] type. Since Values is not of Array type and is of a specific enum array type (in this case Colors[], I am inferring that statement 1 is calling the overloaded version of the GetValues method.
Adding the MSDN GetValues page for quick reference.
My Questions:
Is the above understanding right?
If not can someone pls give an example where we are using the overloaded version of the GetValues method that returns the TEnum[] type?
Also, as I understand from an answer posted by #John that the GetValues method that returns Array type is pre-generics and is not being called in the statement GetValues(GetType(Colors)). Is this understanding correct?
EDIT:
I just realised that the generic overload was only introduced in .NET 5, so any earlier versions can only use the non-generic version. That means .NET Core 3.1 or earlier and any version of .NET Framework. It is always a good idea to read the documentation and confirm exactly what .NET versions a type or method applies to.
ORIGINAL:
Either will work but the first was authored when generics didn't exist. Generic methods are generally better than non-generic ones. You can do this:
Dim values = [Enum].GetValues(GetType(Colors))
or this:
Dim values = [Enum].GetValues(Of Colors)()
and, in the second one, the variable will be type Colors(), which is really what you want.
As for that As Structure generic constraint, it's there because that's as close as you can get to constraining TEnum to be an actual Enum. You can't actually constrain it that far but at least you can constrain it to be a structure, so no one can specify a class when calling that method. As Enums are structures under the hood, because they are all numeric types - Integer by default - under the hood. Someone could still specify a structure that isn't an Enum when calling that method, but the non-generic method would allow them to specify a class as well.

Adding a Dapper Dynamic Output Parameter in VB.NET

I'm trying to use Dapper to call a stored procedure that has a couple Output parameters, using VB.NET (and .NET 4.0).
However, it seems I cannot use the DynamicParameters.Add method, because I'm getting the following compiler error:
'Add' is ambiguous because multiple kinds of members with this name
exist in class 'Dapper.DynamicParameters'.
...when I try to write the following line:
p.Add("#NewRecordID", DbType:=DbType.Int32, direction:=ParameterDirection.Output)
A quick search tells me this sometimes happens when using a C# library that has multiple methods that differ only in name case (VB.NET being case-insensitive). Searching the Dapper source code for DynamicParameters does show the following two overloads for the Add method, but they both use the same case, and the compiler should be able to discern between the two.
public void Add(string name, object value, DbType? dbType, ParameterDirection? direction, int? size)
public void Add(string name, object value = null, DbType? dbType = null, ParameterDirection? direction = null, int? size = null, byte? precision = null, byte? scale = null)
(I've also tried adding scale:=Nothing to the call to force the second overload, to no avail.)
While I can work around this with the input parameters by passing in an anonymous object to the DynamicParameters constructor, I can't find a way around this when adding the output parameters.
I've checked the project references to ensure there aren't multiple or ambiguous assembly references.
Has anybody encountered this problem before, and found a workaround?
At the moment, the only option I can think of is to re-write the stored procedure call without using Dapper, as implied here.
From what I can gather, the following are all potential solutions:
Rewrite the Stored Procedure to not use Output parameters. (The option I was able to use in this case.)
Rewrite the code calling the Stored Procedure to use standard ADO.NET.
Rewrite Dapper to use a different overload pattern for DynamicParameters.Add.
Update the project to use .NET 4.5.
Reimplement IDynamicParameter(s) or possibly subclass DynamicParameters

Confusion about the Argument< T > and Variable< T > in .NET 4.0 Workflow Foundation

I am using Windows Workflow Foundation in .NET 4.0. Below is some syntax/semantic confusion I have.
I have 2 equivalent way to declare an Assign activity to assign a value to a workflow variable (varIsFreeShipping).
(1) Using XAML in the designer.
(2) Using code.
But in approach 2, the it seems I am creating a new OutArgument< Boolean > and assign value to it, not to the original Variable< Boolean> varIsFreeShipping. And OutArgument and Variable are totally different types.
So how could the value assigned to this new Argument finally reach the original Variable?
This pattern seems common in WF 4.0. Could anybody shed some light on this?
Thanks!
As a matter of fact, the second (2) method can be written just as:
Then = new Assign<bool>
{
To = varIsFreeShipping,
Value = true
}
This all works because OutArgument<T> can be initialized through a Variable<T> using an implicit operator.
In your first (1) assign, using the editor, that's what's happening behind the scene; the variable is being implicitly converted from Variable to OutArgument.
WF4 uses alot of implicit operators mainly on Activity<T> from/to Variable<T>, OutArgument<T> from/to Variable<T>, etc. If you look at it, they all represent a piece of data (already evaluated or not), that is located somewhere. It's exactly the same as in C#, for example:
public int SomeMethod(int a)
{
var b = a;
return a;
}
You can assign an argument to a variable, but you can also return that same variable as an out argument. That's what you're doing with that Assign<T> activity (using the variable varIsFreeShipping as the activity's out argument).
This answers your question?

In VB6, how do I call a COM object requiring a pointer to an object?

I'm having trouble with a .NET Assembly that is com visible, and calling certain methods from VB6.
What I have found is that if the parameters are well defined types, (e.g. string), calls work fine. If they are higher level objects, it raises a runtime error '438' suggesting that the property or method is not present. I suspect that this is a question of having the correct signature on the call, but I can't see how to do this correctly.
I believe that I've done everything correct on the .NET side (ComVisible, public interfaces, etc. and even have it down to a simple enough case).
Looking at the output from the typelib viewer, I have the following:
dispinterface ISimple {
properties:
methods:
[id(0x60020000)]
void Add([in] ISimpleMember* member);
[id(0x60020001)]
ISimpleMember* Create();
};
OK. So I have 2 methods in my ISimple interface. One takes an ISimpleMember (Add), whilst the other, returns an ISimpleMember.
The corresponding code in VB looks like this:
Dim item As ISimpleMember
Dim simple As simple
Set item = New SimpleMember
item.S1 = "Hello"
item.S2 = "World"
Set simple = New simple
simple.Add (item) <---- This raised the run time error 438
Set item = simple.Create <---- This works fine, returning me an ISimpleMember
I've tried a couple of things:
1. Dim item as SimpleMember (makes no difference)
2. simple.Add(ObjPtr(item)) - Syntax error
3. simple.Add(ByRef item) - Syntax error
Basically, The run time error is the same as if I had
simple.AMethodThatIHaventWritten()
Also, If I browse References in the VB6 Environment, The Add method is well defined:
Sub Add(member As SimpleMember)
I've found the answer I believe. It was very simple:
When calling a SubRoutine, I shouldn't put the name in braces. the call should have been:
simple.add member
rather than
simple.add(member)
If I change it to a function (i.e. return a value rather than void) the braces are necessary
This seems to work
(Probably) The top 3 VB6 coding mistakes made by devs who now mainly code in C#, Javascript etc. Are:-
Placing ; at the end of lines. Its a syntax error very easily spotted and picked up the compiler.
Not placing Then on the other side of an If condition expression. Again its a syntax error.
Calling a method without retrieving a value and yet using ( ) to enclose the parameter list. With multiple parameters this is a syntax error and easily found. With only one parameter the use of ( ) is interpreted as an expression. Its the result of the ( ) expression which is passed as parameter. This causes problems when ByRef is expected by the callee.

accessing enums in a COM object [jscript]

How do I access an enum that is defined within a COM interface? Specifically, I've created a new instance of an iTunes.Application:
var iTunesApp = WScript.CreateObject("iTunes.Application");
... and I want to be able to use certain enums defined within the COM
iTunesTrackCOM.idl File Reference
[...]
Enumerations
[...]
enum ITVideoKind {
ITVideoKindNone = 0,
ITVideoKindMovie,
ITVideoKindMusicVideo,
ITVideoKindTVShow
}
I've tried iTunesApp.ITVideoKindTVShow, but that doesn't seem to work.
Alternatively, how could I root around the iTunesApp object interactively via a shell or something like that?
You can't use the enum by name. You have to just use the constants: 0, 1, 2...
It's really awesome when you're dealing with bit-fields. You have to use the decimal value of the bit-flag, e.g. the flags parameter to IHTMLTxtRange::findText().
You can use a tool like tlb2const to generate constants from the typelib.
See my answer here:
Is it possible to expose a C# Enum to COM Interop callers, and if so, how?