I've found an article on how to elevate a COM object written in C++ by calling
CoCreateInstanceAsAdmin. But what I have not been able to find or do, is a way to implement a component of my .NET (c#) application as a COM object and then call into that object to execute the tasks which need UAC elevation. MSDN documents this as the admin COM object model.
I am aware that it is possible and quite easy to launch the application (or another app) as an administrator, to execute the tasks in a separate process (see for instance the post from Daniel Moth, but what I am looking for is a way to do everything from within the same, un-elevated .NET executable. Doing so will, of course, spawn the COM object in a new process, but thanks to transparent marshalling, the caller of the .NET COM object should not be (too much) aware of it.
Any ideas as to how I could instanciate a COM object written in C#, from a C# project, through the CoCreateInstanceAsAdmin API would be very helpful. So I am really interested in learning how to write a COM object in C#, which I can then invoke from C# through the COM elevation APIs.
Never mind if the elevated COM object does not run in the same process. I just don't want to have to launch the whole application elevated; I would just like to have the COM object which will execute the code be elevated. If I could write something along the lines:
// in a dedicated assembly, marked with the following attributes:
[assembly: ComVisible (true)]
[assembly: Guid ("....")]
public class ElevatedClass
{
public void X() { /* do something */ }
}
and then have my main application just instanciate ElevatedClass through the CoCreateInstanceAsAdmin call. But maybe I am just dreaming.
Look at Windows Vista UAC Demo Sample Code
(You also need the Vista Bridge sample for UnsafeNativeMethods.CoGetObject method)
Which gives you C# code that shows a few different ways to elevate, including a COM object
(Incomplete code sample - grab the files above)
[return: MarshalAs(UnmanagedType.Interface)]
static internal object LaunchElevatedCOMObject(Guid Clsid, Guid InterfaceID)
{
string CLSID = Clsid.ToString("B"); // B formatting directive: returns {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
string monikerName = "Elevation:Administrator!new:" + CLSID;
NativeMethods.BIND_OPTS3 bo = new NativeMethods.BIND_OPTS3();
bo.cbStruct = (uint)Marshal.SizeOf(bo);
bo.hwnd = IntPtr.Zero;
bo.dwClassContext = (int)NativeMethods.CLSCTX.CLSCTX_ALL;
object retVal = UnsafeNativeMethods.CoGetObject(monikerName, ref bo, InterfaceID);
return (retVal);
}
I think the only way CoCreateInstanceAsAdmin works is if you have registered the COM component ahead of time. That may be a problem if you intend your application to work in an XCopy deployment setting.
For my own purposes in Gallio I decided to create a little hosting process on the side with a manifest to require admin privileges. Then when I need to perform an elevated action, I spin up an instance of the hosting process and instruct it via .Net remoting to execute a particular command registered in Gallio's Inversion of Control container.
This is a fair bit of work but Gallio already had an out of process hosting facility so adding elevation into the mix was not too hard. Moreover, this mechanism ensures that Gallio can perform privilege elevation without requiring prior installation of any other COM components in the registry.
The elements of elevation are processes. So, if I understand your question correctly, and you want a way to elevate a COM object in your process, than the answer is you can't. The entire point of CoCreateInstanceAsAdmin is to NOT run it in your process.
Related
I am writing a VSTA 20151 enabled app.
In it, I need to load an assembly, access a well-known method (a constructor, not that it matters), invoke it, and pass it a COM object (wrapped up so it is a .net object naturally).
This works fine. Now, in order to enable debugging, I need the process that the assembly is loaded from be different than the one that interacts with the VSTA subsystem. The application interacts with the VSTA subsystem; which means I need the assembly to be loaded in a distinct process.
Is there a simple way to load a .net assembly in a separate process, passing it a com object (or a .net object wrapping the com object) to a well-known entry point?
The complex method would involve creating a custom .exe loader that loads the assembly, use IPC to get ahold of the COM interface, wrap it up and pass it to the assembly. Then use IPC to return any error messages. Not certain what kind of IPC I should use. But there are a lot of moving parts here (the two IPC systems, the loader), and I'd hope there would be an easy way to do it without them.
I looked at System.Diagnostic.Process.Start, but it doesn't seem able to "open an assembly as a process and pass it this .net object" among the options.
Apartments (and similar) probably won't work, as the separate process is needed so that a debugger can attach to the VSTA "script" process and pause/advance it without locking up the VSTA "hosting" process (which in the docs says it can lead to deadlocks).
The application is mixed managed/unmanaged, if that matters. Most of the managed component is C#, most of the unmanaged is C++, and most of the interface is C++/cli.
1 VSTA 2015 is a Microsoft solution to allow on-the-fly editing of a "script-like" environment of a .net language, where the Visual Studio IDE workflow is integrated with the application workflow. Note that this is different than pre-VSTA 2012 in fundamental ways: pre-VSTA 2012 information or answers are unlikely to be useful here.
Is there a simple way to have a code library automatically detect if it's being called from a console application or a windows application? I'd like my library not to report to the Windows Event log if it's being called from a console window, but instead report to the console window. If however, it's not being run from within a console window, it should report to the Windows Event Log.
I thought about requiring my the logging component to be passed the log target, but it would be neat if it could just automatically handle these two targets natively. I don't yet require something as extensive as log4net, indeed, if it becomes necessary to provide support to log to a database/file and other as yet unknown logging targets, then I may recommend such a solution. For now though, just having my component auto-detect the environment and log to the console or the event log according to the environment would be plenty.
Just discovered that "Console.Title" will be a blank string in a windows application and it will be automatically set in a console application.
Still a hack though.
Architecturally, passing the logging context into the library component is the right choice. The library doesn't, and indeed shouldn't, know that much context about the environment it's being run in.
Because you want to support these two special cases natively within the library, I'd suggest a unified approach.
Go ahead and create the more generalized logging entry point/knob that the caller controls.
Create a separate entry point/knob that automatically sets the generalized one for the cases that you want to automatically support.
Even that seems too complicated based on your description, though. Have you considered simply using appropriate TraceListeners in your Diagnostics collection, where your console app adds the appropriate TraceListener to output to the console and the non-console app adds the appropriate EventLog TraceListener to output to the Windows event log? This has the added advantage of working well with all the built-in .net logging support without assuming any external dependencies (e.g., log4net).
Variants of this question have been asked before. Namely here and here.
'
The solutions seem to boil down to two options
Using reflection to figure out what
is calling you.
In the case of console application
put a call to console in a try-catch
block and see if it fails or
succeeds.
My own recommendation is to have your library export an interface. The interface has a function or property that return the type of the caller. The calling object has a class that implements the interface and return what type it is. Because complexity is a concern you can control that somewhat by what you place in the interface.
If a application doesn't register itself with the library then you can try throwing an error or trying some scheme of automatic detection.
By using an interface and throwing an error you are making it explicit to the programmer using the library what exactly you expect. The interaction between the two is defined by the interface.
In addition the interaction is more flexible than a automatic scheme because I, as the user, get to choose how my calling binary interacts with your library rather than some mysterious set of rules.
I know it's kind of a hack, but calling Console.Read will throw an exception when there's no console.
bool isConsole = true;
try
{
isconsole = Console.CursorLeft >= int.MinValue;
}
catch( IOException )
{
// Try to attach to parent process's console window
isConsole = AttachConsole( 0xFFFFFFFF );
}
...
[DllImport( "kernel32", SetLastError = true )]
private static extern bool AttachConsole( uint dwProcessId );
It's a side effect so it may not be a reliable method of detection, but it works for now.
When I try to Convert HTML to XHTML Tag I'm getting the following error...
Error: Retrieving the COM class factory for component with CLSID
{59939390-0E6A-4F1B-A742-20C5459501F7} failed due to the following
error: 80040154.
After googling I found few solutions:
Registering the DLL into regsvr32 "E:Source
Code\bin\Interop.HTML2XHTMLLib.dll"
I'm just tried to register the dll. But E:Source Code\bin\Interop.HTML2XHTMLLib.dll was loaded. But the DllRegisterServer entry point was not found this error message was displayed. Why..?
Recompiled my project for x86 and x64.. no use..
VB.NET Code:
Dim xhtmlUtil As New XHTMLUtilities // Here itself im getting the above error.
sFormattedOutput = xhtmlUtil.convertToXHTML(sInputline) //Send it for conversion
My Operating system is Windows XP 32-bit Service pack 3. My application was done in VS2008. currently I'm working with VS2010.
Here what I'm missing. Could any one help me to figure out this problem?
Thanks in advance.
i'm just tried to register the dll. But E:Source Code\bin\Interop.HTML2XHTMLLib.dll was loaded. But the DllRegisterServer entry point was not found this error message was displayed. why?
The Interop.HTML2XHTMLLib.dll file isn't the library you want to register using regsvr32. It is only the managed interop assembly, generated make COM objects accessable for your .NET application. You actually need to register the type library for the HTML2XHTMLLib.dll.
To do this, you have two options:
Find the redistributeable package, that contains the library and install it together with your application.
On your development system, open the "Add references" dialog of Visual Studio. Choose the COM tab and search for the library (just like you did when you've added the reference). There you will find the absolute path to the library. Copy the library to the client system and register it using regsvr32.
Since I do not know the source of the HTML2XHTMLLib, I can only suggest those ways. You should prefer the first one.
Since you've started a bounty on this, I want to go a little bit more into detail on COM and the InterOp.
Differences between COM and .NET assemblies
There are two types of servers in COM: InProc-servers and OutProc-servers. InProc (In Process) are servers we usually know als DLL. OutProc (Out of Process) servers are standing alone, running in their own process. We know them as EXEcutables.
You want to consume an InProc-server. Your COM-server (HTML2XHTMLLib) consists out of two parts:
A type library (.tlb), that contains meta-information about the server, it's contained objects and their accessability.
A library, containing the code where all the objects are implemented. The library also exports the following static functions:
DllGetClassObject – Tries to create an instance of an object, defined inside the server
DllCanUnloadNow – Tells the COM environment, whether or not the server can be released, because it isn't used by any other process any more.
DllRegisterServer – Called by regsvr32 to register the previously mentioned type library in the Windows Registry, to make it visible to clients and the COM environment.
DllUnregisterServer – Does the exact opposite, when called through regsvr32 -u.
The type library can also a resource of the DLL or EXE file, so that there's only one file. For C# developers this seems somehow confusing, since meta-information is directly compiled into a.NET assembly and accessable through reflection.
The InterOp: A wrapper between .NET and COM
So basicly type libraries describe everything that is needed by the .NET reflection to access the objects exposed through COM. But the problem is, that COM-components are stored in a different format:
Usually they are directly compiled into machine code: You cannot link a .NET assembly, compiled with AnyCPU against a COM-server. COM-servers are directly compiled to either x86-assembler, or x86-64-assembler. They have fixed pointer sizes and thus are only compatible with one of the compilation-models.
COM defines rules for memory management. Each COM-object must implement the IUnknown-interface. This interface defines three methods. The methods AddRef and Release are for memory management purposes. Whenever a client accesses an COM object it needs to call AddRef. This increases a counter by one. When the client does not need the object anymore, it calls Release instead of deleting the object, resulting in a counter decrement. If the pointer reaches 0, the object delete's itself. This is different from how .NET manages memory. In .NET the garbage collector visits each object on the heap in a non-deterministic manner (you cannot determinate the exact point of time an object get's deleted) and releases the object, when there are no references left to it.
COM defines rules for identity. Whenever you only want to access an base interface of an object, you have to call the QueryInterface method, defined by IUnknown. This method is guaranteed to allways return the same pointer, when a specific interface get's queried. This might be also true for .NET (besides you are overloading some operators), but the way .NET ensures object identity is different.
COM defines rules for object relations. Crazy stuff like Aggregation and Containment, which do also exist in .NET, but are implemented differently.
COM defines different multithreading rules, like Single Threaded Appartments and Multi Threaded Appartments. Those threading models define how objects interact, when they are coexisting in different manners. In .NET you have to perform each synchronisation process manually.
This list may not be complete, neither I want to go into detail any further, because it is only incidental for your question, but you see, that there are some big differences between .NET and COM. And to manage those differences there is a layer between both worlds: the COM InterOp.
If you are calling a COM server from .NET, the InterOp is nothing more than a .NET assembly, that does all the hard work under the hood. It get's created using the tlbimp.exe tool. Visual Studio typically calls it for you whenever you are referencing a library from the COM tab. The result is the library you wanted to register: InterOp.Libary.dll. This library redefines all types of the type library of the COM server, implements the rules required by COM and performs the actual calls for you. However it is a managed .NET library which does not define the methods, described earlier. This is why regsvr32 cannot find the DllRegisterServer entry point.
The way described above is only a one-way with an unmanaged COM server and a managed .NET client. There is also the other way, with the counterparts tlbexp.exe and regasm.
I have a 3rd party COM object(32 bit) that I need to call from my c# application (64 bit).
I know I have to run the COM object in a separate process.
This COM object has many classes implemented in it, so I'm trying to avoid writing my own remoting wrapper that exposes all the methods. COM+ seems to be the most straightforward solution. I opened the Component Services menu, created a new COM+ Application, added my COM object as a component to this application. Everything seemed to import beautifully.
In my C# application, I added the original COM object as a reference (which automatically generates the type library). Using the type library reference, I can create objects from from the COM+ component (I see them begin to spin in the Component Services window), but when I try to access on of the methods of the object, I get an error saying the interface is not registered.
Does anyone have a clue? I went back and ran regsvr32 on the COM object, but I don't think it was necessary, and it didn't help.
Is my usage in C# correct? VS2008 autocomplete had no problem seeing those methods.
The exact exception is:
"Interface not registered (Exception from HRESULT:0x80040155)"
Unclear about exactly what the permissions and roles are about in the Component Services, I tried setting up the COM+ object identity to run under the System Account, both as a local service and as interactive user. I've added Everyone as a user in the Roles.
Everything is running locally, so there shouldn't be an issue with file privileges or anything like that.
I also want to reiterate that this COM object contains many classes. I successfully instantiated one class object in my client and set some property values.
I also successfully instantiated another class object, but received this exception when attempting to call a method of this second object .... so I don't think there is an issue with which registry my COM object is registered in.
We had a similar situation, working with a COM dll from VFP.
It all depends on rights and permissions, like Yahia says.
We got it working by doing this:
Install VFP oledb 9 drivers (dunno what you have so probably not required).
give Network Service IIS_IUSR full control on the COM folder (required so the DLL can do some logging in its own folder, when called from the website).
run regsvr32.exe "c:\xxx\yourfile.dll" -> this should be successful!
Create COM+ application, and add the DLL as a part
Set the application COM+ credentials on a user wigh sufficient rights
and we had to do some more settings on rights in application pool / IIS, but thats not required for you I guess.
Anyways, just make sure you have enough logging, make sure the dll is registered, and after that its all about rights rights rights..
Good luck with it!
Sorry to use the "Answer" to respond to comments, but it seems to be my only avenue.
The whole purpose of moving to a 64bit operating system was to gain the extra addressable memory space, so running the entire application in 32bit mode is not an option.
It might be relevant to the problem that after successfully creating three class objects, I was able to set properties in one, call a method with no arguments in the second, but it was calling a method in the third, which took the other two objects as arguments that threw the exception.
I currently have a .NET class library written in C# that exposes its functionaility via COM to a C++ program (pre-.NET).
We now want to move the library out-of-process to free up address space in the main application (it is an image-processing application, and large images eat up address space). I remember from my VB6 days that one could create an "OLE automation server". The OS would automatically start and stop the server .exe as objects were created/destroyed. This looks like the perfect fit for us: as far as I can see nothing would change in the client except it would call CoCreateInstance with CLSCTX_LOCAL_SERVER instead of CLSCTX_INPROC_SERVER.
How would I create such an out-of-process server in C#? Either there is no information online about it, or my terminology is off/out of date!
You can actually do this in .NET (I've done it before as a proof-of-concept), but it's a bit of work to get everything working right (process lifetime, registration, etc).
Create a new Windows application. In the Main method, call RegistrationServices.RegisterTypeForComClients- this is a managed wrapper around CoRegisterClassObject that takes care of the class factory for you. Pass it the Type of the managed ComVisible class (the one you actually want to create- .NET supplies the class factory automatically) along with RegistrationClassContext.LocalServer and RegistrationConnectionType.SingleUse. Now you have a very basic exe that can be registered as a LocalServer32 for COM activation. You'll still have to work out the lifetime of the process (implement refcounts on the managed objects with constructors/finalizers- when you hit zero, call UnregisterTypeForComClients and exit)- you can't let Main exit until all your objects are dead.
The registration isn't too bad: create a ComRegisterFunction attributed method that adds a LocalServer32 key under HKLM\CLSID(yourclsidhere), whose default value is the path to your exe. Run regasm yourexe.exe /codebase /tlb, and you're good to go.
You could always expose your .NET class as COM classes using InteropServices and then configure the library as a COM+ application. The .NET library would run out-of-process and be hosted by a DLLHOST.EXE instance.
Here is an article in MSDN that covers all aspects of how to create COM localserver in c# (.net): link
Your post started a while ago and I had the same problem. The following link is absolute gold and tells you everything
http://www.andymcm.com/blog/2009/10/managed-dcom-server.html