Received "" Error when running the below c# code - c#

I get an error when running the following code. When the program comes to the workbook2 != null line of code, it crashes.
Error:
System.Runtime.InteropServices.COMException (0x80010108): The object invoked has disconnected from its clients. (Exception from HRESULT: 0x80010108 (RPC_E_DISCONNECTED))
at Microsoft.Office.Interop.Excel._Workbook.Close(Object SaveChanges, Object Filename, Object RouteWorkbook)
Code:
public void CompleteAuto()
{
if (workbook1 != null)
{
MessageBox.Show("workbook1 is closed");
workbook1.Close(false);
}
if (workbook2 != null)
{
MessageBox.Show("workbook2is closed");
workbook2.Close(false);
}
if (workbook3 != null)
{
MessageBox.Show("workbook3 is closed");
workbook3.Close(false);
}
if (workbook4 != null)
{
MessageBox.Show("workbook4 is closed");
workbook4.Close(false);
}
if (workbook5 != null)
{
MessageBox.Show("workbook5 is closed");
workbook5.Close(false);
}
if (workbook6 != null)
{
MessageBox.Show("workbook6 is closed");
workbook6.Close(false);
}
if (workbook7 != null)
{
MessageBox.Show("workbook7 is closed");
workbook7.Close(false);
}
if (workbook8 != null)
{
MessageBox.Show("workbook8 is closed");
workbook8.Close(false);
}
if (stepByStep == false)
{
MessageBox.Show("Step by Step done!");
loadingForm.Hide();
}
MessageBox.Show("Output successful!");
this.Close();
}
I am new to c# so I don't know if the above code is right or wrong. I just want to multiple if to check if the workbooks had been open. If yes then closed them, if no then the program keep running.
Could anyone help me? Thanks.

Just a guess, as your example is incomplete...
When you close the Workbook, you are not setting it to null.
Add
Workbook1= null;
after Workbook1.Close.
Same for all the other closures.

You need to make a function, which checks if your workbook is opened.
If it is not, it throws. It is not ideal, but it works.
public static IsOpened(Excel.Application currentApp, string workbook)
{
try
{
var item = currentApp.WorkBooks.get_item(workbook);
return true;
}
catch
{
return false;
}
}

From Bob's answer, I successfully solved my question.
Here is my code:
if (workbook1 != null)
{
workbook1.Close(false);
workbook1 = null;
}
And guess what, it works!!!!

Related

Cannot access a disposed object but the program works

IN WPF project, whenever I try to add selected Student in selected university and display it on assoiated table.
Here is image of my table -
https://i.stack.imgur.com/KUHuF.png
I encounter this problem, once I hit update assosiated button.
public System.Data.Linq.Table<Student> Students
{
get
{
return this.GetTable<Student>();
}
}
The above code is in "Dataclasses1.designer.cs" window.
However, upon restarting the program, selected student is sucessfully added to selected university.
Here is my code -
private void UpdateAssociatedStudent_Click(object sender, RoutedEventArgs e)
{
if(ListUniversity.SelectedItem != null || ListStudent.SelectedItem != null)
{
using (dataContext = new DataClasses1DataContext())
{
UniversityManager universityManager = new UniversityManager
{
UniFK = int.Parse(ListUniversity.SelectedValue.ToString()),
StdFK = int.Parse(ListStudent.SelectedValue.ToString())
};
dataContext.UniversityManagers.InsertOnSubmit(universityManager);
dataContext.SubmitChanges();
}
ShowAssociatedStudents();
Sucess.Text = "Student is sucessfully added to University";
}
}
Edit - Adding image for error
https://i.stack.imgur.com/ApPxd.png
I think that you may need to change this line of code:
if(ListUniversity.SelectedItem != null || ListStudent.SelectedItem != null)
to
if(ListUniversity.SelectedItem != null && ListStudent.SelectedItem != null)
I've solved this issue by running try/catch instead of using 'Using' statement. my edited code looks like this.
//Add selected student from selected university in associated student listbox
private void UpdateAssociatedStudent_Click(object sender, RoutedEventArgs e)
{
if(ListUniversity.SelectedItem != null && ListStudent.SelectedItem != null)
{
try
{
uniManager = new UniversityManager()
{
UniFK = Convert.ToInt32(ListUniversity.SelectedValue),
StdFK = Convert.ToInt32(ListStudent.SelectedValue)
//UniFK = int.Parse(ListUniversity.SelectedItem.ToString()),
//StdFK = int.Parse(ListStudent.SelectedItem.ToString())
};
dataContext.UniversityManagers.InsertOnSubmit(uniManager);
dataContext.SubmitChanges();
ShowAssociatedStudents();
}
catch (FileNotFoundException)
{
Console.WriteLine("File Not Found.");
}
catch (OutOfMemoryException)
{
Console.WriteLine("Out of Memory.");
}
catch (IOException)
{
Console.WriteLine("An I/O error has occured.");
}
}
else
{
Failed.Text = "Please select the missing items from either university or student.";
}
}

UI suppression - client stuck at SigningIn state

I try to sign in to Skype For Business via my application.
When I'm with UI on, I can sign in.
When I set UI Suppression, my client is stuck at the signing in the state. Neither credentials event nor SigninCallback event nor SignInDelayed event is fired.
Can you help me?
Here is my code:
public void StartUpSkype()
{
try
{
_LyncClient = LyncClient.GetClient();
if (_LyncClient == null)
{
throw new Exception("Unable to obtain client interface");
}
if (_LyncClient.InSuppressedMode == true)
{
if (_LyncClient.State == ClientState.Uninitialized)
{
Object[] _asyncState = { _LyncClient };
_LyncClient.BeginInitialize(InitializeCallback, _asyncState);
}
}
_LyncClient.SignInDelayed += _LyncClient_SignInDelayed;
_LyncClient.StateChanged += _Client_ClientStateChanged;
_LyncClient.CredentialRequested += _LyncClient_CredentialRequested;
}
catch (NotStartedByUserException h)
{
DisplayErrorMessage("Lync is not running");
}
catch (Exception ex)
{
DisplayErrorMessage("General Exception");
}
}
void _Client_ClientStateChanged(Object source, ClientStateChangedEventArgs data)
{
if (data != null)
{
if (data.NewState == ClientState.SignedIn)
{
DisplayErrorMessage("Signed in");
UserIsSignedIn?.Invoke(_LyncClient);
}
if (data.NewState == ClientState.SignedOut)
{
string login = ConfigurationManager.AppSettings["loginSkypeClient"];
string password = ConfigurationManager.AppSettings["pwdSkypeClient"];
_LyncClient.SignInConfiguration.ForgetMe(login);
try
{
// starts the sign in process asynchronously
IAsyncResult asyncResult = _LyncClient.BeginSignIn(login, login, password, SigninCallback, _LyncClient);
// But wait for the results because the events cannot be registered within a worker thread.
asyncResult.AsyncWaitHandle.WaitOne();
}
catch (Exception e)
{
throw e;
}
}
}
}
void _LyncClient_CredentialRequested(object sender, CredentialRequestedEventArgs e)
{
string login = ConfigurationManager.AppSettings["loginSkypeClient"];
string password = ConfigurationManager.AppSettings["pwdSkypeClient"];
if (e.Type == CredentialRequestedType.SignIn)
{
e.Submit(login, password, false);
}
}
private void SigninCallback(IAsyncResult ar)
{
if (ar.IsCompleted == true)
{
try
{
((LyncClient)ar.AsyncState).EndSignIn(ar);
}
catch (RequestCanceledException re)
{
throw re;
}
}
}
private void InitializeCallback(IAsyncResult ar)
{
if (ar.IsCompleted == true)
{
object[] asyncState = (object[])ar.AsyncState;
((LyncClient)asyncState[0]).EndInitialize(ar);
//_ThisInitializedLync is part of application state and is
//a class Boolean field that is set to true if this process
//initialized Lync.
_ThisInitializedLync = true;
}
}
The login + password are correct because I can sign in with them when the UI is on.
The problem only happens when the UI is suppressed.
I've tried many things, I am desperate right now.
Please check the version of SkypeForBusiness. If it is 2016 then it is happening due to ModernAuthentication enabled on both client and tenant office365.
In case ModernAuthentication is enabled, the LyncSDK is not capable enough to handle ModernAuth as SDK doesn't support and Microsoft has no plans to upgrade the SDK.

After scenario Cleanup in Specflow - try catch finally

I am try to clean up the scenario by capturing screenshots
The problem I face is when I try to see how many times "try catch finally" is executed..it's executed nearly 20 times after initial try-finally-it goes directly to catch
Here is my code
[AfterScenario]
public void CleanUp()
{
int aaa = 0;
try
{
if (ScenarioContext.Current.TestError != null)
{
//Taking screenshot
}
Console.WriteLine("try");
}
catch
{
Console.WriteLine("Catch");
if (Browser != null)
{
Browser.Dispose();
Browser = null;
}
return;
}
finally
{
Console.WriteLine("finally");
if (Browser != null)
{
Browser.Dispose();
Browser = null;
Console.WriteLine("finallya");
}
}
return;
}
try
finally
after this why it goes to Catch again? when I am doing some thing wrong here?

goto in c# and its usage

I have a subroutine. It comapares whether values are empty then doing something. For example, if they are empty, then warnings are raised.
The code works fine. But when value are not empty, the warnings are still pop out. Please help me to correct the logic.
Thanks.
private void btnNew_Click(object sender, EventArgs e)
{
try
{
if (txtbox1.Text.ToString().Trim() == string.Empty)
{
goto Msg1;
}
if (txtbox2.Text.ToString().Trim() == string.Empty)
{
goto Msg2;
}
DataRow dr = mydataSet.Tables[0].NewRow();
dr["Descript"] = txtbox1.Text;
dr["Abbr"] = txtbox2.Text;
dr["SortOrder"] = Convert.ToDecimal(numericOrder.Value);
if (SortOrders.Contains((decimal)dr["SortOrder"]))
{
goto Msg3;
}
mydataSet.Tables[0].Rows.Add(dr);
dgv.DataSource = mydataSet.Tables[0];
Msg1:
MessageBox.Show("Description is required.");
Msg2:
MessageBox.Show("Abbr is required.");
Msg3:
MessageBox.Show("Please select another one, this one is already used.");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
From the above code, you see. if txtbox1 has some value, the program still displays Msg1. I want to avoid it.
Because labels are just labels, and code after them is executed sequentially.
Why can't you do just this:
try
{
if (txtbox1.Text.ToString().Trim() == string.Empty)
{
MessageBox.Show("Description is required.");
return;
}
if (txtbox2.Text.ToString().Trim() == string.Empty)
{
MessageBox.Show("Abbr is required.");
return;
}
DataRow dr = mydataSet.Tables[0].NewRow();
dr["Descript"] = txtbox1.Text;
dr["Abbr"] = txtbox2.Text;
dr["SortOrder"] = Convert.ToDecimal(numericOrder.Value);
if (SortOrders.Contains((decimal)dr["SortOrder"]))
{
MessageBox.Show("Please select another one, this one is already used.");
return;
}
mydataSet.Tables[0].Rows.Add(dr);
dgv.DataSource = mydataSet.Tables[0];
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
It's so much more readable.
Restructure your code to avoid goto - it is a relic and not much use in a properly object oriented codebase.
Returning from the method, throwing exceptions or building an errors dictionary are all better options than using goto.
For example, you can have a List<string> errors which you add to when you get an error condition.
If it is empty, no errors were encountered, if it isn't, there were.
This is a good case were goto is the wrong way to go. Use something like this instead.
private void btnNew_Click(object sender, EventArgs e)
{
try
{
bool error = false;
if (txtbox1.Text.ToString().Trim() == string.Empty)
{
MessageBox.Show("Description is required.");
error = true;
}
if (txtbox2.Text.ToString().Trim() == string.Empty)
{
MessageBox.Show("Abbr is required.");
error = true;
}
if (SortOrders.Contains(Convert.ToDecimal(numericOrder.Value)
{
MessageBox.Show("Please select another one, this one is already used.");
error = true;
}
if(error)
return;
DataRow dr = mydataSet.Tables[0].NewRow();
dr["Descript"] = txtbox1.Text;
dr["Abbr"] = txtbox2.Text;
dr["SortOrder"] = Convert.ToDecimal(numericOrder.Value);
mydataSet.Tables[0].Rows.Add(dr);
dgv.DataSource = mydataSet.Tables[0];
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Edit
Just figured that my code didn't actually do the same as his first sample since it only displayed the first error no matter how many that occured. Updated my sample to accomodate for that.
I've always been taught to avoid goto like the plague, and it's something I've followed for years. I've never even considered it to be an option when writing code.
Thinking about it though, I did read an article a few years ago (which I can't find now) which said you could credibly use gotos only if you used it to jump down code, and not up: a rule that is stuck to here.
Check here for more info: Does anyone still use [goto] in C# and if so why?
There are better ways of using goto statement, for instacne using "return" (when used in the middle of a method), "break" and "continue". Have you ever used one of these?
private void btnNew_Click(object sender, EventArgs e)
{
try
{
var description = txtbox1.Text.Trim();
if (string.IsNullOrEmpty(description))
{
MessageBox.Show("Description is required.");
return;
}
var abbr = txtbox2.Text.Trim();
if (string.IsNullOrEmpty(abbr))
{
MessageBox.Show("Abbr is required.");
return;
}
var numericOrderValue = Convert.ToDecimal(numericOrder.Value);
if (SortOrders.Contains(numericOrderValue)
{
MessageBox.Show("Please select another one, this one is already used.");
return;
}
DataRow dr = mydataSet.Tables[0].NewRow();
dr["Descript"] = description;
dr["Abbr"] = abbr;
dr["SortOrder"] = numericOrderValue;
mydataSet.Tables[0].Rows.Add(dr);
dgv.DataSource = mydataSet.Tables[0];
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void btnNew_Click(object sender, EventArgs e)
{
try
{
if (txtbox1.Text.ToString().Trim() == string.Empty)
{
MessageBox.Show("Description is required.");
}
if (txtbox2.Text.ToString().Trim() == string.Empty)
{
MessageBox.Show("Abbr is required.");
}
DataRow dr = mydataSet.Tables[0].NewRow();
dr["Descript"] = txtbox1.Text;
dr["Abbr"] = txtbox2.Text;
dr["SortOrder"] = Convert.ToDecimal(numericOrder.Value);
if (SortOrders.Contains((decimal)dr["SortOrder"]))
{
MessageBox.Show("Please select another one, this one is already used.");
}
mydataSet.Tables[0].Rows.Add(dr);
dgv.DataSource = mydataSet.Tables[0];
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Try this. It works.

Keep WCF Service Connected

How can I keep my WCF Service Client Connected with WinForm even if a Faulted State appened ?
Thanks.
Answer myself :)
You might subscribe to InnerChannel Events
svc.InnerChannel.Closed += InnerChannel_Error;
svc.InnerChannel.Closing += InnerChannel_Error;
svc.InnerChannel.Faulted += InnerChannel_Error;
Then Handle Exceptions and Recreate the Service Proxy
private void InnerChannel_Error(object sender, EventArgs e)
{
var svc = _entrepotService as EntrepotServiceProxy;
try
{
if (svc != null)
{
if (svc.State != CommunicationState.Faulted)
{
svc.Close();
}
else
{
svc.Abort();
}
}
}
catch (CommunicationException)
{
if (svc != null) svc.Abort();
}
catch (TimeoutException)
{
if (svc != null) svc.Abort();
}
catch
{
if (svc != null) svc.Abort();
throw;
}
_entrepotService = new EntrepotServiceProxy();
}
As far as I know, a faulted state is usually terminal to a WCF proxy. So no, I don't think so.

Categories

Resources