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
Related
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;
}
here is the error I am getting :
System.ExecutionEngineException was unhandled
HResult=-2146233082
Message=Exception of type 'System.ExecutionEngineException' was thrown.
InnerException:
code Update:
here is my code
void WriteGraph(int[] vData)
{
string tempWrite = "";
try
{
for (int y = 0; y < vData.Length;)
{
for (int i = 0; i < 20; i++)
{
tempWrite = tempWrite + vData[i] + ",";
y++;
}
File.AppendAllText(name2, tempWrite);
}
File.AppendAllText(name2, Environment.NewLine);
}
catch ( Exception e)
{
AppendTextBox(e.Message.ToString());
}
}
it fails at tempWrite = tempWrite + vData[i] + ",".
not that is in a loop so it does write some values to the file.
I open the file in Excel and it goes from A to LW
before it died ...
the question is why ?
here is the loop :
void PlotSpectrum(int []vData)
{
ArrayList listDataSource = new ArrayList();
// Populate the list with records.
for (int i = 0; i < vData.Length; i++)
{
WriteGraph(Convert.ToString(vData[i]));
listDataSource.Add(new Graph_Class(i, vData[i]));
}
// Bind the chart to the list.
ChartControl myChart = chartControl1;
myChart.DataSource = listDataSource;
// Create a series, and add it to the chart.
Series series1 = new Series("Spectrum", ViewType.Line);
myChart.Series.Add(series1);
// Adjust the series data members.
series1.ArgumentDataMember = "X";
series1.ValueDataMembers.AddRange(new string[] { "Y" });
// Access the view-type-specific options of the series.
((LineSeriesView)series1.View).ColorEach = true;
series1.LegendTextPattern = "{A}";
try
{
//myChart.Update();
// myChart.Refresh();
}catch(Exception err)
{
AppendTextBox(err.Message.ToString());
print("Error in Graph: ", DateTime.Now.ToString(), err.Message.ToString());
}
}
The same thing is happening for me, but it only throws this exception when a yarn rebuild finishes (front-end is React). I am using IIS Express to run locally. I wonder if it doesn't like that the files are changing while the app is running.
This seems to fix it:
Go to Tools, Options, Projects and Solutions, Web Projects; and check "Use the 64 bit version of IIS Express for web sites and projects".
In my case this happened in Service Fabric startup before it has a chance to begin running. The exception shows up in the Event Viewer rather than VS.
This problem happens because something failed before throw ExecutionEngineException.
I faced this issue (typing Japanese characters in TextBox on WPF app), I solved activating Common Language Runtime Exceptions in Exceptions Settings in VS
and checking the values of each runtime exception(before get crash) and I found a null value in one of the variables in a previous method but the crash was thrown many seconds after that.
You can find a deep explanation here: Why this code throws System.ExecutionEngineException
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?
I have a simple C# console application that talks to a webservice. I am not sure if the way I am handling expections and returning error codes are proper. Would like to have comments on good pratice to do this. (I am using CommandLine.dll for option parsing)
class Program
{
static int Main(string[] args) {
var options = new Options();
if (CommandLine.Parser.Default.ParseArguments(args, options)) {
try {
var client = new MyWebService();
var response = client.MyFunction(new MyRequest() { Param1 = options.param1, Param2 = options.Param2 });
if (response.ErrorCode != 0) {
Console.WriteLine("Error code= " + response.ErrorCode);
}
else {
File.WriteAllText(options.OutputFile, response.File);
return 0;
}
}
catch (Exception exp) {
Console.WriteLine(exp.Message);
return 1;
}
}
return 1;
}
}
You should use the Console.Error.* to write errors. And I'll say that this:
if (response.ErrorCode != 0) {
Console.Error.WriteLine("Error code= " + response.ErrorCode);
return 1;
} else {
File.WriteAllText(options.OutputFile, response.File);
}
plus a final
return 0;
after the catch would be better, so that if you have multi-stage operations to do, it's easier to code (fall-through == ok, error == fast abort)
with multi-stage I mean:
call ws1
check for non-Exception errors of ws1, if errors abort
call ws2
check for non-Exception errors of ws2, if errors abort
call ws3
check for non-Exception errors of ws3, if errors abort
return success
In the cmd prompt, to save errors:
myprogram 2>err.txt
to redirect output + error:
myprogram > err.txt 2>&1
(the last one was taken from https://stackoverflow.com/a/1420981/613130)
Last thing: if the parsing of the arguments goes wrong, you should output an error.
You should refactor the MyWebService class and the MyFunction to throw exceptions if an error occurs. Instead of returning error codes. That gives you full flexibility in terms of who at which level can handle the errors and it makes the code much more readable.
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...