I am modifying an ASP.NET application that uses a COM reference. The code creates an instance of the object the following way:
public static object COMCreateObject (string sProgID)
{
try
{
Type oType = Type.GetTypeFromProgID(sProgID);
if (oType != null)
{
return Activator.CreateInstance(oType);
}
else
{
throw new ApplicationException(
"Could not resolve ProgID for " + sProgID +
" (Ensure the component is registered properly)");
}
}
catch (Exception oExc)
{
PageInclude.ermHandleError(
"An error occured whilst creating " + sProgID +
" - " + oExc.ToString());
throw oExc;
}
}
The GetTypeFromProgId returns a valid Type of System._COMObject, however three of the properties (DeclaringMethod, GenericParameterAttributes and GenericParameterPosition) are returned with an InvalidOperationException ("Method may only be called on a Type for which Type.IsGenericParameter is true.").
So then calling the Activator.CreateInstance(oType) also fails (Creating an instance of the COM component with CLSID {508B4562-C89D-4DE9-4523-E6D507B3E3F2} from the IClassFactory failed due to the following error: 800aeb29.)
I'm unsure if the exceptions on the COM component are to blame (it's not a .NET component, so these fields may be missing?).
Any Ideas?
Related
Im trying to make a custom shell.
public static void CallMethod(string method, string[] args)
{
try
{
Type type = typeof(Program);
MethodInfo methodInfo = type.GetMethod(method);
methodInfo.Invoke(method, args);
}
catch(TargetException)
{
Console.WriteLine("The method + '" + method + "' does not exist.");
}
catch(TargetParameterCountException)
{
Console.WriteLine("The parameter count for '" + method +"' does not fit.");
}
catch(Exception)
{
Console.WriteLine("An unexpected error occured.");
}
}
I am expecting TargetException to be thrown when the method-string doesnt contain an existing method - like the MS documentation says. But in this case the Exception is thrown. Little example: There is no function example(), so it should throw TargetException when method contains "example", but it seems that another Exception is thrown
My question ist what exception is thrown in this specific case?
I have a project that is attempting to connect to Sage 200. However it is complaining that the type initialisation has failed now usually that is to do with assembly not being in the cache however this time it is. I have restarted,
The error that I am receiving I also ran the gac utility to ensure that it was in the assembly cache and as you see below it is Sage.
The main error is:
{"The type initializer for 'Sage.MMS.SAA.Client.SAAClientAPI' threw an
exception."}
But when debugging further the below is revealed
"Cannot cast the underlying exported value of type
'Sage.MMS.SAA.Client.ISAAClient
(ContractName=\"Sage.MMS.SAA.Client.ISAAClient\")' to type
'Sage.MMS.SAA.Client.ISAAClient'."
This code works in other imports so I think it is something to do with the assembly file.
public bool ConnectToSage()
{
try
{
application = new Sage.Accounting.Application();
// Use the Connect method (no parameters required)
application.Connect();
foreach (var item in application.Companies)
{
if (((Sage.Accounting.Company)item).Name == Properties.Settings1.Default.CompanyName)
{
application.ActiveCompany = (Sage.Accounting.Company)item;
log.Info("Connected to company: " + Properties.Settings1.Default.CompanyName);
return true;
}
}
}
catch(TypeInitializationException ex)
{
}
return false;
}
Environment:
Microsoft Visual Studio 2010 SP1
C# -- .NET 4.0
Problem:
Everything works fine, except the installation.
After much thought and research, I suspect that the problem is an attempted cast from -- “COM object of type 'System.__ComObject' to interface type 'WUApiLib.UpdateInstaller'.” As can be seen in the code, the IID and type have been set but the values of the parameters are suspect. The Following is the runtime error report:
System.InvalidCastException was caught. Message=Specified cast is not
valid. Source=PROGRAM_NAME StackTrace:
at WUApiLib.IUpdateInstaller.Install()
at PROGRAM_NAME.WindowsUpdates.InstallUpdates(UpdateCollection updatesToInstall) in %PATH%\visual studio 2010\Projects\ …
InnerException:
Request:
After many hours of research and study, any help to resolve the problem of installing the updates would be greatly appreciated. Please see the following code snippets.
Program attempts the following:
-- Windows update services are enabled (No problems)
-- That the host machine needs to be updated: (No problems)
-- Downloads the updates: (No problems)
public static UpdateCollection DownloadUpdates()
{
// Returns UpdateCollection object.
}
-- Attempts to install the updates. (Exception: Specified cast is not valid.)
public static void InstallUpdates(UpdateCollection updatesToInstall)
{
IUpdateInstaller updateInstaller;
Console.WriteLine("Creating UpdateInstasller...");
//Type itype = Type.GetTypeFromProgID("Microsoft.Update.Session", true);
//Type t = Type.GetTypeFromProgID("Microsoft.Update.Session", "127.0.0.1")
Type itype = Type.GetTypeFromProgID("Microsoft.Update.Installer", true);
updateInstaller = (UpdateInstaller)Activator.CreateInstance(itype);
updateInstaller.Updates = updatesToInstall;
updateInstaller.ClientApplicationID = "{3442D4FE-224D-4CEE-98CF-30E0C4D229E6}"; // Unsure of IID
IInstallationResult installationResult;
Console.WriteLine("Creating UpdateInstallationResult...");
updateInstaller.IsForced = true;
if (updateInstaller.IsBusy == false)
{
try
{
installationResult = updateInstaller.Install(); // ***Bad Cast exception here.***
if (updatesToInstall.Count > 0)
{
for (int i = 0; i < updatesToInstall.Count; i++)
{
if (installationResult.GetUpdateResult(i).HResult == 0)
Console.WriteLine("Installed : " + updatesToInstall[i].Title);
else
Console.WriteLine("Failed : " + updatesToInstall[i].Title);
// Is Reboot Required?
if (installationResult.RebootRequired == true)
Console.WriteLine("Reboot is required for one of more updates.");
} // end for
} // end if
} // end try
catch (Exception e)
{
Console.WriteLine("Error:: " + e.Message + "\n");
}
} // end if
} // end method
I am developing a ComVisible library in .NET which is then called in an old VB6 class. What I basically do in the class is calling a web service, parsing the response and returning an object with necessary data. The web service is designed so that it returns a SoapException if called with wrong parameter(s). Here is a part of my code:
private static WCFPersonClient _client;
private static ReplyObject _reply;
public BFRWebServiceconnector()
{
_client = new WCFPersonClient("WSHttpBinding_IWCFPerson");
_reply = new ReplyObject ();
}
[ComVisible(true)]
public ReplyObject GetFromBFR(string bestallningsID, string personnr, bool reservNummer = false)
{
try
{
var response = new XmlDocument();
//the service operation returns XML but the method in the generated service reference returns a string for some reason
var responseStr = _client.GetUserData(orderID, personnr, 3); reason.
response.LoadXml(responseStr);
//parse the response and fill the reply object
.......
}
catch (Exception ex)
{
_reply.Error = "Error: " + ex.Message;
if (_client.InnerChannel.State == CommunicationState.Faulted) _client = new WCFPersonClient("WSHttpBinding_IWCFPerson"); //recreate the failed channel
}
return _reply;
}
Once I try to call this method from my VB6 code with correct parameters, I get a proper reply. But if I call it with a wrong parameter, I get a -245757 (Object reference was not set to an instance of an object) runtime error in my VB6 program and it seems that it's not caught by the catch clause in my C# code (while I would expect an empty ReplyObject with filled Error field returned by the method).
I have created a test C# project and copied the same method (i.e. I call the same web service from within the .NET platform) and I can confirm that in this case the SoapException is being properly caught.
Is this behavior intentional? Is there a way to catch the SoapException within a ComVisible class (since I really would like to include the error message into my reply object)?
UPD: My VB6 code is following:
Set BFRWSCReply = New ReplyObject
Set BFRWSC = New BFRWebbServiceconnector
Set BFRWSCReply = BFRWSC.GetFromBFR(m_BeställningsID, personnr)
If Not IsNull(BFRWSCReply) Then
If BFRWSCReply.Error= "" Then
m_sEfternamn = BFRWSCReply.Efternamn
//etc i.e. copy fields from the ReplyObject
Else
MsgBox BFRWSCReply.Error, vbExclamation
End If
End If
(this is just a guess and is more fitting for a comment but it's pretty long)
It's possible that the .NET runtime is disposing of the ReplyObject COM object when the BFRWebServiceconnector class goes out of scope, maybe because it is a property of the class and not created within the method?
Try creating the ReplyObject within GetFromBFR instead of making it a property of the class. That also might prevent weird errors from multithreaded access if the COM object is called from different threads.
Also if there's a particular line in the VB program that is throwing the error (after you call GetFromBFR), you could see if the variable is Nothing within VB to try and narrow down the problem.
Like I said, just a guess. Feel free to refute it. :)
I'm very ashamed that the reason was very very simple... Instead of following:
catch (Exception ex)
{
_reply.Error = "Error: " + ex.Message;
if (_client.InnerChannel.State == CommunicationState.Faulted) _client = new WCFPersonClient("WSHttpBinding_IWCFPerson"); //recreate the failed channel
}
I had actually following code:
catch (Exception ex)
{
_reply.Error = "Error: " + ex.Message + "; " + ex.InnerException.Message;
if (_client.InnerChannel.State == CommunicationState.Faulted) _client = new WCFPersonClient("WSHttpBinding_IWCFPerson"); //recreate the failed channel
}
and it turns out that ex.InnerException was null which caused the NullPointerException...
In the following method, the first catch block is never run, even when an exception of type ExceptionType is thrown:
/// <summary>
/// asserts that running the command given throws an exception.
/// </summary>
public static void Throws<ExceptionType>(ICommand cmd)
where ExceptionType : Exception
{
// Strangely, using 2 catch blocks on the code below makes the first catch block do nothing.
try
{
try
{
cmd.Execute();
}
catch (ExceptionType)
{
return;
}
}
catch (Exception f)
{
throw new AssertionException(cmd.ToString() + " threw an exception of type " + f.GetType() + ". Expected type was " + typeof(ExceptionType).Name + ".");
}
throw new AssertionException(cmd.ToString() + " failed to throw a " + typeof(ExceptionType).Name + ".");
}
as indicated by the following test:
[Test]
public void Test_Throws_CatchesSpecifiedException()
{
AssertThat.Throws<AssertionException>(
new FailureCommand()
);
}
using the following class:
class FailureCommand : ICommand
{
public object Execute()
{
Assert.Fail();
return null; // never reached.
}
public override string ToString()
{
return "FailureCommand";
}
}
giving the following output in NUnit:
TestUtil.Tests.AssertThatTests.Test_Throws_CatchesSpecifiedException:
FailureCommand threw an exception of type NUnit.Framework.AssertionException. Expected type was AssertionException.
I also tried using 2 catch blocks for 1 try block (instead of nesting a try/catch within an outer try), but got the same results.
Any ideas as to how to catch the exception specified as a type parameter in one catch block, but catch all other exceptions in the other?
Works fine for me in this test:
using System;
using System.IO;
class Test
{
static void Main()
{
Throws<ArgumentNullException>(() => File.OpenText(null));
}
public static void Throws<ExceptionType>(Action cmd)
where ExceptionType : Exception
{
try
{
try
{
cmd();
}
catch (ExceptionType)
{
Console.WriteLine("Caught!");
return;
}
}
catch (Exception f)
{
Console.WriteLine("Threw an exception of type " + f.GetType()
+ ". Expected type was " + typeof(ExceptionType) + ".");
}
Console.WriteLine("No exception thrown");
}
}
How certain are you that the two AssertionException exceptions are identical? Are they definitely in the same namespace (print typeof(ExceptionType) rather than just the Name property)? Are they from the same assembly? I wouldn't be surprised to find some oddities due to multiple test framework versions coexisting...
Try it with an exception other than AssertionException to make life simpler.
See this thread for more info:
Why can't I catch a generic exception in C#?
Seems to be a bug:
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=362422&wa=wsignin1.0
I haven't debugged this code or looked at it too long but could it be that you first "return" statement is causing the code to HALT and leave the method. Therefore, the exception is "caught" or "handled" (however you look at it) and the outer try/catch block is never executed.
Are you trying to do this?
try
{
try
{
cmd.Execute();
}
catch (ExceptionType)
{
throw;
}
}
catch (Exception f)
{
throw new AssertionException(cmd.ToString() + " threw an exception of type " + f.GetType() + ". Expected type was " + typeof(ExceptionType).Name + ".");
}