COM Interop fails when moving to new server - asp.net

I've run into a problem I just can't seem to solve. The background: Years ago, I developed a web site for one of my customers using ASP 2.0 and Ajax. One function of the web site is to produce customer invoices, on demand. Their in-house production system is written in Visual Foxpro 8 with SQL Server 2005 on the back end. Since I already had an invoice generation object that would produce a PDF file, I rolled up a COM EXE and created a COM wrapper for use in my ASP page. It works great for years, but now we're trying to move the page to a different location and things aren't working so great.
The network techs have re-produced the environment and the rest of the web site runs perfectly. I can even instantiate the COM object (I've logged the init and all is well), but the very first call to one of the objects methods results in an "Exception from HRESULT: 0x80010105 (RPC_E_SERVERFAULT))". I'm just plain stuck!
Here's what does work:
1) Using a visual foxpro program from the same server I can instantiate the object, call the generate invoice method and produce the PDF - no problem whatsoever.
2) Using VBScript from a very simple ASP page I can use Server.CreateObject() to instantiate the object and successfully generate the invoice from there.
So far I know:
1) the object is registered correctly and is launching as the proper user, with all of the rights needed to do it's business.
2) the wrapper for the COM EXE and COM object versions are matched.
I apologize for the long post. To make a long story short: Why would ASP.NET not be able to make a call to any method of a VFP COM object after it's been instantiated successfully?
Thanks in Advance - I'm seriously stuck on this one.
Erik

For those running into the same situation, adding the COM EXE to the Data Execution Prevent (DEP) exception list allowed the calls to the objects methods.

Did you compile it as an EXE, a runtime DLL, or Multi-Threaded DLL. Additionally, a problem I've had before is that of single or multiple instances of an OlePublic dll entry. To confirm, modify your project... then from the Top Menu, click "Project", then "Project Info". On the third tab is "Servers" showing the available servers in your project. On the right side of it is "Instancing" this would be either single or multiple. Sometimes, just throwing this to single has solved instances for me. However, if multi-threading, make sure you have the multi-threaded dll too.. VFP9T.DLL
--- EDIT PER RESPONSE...
Since you compiled it as an EXE, Its probably going to show up as a distributed COM object. Go to the Windows "Start", and run "DCOMCNFG" which will bring up the DCOM Configuration manager. You'll have to scroll down the list of items until you find your exe (OlePublic class name) and might have to revise permissions, who can launch / access / execute... apply impersonate, etc...
FOR TESTING ONLY --- You could set this COM server as impersonate Administrator -- JUST TO TEST and see if any errors or not. If no errors, then you'll know its a permissions thing, then change it back to a more restricted user.

Related

Run Batch File in Asp.net C#

I am using asp.net C# 4.0
I have a batch which will open a text file.
Batch File query
ECHO OFF
start D:\accounts\request\08__processing\0377e792-4ca9-4550-b78c-de2bdf26611f.txt
ASp.net Code
System.Diagnostics.Process.Start("D:\\bacthFile.bat");
when i double click on the batch file its opening the text file.But when run above code its not opening any notepad.
it is not showing any exception also.
Please Help
Thanks
This is the wrong way to read a text file from ASP.NET, you need to use System.IO and put files you need to read somewhere where ASP.NET can get at them, eg.. App_data. That said, here is how to do it the wrong way: IIS runs on an invisible virtual window--it's a service. There is a way to get some services to display the UI, I forget how. In any case, you'd have to RDP onto the server, to see such a window after starting the service and goosing it into displaying a UI (this trick might not even work for IIS).
Next, as commenters noted, on IIS, you'll have one set of credentials different from your own (depends on what version of IIS)-- in any case, it will have restricted access and be somewhat sandboxed. If you set up impersonation and windows authentication in the web.config, sometimes you can get your request to run with your credentials.
Next, if the web host runs in medium trust, you might not be able to launch arbitrary apps from the asp.net appdomain.
Finally, the only way this could ever work is if your app is always running locally with casinni (the visual studio development server)-- but in that case, you could simplify things a lot by using a console app instead of asp.net unless you really need the HTML templating, say for output.

Crystal Reports Viewer: Failed to Open the Connection error

Currently I'm working on a piece of code that involves using the Crystal Reports Viewer to export .RPT files to PDF. My problem is that the code works on literally everything except the website I'm planning to eventually put it on.
When placed on the website it throws back the error "Failed to open the connection." which I believe is connected to the SQL Server connection that's formed in order to read data for the report itself.
The code itself is solid and works when used in a separate console application I built to test it whether said code is run on my local machine or on the server itself. It even runs when I test the website in Visual Studio's virtual host.
I've narrowed it down to being some sort of permissions issue, but I am not knowledgeable enough in the various permissions settings to figure out which ones specifically apply to this situation. It's worth mentioning that other pages on the website are directly connecting to the same database, but they are doing so directly through Linq instead of going through the Crystal Report Viewer.
So does anybody know which settings I need to modify in order to fix the connection error.
An added note: One of the other suggestions is to make sure there's an ODBC DNS in place that matches the one being used by the code. I have created such a DNS already.
Application Pool dictates how your application runs in many ways. You can probably configure the web.config to run under the credentials, or access level of your choice.
Solution for people who didn't read the comments:
Change the identity under the advanced setting's of your application pool to the desired level of access.
Glad I could help.- J

Editing an Excel document with Macros in ASP.net

Is it possible in any way to edit an excel sheet through an ASP.net page that contains macro. I have tried to open the Excel sheet and it seems to just hang rather than load the excel. Testing on a page without macros works perfectly fine?
Disclaimer: I don't know the Excel license agreement and I don't know if utilizing Excel in a server process violates it or not. This is purely a technical description of how to get it working. The reader is advised to check the license agreement to see if it's allowed to do so or not. Different Office versions may have different license agreements. I used this method at several Fortune 100/500 companies and they didn't seem to care. Go figure.
This solution works but it has some limitations and require a fair amount of control over the server where it runs. The server also needs to have lots of memory.
To start, make sure that you perform a complete installation of every single Office feature on the server so that Excel won't try to install something if you attempt to use a feature that's not present.
You also need to create a dedicated user account on the server that has the right privileges. I can't tell you what exactly because in my case we controlled the server and we gave admin rights to this user.
When you have the user account, you need to log in as that user and run Excel (preferably all Office applications) at least once so that it can create its settings.
You also need to configure Excel to run under this user account when it's created as a COM object. For this, you need to go into DCOM Config on the server and configure Launch and Activation Permissions for the Excel.Application object to use your new user account. I'm not sure if I remember correctly, but I think after this step, running Excel as an interactive user was slightly problematic.
By default, Office applications try to display various messages on the screen: warnings, questions, etc. These must be turned off because when you utilize an Office application from a web application, it runs on the server so a human user won't be around to dismiss these messages - the Office program will just sit around indefinitely, waiting for the message to be dismissed.
You need to set (at the minimum) these properties:
DisplayAlerts = false
AskToUpdateLinks = false
AlertBeforeOverwriting = false
Interactive = false
Visible = false
FeatureInstall = 0 'msoFeatureInstallNone
to disable UI messages from Excel. If you use Excel 2010, there may be more, but I'm not familiar with that.
If you have Excel files with macros in them, you may have to disable macro security in Excel - that can't be done programmatically, for obvious reasons.
To access Excel services, implement a manager object that will actually hold the Excel reference - don't try to hold the Excel.Application object in the page because your page code will become very complicated and you may not be able to properly clean things up.
The object that holds the Excel reference may be a separate DLL or an out-of-process server. You must make sure, however, that when you acquire an instance of Excel on a given thread you always create a new Excel instance. The default is that an already running Excel instance will also serve other requests but that won't work for you because the same Excel instance cannot be shared among multiple threads. Each request-processing thread in IIS must have its own Excel instance - if you share instances, you'll have all kinds of problems. This means that your server will need to have quite a bit of memory to have many instances of Excel running. This was not an issue for me becasue we controlled the server.
If you can, try to create an out-of-proc (.exe) COM server because this way you can hold the Excel reference in a separate process. It's possible to get it working using an in-proc (.dll) COM object but it'll be more risky to your application pool - if Excel crashes, it'll crash your app pool as well.
When you have an .exe server, you can pass parameters in several possible ways:
Make your manager objet a COM object and pass parameters as properties.
Pass parameters as command-line parameteres to the .exe as it starts up.
Pass parameters in a text/binary file; pass the name of the file on the command-line.
I used all these and found the COM object option the cleanest.
In your manager object, follow these guidelines:
Wrap every single function that uses Excel in a try..catch block to capture any possible exception.
Always explicitly release all Excel objects by calling Marshal.ReleaseComObject() and then setting your variables to null as soon as you don't need them. Always release these objects in a finally block to make sure that a failed Excel method call won't result in a dangling COM object.
If you try to use any formatting features in Excel (page header, margins, etc.) you must have a printer installed and accessible to the user account that you use to run Excel. If you don't have an active printer (preferably attached to the server), formatting-related features may not work.
When an error happens, close the Excel instance that you're using. It's not likely that you can recover from Excel-related errors and the longer you keep the instance, the longer it uses resources.
When you quit Excel, make sure that you guard that code against recursive calls - if your exception handlers try to shut down Excel while your code is already in the process of shutting down Excel, you'll end up with a dead Excel instance.
Call GC.Collect() and GC.WaitForPendingFinalizers() right after calling the Application.Quit() method to make sure that the .NET Framework releases all Excel COM objects immediately.
Edit: John Saunders may have a point regarding the license agreement - I can't advise about that. The projects that I did using Word/Excel were all intranet applications at large clients and the requirement to use Word/Excel was a given.
The link he provided also has some tools that may be useful, although those libraries won't have full Excel functionality and if that's what you need, you don't have a choice. If you don't need full Excel functionality, check out those libraries - they may be much simpler to use.
A few links that may be useful to people trying to implement this approach:
StackOverflow question
Possible alternate products
COM server activation and window stations
The story changed a little while ago, with HPC Services for Excel.
With that, you can do Office Automation on a web server. I'm still trying to determine how it fits my situation, but you may want to check it out.

Error 0x800401F3 One process works one doesn't same website

I'm stuck on this one. I hope someone here has some experience with this. Here is the situation. I have set up a web page that allows users to upload flat files to be loaded into SQL Server 2005 using SSIS. There are two difference SSIS processes depending on the file type. The decision of which SSIS process to use is made by the user on the website.
Once the file is uploaded by the user the process is started by a .NET Process object. The command line is the normal command line you'd expect to see to start dtexec with a specific SSIS file and that sets a couple variables. For example:
dtexec /f /De /set value
The ASP.NET Anonymous User is running as a domain user account. All SSIS package files for both SSIS processes are in the same directory. The domain user account has full privileges on that directory. The same method in ASP.NET starts either of the processes. The only difference is the WebMethod called by the website. One WebMethod for each type. It is in these WebMethods where the unique arguments are assigned to the command line text for SSIS.
Here is where I have run into the problem. When running the website process "1", it runs fine, but process "2" fails with the error mentioned above. When I capture the Standard Output I receive this:
Microsoft (R) SQL Server Execute
Package Utility Version 9.00.4035.00
for 32-bit Copyright (C) Microsoft
Corp 1984-2005. All rights reserved.
Started: 10:34:14 AM Could not create
DTS.Application because of error
0x800401F3 Started: 10:34:14 AM
Finished: 10:34:14 AM Elapsed: 0.016
seconds
I don't understand how everything can be nearly identical yet only one will run. One final thing, both methods work fine when I am testing directly from Visual Studio. I figure it must be something with the Anonymous User account used, but I can't figure out why one process would work and the other not work when they are so similar.
Any help will be greatly appreciated.
Rob
Found the problem. The error code was a phantom. What happened was a Connection Component was being fed by a variable that was holding a path to a folder the new account could not go to. Even though in process it would be replaced with a good target it was failing in validation. This is why there was no logs. I didn't have the logging level high enough to see it and it acted like a security issue. Which is was in a way of looking at it.

Keeping tables cached on server in ASP.NET project

I have an ASP.NET project which is a front-end to a database. In addition to the large tables, the DB contains a few small tables to help normalize the larger tables with common values. I have a VB.NET project which loads the smaller tables into memory, using "Shared" (i.e., "static" in C#) member variables, and uses them. I have a call to load the tables in Global.asax - Application_Start. This works for a while. That is, Application_Start runs when I first run my project, loads the cached values, and will correctly keep them in memory for a while.
What I'm seeing (when running my project via Visual Studio 2008 Debugger, hosted locally) is:
A) The Application_Start code will run more than once. Not in a row, but after the user has navigated to some other pages, I'll see (my breakpoint in) another call to initialize the cache, coming form Application_Start. Is it expected?
B) The "Shared" variable that was set to True when the cache was initialized is now False again (which should only happen when the class is first loaded). Similarly, all the data that was chached is no longer present. That is, it looks like VB is unloading all the Shared members. Is this expected?
If these are the expected behaviors, is there a way to do what I want? The code is in a module that is also used by other (non-ASP.NET) projects, and seems to work correctly for them. I'd rather not have to duplicate this functionality for something specific to ASP.NET, but would like to know what my options are. Thanks for any advice.
Here is an article you might find helpful about Caching Data at Application Startup. It sounds like you are doing everything right, but Application_Start should only get called once, unless some external change happens that restarts the app pool, but in this case i would think you would get detached from the debugger (assuming you are attached to the app pool process for your asp.net application).

Resources