I need to test old legacy remoting service.
The code comes with ready to use client side which means I have an object that takes care of all the channeling implementation.
When connecting to this client from executable - everything is good and works great, but when trying to do the same operation using dll (nunit is the test framework) SecurityException is thrown whenever I'm trying to query the service.
Why there is difference using dll code over executable?
This is the error message:
Type System.Runtime.Remoting.ObjRef and the types derived from it
(such as System.Runtime.Remoting.ObjRef) are not permitted to be
deserialized at this security level.
needless to say I have no access to the server side code, but it is .Net 4.5 (although remoting) and the test code is also .Net 4.5, and I must mention I run the code on the same machine
This is the code generates the client side channel
public class RemoteClient
{
public static RemoteClient GenerateClient()
{
SetupHttpChannelAndBuildUrl();
cm_remote obj = null;
try
{
obj = (cm_remote) Activator.GetObject(typeof (cm_remote_base), url);
obj.DoSomething();
return obj;
}
catch (Exception e)
{
...
}
}
private static SetupHttpChannelAndBuildUrl()
{
...
}
public void DoSomethig()
{
...
}
}
and this is the both dll and exe code triggering the functionality:
public RemoteClient GetRemoteClient()
{
return RemoteClient.GenerateClient();
}
from exe it returns instance of RemoteClient, from dll returns null
Related
I am trying to extend an application which supports COM/ActiveX objects. The COM dll needs to send some data to other system on local network for further processing and actions.
I have tested a basic WCF Host-Client setup and it works fine from console client to console host. But now I need to send data through a client in com-visible dll.
This is the code of the dll :
namespace Client
{
[Guid("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")]
[ComVisible(true)]
public interface ISend
{
[DispId(1)]
bool SendData(string msg);
}
[ClassInterface(ClassInterfaceType.None), Guid("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"), ProgId("Client.Send")]
[ComVisible(true)]
public class Send : ISend
{
static BasicHttpBinding binding = new BasicHttpBinding();
static EndpointAddress endpoint = new EndpointAddress(new Uri("http://192.168.1.6:8000/WCFHost/Service/GetData"));
GetDataClient client = new GetDataClient(binding, endpoint);
[ComVisible(true)]
public bool SendData(string msg)
{
try
{
if (client.getData(msg))
{
client.Close();
return true;
}
else
{
client.Close();
return false;
}
}
catch (Exception e)
{
client.Abort();
return false;
}
}
}
}
The dll works fine as a reference but cannot create object through target application(It has the functionality to access COM/ActiveX objects). When I try to access the dll by :
obj = CreateObject ("Client.Send");
obj.SendData("Hello")
It says :
COM/object handle is null
on second line nothing more!
I created a com-visible dll in similar way using Remoting to achieve this and it worked like a charm. But now its not working as a WCF Client.
It would be really appreciated if someone could point out what I am doing wrong.
I had moved to Remoting where this was not a problem, but I was suggested to stay away from it and achieve this through WCF.
P.S : I am new to C# so please excuse any stupid mistakes.
COM does not support static methods, see here for further details. You'll need to remove the static keyword from the class in order to let your client create an instance. This will also allow you to implement the interface, which is not possible for static classes.
As a side note, your code shouldn't even compile, since the static modifier on an interface is illegal. Remove it as well, then recompile and re-register your DLL.
I have a WCF service written in C# what works fine. It's the usual self-hosted type in a Win32 console application. But now, for reasons of special updating (it's not a simple desktop computer where you simply update a program using the usual installers but a special embedded system) I'd like to move the actual type implementing the service to a DLL which is loaded by a very simple loader executable using reflection:
string DllFilename = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "myservice.dll");
var ServicesDll = Assembly.LoadFrom(DllFilename);
var ServicesType = ServicesDll.GetType("MyNamespace.MyServices");
var Instance = (ServiceBase)Activator.CreateInstance(ServicesType);
ServiceBase.Run(new ServiceBase[] { Instance });
I can deploy the service all three ways, either installing it normally via MSI, or using sc.exe, or even with a self-managing code like this:
ServicesType.GetMethod("InstallService").Invoke(null, null);
ServicesType.GetMethod("StartService").Invoke(null, null);
where
public class MyServices : ServiceBase {
//...
public static void InstallService() {
if (!IsInstalled())
using (AssemblyInstaller installer = GetInstaller()) {
var state = new Hashtable();
try {
installer.Install(state);
installer.Commit(state);
}
catch {
installer.Rollback(state);
throw;
}
}
}
public static void StartService() {
if (IsInstalled())
using (var controller = new ServiceController("MyService")) {
if (controller.Status != ServiceControllerStatus.Running) {
controller.Start(); // fails here
controller.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(10));
}
}
}
//...
}
As I mentioned in the beginning, everything works just fine in an EXE. But as soon as the MyService type is in the DLL, InstallService is still OK but StartService fails with System.ComponentModel.Win32Exception: %1 is not a valid Win32 application. It seems that Windows expects the service executable (which it stores itself not as the EXE I actually installed but as the DLL the service was implemented in) to be an executable to be called at its leisure.
How can I circumvent this limitation, maybe to signal somehow that it's my loader EXE that I want to be called, not the dependent DLL?
Split your MyServices into two classes - one a thin wrapper inherited from ServiceBase (to live in .EXE) and another doing real work including self-hosting to live in updatable .DLL. The first one can take an instance of the second as a .ctor argument and delegate start/stop calls to it.
You may also want to look at Topshelf.
I finally went with Rene's suggestion, the bulk of the service stays in an EXE and loaded as an assembly into the loader. Fortunately, loading an assembly can be done both from EXE and DLL.
OK, so I have the C# DLL method:
public void DeletePublisher(string strName)
{
try
{
if (_PublisherData.PublisherDictionary.ContainsKey(strName))
_PublisherData.PublisherDictionary.Remove(strName);
}
catch (Exception ex)
{
SimpleLog.Log(ex);
}
}
It works fine. If there is a exception it is detected and added to the log.
At the moment, the above is called via MFC in my C++ project using a wrapper:
bool CMSATools::DeletePublisher(CString strPublisher)
{
bool bDeleted = false;
if (m_pInterface != nullptr)
{
CComBSTR bstrPublisher = strPublisher.AllocSysString();
throw_if_fail(m_pInterface->DeletePublisher(bstrPublisher));
bDeleted = true;
}
return bDeleted;
}
They both work fine. The issue is that fact that the CPP method currently has no knowledge of the C# method having failed. Now, in this particular instance I know I could change the signature of the DLL method to return false for a exception failure occurring and examine that return value in the CPP file.
But, in other instances I am already using the return value and thus, it would seem for consistency to me, that I pass in a bool bExceptionRaised parameter instead to my methods in the DLL.
That way, I can test that value when the method seemed to complete and if it is false act accordingly.
At the moment my application doesn't realise that an exception occurred and that is confusion.
Can I assume that either of these methodologies are the simplest approach to what I am trying to detect?
Update
Based on the answer provided I have tried to follow this tutorial and I am getting confused. I have tried to follow it and I can't create a CLR DLL and build it that is a bridge to my C# DLL file.
Whilst I appreciate the answer I feel like it is breaking up everything I have worked on since the C# DLL already handles and logs it's exceptions. Whilst I would like to learn how to build this bridge for the future, I still think perhaps at the point in time just changing my signatures is sufficient. Either way, my attempt a basic build of a bridge is failing.
Use a C++/CLI wrapper for the access of the managed component.
With C++/CLI you can directly use the C# component can catch the managed exception and you can throw a native exception or even return true or false... whatever you want.
void DoManagedStuff(SOMEDATA somedata)
{
try
{
auto sm = ConvertToSomeDataToManaged(somedata);
CallManagedCode(sm);
}
catch (Exception^ e)
{
throw CMyNativeException();
}
}
This is example code in java.
Shared interfaces:
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Compute extends Remote {
public Object executeTask(Task t) throws RemoteException;
}
Task (this will be passed as parameter):
import java.io.Serializable;
public interface Task extends Serializable {
public Object execute();
}
Server:
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class ComputeEngine extends UnicastRemoteObject implements Compute {
public ComputeEngine() throws RemoteException {
super();
}
public Object executeTask(Task t) {
return t.execute();
}
public static void main(String[] args) {
setRmiCodebase();
System.setSecurityManager(new RMISecurityManager());
try {
Compute engine = new ComputeEngine();
Naming.rebind("//localhost:1099/Compute", engine);
System.out.println("ComputeEngine started.");
} catch (Exception ex) {
ex.printStackTrace();
}
}
private static void setRmiCodebase() {
String codebase = System.getProperty("java.rmi.server.codebase");
if (codebase != null)
return;
// set codebase based on location of this clsas (is it in jar or filesistem?)
}
}
Client:
import java.math.BigDecimal;
/**
* Calculates Pi to arbitrary number of digits:
*/
public class Pi implements Task {
public Pi(int digits) {
this.digits = digits;
}
public Object execute() {
return computePi(digits);
}
public static BigDecimal computePi(int digits) {
// compute Pi
}
}
Client main:
import java.math.BigDecimal;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
public class ComputePi {
public static void main(String[] args) {
setRmiCodebase();
System.setSecurityManager(new RMISecurityManager());
try {
Compute comp = (Compute)Naming.lookup("//localhost:1099/Compute");
Pi task = new Pi(100);
BigDecimal pi = (BigDecimal)comp.executeTask(task);
System.out.println(pi);
} catch (Exception ex) {
ex.printStackTrace();
}
}
private static void setRmiCodebase() {
String codebase = System.getProperty("java.rmi.server.codebase");
if (codebase != null)
return;
// set codebase based on location of this clsas (is it in jar or filesistem?)
}
}
As you can see, code (not just data) from client is transfered to server and executed there and result of computation is returned. Server does not know that class Pi exists, it only knows about Task interface.
I need something like this to work in .net environment (C# if it is important). WCF would be nice, but I am looking for the most straightforward solution, so WCF is not compulsory. I am not sure even what keyword to use to google documetation or solution for this.
Any help will be appreciated.
Afaik .NET doesn't support this out of the box - you can do remoting but that won't (as is) let you run code from the client on the server. I think you would have to implement something that transfers the dll containing the code you want to execute to the server, and then probably load that dll in a separate AppDomain (because you can't unload dll's unless you load them into a separate AppDomain), and then have a way to specify the class to run.
.NET does not natively support "sending code" to be executed on another computer. Typically the necessary code would be compiled to assemblies and pre-installed on the server before it is called by the client. This is true of both remoting and WCF. You could have a two-way remoting situation where the server calls back to a method on the client via WCF, but I suspect this is not what you want. The only way I'm aware of to really run dynamic code on the server is to generate dynamic code, send it to the server as a string, and then have the server compile it to an in-memory assembly on the fly and then execute it. If you are interested in doing so, take a look at my answer to a similar question:
Autovivified properties?
However, it's not exactly something I would suggest in most cases. I would suggest you rethink your design, first, to see if there is any way to do what you need in a typical ".NET way".
What You want is .NET Remoting.
Here's link to article showing how to migrate from RMI to .NET Remoting.
But according to this MSDN article this is a legacy technology and You should use WCF.
Edit:
You can't "just like that" get .NET Remoting functionality with WCF.
Here you can read discussion about porting from .NET Remoting to WCF.
But if you don't know WCF at all You shoud start here. And You probably won't get your results fast :).
This MSDN page has more or less this exact use case you described. You just need to modify the ServiceContract
http://msdn.microsoft.com/en-us/library/system.servicemodel.netnamedpipebinding.aspx
You would probably only need to modify this part:
[ServiceContract(Namespace = "http://UE.Samples")]
public interface ICalculator
{
[OperationContract]
double Add(double n1, double n2);
}
// Service class which implements the service contract.
public class CalculatorService : ICalculator
{
public double Add(double n1, double n2)
{
return n1 + n2;
}
Instead of scalar values put your executeTask method with parameter of your own class there.
I don't believe .NET has a built-in solution for transferring executable code from client to server. Assuming the security constraints allow it, you might consider sending interpretable code such as Python or JavaScript which could be executed server-side via IronPython or IronJS respectively. If C# is a requirement (and you still have access to the source code), sending the source and compiling server-side (via Roslyn or the Mono's evaluator).
I am using VMware Workstation 6.5 on Windows Vista x64.
I am trying to write some C# code that uses VMware Vix v1.6.1 COM API to get a list of registered virtual machines.
The code I am using is as follows:
using System;
using VixCOM;
namespace ConsoleApplication48
{
internal class Program
{
private static void Main()
{
var lib = new VixLibClass();
object results = null;
var job = lib.Connect(Constants.VIX_API_VERSION, Constants.VIX_SERVICEPROVIDER_VMWARE_WORKSTATION, null, 0,
null, null, 0, null, null);
var err = job.Wait(new[] {Constants.VIX_PROPERTY_JOB_RESULT_HANDLE}, ref results);
if (lib.ErrorIndicatesFailure(err))
Console.WriteLine("Error: " + err);
var host = (IHost)((object[])results)[0];
job = host.FindItems(Constants.VIX_FIND_REGISTERED_VMS, null, -1, new DiscoveryCallback(lib));
job.WaitWithoutResults();
host.Disconnect();
}
}
internal class DiscoveryCallback : ICallback
{
protected VixLibClass lib;
public DiscoveryCallback(VixLibClass lib)
{
this.lib = lib;
}
#region ICallback Members
public void OnVixEvent(IJob job, int eventType, IVixHandle moreEventInfo)
{
// this method is never called
}
#endregion
}
}
I am aware that the COM dll is 32-bit, so I made sure that the test application is compiled as 32-bit.
Also I made sure that all VMware services are running.
There are no exceptions thrown, no errors returned (as far as I can see) and no events written into the event log.
Strangely enough the above code works when I try to get a list of running VMs using constant VIX_FIND_RUNNING_VMS.
Any ideas on what might be causing this?
Thanks,
Arnie
Quick update on the situation.
I've had a closer look at the official documentation for the FindItems() method. Constant VIX_FIND_REGISTERED_VMS is not listed as a supported parameter - only constant VIX_FIND_RUNNING_VMS is.
My guess is this means that currently VIX API offers no way to get a list of VMs registered on a VMware Workstation instance.
That also would explain why the vmrun.exe command-line utility offers no way of getting registered VMs.
I guess I'll just have to wait until the next version of the VIX API is released.