Developing VideoReDo code in C#

tony.v

New member
I have been using VideoReDo for years and need to develop an C# application that converts video files differently than is available using Batch Manager. I am having difficulty getting things working so I have a few questions that I hope can be answered here.

My development environment is C#, VS 2019, 64 bit using WPF. I have created a new VideoReDoTypeLib.dll using the latest version of VideoRedo v6. I am trying to use this library in the time honoured way in C# rather than using InvokeMember all of the time but when I run the following code:

VideoReDo vrd = new VideoReDo();
bool res = vrd.FileOpen(file.FullName, true);
isSuccess = vrd.FileSaveAs(outFile, VRDProfile);

I keep getting the following error:

Unable to cast COM object of type 'System.__ComObject' to interface type 'VideoReDoTypeLib.VideoReDo'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{8BAC5BE1-FC3B-450E-947D-2C91E8D7DA16}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).

I must be missing something pretty fundamental.

Can anyone help, please? Can you point me to some examples that work in C# in a Windows Forms or WPF environment?

Tony
 

Dan203

Senior Developer
Staff member
You need to get a handle to the object "VideoReDoPro6.VideoReDoSilent" for a headless interface or "VideoReDo6.Application" if you want VRD to be visible.

And if you use silent then you need to call the VRDInterface function to get the handle to the object that you can actually call functions on.

I don't have any C# examples handy, but here's how it's done in VB...
Code:
if  quietMode = true  then
    Set VideoReDoSilent = WScript.CreateObject( "VideoReDo6.VideoReDoSilent" )
    Set VideoReDo = VideoReDoSilent.VRDInterface
else
    Set VideoReDo = WScript.CreateObject( "VideoReDo6.Application" )
end if
 

tony.v

New member
What is WScript and how do I access it in C#?

I guess the easiest way to do this would be to point me to an existing C# example:).

BTW, I have everything working when I use InvokeMember. But I would like to be able to do it using the DLL because that is the standard way in C#.

Tony
 

Dan203

Senior Developer
Staff member
What is WScript and how do I access it in C#?

I guess the easiest way to do this would be to point me to an existing C# example:).

BTW, I have everything working when I use InvokeMember. But I would like to be able to do it using the DLL because that is the standard way in C#.

Tony
WScript is Windows Scripting Host. It's a way to use VBScript or Javascript to do little script things in windows. Like an advanced batch file.

I don't have any examples of using the COM interface in C# unfortunately. I know that VAP is written in C# maybe @dlflannery can give you a hint. I don't do much C# programming myself so I'm not really an expert on how exactly it works with COM.
 

dlflannery

Moderator
What is WScript and how do I access it in C#?

I guess the easiest way to do this would be to point me to an existing C# example:).

BTW, I have everything working when I use InvokeMember. But I would like to be able to do it using the DLL because that is the standard way in C#.

Tony
VAP6, link in signature, runs VideoReDo COM routines by running VBScripts as process objects in C#. It captures text output from the StdOut of the process and signals aborts by placing a semaphore file. If you install VAP6 you can see the numerous .vbs files it uses.

This is a totally different approach from yours and I can’t offer any help regarding your specific issues. If you have questions about my approach, post them in the VAP sub-forum and i will be glad to help.
 

tony.v

New member
That's okay.

I'll go with what I've developed so far.

It just niggles a bit that I haven't found out how to do it the other way:).

Tony
 

Dan203

Senior Developer
Staff member
OK I played with this for a bit and there seems to be an incompatibility between our COM interface and the way C# imports the tlb file. It appears to be trying to use the interface GUID to call the methods. But the system we use to generate the COM interface (MFC) registers the coclass GUID with the system, not the interface directly, so when C# tries to call a method it's looking for the interface GUID which doesn't exist. This seems to be a fundamental incompatibly between the way MFC generates the COM interface odl file and the way that tlbimp creates it's DLL file. I have no idea which is wrong. When I import the tlb file into another MFC project the class it creates does work correctly. I also had success pulling the tlb into Qt Creator. So I'm leaning toward something being wrong with tlbimp. I looked at the code it generates in a decompiler and it uses inheritance to pull the functions from the interface class it creates into the coclass it creates, so I'm guessing that's where the issue is. For it to work correctly the functions would need to be direct members of the coclass class and pointing to the coclass GUID.

But I am not an expert in COM though, so maybe there is something else that could be done to make this work. But I traced it as best I could and this is what I'm seeing as the issue.
 

tony.v

New member
Every now and again I get a video file that, when VRD converts it, VRD displays some messages in message boxes, saying that there is something wrong with the transport stream.

I can't see any way to intercept these messages in my code - the FileSaveAs returns true anyway.

Is there a way to trap errors in the loop after FileSaveAs.

Here's my code:

ret2 = (bool)vrd_type.InvokeMember("FileSaveAs", System.Reflection.BindingFlags.InvokeMethod, null, vrd_program, vrd_filesave);

if (ret2)
{
ret3 = 0;

do
{
ret3 = (int)vrd_type.InvokeMember("OutputGetState", System.Reflection.BindingFlags.GetProperty, null, vrd_program, null);
percent = (double)vrd_type.InvokeMember("OutputGetPercentComplete", System.Reflection.BindingFlags.GetProperty, null, vrd_program, null);
Thread.Sleep(TimeSpan.FromSeconds(1));
(sender as BackgroundWorker).ReportProgress((int)percent);
if (worker.CancellationPending)
{
e.Cancel = true;
ret3 = 0;
}
} while (ret3 != 0);

if (e.Cancel == false)
{
isSuccess = true;
}
}
else
{
isSuccess = false;
}

vrd_type.InvokeMember("FileClose", System.Reflection.BindingFlags.InvokeMethod, null, vrd_program, null);

I think the message boxes are being displayed in the do loop. Is there a method to check for errors?

Tony
 

Dan203

Senior Developer
Staff member
Yes. I did this to create a type library based on the latest version of VideoReDo.
Yeah I posted that before I tried it myself. After trying it myself is when I discovered the issue where the library being created by C#/.Net was calling the wrong GUID when trying to call the functions. As explained above that seems to be an incompatibility between the technology we use to created the COM interface (MFC) and the way the tlbimp program imports it into the C#/.Net DLL. Not sure who exactly is in the wrong there.
 

Dan203

Senior Developer
Staff member
I was wondering whether OutputGetState would return 2 (Paused) when VRD displays a dialog
Most dialogs are suppressed by the COM interface to prevent locking it when an error occurs*, but some can't be because they're fired from secondary DLLs that have no concept of whether the program is running from COM or not. I'm not 100% sure if this dialog is one of those or not. However if a file succeeds or fails the OutputGetState should be set to None. The way batch handles errors is it calls OutputGetCompletedInfo which returns an XML string. I then do a quick parse and look for the attribute "errors" in the main tag. If it's greater than 0 then that means there was some sort of error and and I parse the XML further to figure out what it is.

* The VRD COM interface is really just running a hidden version of VRD off screen. So if a modal dialog displays then it blocks all further calls to the COM API. However the only ones I'm aware of that break through COM are ones relating to registration and security.
 
Top Bottom