473,748 Members | 2,887 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

accessing COM from C# with an IStream** parameter

Hallo,

I'm trying to call a COM function from C#.
The function has a parameter from the type array of IStream* (IStream**).
The COM component (out-proc-server (.exe)) has the following code:

(C++)

STDMETHODIMP CIntf::SendFile s(int noOfStreams, IUnknown** dataStreams)
{
for(int i = 0; i < noOfStreams; i++)
{
if(*(dataStream s + i))
{
IStream* iStream;
hr = (*(dataStreams + i))->QueryInterface (IID_IStream,
(void**)&iStrea m);
... ...
}
}
}

I can't change the code of the COM component.
If I'm calling the function from C# I get an E_NOINTERFACE error from
QueryInterface in the COM component.
Does anyone has an idea about the problem in my C# code?

I asked the same in the german newsgroup, but I got no answer. I hope you
are better here.

Best reguards
Ralf Beckers

(C#)

public void SendFiles(strin g file)
{

FileStream fs = new FileStream(file , FileMode.Open);
StreamReader sr = new StreamReader(fs , Encoding.Defaul t);
string trc = sr.ReadToEnd();
sr.Close();
fs.Close();

byte[] data = Encoding.Defaul t.GetBytes(trc) ;

IStorage storage;
ComTypes.IStrea m stream;

int err = StgCreateDocfil e(null,
STGM.CREATE | STGM.READWRITE | STGM.TRANSACTED |
STGM.SHARE_EXCL USIVE | STGM.DELETEONRE LEASE,
0, out storage);

storage.CreateS tream("TRTFiles .trt", (uint)(STGM.REA DWRITE |
STGM.SHARE_EXCL USIVE), 0,0, out stream);
stream.Write(da ta, data.Length, IntPtr.Zero);
stream.Commit(( int)STGC.OVERWR ITE);

storage.Commit( (int)STGC.OVERW RITE);
IntPtr ptr = Marshal.GetIUnk nownForObject(s tream);
IntPtr[] arr = { ptr };
IntPtr buffer = Marshal.AllocCo TaskMem( Marshal.SizeOf( typeof(IntPtr ))
* arr.Length );
Marshal.Copy(ar r, 0, buffer, arr.Length );

object obj = buffer;
this.intf.SendF iles(1, ref obj);
Marshal.FreeCoT askMem((IntPtr) buffer);
}
[DllImport("ole3 2.dll")]
static extern int StgCreateDocfil e([MarshalAs(Unman agedType.LPWStr )]string
pwcsName, STGM grfMode, uint reserved, out IStorage ppstgOpen);

[Flags]
public enum CSMFlags : short
{
NONE = 0,
EVENT_EN = 0x0100,
POLLED_EVENTS = 0x0001
}
[Flags]
public enum CSMFilterType : byte
{
ENABLE_MSG = 0x00,
BLOCK_MSG = 0x01,
NO_FILTER = 0x02
}
[Flags]
internal enum STGC : int
{
DEFAULT = 0,
OVERWRITE = 1,
ONLYIFCURRENT = 2,
DANGEROUSLYCOMM ITMERELYTODISKC ACHE = 4,
CONSOLIDATE = 8
}
[Flags]
internal enum STGM : int
{
DIRECT = 0x00000000,
TRANSACTED = 0x00010000,
SIMPLE = 0x08000000,
READ = 0x00000000,
WRITE = 0x00000001,
READWRITE = 0x00000002,
SHARE_DENY_NONE = 0x00000040,
SHARE_DENY_READ = 0x00000030,
SHARE_DENY_WRIT E= 0x00000020,
SHARE_EXCLUSIVE = 0x00000010,
PRIORITY = 0x00040000,
DELETEONRELEASE = 0x04000000,
NOSCRATCH = 0x00100000,
CREATE = 0x00001000,
CONVERT = 0x00020000,
FAILIFTHERE = 0x00000000,
NOSNAPSHOT = 0x00200000,
DIRECT_SWMR = 0x00400000
}

[ComImport]
[Guid("0000000b-0000-0000-C000-000000000046")]
[InterfaceType(C omInterfaceType .InterfaceIsIUn known)]
interface IStorage
{
void CreateStream(
/* [string][in] */ string pwcsName,
/* [in] */ uint grfMode,
/* [in] */ uint reserved1,
/* [in] */ uint reserved2,
/* [out] */ out ComTypes.IStrea m ppstm);
void OpenStream(
/* [string][in] */ string pwcsName,
/* [unique][in] */ IntPtr reserved1,
/* [in] */ uint grfMode,
/* [in] */ uint reserved2,
/* [out] */ out ComTypes.IStrea m ppstm);
void CreateStorage(
/* [string][in] */ string pwcsName,
/* [in] */ uint grfMode,
/* [in] */ uint reserved1,
/* [in] */ uint reserved2,
/* [out] */ out IStorage ppstg);
void OpenStorage(
/* [string][unique][in] */ string pwcsName,
/* [unique][in] */ IStorage pstgPriority,
/* [in] */ uint grfMode,
/* [unique][in] */ IntPtr snbExclude,
/* [in] */ uint reserved,
/* [out] */ out IStorage ppstg);
void CopyTo(
/* [in] */ uint ciidExclude,
/* [size_is][unique][in] */ Guid rgiidExclude, // should this be an array?
/* [unique][in] */ IntPtr snbExclude,
/* [unique][in] */ IStorage pstgDest);
void MoveElementTo(
/* [string][in] */ string pwcsName,
/* [unique][in] */ IStorage pstgDest,
/* [string][in] */ string pwcsNewName,
/* [in] */ uint grfFlags);
void Commit(
/* [in] */ uint grfCommitFlags) ;
void Revert();
void EnumElements(
/* [in] */ uint reserved1,
/* [size_is][unique][in] */ IntPtr reserved2,
/* [in] */ uint reserved3,
/* [out] */ out IEnumSTATSTG ppenum);
void DestroyElement(
/* [string][in] */ string pwcsName);
void RenameElement(
/* [string][in] */ string pwcsOldName,
/* [string][in] */ string pwcsNewName);
void SetElementTimes (
/* [string][unique][in] */ string pwcsName,
/* [unique][in] */ ComTypes.FILETI ME pctime,
/* [unique][in] */ ComTypes.FILETI ME patime,
/* [unique][in] */ ComTypes.FILETI ME pmtime);
void SetClass(
/* [in] */ Guid clsid);
void SetStateBits(
/* [in] */ uint grfStateBits,
/* [in] */ uint grfMask);
void Stat(
/* [out] */ out ComTypes.STATST G pstatstg,
/* [in] */ uint grfStatFlag);
}

[ComImport]
[Guid("0000000d-0000-0000-C000-000000000046")]
[InterfaceType(C omInterfaceType .InterfaceIsIUn known)]
public interface IEnumSTATSTG
{
// The user needs to allocate an STATSTG array whose size is celt.
[PreserveSig]
uint
Next(
uint celt,
[MarshalAs(Unman agedType.LPArra y), Out]
ComTypes.STATST G[] rgelt,
out uint pceltFetched
);
void Skip(uint celt);
void Reset();
[return:MarshalA s(UnmanagedType .Interface)]
IEnumSTATSTG Clone();
}

Jan 16 '08 #1
4 8103
Hi Ralf,

Based on my understanding, you are trying to pass an array of interface
pointers to a COM component, right?

To pass array in COM, you need SAFEARRAY.

Here's some key steps:

1) In your IDL:

[id(3), helpstring("met hod SendFiles2")] HRESULT SendFiles2([in,out]
SAFEARRAY(IUnkn own*)* m);

2) Here's some example code on how to retrieve the element in a SAFEARRAY
with index 0:

STDMETHODIMP CSimpleObject:: SendFiles2(SAFE ARRAY ** m)
{
IUnknown* punk;
long elementNumber = 0;
HRESULT hr = S_OK;
hr = SafeArrayGetEle ment(*m, &elementNumb er, &punk);
if (SUCCEEDED(hr)) {
IStream* pstream;
hr = punk->QueryInterface (IID_IStream, (void**)&pstrea m);
}
...

3) In C#, after you re-adding the reference, you should see this method now
has signature (ref Array). To call this method:

Array T = Array.CreateIns tance(typeof(IS tream), 1);
T.SetValue(stre am, 0);
intf.SendFiles2 (ref T);
Hope this helps.

Regards,
Walter Wang (wa****@online. microsoft.com, remove 'online.')
Microsoft Online Community Support

=============== =============== =============== =====
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
=============== =============== =============== =====

This posting is provided "AS IS" with no warranties, and confers no rights.

Jan 17 '08 #2
Hi Walter,

thanx for your answer.
But as I wrote in my question, I can't change anything at the interface of
the C++ COM component.
I need a way to use the existing interface without any modifications.

The interface is described in the IDL file as:

[
object,
uuid(A0926B7C-D57F-4F5E-9115-8F6ADB890DC1),
dual,
helpstring("IIn tf Interface"),
pointer_default (unique)
]
interface IIntf : IDispatch
{
[id(21), helpstring("met hod SendFiles")]
HRESULT SendFiles(
[in] INT num,
[in, ref, size_is(num)] IUnknown** arr);

and my DevStudio generates:
using System;
using System.Runtime. InteropServices ;

[ClassInterface( 0)]
[TypeLibType(2)]
[Guid("A0926B7C-D57F-4F5E-9115-8F6ADB890DC1")]
public class CIntfClass :IIntf , CIntf
{
public CIntfClass ();
[DispId(1)]
public virtual void SendFiles(int num, ref object arr);
}

Regards
Ralf
""Walter Wang [MSFT]"" <wa****@online. microsoft.comsc hrieb im Newsbeitrag
news:mP******** ******@TK2MSFTN GHUB02.phx.gbl. ..
Hi Ralf,

Based on my understanding, you are trying to pass an array of interface
pointers to a COM component, right?

To pass array in COM, you need SAFEARRAY.

Here's some key steps:

1) In your IDL:

[id(3), helpstring("met hod SendFiles2")] HRESULT SendFiles2([in,out]
SAFEARRAY(IUnkn own*)* m);

2) Here's some example code on how to retrieve the element in a SAFEARRAY
with index 0:

STDMETHODIMP CSimpleObject:: SendFiles2(SAFE ARRAY ** m)
{
IUnknown* punk;
long elementNumber = 0;
HRESULT hr = S_OK;
hr = SafeArrayGetEle ment(*m, &elementNumb er, &punk);
if (SUCCEEDED(hr)) {
IStream* pstream;
hr = punk->QueryInterface (IID_IStream, (void**)&pstrea m);
}
..

3) In C#, after you re-adding the reference, you should see this method
now
has signature (ref Array). To call this method:

Array T = Array.CreateIns tance(typeof(IS tream), 1);
T.SetValue(stre am, 0);
intf.SendFiles2 (ref T);
Hope this helps.

Regards,
Walter Wang (wa****@online. microsoft.com, remove 'online.')
Microsoft Online Community Support

=============== =============== =============== =====
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
=============== =============== =============== =====

This posting is provided "AS IS" with no warranties, and confers no
rights.
Jan 17 '08 #3
Hi Ralf,

I'm not sure if we could do that from .NET side but I will do some further
research.

Regards,
Walter Wang (wa****@online. microsoft.com, remove 'online.')
Microsoft Online Community Support

=============== =============== =============== =====
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
=============== =============== =============== =====

This posting is provided "AS IS" with no warranties, and confers no rights.

Jan 19 '08 #4
Hi Ralf,

I'm writing to check the status of this post. Please feel free to let me
know if there's anything else I can help. Thanks.
Regards,
Walter Wang (wa****@online. microsoft.com, remove 'online.')
Microsoft Online Community Support

=============== =============== =============== =====
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
=============== =============== =============== =====

This posting is provided "AS IS" with no warranties, and confers no rights.

Jan 25 '08 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
3731
by: Thomas Matthews | last post by:
Hi, In some threads, some people mentioned that variable initialization is best performed in an initialization list. Is there a way to initialize a variable from an istream in an initialization list? Example: class My_Class {
7
4246
by: ragi | last post by:
Short version of my program: ifstream File; File.open("test.txt"); if(!File.good()) return; Func(File); <--cannot convert parametr 1 from 'std::ifstream' to 'std::istream'
13
2882
by: Peteroid | last post by:
These don't work (I'm using VS C++.NET 2005 Express with clr:/pure syntax): ostream& operator <<( ostream& output, String^ str ) { output << str ; //compile error return output ; } istream& operator >>( istream& input, String^ str )
13
3732
by: Randy | last post by:
Is there any way to do this? I've tried tellg() followed by seekg(), inserting the stream buffer to an ostringstream (ala os << is.rdbuf()), read(), and having no luck. The problem is, all of these methods EXTRACT the data at one point or another. The other problem is there appears to be NO WAY to get at the actual buffer pointer (char*) of the characters in the stream. There is a way to get the streambuf object associated with the...
5
3066
by: Gunnar Liknes | last post by:
Hi, I am trying to access COM component - method that takes a IStream (ByRef) parameter from ASP (Not ASP.NET). So far I have had no luck and google drowns my search with ASP.NET examples... I mange to create the object and call methods that returns strings (BSTR)
3
3379
by: KWienhold | last post by:
I'm currently writing an application (using Visual Studio 2003 SP1 and C#) that stores files and additional information in a single compound file using IStorage/IStream. Since files in a compound file aren't really useful to a user, I use the IStream::Read function together with a StreamWriter to extract single files from my compound document. When I first tested these functions everything seemed to work fine (and basically, it does),...
21
6917
by: Peter Larsen [] | last post by:
Hi, I have a problem using System.Runtime.InteropServices.ComTypes.IStream. Sample using the Read() method: if (IStreamObject != null) { IntPtr readBytes = IntPtr.Zero; IStreamObject.Read(buffer, size, readBytes);
2
4438
by: Colonel | last post by:
It seems that the problems have something to do with the overloading of istream operator ">>", but I just can't find the exact problem. // the declaration friend std::istream & operator>(std::istream & in, const Complex & a); // the methods correspond to the friend std::istream & operator>(std::istream & in, const Complex & a) { std::cout << "real: ";
3
4552
by: Kourosh | last post by:
Hi all, I'm trying to call a COM function from C# The function gets a paramter of type IStream in C++. I've found the type System.Runtime.InteropServices.ComTypes.IStream, however I'm not sure how to create an instance of it to pass as the parameter. Anyone can tell me what to do? i dont know what to pass in as the parameter, because I'm not sure how to create an instance of the "IStream" object in C#
0
8830
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9544
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9372
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9324
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9247
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
6074
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4606
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
3313
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2783
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.