C
C#3mo ago
PizzaWizard

Understanding COM interface references for an ASP.NET REST API...

Hi all, I'm new-ish to Windows, so forgive me but my knowledge of COM is pretty amateur. I'm running a simulation application on a backend server that implements the COM interface IDispatch to create an interface called IRemoteControl like so:
interface IRemoteControl : IDispatch
{
HRESULT NewModel();
HRESULT LoadModel(BSTR);
HRESULT SaveModel(BSTR);
HRESULT CloseModel();
HRESULT StartSimulation(BSTR);
HRESULT StopSimulation();
HRESULT ResetSimulation(BSTR);
HRESULT GetValue(BSTR,[out,retval]VARIANT*);
HRESULT SetValue(BSTR,VARIANT);
HRESULT Quit();
};
interface IRemoteControl : IDispatch
{
HRESULT NewModel();
HRESULT LoadModel(BSTR);
HRESULT SaveModel(BSTR);
HRESULT CloseModel();
HRESULT StartSimulation(BSTR);
HRESULT StopSimulation();
HRESULT ResetSimulation(BSTR);
HRESULT GetValue(BSTR,[out,retval]VARIANT*);
HRESULT SetValue(BSTR,VARIANT);
HRESULT Quit();
};
We have a single host machine and expect 4-6 users at a time to be sending messages over an API to start, stop, and reset simulations all running on separate instances of this application on the backend server. I can start the program and manipulate it quite easily in ASP.NET. I import the application's included Type Library DLL as a project dependency, then I can do something like
[HttpPost("remote-control/create")]
public IActionResult CreateRemoteControl(string? updatedPath)
{
RemoteControl remoteControl = new();
return OK();
// Handle other cases, etc.
}
[HttpPost("remote-control/create")]
public IActionResult CreateRemoteControl(string? updatedPath)
{
RemoteControl remoteControl = new();
return OK();
// Handle other cases, etc.
}
Whenever I send subsequent calls over a different route to do something like start/stop/reset the simulation, I'm able to do so on the most recently-spawned application instance. However, when multiple users are connected to this server at the same time, I want to be able to assign each user a specific instance of this application, so that subsequent calls only affect that user's instance (so that a user can't send a "reset" message that resets the most recently spawned process, even if it was spawned by another user). I can find the process ID of a spawned RemoteControl object using string currentProcessID = remoteControl.GetCurrentProcessId().ToString();, but I don't know how to use that to restrict commands to specific COM interfaces.
5 Replies
PizzaWizard
PizzaWizard3mo ago
Hit the limit on the previous message. Happy to read up and educate myself instead of just waiting for someone to write code for me, but there's a LOT of documentation on COM/OLE, and it's pretty overwhelming for someone who doesn't spend any time in low-level systems/OS programming or C/C++. Would be happy to be pointed in the right direction to get signal from the noise. Thanks!
lycian
lycian3mo ago
Whenever I send subsequent calls over a different route to do something like start/stop/reset the simulation, I'm able to do so on the most recently-spawned application instance.
If the lifetime of the ASP.NET server is tied to the spawned application instances you could easily just keep a map of user:IRemoteControl if I'm understanding your scenario correctly
PizzaWizard
PizzaWizard3mo ago
The server will persist across multiple user connections, it essentially never turns off. So do I just give every user a token, and then store that in a dictionary with their remoteControl object? My question would then be, if I wanted to let a user execute a command like remoteControl.StartSimulation() to start a new simulation on their specific instance, I could just pass the user's token and say something like userMap["thisUserToken"] and get back a specific remoteControl object? I was concerned that I would just be passing the reference to the same remoteControl back and forth...
lycian
lycian3mo ago
As long as you new up a new RemoteControl for each UserToken then the references are unique.
static Dictionary<string, IRemoteControl> RemoteControlMapping = new();

[HttpPost("remote-control/create")]
public IActionResult CreateRemoteControl(string userToken)
{
if (RemoteControlMapping.TryGet(userToken, out var _))
{
// handle if it already exists?
}

RemoteControlMapping[userToken] = new RemoteControl();
return OK();
}
static Dictionary<string, IRemoteControl> RemoteControlMapping = new();

[HttpPost("remote-control/create")]
public IActionResult CreateRemoteControl(string userToken)
{
if (RemoteControlMapping.TryGet(userToken, out var _))
{
// handle if it already exists?
}

RemoteControlMapping[userToken] = new RemoteControl();
return OK();
}
roughly that, although you'll probably want some locking/concurrency checks static is important there since it becomes shared. I'm assuming no need for complex DI etc
PizzaWizard
PizzaWizard3mo ago
Excellent. This is a very limited-scope application and should only ever have 2-3 simultaneous users and 10ish total users. So trying to keep things as simple as possible (Except of course, for the fact that I'm using a single computer spawning multiple COM applications to act as a backend for a web app and ignoring the stateless part of REST entirely)
Want results from more Discord servers?
Add your server