This results in a COMException: 8001010d, See below for full exception.
According to some threads I have found using Google, the problem is that
WndProc is using COM and therefore I can't call a COM server from WndProc.
Anyone that has an idea on how to solve this?
// Anders
Exception:
System.Runtime.InteropServices.COMException was unhandled
Message="Hämtningen av COM-klassfabriken för komponenten med CLSID
{14660C3E-3CF7-4CA5-9B32-913F3DD6F19F} misslyckades på grund av följande
fel: 8001010d."
Source="DCMarkerLib"
ErrorCode=-2147417843
StackTrace:
vid DCMarkerLib.LEngine.CreateDocument(Dictionary`2 dict,
DocsType type) i C:\Users\ame\Documents\Visual Studio
2008\Projects\SandvikCoromant\DCMarker\DCMarkerLib\LEngine.cs:rad 460
vid DCMarkerLib.LEngine.CreateImage(Dictionary`2 dict, String
id) i C:\Users\ame\Documents\Visual Studio
2008\Projects\SandvikCoromant\DCMarker\DCMarkerLib\LEngine.cs:rad 854
vid DCMarkerLib.Job.CreateImage(Dictionary`2 dict, Int32 block)
i C:\Users\ame\Documents\Visual Studio
2008\Projects\SandvikCoromant\DCMarker\DCMarkerLib\Job.cs:rad 259
vid DCMarkerLib.Job.Parse() i C:\Users\ame\Documents\Visual
Studio 2008\Projects\SandvikCoromant\DCMarker\DCMarkerLib\Job.cs:rad 133
vid DCMarker.Form1.button1_Click(Object sender, EventArgs e) i
C:\Users\ame\Documents\Visual Studio
2008\Projects\SandvikCoromant\DCMarker\DCMarker\Form1.cs:rad 91
vid System.Windows.Forms.Control.OnClick(EventArgs e)
vid System.Windows.Forms.Button.OnClick(EventArgs e)
vid System.Windows.Forms.Button.PerformClick()
vid DCMarker.Form1.loadBtnfnc() i C:\Users\ame\Documents\Visual
Studio 2008\Projects\SandvikCoromant\DCMarker\DCMarker\Form1.cs:rad 39
vid DCMarker.Form1.WndProc(Message& m) i
C:\Users\ame\Documents\Visual Studio
2008\Projects\SandvikCoromant\DCMarker\DCMarker\Form1.cs:rad 55
vid
System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
vid
System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
vid System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr
hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
vid System.Windows.Forms.UnsafeNativeMethods.PeekMessage(MSG&
msg, HandleRef hwnd, Int32 msgMin, Int32 msgMax, Int32 remove)
vid
System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32
dwComponentID, Int32 reason, Int32 pvLoopData)
vid
System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32
reason, ApplicationContext context)
vid
System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32
reason, ApplicationContext context)
vid System.Windows.Forms.Application.Run(Form mainForm)
vid DCMarker.Program.Main() i C:\Users\ame\Documents\Visual
Studio 2008\Projects\SandvikCoromant\DCMarker\DCMarker\Program.cs:rad 32
vid System.AppDomain._nExecuteAssembly(Assembly assembly,
String[] args)
vid System.AppDomain.ExecuteAssembly(String assemblyFile,
Evidence assemblySecurity, String[] args)
vid
Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
vid System.Threading.ThreadHelper.ThreadStart_Context(Object state)
vid System.Threading.ExecutionContext.Run(ExecutionContext
executionContext, ContextCallback callback, Object state)
vid System.Threading.ThreadHelper.ThreadStart()
InnerException:
CODE:
private delegate void loadBtn();
private void loadBtnfnc()
{
button1.PerformClick();
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_COPYDATA:
Win32.CopyDataStruct CD =
(Win32.CopyDataStruct)m.GetLParam(typeof(Win32.CopyDataStruct));
string strData =
System.Runtime.InteropServices.Marshal.PtrToStringAuto(CD.lpData);
textBox1.Text = strData;
textBox1.Refresh();
// load job file
loadBtn x = loadBtnfnc;
x();
break;
default:
// let the base class deal with it
base.WndProc(ref m);
break;
}
}
0x8001010d is RPC_E_CANTCALLOUT_ININPUTSYNCCALL (see below for a simple
program that helps turn error codes into messages, using the built-in
support from .NET's Marshal class).
Because the WM_COPYDATA message is being sent inter-process already, COM
restricts the use of synchronous calls as a way of ensuring against
deadlock conditions. This is true even in situations such as yours
where deadlock is unlikely to occur.
See http://support.microsoft.com/kb/131056 for more details.
Without a fully working concise-but-complete code example, it's hard to
say for sure what the best way to fix the issue would be. Personally, I
would try to avoid using the WM_COPYDATA in the first place. IMHO there
are better inter-process mechanisms one can use, including named pipes,
shared memory, or even network sockets.
But assuming you are stuck using WM_COPYDATA (perhaps you don't have
control over the other program), one possibility is to try using the
Control.BeginInvoke() method to queue the call rather than trying to
execute it immediately. For example:
private void loadBtnfnc()
{
BeginInvoke((MethodInvoker)delegate
{
button1.PerformClick();
});
}
(Your code example also seems a bit odd, in that you call the method by
first creating a delegate instance and then invoking it, but I suppose
maybe that's because of some other generalization that really exists in
your program but which is hidden in the example you provided).
Hope that helps.
Pete
using System;
using System.Globalization;
using System.Runtime.InteropServices;
namespace FormatWin32Error
{
class Program
{
static void Main(string[] args)
{
string strInput;
Console.WriteLine("Enter a hexadecimal Win32 error code: ");
while ((strInput = Console.ReadLine()) != "")
{
uint error;
if (strInput.ToLower().StartsWith("0x"))
{
strInput = strInput.Substring(2);
}
if (!uint.TryParse(strInput, NumberStyles.HexNumber,
CultureInfo.InvariantCulture, out error))
{
Console.WriteLine("invalid input");
continue;
}
try
{
Exception exc1 = Marshal.GetExceptionForHR((int)error);
Console.WriteLine("\"{0}\"", exc1.Message);
}
catch (Exception exc)
{
Console.WriteLine("Failed to get message. {0}:
\"{1}\"",
exc.GetType().Name, exc.Message);