Marshal.GetActiveObject throws an exception in a C# webservice but

O

OfurGørn

....it does not throw the exception in a C# form. The same code works
perfectly in C# forms application. It seems like the computer noes not let
ASPNET get into the ROT, where the object I want is. I have experienced with
changing users, impersonating and so on, but with no luck.
I test which user I am before the faulty code, with

WindowsIdentity.GetCurrent().Name

where I was the user ASPNET when I started, but now I am "myself" who,
incidentally am running the process I am trying to reach.

the exceptions are:
"System.NullReferenceException: Object reference not set to an instance of
an object", when I run a method from the object I am trying to load.
"System.Runtime.InteropServices.COMException (0x800401E3): Operation
unavailable at System.Runtime.InteropServices.Marshal.GetActiveObject(Guid&
rclsid, UInt32 reserved, Object& ppunk) at
System.Runtime.InteropServices.Marshal.GetActiveObject(String progID)", when
I try to access the external object itself with Marshal.GetActiveObject()

Like I typed before, exactly the same code works in the windows forms
version of C#, but with the web service this seems impossible.

This error is driving me mad !!! I have been trying to fix this but am
afraid that I've become so frustrated that I cannot see the solution now -
typically a simple solution....

________________________
Gunnar Gudmundsson
 
K

Kevin Yu [MSFT]

Hi Gunnar,

First of all, I would like to confirm my understanding of your issue. From
your description, I understand that when you're trying to get the currenty
identity name using WindowsIdentity.GetCurrent().Name, and
NullReferenceException was thrown. If there is any misunderstanding, please
feel free to let me know.

I have tried it on my computer, however, it works fine and returns NT
AUTHORITY\SYSTEM as the name.

I suggest you add the following line before getting the identity name.

AppDomain.CurrentDomain.SetPrincipalPolicy(System.Security.Principal.Princip
alPolicy.WindowsPrincipal);

Also, you can try to use the following to get the identity for alternative.
(But make sure to add the above line.)

System.Threading.Thread.CurrentPrincipal.Identity.Name

HTH.

Kevin Yu
=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."
 
O

OfurGørn

hello Kevin, and many thanks for the answer.
We have a bit of a misunderstanding here.
I have no issues with the identity. I have althogh problems in running
Marshal.GetActiveObject() in a web service, as the object supposed to get a
value from that is null. When I try to use that handle I get a
COMexceptionError:
"System.Runtime.InteropServices.COMException (0x800401E3): Operation
unavailable at
System.Runtime.InteropServices.Marshal.GetActiveObject(Guid&
rclsid, UInt32 reserved, Object& ppunk) at
System.Runtime.InteropServices.Marshal.GetActiveObject(String progID)"

The reason this is bugging me a lot is that I have written a C# form
application with the same code, which works perfectly. There is something
different with the C# web service that results with that I cannot get access
to the obejct using Marshal.GetactiveObject()

I am hoping that this is something very simple for you guys, as I have no
more ideas to resolve this.

regards,
Gunnar
 
M

[MSFT]

Hello,

You need to give enough permissions to the user that the Web Service is
running under.

Take a look at:
Q317012 - INFO: Process and Request Identity in ASP.NET
Q306158 - INFO: Implementing Impersonation in an ASP.NET Application

Also, Marshal.GetActiveObject() method uses SecurityAction.LinkDemand to
prevent it from being called from untrusted code; only the immediate caller
is required to have SecurityPermissionAttribute.UnmanagedCode permission.
You may try following code in your APP to see it can work:

PermissionSet ps = new PermissionSet(PermissionState.None);
ps.AddPermission( new
SecurityPermission(SecurityPermissionFlag.UnmanagedCode ) );
ps.Assert();

Hope this help,

Luke
 
O

OfurGørn

Hi Luke

Thanks for the reply. Unfortunately, this solution does not work either.
The faulty code is as follows now:

// check which user we are
string user= WindowsIdentity.GetCurrent().Name;

// impersonate - unneccessary for form application
if (impersonateValidUser("Administrator", "MyComputer", "passWord"))
{
// just for kicks, check who we are now...
// should be the impersonated user
string impostor = WindowsIdentity.GetCurrent().Name;
// check if tstApp is running
System.Diagnostics.Process[] processes;
processes = Process.GetProcessesByName("tstApp32");
// check if the executable is running
if (processes.Length == 0)
{
zVal.zenError += "ZRT: tstApp32 is NOT running !! ";
}
else
{
zVal.zenError += "ZRT: tstApp32 is running !! ";
// the test application is found, get the handle !!
// the permissions have to be in order...
System.Security.PermissionSet ps = new
System.Security.PermissionSet
(System.Security.Permissions.
PermissionState.None);
ps.AddPermission(new
System.Security.Permissions.SecurityPermission
(System.Security.Permissions.

SecurityPermissionFlag.UnmanagedCode));
ps.Assert();

// the permissions should now be in order.... get the handle !!!
m_tstApplication = Marshal.GetActiveObject("tst.Application")
as tst.Application;
}

I am clueless now.... do you have any ideas on what I am doing wrong ????
The variable "impostor" now contains the same as the variable in my Form
program (that works), I added the ps stuff now, but cant see any difference.

What do you mean by giving enough permissions to the user that the Web
Service is running under ?? Isn't it enough to impersonate ? if not, how do I
give ASPNET the required permissions, do I change the permissions for the
executable that I run to start the "tst.Application" in the ROT.

I think we are getting somewhere now :)
best regards,
Gunnar
 
M

[MSFT]

Hi Gunnar,

Is "tst.Application" an application developped by your team? Not all
application are able to automate in asp.net. Have you try your code with
other applications. For example, Word or Excel?

Luke
 
O

OfurGørn

Hi Luke.

Tst.Application is an external application, that is developed elsewhere. I
do not have access to the source code for it. The problem is that I thought
that if I can develop a C# .NET form application, the code should work in C#
web service.....

I could send the author of the application a note regarding this, but it
would be better if I could be more precise on how the automation should be in
order for the web servive to be able to access it.

I will test my application with Word now, I expect it to work without
problems.

Any extra thoughts on this would be well appreciated.

Gunnar
 
M

[MSFT]

Hi Gunnar,

Based on my experience, some component may work in a winform but not in a
web service (ASP.NET) application. This is caused by security and many
other issues, for example, we cannot perform any UI related operation in a
web service. What is the result you test with Word?

Luke
 
O

OfurGørn

Hi Luke.

I wrote a VERY simple application to test Word. First, I wrote it as a C#
form application, and when that worked, I wrote it as a web service. The
"good" news is that I get exactly the same error as in the other one. The
code follows:

/******* CODE *******/
public Word.Application wordApp;
[WebMethod]
public string isWordThere()
{
// impersonate - unneccessary for form
if (impersonateValidUser("Administrator", "localhost", "password"))
{
try
{
// get the active object
wordApp = Marshal.GetActiveObject("Word.Application.11") as
Word.Application;
// stop impersonation
undoImpersonation();
// AOK - return a string to say so
return "AOK: word is running !!!! ";
}
catch (System.Exception ex)
{
undoImpersonation();
// exception - return it to see it
return "exception: "+ex.ToString();
}
}
else
{
// I dont think I need to undo a failed impersonation....
undoImpersonation();
// tell the user that the impersonation failed
return "impersonation failed";
}
}
/******* END CODE *******/

The thing is, I can use word if I dont use Marshal.GetActiveObject(), but
use appWord = new Word.Application() in stead. I haven't tried that in my
application, and the reason for that is that the supplier of the software
expects me to use the Marshal method.

The impersonation code is from one of microsofts articles mentioned before
in this thread - therefore not copied into this reply.

As before, I get the following error:
/***** ERROR *****/
System.Runtime.InteropServices.COMException (0x800401E3): Operation
unavailable
at System.Runtime.InteropServices.Marshal.GetActiveObject(Guid& rclsid,
UInt32 reserved, Object& ppunk)
at System.Runtime.InteropServices.Marshal.GetActiveObject(String progID)
at OfiiceWebService.OfficeService.isWordThere()
in c:\inetpub\wwwroot\ofiicewebservice\officeservice1.asmx.cs:line 101
/***** END ERROR *****/

I am going to experiment with a Marshal-less version of my software, but to
indulge the external software provider (and my boss :) ), I want to have a
Marshal version working at some point.

I have been experimenting with the dcomcnfg utility to grant permissions for
my application and word, but with no luck.

I am getting more sure that the error has a trivial solution - which I
cannot see.
regards
Gunnar
 
O

OfurGørn

It seems like Marshaling is the only way to go on my application, do you have
any ideas ???

regards,
Gunnar

OfurGørn said:
Hi Luke.

I wrote a VERY simple application to test Word. First, I wrote it as a C#
form application, and when that worked, I wrote it as a web service. The
"good" news is that I get exactly the same error as in the other one. The
code follows:

/******* CODE *******/
public Word.Application wordApp;
[WebMethod]
public string isWordThere()
{
// impersonate - unneccessary for form
if (impersonateValidUser("Administrator", "localhost", "password"))
{
try
{
// get the active object
wordApp = Marshal.GetActiveObject("Word.Application.11") as
Word.Application;
// stop impersonation
undoImpersonation();
// AOK - return a string to say so
return "AOK: word is running !!!! ";
}
catch (System.Exception ex)
{
undoImpersonation();
// exception - return it to see it
return "exception: "+ex.ToString();
}
}
else
{
// I dont think I need to undo a failed impersonation....
undoImpersonation();
// tell the user that the impersonation failed
return "impersonation failed";
}
}
/******* END CODE *******/

The thing is, I can use word if I dont use Marshal.GetActiveObject(), but
use appWord = new Word.Application() in stead. I haven't tried that in my
application, and the reason for that is that the supplier of the software
expects me to use the Marshal method.

The impersonation code is from one of microsofts articles mentioned before
in this thread - therefore not copied into this reply.

As before, I get the following error:
/***** ERROR *****/
System.Runtime.InteropServices.COMException (0x800401E3): Operation
unavailable
at System.Runtime.InteropServices.Marshal.GetActiveObject(Guid& rclsid,
UInt32 reserved, Object& ppunk)
at System.Runtime.InteropServices.Marshal.GetActiveObject(String progID)
at OfiiceWebService.OfficeService.isWordThere()
in c:\inetpub\wwwroot\ofiicewebservice\officeservice1.asmx.cs:line 101
/***** END ERROR *****/

I am going to experiment with a Marshal-less version of my software, but to
indulge the external software provider (and my boss :) ), I want to have a
Marshal version working at some point.

I have been experimenting with the dcomcnfg utility to grant permissions for
my application and word, but with no luck.

I am getting more sure that the error has a trivial solution - which I
cannot see.
regards
Gunnar
Hi Gunnar,

Based on my experience, some component may work in a winform but not in a
web service (ASP.NET) application. This is caused by security and many
other issues, for example, we cannot perform any UI related operation in a
web service. What is the result you test with Word?

Luke
 
M

[MSFT]

Hi Gunnar

I am performing further research on this issue and will update you as soon
as possible.

Luke
 
M

[MSFT]

Hello,

Based on my research, GetActiveObject obtains a running instance of an
object from the running object table (ROT). Each WinStation has it's own
ROT. The interactive desktop is one WinStation and has it's own ROT and
that is where the desktop application will have registered the running
object. The ASP.NET process is running under a seperate account and exists
in a non-interactive WinStation with its own ROT. That is why it fails.

I think the only way for this to work would be to launch the third party
application process from ASP.NET so it exists in the same WinStation. Of
course the application will then not be visible and the user cannot
interact with it.

Luke
 
O

OfurGørn

Could I write a program that acts in between the two, i.e. to talk with the
third party program, and with the web service. That is, a program that the
web service has access to, and which has access to the local ROT ?

any suggestions there?
Gunnar
 
M

[MSFT]

Hi Gunnar,

As we discuss before, the proxy application need to be in same WinStation
with the third party app. This means we need a win form application. Also,
the web service app need to communicate with this win form application, you
may take a look at reflection in .NET to implement this.

Luke
 
O

OfurGørn

Hi Luke.
Thanks for all the help... I am hoping that we solve this soon, as I am
dying to click the "helpful" button here above ;)

Ok... I am confused now. I just wrote a method to run the third party
service, and the application pops up in task manager under the user name
ASPNET. The same error pops up, and I am starting to think the problem is
not the userspace thing at all. The only difference I see is that the user
name I print out from my application is IUSR_LOCALHOST (where localhost is
the name of my workstation) while the third party application is under the
user name ASPNET. I tested the regular methods of the 3rd party app while it
is running under ASPNET, and it doesn't work. When the program is started
under ASPNET is does not work correctly. This is a huge problem now. The
last thing I can think of now is to write a form application that the web
service starts a new instance of, but I can't help to wonder if that will
work at all, as the form application will be started under ASPNET => I can't
see if that will get access to my 3rd party app, as that seems to require
that there is a "normal" user that runs it. Due to my lack of experience with
the .net automation/reflection, I do not know where to start here, so a
pointer in the right direction there would be well appreciated.

I am still hoping that I can get the Marshaling part to work in the web
application - as that would be the most elegant solution to my problem.

any ideas ?
Gunnar

FYI: The run method for the 3rd party app:
public bool launch3rdApp()
{
/*variables*/
bool retBool = false;
System.Diagnostics.Process[] processes;

/*check if 3rd party app is running*/
processes = Process.GetProcessesByName("tstApp");
if (processes.Length == 0)
{
/*if not running, launch it and return true*/
System.Diagnostics.ProcessStartInfo psi =
new ProcessStartInfo(@"C:\tstApp.exe");
psi.WindowStyle =
ProcessWindowStyle.Minimized;
System.Diagnostics.Process listFiles;
listFiles = System.Diagnostics.Process.Start(psi);
retBool = true;
}
else
{
/*if running, do nothing and return false*/
retBool = false;
}
return retBool;
}
 
M

[MSFT]

Hi Gunnar,

When you start a process from ASP.NET, its owner always is ASPNET or
Network Service. I think the Winform application should be start on desktop
and communicate with it in ASP.NET.

To make the Marshaling part to work in the web application, the third
party should support early binding like:

Word WordApp= new Word()

Have you consult them for this?

Luke
 
O

OfurGørn

Hi Luke.

I have consulted them. They are clueless, as they are definetly not .NET
people.

Becuase of my newbie status, do you know of any examples on how to make my
web service access a form application ??

I am testing a WebService to Form Application solution now, hoping that will
solve this.

Thanks for all the help
Gunnar
 
O

OfurGørn

I just thought of something.... as I have seen a LOT of posts on this
problem, i.e. marshaling and getting the com exception 0x800401E3, dating
back to 1998, I was wondering if anyone has succeeded in marshaling from a
(web) service ???

I have been trying to write a simple form application that I can access from
my webservice and I just keep getting in trouble - does anyone know of an
example where I can see how to make a form app ready for a web service ?

/g
 
O

OfurGørn

Hi Luke

I got an example from the 3rd party developer on how to access their
program. The problem is that it is a asp code, and I have been trying to
"port" that to the c# web service. The call they use is the following
try {
var tstApp = Server.CreateObject('Test.Application');
}
The following and preceeding code is alomst identical to that I have been
using as support, but they use Server.CreateObject in stead of
Marshal.GetActiveObject. Any ideas there ??
The closest I can find is HttpServerUtility.CreateObject, but that is
obviously worng as that doesn't even compile.

best regards,
Gunnar
 
S

Steven Cheng[MSFT]

HI Gunnar,

Thanks for your followup. We're currently finding some further resource to
assist you on this issue and will update you as soon as possible.

Thanks & Regards,

Steven Cheng
Microsoft Online Support

Get Secure! www.microsoft.com/security
(This posting is provided "AS IS", with no warranties, and confers no
rights.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top