|
It seem's you might not correctly release the BSTR accociated with the VARIANT *p1 variable.
You might have manually to release variant accoiated with myInt variable.
|
|
|
|
|
It was my first guess, but I don't think so...each time I receive a call (from the loop) I receive the same integer VT_BYREF | VT_I2 (which is deallocated by VariantClear).
It seems that this BSTR is lost between calls, causing the leak (obviously myInt is an integer and can't reflect changes).
|
|
|
|
|
If the BSTR is lost why don't you use BSTR* as variable type instead of VARIANT.
Which version of VB are you using?
|
|
|
|
|
I can't change that interface, the real code is far more complicated, basically I need to receive a VARIANT* and change their value, and the new value comes from a c++ string.
I'm testing using VB 6.
Thanks.
|
|
|
|
|
I suspect that rather than 'new BSTR', you should use CoTaskMemAlloc[^] to allocate memory in a COM server:
BSTR *pBSTR = (BSTR*)CoTaskMemAlloc(sizeof(BSTR));
However - one other thing strikes me - why pass the BSTR back by reference? Why not use this?
VariantClear( p );
VariantInit( p );
p->vt = VT_BSTR;
p->pbstrVal = SysAllocString( L"abc" );
One less allocation, one less place to leak memory!
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|
|
Hi
The same happens with CoTaskMemAlloc, and using VT_BSTR instead of VT_BSTR | VT_BYREF.
Thanks anyway.
|
|
|
|
|
How CallService is defined in IDL file? If it's "CallService([in] VARIANT *p1)", then you cannot change the parameter. If it's "CallService([in,out] VARIANT *p1), then you cannot receive the parameter in Integer.
IAC, VB passes myInt variable as VT_BYREF | VT_I2 to be possible to change the myInt value. It's made only during call some method. Inside VB don't store variant by this manner.
STDMETHODIMP CDCSClient::CallService( VARIANT *p )
{
VariantClear( p );
p->vt = VT_BSTR;
p->bstrVal = SysAllocString( L"abc" );
return S_OK;
}
If you desire to pass BSTR by reference, you should keep out this address and make sure to free this BSTR after using.
BSTR g_pBSTR = NULL; // global scope, so somewhere should be "if (!g_pBSTR) SysFreeString(g_pBSTR);"
STDMETHODIMP CDCSClient::CallService( VARIANT *p )
{
VariantClear( p );
p->vt = VT_BSTR | VT_BYREF;
if (!g_pBSTR) g_pBSTR = SysAllocString( L"abc" );
p->pbstrVal = &g_pBSTR;
return S_OK;
}
With best wishes,
Vita
|
|
|
|
|
The parameter is defined as [in,out,optional].
And yes, now I understand, as I suspected, I can't reallocate the VT_BYREF | VT_I2 inside my ATL code.
The only thing still not 100% clear which confused me is that I can define a VB procedure receiving a byref variant, do the same thing receiving my int, and changing it to String and no leak happens. That was my first test.
But the difference is: there's no COM in this scenario, and the pure VB allocation\dellocation mechanisms are not the same.
Thanks a lot !
|
|
|
|
|
STDMETHODIMP CDCSClient::CallService( VARIANT *p)
{
if (V_VT(p) == (VT_VARIANT | VT_BYREF))
{
VARIANT *p2 = V_VARIANTREF(p);
p2->vt = VT_BSTR;
p2->bstrVal = SysAllocString( L"abc" );
return S_OK;
}
}
Dim v As Variant
v = 1
Debug.Print TypeName(v) & " " & v
Call obj.CallService(v)
Debug.Print TypeName(v) & " " & v
With best wishes,
Vita
|
|
|
|
|
About memory leaks. VB allocation\dellocation mechanisms are the same with COM.
p->vt = VT_BSTR | VT_BYREF;
BSTR *pBSTR = new BSTR;
*pBSTR = SysAllocString( L"abc" );
p->pbstrVal = pBSTR;
There are 2 memory allocations in statements "= new BSTR" and "= SysAllocString".
The VARIANT with VT_BYREF|VT_BSTR isn't an owner of its values, so freeing of the VARIANT doesn't free neither pbstrVal nor *pbstrVal. And finally you have memory leaks.
The VARIANT with VT_BSTR (without VT_BYREF) is an owner of its values, so freeing of the VARIANT frees bstrVal.
p->vt = VT_BSTR;
p->bstrVal = SysAllocString( L"abc" );
And there are no memory leaks.
With best wishes,
Vita
|
|
|
|
|
Hi,
I am trying to call the Win 32 API messagebox function from c#.
However, i finding my code not working:
could you please help me correct it:
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace ConsoleApplication5
{
class Program
{
public const String UserReference = "user32.dll";
[DllImport(UserReference, SetLastError = true)]
private static extern Int32 MessageBox(IntPtr hWnd, String pText,
String pCaption, Int32 uType);
static void Main(string[] args)
{
IntPtr ProblemCauser = (IntPtr)(-100);
MessageBox(ProblemCauser, "hello", "check", 0);
Int32 ErrorCode = Marshal.GetLastWin32Error();
Console.WriteLine("Error Code: " + ErrorCode.ToString());
Console.ReadLine();
}
}
}
|
|
|
|
|
Your arguments are invalid!
nicetohaveyou wrote: IntPtr ProblemCauser = (IntPtr)(-100) .
-100 is a number not pointer to valid window.
Call it like that
MessageBox(this.Handle,"hello", "check", 0)
into Form body or
MessageBox(IntPtr.Zero,"hello", "check", 0)
|
|
|
|
|
On one side I have a C# application (WPF) from which I want to call an Office Add-In class. On my Office Add-In project I've exposed a class and an interface to COM. I'm able to call functions from my exposed Add-In object, but I'm not able to register an event, which should by fired by the exposed Add-In project.
My C# code:
officeAddIn = excel.COMAddIns.Item(ref addinName);
object obj = officeAddIn.Object;
IAddInUtilities m_excelFIMAddInUtils = (IAddInUtilities)obj;
AddInEnablingEventHandler addInEnablingEventHandler = new AddInEnablingEventHandler(m_excelFIMAddInUtils_AddInEnablingEvent);
m_excelFIMAddInUtils.EnableAddIn(true);
m_excelFIMAddInUtils.AddInEnablingEvent += addInEnablingEventHandler
My AddIn Project:
[ComVisible(false)]
[Serializable()]
public delegate void AddInEnablingEventHandler();
public partial class ExcelFIMAddIn
{
private AddInFIMUtilities m_utilities;
private Office.IRibbonExtensibility m_ribbon;
protected override object RequestComAddInAutomationService()
{
if (m_utilities == null)
{
m_utilities = new AddInFIMUtilities();
}
return m_utilities;
}
protected override Office.IRibbonExtensibility CreateRibbonExtensibilityObject()
{
RibbonExcelFIM ribbon = new RibbonExcelFIM();
ribbon.FIMSaveEvent += new FIMSaveEventHandler(ribbon_FIMSaveEvent);
return ribbon;
}
}
[Guid("6CA66587-1A1E-4cd6-B55A-20F07F18C343")]
[ComVisibleAttribute(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IAddInUtilities
{
void EnableAddIn(bool isAddInEnabled);
event AddInEnablingEventHandler AddInEnablingEvent;
}
[ComVisibleAttribute(true)]
[Guid("F2FA4759-AEA0-4f4e-838B-3BBBC77837AB")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("AddInFIMUtilites")]
[Serializable()]
public class AddInFIMUtilities : StandardOleMarshalObject, IAddInUtilities
{
public event AddInEnablingEventHandler AddInEnablingEvent;
public void EnableAddIn(bool isAddInEnabled)
{
m_isAddInEnabled = isAddInEnabled;
if (isAddInEnabled)
{
if (AddInEnablingEvent != null)
{
AddInEnablingEvent();
}
else
{
}
}
}
}
What I'm doing wrong? Is there a solution which someone can provide me?
Thanks in advance
Marcel
|
|
|
|
|
I found out a solution that works. If someone has a better working solution, please post it
The code snippet of my new code in C#:
m_excelAddInUtils = (IAddInUtilities)obj;
IpcChannel serverChannel = new IpcChannel("localhost:0");
ChannelServices.RegisterChannel(serverChannel);
AddInFIMUtilities addInUtilClass = new AddInFIMUtilities();
m_excelAddInUtils.AddToSaveObserverList(addInUtilClass);
addInUtilClass.AddInSaveEvent += new AddInSaveEventHandler(addInUtilClass_OnFIMSaved);
The new delegate in Add-In class:
public delegate void AddInSaveEventHandler();
On the Add-In class I created a new IDispatch Interface:
[Guid("69075652-6A6D-442c-B534-5816D5046F04")]
[ComVisibleAttribute(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IAddInEvents
{
void AddInSaveEventHandler();
}
And extended the Main method interface:
[Guid("6CA66587-1A1E-4cd6-B55A-20F07F18C343")]
[ComVisibleAttribute(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
public interface IAddInUtilities
{
[DispId(1)]
void AddToSaveObserverList(IAddInUtilities addInUtils);
[DispId(2)]
void FireSaveEvent();
}
The new methods in the Utility class:
public void AddToSaveObserverList(IAddInUtilities addInUtils)
{
Globals.ExcelFIMAddIn.SaveObserverList.Add(addInUtils);
}
public void FireSaveEvent()
{
AddInSaveEvent();
}
On the Add-In class itself, these extensions are required:
<pre>private List<IAddInUtilities> m_saveObserverList = new List<IAddInUtilities>();
public List<IAddInUtilities> SaveObserverList
{
get { return m_saveObserverList; }
}
And eventually firing the event:
foreach (IAddInUtilities addInFIMUtil in this.SaveObserverList)
{
try
{
((AddInFIMUtilities)addInUtil).FireSaveEvent();
}
catch
{
}
}
modified on Monday, August 10, 2009 6:52 AM
|
|
|
|
|
Hi,
I am new to COM Component development. I dont have that much idea. So plz give me sample code or sample program. Thanks in Advance..
regards,
kannak....
kannak
|
|
|
|
|
|
Hi David...
Thanks for responding..i will go through ....
Regards,
kannak......
kannak
|
|
|
|
|
When I try to play an .avi file in a Windows Media Player component, it is like 1 second black between each new play. It says 'Media has been found' (a translation of myswlf of the Dutch version). Is this solvable? The avi file is a copy of the Vista copy file dialog which musn't be black between every loop.
Thanks.
|
|
|
|
|
Sorry for asking this question too fast - I found out that this component can play without any black pause in between!
Thanks.
|
|
|
|
|
How to set output parameter value to javascript use invoke function's pDispParams.
in javascript
<script type="text/javascript"><br />
var fVal;
external.GetFloat(fVal);<br />
</script>
How do it in Invoke function???
STDMETHODIMP CImpIDispatch::Invoke(<br />
DISPID dispIdMember,<br />
REFIID ,<br />
LCID ,<br />
WORD wFlags,<br />
DISPPARAMS* pDispParams,<br />
VARIANT* pVarResult,<br />
EXCEPINFO* ,<br />
UINT* puArgErr)<br />
{<br />
return S_OK;<br />
}
Hongjun Ge
|
|
|
|
|
You have no chance to transmit any value to javascript by parameter in parameter's list of GetFloat function. Only by [out,retval] parameter of one. I.e. by syntax "fVal = external.GetFloat();". For this action, you should assign right value to pVarResult parameter of CImpIDispatch::Invoke.
With best wishes,
Vita
|
|
|
|
|
Thanks for your reply.
In msdn document descriptions like below.Why they can implement the oCustCalenderObj parameter as out.
http://msdn.microsoft.com/en-us/library/aa770041(VS.85).aspx[^]
<SCRIPT language="JScript"><br />
function MyFunc(iSomeData)<br />
{<br />
var oCustCalendarObj;<br />
external.GetCustomCalender(oCustCalenderObj);<br />
oCustCalerdarObj.doStuffWithIt();<br />
.<br />
.<br />
.<br />
}<br />
</SCRIPT>
Hongjun Ge
|
|
|
|
|
I don't know, but all I said is correct. I didn't meet with GetCustomCalender declaration, but "Get" prefix requires [out,retval] parameter.
AFAIK JScript passes all arguments by value, so server doesn't have a way to modify them. And there is only one case - VARIANT* pVarResult parameter of Invoke.
You can assign some value to this parameter and view the result.
With best wishes,
Vita
|
|
|
|
|
Thanks for your reply. My be there have some way to implement it that we didn't find, But thanks again.
Hongjun Ge
|
|
|
|
|
I'm automating MS Word and so far I've found out that the easiest way to do it is to put as much of the code as possible in VBA macros (in a *.dot file loaded through COM automation), and call those macros.
m_Application.CreateDispatch(_T("Word.Application"));
...............
m_AddIns.AttachDispatch(m_Application.get_AddIns());
m_AddIn.AttachDispatch(m_AddIns.Add(_T("MyMacros.dot"), &vtOptional));
...............
m_Application.Run("MyMacro1");
The problem is I can't pass arguments to MyMacro1, and I need to in some cases. CApplication::Run accepts only 1 parameter and that's the macro name. But how can I pass additional arguments to the macro?
There is sufficient light for those who desire to see, and there is sufficient darkness for those of a contrary disposition.
Blaise Pascal
|
|
|
|