Autocad Instance not creating after deployment - c#

I am getting an issue regarding running autocad application using C#. As i am beginner most of my code is copy pasted from net.
The problem is i am developing an web application using c# which will create an instantiate autocad instance at runtime. Every thing goes fine on development server as well as on my local IIS server. but when i am deploying the web application on the server(window server 8) i am getting the below error
Operation unavailable (Exception from HRESULT: 0x800401E3 (MK_E_UNAVAILABLE))
at System.Runtime.InteropServices.Marshal.GetActiveObject(Guid& rclsid, IntPtr reserved, Object& ppunk)
at System.Runtime.InteropServices.Marshal.GetActiveObject(String progID)
at DQMF.CDQMF.createAacdApplicationInstance(String progID)
I think it is because of some privilege issue. as on my local machine autocad instance is running with privilege of system and on server(windows server 8) it is running(with development server) as administrative privilege.
AcadApplication createAacdApplicationInstance(string progID)
{
AcadApplication app = null;
try
{
app = (AcadApplication)Marshal.GetActiveObject(progID);
}
catch (Exception e)
{
try
{
Type acType = Type.GetTypeFromProgID(progID);
app = (AcadApplication)Activator.CreateInstance(acType, true);
app.Visible = false;
app.Width = 1;
app.Height = 1;
app.WindowState = AutoCAD.AcWindowState.acMin;
app.Visible = false;
}
catch (Exception ex)
{
//File.AppendAllText("D:/test/DQMS_log.txt", ex.Message+" progID is: "+progID+Environment.NewLine+"app caption: "+app.Caption);
}
}
return app;
}
If you want some more detail i can give

Your marshalling is failing because the ASP.NET process runs on a separate account, and has a completely different Running Object Table (ROT). I am pretty sure for this to work you'll have to instanciate a new session from the ASP.NET side.

When working with visual interops, it is not as straightforward to run instances of applications that expect direct user interaction from asp.net.
You may have to use a windows form or WPF application to work with AutoCAD. The issue may be that the AutoCAD.Application interop does not allow for non-visual interaction.

Related

Open Powerpoint presentation from an ASP.NET Web app running localhost

I'm trying to execute a Powerpoint presentation from a .NET MVC Web app. I'm using the office.interopt.powerpoint libraries and everything works fine while i'm on VisualStudio. But, if i deploy the web app in a IISExpress server (not in VS), the Powerpoint application doesn't open as top-most window and it doesn't works properly, and if i deploy it in a IIS Server, the Powerpoint doesn't starts at all.
I know that the problem has something to be with the IISUSR credentials as i (as a web app) don't have the rights to execute the application.
The question is: is there a way to start a Powerpoint application as a different user using the interop libraries? I know it is possible to start a new Process as a different user with "ProcessStartInfo", but if i do that way i should execute one Powerpoint process for each presentation that i need to open and i wouldn't have access to the presentation's controls like nextSlide and so... The idea is to execute the Powerpoint once and then open, close and control many presentations.
The code that i have for now:
To start the Powerpoint app (this is executed once):
app = new Application();
app.Visible = MsoTriState.msoTrue;
app.PresentationClose += ClosePPT;
app.Activate();
app.WindowState = PpWindowState.ppWindowMinimized;
ppts = app.Presentations;
To open a new presentation:
public void LoadPPT(string pptPath)
{
try
{
//Close all opened presentations if any
if (ppts.Count > 0)
foreach (Presentation p in ppts)
p.Close();
//Open new presentation
ppt = ppts.Open(pptPath, MsoTriState.msoTrue, MsoTriState.msoFalse, MsoTriState.msoFalse);
SlideShowSettings sss = ppt.SlideShowSettings;
sss.Run();
while (app.SlideShowWindows.Count <= 0) ;
SlideShowWindow ssw = ppt.SlideShowWindow;
ssw.Activate();
//if (!SetWindowPos((IntPtr)ssw.HWND, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW))
//{
// int error = Marshal.GetLastWin32Error();
// NLog.LogManager.GetCurrentClassLogger().Debug("Error " + error);
//}
ssv = ssw.View;
}
catch (Exception e)
{
NLog.LogManager.GetCurrentClassLogger().Debug("Excepcion en PPT. " + e.Message);
while (e.InnerException != null)
{
NLog.LogManager.GetCurrentClassLogger().Debug("INNER. " + e.InnerException.Message);
e = e.InnerException;
}
}
}
As you can see, i've also tried to set the window of the slideshow presentation at top-most position using the Win32 "SetWindowPos", but with the same result.
I'm trying to execute a Powerpoint presentation from a .NET MVC Web app. I'm using the office.interopt.powerpoint libraries
Microsoft does not currently recommend, and does not support, Automation of Microsoft Office applications from any unattended, non-interactive client application or component (including ASP, ASP.NET, DCOM, and NT Services), because Office may exhibit unstable behavior and/or deadlock when Office is run in this environment.
If you are building a solution that runs in a server-side context, you should try to use components that have been made safe for unattended execution. Or, you should try to find alternatives that allow at least part of the code to run client-side. If you use an Office application from a server-side solution, the application will lack many of the necessary capabilities to run successfully. Additionally, you will be taking risks with the stability of your overall solution. Read more about that in the Considerations for server-side Automation of Office article.
You may consider using any third-party components designed for the server-side execution (ASP.NET controls that can host PowerPoint presentations).

Autodesk.Inventor.Interop.dll on WinServer 64-bit 2012 R2 - interface non registred

i'm trying to develop a very simple web application based on the Autodesk Inventor engine.
I'm developing on Win7 64-bit with Visual Studio 2010 and Inventor 2015 and everything it's working perfectly on debugging but when i publish on the web server i get the error:
HRESULT: 0x800401F3 (CO_E_CLASSSTRING)
and the message
interface string not valid
The C# code line where i receive the error is:
Inventor.Application _invApp = (Inventor.Application)Marshal.GetActiveObject("Inventor.Application");
The full code for my test is the following:
using Inventor;
using System.Runtime.InteropServices;
namespace web_debug_cs
{
public partial class debug_runinventor : Ssytem.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e) { startInventorApplication(); }
private void startInventorApplication()
{
string sDebug = string.Empty;
try
{
Inventor.Application _invetorApp = (Inventor.Application)Marshal.GetActiveObject("Inventor.Application");
sDebug = "Success!!!";
}
catch (Exception ex) { sDebug = "UNSUCCESS!<br />" + ex.Message; }
lblAnswer.Text = sDebug;
}
}
}
I get this code directly from the Inventor 2015 guide, but (repeat) on the local machine everything it's ok, but not on the server.
I checked the permission (everyone: full control)
I registred manually with regsvr32 (impossible to register) both on system32 and SysWOW64
I registred on the framework 32 and 64 with regasm (registration success!)
I set the web site to work with 32-bit application
but nothing could solve this issue.
I thought about the possibility to import manually the dll with pInvoke, but with no success...
I googled a lot, i tryed to ask to Autodesk with no success.
I started Inventor on the Server to verify if it works, and it work perfectly!
Could anyone try to help me?
Thanks in advance for any kind reply!
Emanuele
I would not expect this to work due a simple reason: the webpage is running as a service, and Inventor runs as a user-level application. Imagine the following: the web page is requested by 100 clients/browsers, your app will launch Inventor 100 times. But more than that, the webpage is not on the user-level.
The best chance to work would be: your webpage receives a request (let's say create a .ipt file), create a record that the action must be performed (for instance, a new .txt file with instructions or a database entry), a Windows services detects the request and launch Inventor to process it. In this case you'll have a queue where requests are placed by your webpage, but processed later.
But I must say this is not supported nor allowed on the EULA, please review it.

ASP.NET Web Application - on deploy, System.Speech.dll object not getting set to an instance of an object

I have an ASP.NET web application that uses System.Speech to transform text to a WAV file. It works fine locally but when I deploy it to the server, I get the below error message. This is using Windows Server 2012, ASP.NET 4.5, and IIS 8.5:
Object reference not set to an instance of an object.
System.Speech
at System.Speech.Internal.ObjectTokens.RegistryDataKey..ctor(String fullPath, RegistryDataKey copyKey)
at System.Speech.Internal.ObjectTokens.SAPICategories.DefaultDeviceOut()
at System.Speech.Internal.Synthesis.VoiceSynthesis..ctor(WeakReference speechSynthesizer)
at System.Speech.Synthesis.SpeechSynthesizer.get_VoiceSynthesizer()
at QuinnSDS.handlerTransform.<>c__DisplayClass6.<ProcessRequest>b__1()
The code which is generating this error message runs on the server:
if (context.Request.ContentLength > 0)
{
string line = new StreamReader(context.Request.InputStream).ReadToEnd();
// ********* generate wav file voicing the response *****************
// Using Microsoft voices
// initiate new instance of speech synthesizer
Thread t = new Thread(() =>
{
try
{
// The object creation works fine
System.Speech.Synthesis.SpeechSynthesizer synth = new System.Speech.Synthesis.SpeechSynthesizer();
if (synth != null)
{
// The code breaks at synth.GetInstalledVoices() below. It will break any time I try to do anything with the synth object
foreach (System.Speech.Synthesis.InstalledVoice voice in synth.GetInstalledVoices())
{
System.Speech.Synthesis.VoiceInfo info = voice.VoiceInfo;
string voiceName = info.Name;
ws.WriteLine(voiceName);
}
}
}
catch (Exception e)
{
ws.WriteLine(e.Message);
ws.WriteLine(e.Source);
ws.WriteLine(e.StackTrace);
}
//... code continues...
It does not break when the Speech Synthesis object is created; it breaks whenever I try to use that object in any way.
I'm not sure if it's an access issue but I'm pretty new to ASP.NET and IIS and I can't figure out how to give the web app access to the GAC or if that's even what the problem is. I tried changing the property Local Copy for the System.Speech reference to True in Visual Studio, before I deploy the app, but that hasn't worked. I searched online and while the "object reference not set to an instance of an object" seems fairly common, I cannot find any similar issues where it is because of a .NET framework class library...I have run the text-to-speech code locally on the server and it ran fine. I have not run the entire app locally on the server because the web app requires speech input and there is not a microphone on the server.
Any ideas of anything to try would be most welcome!
What user account is the code running under when executed from ASP.NET? If the Speech API is touching the registry like the call stack suggests, it possibly has different permissions than the account you used to run the code manually.
If you can't just make the application pool for your site run with the same account you log into the machine with, I've had some success using Process Monitor to track down this kind of problem before. Basically, execute the code that fails while Process Monitor is running and look for 'ACCESS DENIED' in the 'Result' column (or anything else that looks suspicious). Quickly switching the application pool to use your standard user account will be the fastest way to rule out security or permission related problems though.

Problems accessing Outlook from c# Application

I'm writing a console application, which checks the contents of an outlook mailbox, in order to read the contents of specific emails into a database.
This application works fine within Visual studio, whether or not Outlook is open.
If I build the application and run it from the exe it only works when Outlook is open, which isn't really a problem.
However, I need to run it from a scheduled task as it has to run every few minutes. This will not work at all.
I'm using the following code:
System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcessesByName("OUTLOOK");
int collCount = processes.Length;
if (collCount != 0)
{
OutlookApp = Marshal.GetActiveObject("Outlook.Application") as Application;
}
else
{
OutlookApp = new Application();
}
The error message I'm getting is:
System.Runtime.InteropServices.COMException (0x800401E3): Operation
unavailable (Exception from HRESULT: 0x800401E3 (MK_E_UNAVAILABLE))
at System.Runtime.InteropServices.Marshal.GetActiveObject(Guid&
rclsid, IntPtr reserved, Object& ppunk) at
System.Runtime.InteropServices.Marshal.GetActiveObject(String progID)
at ImportCruiseEmails.Program.Main()
On the line :
Marshal.GetActiveObject("Outlook.Application") as Application;
Both Outlook and the console application are running under my user account, which has administrator permissions. I've been pulling my hair out with this all afternoon. Can anybody please shed any light on it? Cheers!
Even through the user accounts are the same, security contexts are different since the scheduler runs as a service. And no Office app can be used in a service.
Your options are
In case of an Exchange Server, use EWS to access the mailbox.
Extended MAPI (C++ or Delphi only)
Redemption (I am its author, any language) - it wraps Extended MAPI and its RDO family of objects can be used from a service.

Control IIS 7 server from Windows 2003 server programmatically

We run various jobs using a Windows 2003 server. Some of these jobs send app pool commands to web servers running IIS 6 (recycle, start, stop). Now we have a Windows 2008 web server running IIS 7, and we want to send the same commands. This is all done using C#.
This is the code we use to send commands for IIS 6:
var methodToInvoke = "Stop"; // could be "Stop", "Start", or "Recycle"
var co = new ConnectionOptions
{
Impersonation = ImpersonationLevel.Impersonate,
Authentication = AuthenticationLevel.PacketPrivacy
};
var objPath = string.Format("IISApplicationPool.Name='W3SVC/AppPools/{0}'", appPoolName);
var scope = new ManagementScope(string.Format(#"\\{0}\root\MicrosoftIISV2", machineName), co);
using (var mc = new ManagementObject(objPath))
{
mc.Scope = scope;
mc.InvokeMethod(methodToInvoke, null, null);
}
This code doesn't work for IIS 7 due to underlying changes, so we're currently trying this:
using (ServerManager serverManager = ServerManager.OpenRemote(machineName))
{
var appPool = serverManager.ApplicationPools[appPoolName];
if (appPool != null)
{
appPool.Stop(); // or app.Start() or app.Recycle()
serverManager.CommitChanges();
}
}
The above code works fine on my workstation, which runs Windows 7 (and, thus, IIS 7.5). However, it does not work when I deploy this code to our application server. It get this error:
System.InvalidCastException:
Unable to cast COM object of type 'System.__ComObject' to interface type
'Microsoft.Web.Administration.Interop.IAppHostWritableAdminManager'.
This operation failed because the QueryInterface call on the COM component for the
interface with IID '{FA7660F6-7B3F-4237-A8BF-ED0AD0DCBBD9}' failed due to the following error:
Interface not registered (Exception from HRESULT: 0x80040155).
From my research, this is due to the fact that IIS 7 is not available on the Windows Server 2003 server. (I did include the Microsoft.Web.Administration.dll file.)
So my questions are:
Is it possible for the above code for IIS 7 to work at all from a Windows 2003 server?
If no to #1, is there a better way of doing this?
From reading around it doesn't appear to be possible to do what you're looking for. It's not enough to include the dll files.
According to http://forums.iis.net/t/1149274.aspx..
In order to use Microsoft.Web.Administration you need to have IIS installed, at the bare minimum you need to install the Configuration API's which are brought through installing the Management Tools.
Unfortunately there is no SDK that enables this and it has several dependencies on other components that wouldn't let you just take it to another machine and make it work (such as COM objects, DLL's, etc).
I'd be interested in knowing if you've found a way round this.
Thanks
Try controlling the IIS pool with DirectoryEntry instead.
See this topic:
Check the status of an application pool (IIS 6) with C#
Microsoft.Web.Administration, it relies on System.Web.dll which was provided by framework 4, not client profile.

Categories