MK_E_UNAVAILABLE in Marshal.GetActiveObject("Word.Application") - c#

0x800401E3 (MK_E_UNAVAILABLE) error occurs in my case when UAC (User Account Control) isn't set to the un-restrictive "Never Notify Me".
Microsoft.Office.Interop.Word.Application wd =
(Microsoft.Office.Interop.Word.Application)
System.Runtime.InteropServices.Marshal.GetActiveObject("Word.Application");
The error is thrown when the code is run after publishing and installing the project. While debugging in the editor instead, everything is fine.
Is this due to security settings or credentials ? How to write such code correctly pls ?
Win Word is open and a document is open too, of course, and this code has always worked fine with UAC set to "Never Notify Me".

Running word as a service is nasty business see for instance here . I went through quite a few problems making it work. The way I made it work was to run it in separate process which launches it only once. The main program communicates with the process by sending commands as strings to stdin of the process and waiting for response on the stdout. If the response does not come in time allotted the process is killed and restarted

Related

C# COM application crash debugging

The C# console application running .NET 4.5.2 (app1) opens a COM application (app2) and does some work with that app2's API. So far all of the work is successful, but sometimes when app1 attempts to close app2, app2 hangs permanently.
If the process for app2 is ended with task manager then app1 reports access denied. Does that occur because the terminated process is no longer available or does it occur because it was blocking a thread in app1 and it was unable to report the error until the thread was allowed to continue?
The code used to terminate app2 is
private static void CloseSW(SldWorks swApp, Process sw_proces)
{
// Close with API call
if (Task.Run(() => { swApp.CloseAllDocuments(true); swApp.ExitApp(); }).Wait(TimeSpan.FromSeconds(20)))
return;
// Kill process if API call failed
if (Task.Run(() => { SWHelper.CloseSW(sw_proces); }).Wait(TimeSpan.FromSeconds(20)))
return;
// Unable to close SolidWorks, ignore error and continue
// This will eventually cause SolidWorks to crash and the crash handler will take over
}
This code should never take much more than 40 seconds to complete, but maybe the COM interop is causing some unexpected behaviour?
I am unable to reproduce this error on a development machine. What it the best way to trace the exact point of failure? It is possible that the failure is not in CloseSW but some point before this. Is there a better way to trace the error than to write each line to a log file?
It is also worth noting that this code works for 60 - 150 runs before it has any errors and both applications are closed between each run.
I have control of the remote environment so remote debugging is an option, but I've never set that up before.
Typically with COM interops causing issues is that IIS is having issues with the object using the current ISAPI.dll. Please verify that your permissions are configured within your assembly to work with your current version of IIS>
A few questions to help assist would be, which framework version are you using, which version of IIS and what is your Application Pool using for a framework.
HTH

Process.Start won't work

I am trying to launch a process from a web page's back-end code/app pool. This process will launch an App that i built myself.
For some reason, the process only works / runs when i start it from VS2013... it never works when i launch it from IIS(7.5) itself.
I am on a Windows 7 machine (both IIS host, and App location), and I've setup my web site to only be accessible via internal network.
Here's the code, followed by the config / attempts to fix the issue:
protected void btn_DoIt_Click(object sender, EventArgs e)
{
string file_text = this.txt_Urls.Text;
if (!String.IsNullOrWhiteSpace(file_text))
File.WriteAllText(ConfigurationManager.AppSettings["filePath"], file_text);
ProcessStartInfo inf = new ProcessStartInfo();
SecureString ss = GetSecureString("SomePassword");
inf.FileName = #"........\bin\Release\SomeExecutable.exe";
inf.Arguments = ConfigurationManager.AppSettings["filePath"];
inf.UserName = "SomeUserName";
inf.Password = ss;
inf.UseShellExecute = false;
//launch desktop app, but don't close it in case we want to see the results!
try
{
Process.Start(inf);
}
catch(Exception ex)
{
this.txt_Urls.Text = ex.Message;
}
this.txt_Urls.Enabled = false;
this.btn_DoIt.Enabled = false;
this.txt_Urls.Text = "Entries received and process started. Check local machine for status update, or use refresh below.";
}
Here are the things I've tried to resolve the issue:
Made sure the executing assembly was built with AnyCPU instead of
x86
Ensured that the AppPool that runs the app, also runs under the same account (SomeUsername) as the ProcessStartInfo specified.
Ensured that the specific user account has full access to the executable's folder.
Ensured that IIS_USR has full access to the executable's folder.
Restarted both the app pool and IIS itself many times over implementing these fixes
I am now at a loss as to why this simply will not launch the app... when i first looked into the event log, i saw that the app would die immediately with code 1000:KERNELBASE.dll, which got me on the AnyCPU config instead of X86 fix... that fixed the event log entries but the app still doesn't start (nothing comes up in task manager), and i get no errors in the event log...
if someone could help me fix this problem i would really appreciate it. This would allow me to perform specific tasks on my main computer from any device on my network (phone, tablet, laptop, etc etc) without having to be in front of my main PC...
UPDATE
The comment to my OP, and ultimate answer from #Bradley Uffner actually nailed the problem on the head: My "app" is actually a desktop application with a UI, and in order to run that application, IIS would need to be able to get access to the desktop and the UI, just like if it were a person sitting down in front of the PC. This of course is not the case since IIS is running only as a service account and it makes sense that it shouldn't be launching UI programs in the background. Also see his answer for one way of getting around this.
Your best bet might be to try writing this as 2 parts. A web site that posts commands to a text file (or database, or some other persistent storage), and a desktop application that periodically polls that file (database, etc) for changes and executes those commands. You could write out the entire command line, including exe path command arguments, and switches.
This is the only way I can really think of to allow a service application like IIS to execute applications that require a desktop context with a logged in user.
You should assign a technical user with enough high priviliges to the running application pool. By default the application pool is running with ApplicationPoolIdentity identy which has a very low priviliges.

How to verify my C# code run an IISRESET command in administrator mode

I have created a windows service that checks a database for errors and if a specific one shows up I want it to perform an IISRESET command.
The problem is, if I run and IISRESET command without the elevated privileges then it won't actually do the reset. So I have my code doing all I want, but I'm not sure if the IISRESET command is being run as an administrator and I don't know how to verify that.
Here is the code I have
ErrorCheckerEventLog.WriteEntry("Performing IISReset", EventLogEntryType.Warning);
Process process = new Process();
process.StartInfo.Verb = "runas";
process.StartInfo.FileName = "iisreset.exe";
process.StartInfo.UseShellExecute = true;
process.StartInfo.CreateNoWindow = false;
process.StartInfo.RedirectStandardError = false;
process.StartInfo.RedirectStandardOutput = false;
process.Start();
process.WaitForExit();
ErrorCheckerEventLog.WriteEntry("IISReset finished", EventLogEntryType.Information);
In the Application event log I get these:
Listener Adapter protocol 'net.tcp' successfully connected to Windows Process Activation Service.
Listener Adapter protocol 'net.pipe' successfully connected to Windows Process Activation Service.
In the system event log I get these:
IIS start command received from user testing\neil.kenny. The logged data is the status code.
It all looks good to me, but I'm still not sure it actually did the reset. It could have just ran the iisreset command which then output the access denied message.
How do I properly verify this?
If you want to test it manually:
First thing come to my mind is keep the browser open with any site on the IIS being reset. Press F5 all time. Site will go down and soon will be up again.
Check in event viewer and look for event entries indicating IIS has been restarted (Check System logs). This question might help. here you have a pic. One image is better than thousand words:
What to look for exactly:
Several events indicating that some services has been stopped. Source is Service Control Manager. Among them look for the one saying "The World Wide Web Publishing Service entered stopped state"
Event from source IIS-IISReset with content "IIS stop command received from user xxxx"
Several events indicating that some services has been started. Source is Service Control Manager. Among them look for the one saying "The World Wide Web Publishing Service entered running state"
Event from source IIS-IISReset with content "IIS start command received from user xxxx"
Just a thought ... depending on your requirements you could do something like ...
1.
Call up a web page or wcf endpoint that lives on a site hosted on the iis instance that you wrote to put something in the application state.
2.
Run your code.
3.
Call it again with params telling it to retrieve the application variable, if its null and takes a while chances are that app got reloaded due to an iisreset.
Not ideal if your code has nothing to do with the apps hosted on the box so then I figured ... why not just retrieve that event log information?
There's an example of that on this: Read event log in C# ... question, admittedly a very simple one but you're looking in a specific time period that was very recent and logs read from the most recent down, thus rendering your search very quick (e.g. should be in the top say 100 events on the busiest of servers).

My C# application is returning 0xE0434352 to Windows Task Scheduler but it is not crashing

I have written a few C# apps that I have running via windows task scheduler. They are running successfully (as I can see from the log files that they are writing ) but windows task scheduler shows them returning a last run result of 0xE0434352. Is there something I need to do in my C# application so that it returns a success code to the windows task scheduler?
Another option is to simply use the Application log accessible via the Windows Event Viewer. The .Net error will be recorded to the Application log.
You can see these events here:
Event Viewer (Local) > Windows Logs > Application
When setup a job in new windows you have two fields "program/script" and "Start in(Optional)". Put program name in first and program location in second.
If you will not do that and your program start not in directory with exe, it will not find files that are located in it.
Hans Passant was correct, I added a handler for AppDomain.CurrentDomain.UnhandledException as described here http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception(v=vs.71).aspx I was able to find the exception that was occurring and corrected it.
I was referencing a mapped drive and I found that the mapped drives are not always available to the user account that is running the scheduled task so I used \\IPADDRESS instead of MAPDRIVELETTER: and I am up and running.
In case it helps others, I got this error when the service the task was running at didn't have write permission to the executable location. It was attempting to write a log file there.
I had this issue and it was due to the .Net framework version. I had upgraded the build to framework 4.0 but this seemed to affect some comms dlls the application was using. I rolled back to framework 3.5 and it worked fine.
I got the same error but I have fixed it by changing the file reading path from "ConfigFile.xml" to AppDomain.CurrentDomain.BaseDirectory.ToString() + "ConfigFile.xml"
In my case, this error due to file path error because task manager starts program from "System32" as initial path but the folder we thought.
I was getting the same message message within dotNet Core 2.2 using MVC 5, however nothing was being logged to the Windows Event Viewer.
I found that I had changed the Project sdk from Microsoft.NET.Sdk.Web to Microsoft.NET.Sdk.Razor (seen within the projects.csproj file). I changed this back and it worked fine :)
In my case it was because I had message boxes. Once I commented that code out, it started working. I remembered that could be a problem when I looked at the event log as suggested in this thread. Thank you everyone!
I encountered this problem when working with COM objects. Under certain circumstances (my fault), I destroyed an external .EXE process, in a parallel thread, a variable tried to access the com interface app.method and a COM-level crash occurred. Task Scheduler noticed this and shut down the app. But if you run the app in the console and don't handle the exception, the app will continue to work ...
Please note that if you use unmanaged code or external objects (AD, Socket, COM ...), you need to monitor them!
Also message box in PowerShell. I converted PowerShell script to exe. When running as admin it's worked but in task schedule I received this error also.
There was an line in PowerShell script with write-output. After commented this line and compile new exe Task Schedule was completed successfully.
It is permission issue in my case the task scheduler has a user which doesn't have permission on the server in which the database is present.

Problem with calling Console application (WCF Service) from webform

I am using a ASP.net webform application to run an existing console application which get all records from DB and send them through a third party WCF service. Locally everything is working fine. When I run the application it opens the console, gets the records and sends them. But now I pushed my files over to Test server along with the exe file and related config files. But when I access the application through the browser (test url) I get the same error message time and again and I don't see the console window. Sometimes everything works fine but never two times in a row.
The error message is:
"There was no end point listening at '.....svc' that could accept message. This is often caused by incorrect address or soap action.
System.net.webexception. Remote name could not be resolved
at System.Net.HttpWebRequest.GetRequestStream
at System.ServiceModel.Channels.HttpOutput.Webrequest.HttpOutput.GetOutputStream()
The code I have used in the webform to call console application is:
ProcessStartInfo p = new ProcessStartInfo();
p.Arguments = _updateNow.ToString();
p.FileName="something";
p.UseShellExecute = false;// tried true too without luck
Process.Start(p);
Error message denotes "there is no end point" and sounds like there is problem with the WCF service but if I double click the executable in Test there is no problem. What could be the possible problem or should I redo the console application functionality to my main webform application?
Update: After adding Thread.Sleep(3000) after Process.Start(p), I'm having no problem. So seems like main application is not waiting for the batch process to complete. How to solve this problem?
It seems like there is a short delay between starting the console application and the WCF web service becoming initialise and available to use - this is to be expected.
You could either:
Work around the issue using Thread.Sleep() and possibly with a couple of catch - retry blocks.
You could have the console application report to the creating process when it is ready to recieve requests (for example by having it write to the standard output and using redirected streams).
However at this point I'd probably reconsider the architecutre slightly - starting a new process is relativley costly, and on top of that initialising a WCF serice is also relatively costly too. If this is being done once per request then as well as the above timing issues you are also incurring performance penalties.
Is it not possible to change the architecutre slightly so that a single external process (for example a Windows service) is used for all requests instead of spawning a new process each time?

Categories