Cross-project event - c#

I have 2 projects acting as a webserver and a game server. The game server has the webserver as a dependency so I can access its files in the code and I then want to subscribe to an event in the web server.
I have a Discord bot sending information to the webserver that in turn needs to send data to the game server. But as I can't access the game servers file from the webserver I created a static event in the webserver that the game server, in turn, subscribes to. But the event is always null, no matter what I do. Is it even possible to subscribe to an event cross-project like this?
Here is the event:
public static event EventHandler<CommandEventArgs> RecievedCommand = delegate{};
Here is the invoking method:
public static void InvokeEvent(string exector, string command, string channel)
{
if (!ulong.TryParse(exector, out var user))
{
Console.WriteLine("Not a user");
return;
}
if (!ulong.TryParse(channel, out var from))
{
Console.WriteLine("not a channel");
return;
}
Console.WriteLine("Full invoke");
CommandEventArgs cmd = new CommandEventArgs();
cmd.Channel = channel;
cmd.Command = command;
cmd.Executor = exector;
RecievedCommand.Invoke(typeof(BotBridge), cmd);
}
Here you can see how I invoke it:
if (query["execute"] != null)
{
Console.WriteLine("Invoking");
BotBridge.InvokeEvent(query["user"], query["command"], query["channel"]);
Write(context, "Success!", false);
return;
}
And here is a picture from the game server where I subscribe to the event. The event is registered in the creation of this class so I know for sure the code reaches that part:
BotBridge.RecievedCommand += HandleBotCommand;
}
public void HandleBotCommand(object sender, CommandEventArgs e)
{
The webserver reaches Console.Writeline("Full invoke") in the invoking method but nothing else happens after that. Any ideas?

It's not possible to subscribe to an event from a separate process via a project reference.
Even though your game server is referring the "correct web server code/project", it's not pointing to the correct instance.
Here's what's happening:
Your game server code is subscribing to an event from the web server assembly, but in its own process. It's not subscribing to the actually deployed web server.
In red: what you were expecting.
In green: what is actually happening.
For your situation, you would need another communication mechanism such as HTTP, TCP, etc.

Related

Is there a way to execute my wpf application using msmq trigger?

My Executable file (C# WPF Solution) is not running properly when being called by MSMQ Trigger.
I am sending a notification mesasge to the queue (named sometestname):
I have a class called MyNotification that includes this static method:
public class MyNotification {
public static void SendNotification(String destination,String msg){
string s = #".\Private$\sometestname" + "-" + destination;
if(!MessageQueue.Exists(s))
MessageQueue.Create(s,false);
MessageQueue q = new MessageQueue(s);
Message msg = new Message();
msg.Body = msg;
q.Send(message);}
}
a WPF Solution that uses this class:
void ButtonBase_OnClick(object sender,RoutedEventArgs s){ MyNotification.SendNotification("user1","testing message");}
the .exe that will be fired from trigger (when the message is received) :
Public MainWindow(){
String queueName = #".\Private\sometestname-user1";
MessageQueue msgq = new MessageQueue(queueName,false);
try{
msgq.Purge();
}
catch(MessageQueueException e){
string filename = #"C:\Users\user1\Desktop\error.txt";
File.Create(filename);
}
}
Note that:the message is arriving to the queue,and the executable file is showed running in the background,but it catches an error.
When the executable file is executed manually,it executes nromally without any errors(i.e. no file is created).
But When its fired from the MSMQ Trigger(Includes a rule the invoke standalone executable when message arrives),it catches an exception(i.e. file is created).
I think you could create a windows service that runs your exe.
Instead of having a MSMQ trigger, the service would listen to msmq for a message to appear.
A windows service still can't just run a desktop app. At least not in a straight forward way.
It can use the approach explained here:
https://www.codeproject.com/Articles/35773/Subverting-Vista-UAC-in-Both-and-bit-Archite
There's a comment in this thread from someone says they got the approach to work on Win10.
How can I run an EXE program from a Windows Service using C#?
Having said that.
You will need to write, install and run that windows service.
Maybe a simpler approach would be to start up your wpf app minimised and with it's taskbar icon hidden when the user logs on. That then listens for the msmq message. When it receives one it shows a window.

Process launcher launching process inside of a windows service but the application window is not opening [duplicate]

I currently have a single application that needs to be started from a windows service that i am coding in .net 3.5. This application is currently running as the user who ran the service, in my case the SYSTEM user. If running as the SYSTEM user it does not show the application to the users desktop. Thoughts? advice?
//constructor
private Process ETCHNotify = new Process();
//StartService()
ETCHNotify.StartInfo.FileName = baseDir + "\\EtchNotify.exe";
ETCHNotify.StartInfo.UseShellExecute = false;
//BackgroundWorkerThread_DoWork()
if (!systemData.GetUserName().Equals(""))
{
// start ETCHNotify
try {
ETCHNotify.Start();
}
catch (Exception ex)
{
systemData.Run("ERR: Notify can't start: " + ex.Message);
}
}
I only execute the try/catch if the function i have written GetUserName() (which determines the username of the user running explorer.exe) is not null
again to reiterate: desired functionality is that this starts ETCHNotify in a state that allows it to interact with the currently logged in user as determined by GetUserName()
Collage of some post found around (this and this)
Note that as of Windows Vista, services are strictly forbidden from interacting directly with a user:
Important: Services cannot directly interact with a user as of Windows
Vista. Therefore, the techniques mentioned in the section titled Using
an Interactive Service should not be used in new code.
This "feature" is broken, and conventional wisdom dictates that you shouldn't have been relying on it anyway. Services are not meant to provide a UI or allow any type of direct user interaction. Microsoft has been cautioning that this feature be avoided since the early days of Windows NT because of the possible security risks.
There are some possible workarounds, however, if you absolutely must have this functionality. But I strongly urge you to consider its necessity carefully and explore alternative designs for your service.
Use WTSEnumerateSessions to find the right desktop, then CreateProcessAsUser to start the application on that desktop (you pass it the handle of the desktop as part of the STARTUPINFO structure) is correct.
However, I would strongly recommend against doing this. In some environments, such as Terminal Server hosts with many active users, determining which desktop is the 'active' one isn't easy, and may not even be possible.
A more conventional approach would be to put a shortcut to a small client app for your service in the global startup group. This app will then launch along with every user session, and can be used start other apps (if so desired) without any juggling of user credentials, sessions and/or desktops.
Ultimately in order to solve this i took the advice of #marco and the posts he mentioned. I have created the service to be entirely independent of the tray application that interacts with the user. I did however install the Tray application via registry 'start up' methods with the service. The Service installer will now install the application which interacts with the user as well... This was the safest and most complete method.
thanks for your help everyone.
I wasn't going to answer this since you already answered it, (and it's oh, what? going on 2.5 years OLD now!?) But there are ALWAYS those people who are searching for this same topic, and reading the answers...
In order to get my service to Interact with the Desktop, no matter WHAT desktop, nor, how MANY desktops, nor if the service was even running on the SAME COMPUTER as the desktop app!! None of that matters with what I got here... I won't bore you with the details, I'll just give you the meat and potatoes, and you and let me know if you want to see more...
Ok. First thing I did was create an Advertisement Service. This is a thread that the service runs, opens up a UDP socket to listen for broadcasts on the network. Then, using the same piece of code, I shared it with the client app, but it calls up Advertise.CLIENT, rather than Advertise.SERVER... The CLIENT opens the port I expect the service to be on, and broadcasts a message, "Hello... Is there anybody out there??", asking if they're there ANY servers listening, and if so, reply back to THIS IP address with your computer name, IP Address and port # where I can find the .NET remoting Services..." Then it waits a small amount of time-out time, gathers up the responses it gets, and if it's more than one, it presents the user with a dialog box and a list of services that responded... The Client then selects one, or, if only ONE responded, it will call Connect((TServerResponse) res); on that, to get connected up. At this point, the server is using Remoting Services with the WellKnownClientType, and WellKnownServerType to put itself out there...
I don't think you are too interested in my "Auto-Service locater", because a lot of people frown on UDP, even more so when your app start broadcasting on large networks. So, I'm assuming you'd be more interested in my RemotingHelper, that gets the client connected up to the server. It looks like this:
public static Object GetObject(Type type)
{
try {
if(_wellKnownTypes == null) {
InitTypeCache();
}
WellKnownClientTypeEntry entr = (WellKnownClientTypeEntry)_wellKnownTypes[type];
if(entr == null) {
throw new RemotingException("Type not found!");
}
return System.Activator.GetObject(entr.ObjectType, entr.ObjectUrl);
} catch(System.Net.Sockets.SocketException sex) {
DebugHelper.Debug.OutputDebugString("SocketException occured in RemotingHelper::GetObject(). Error: {0}.", sex.Message);
Disconnect();
if(Connect()) {
return GetObject(type);
}
}
return null;
}
private static void InitTypeCache()
{
if(m_AdvertiseServer == null) {
throw new RemotingException("AdvertisementServer cannot be null when connecting to a server.");
}
_wellKnownTypes = new Dictionary<Type, WellKnownClientTypeEntry>();
Dictionary<string, object> channelProperties = new Dictionary<string, object>();
channelProperties["port"] = 0;
channelProperties["name"] = m_AdvertiseServer.ChannelName;
Dictionary<string, object> binFormatterProperties = new Dictionary<string, object>();
binFormatterProperties["typeFilterLevel"] = "Full";
if(Environment.UserInteractive) {
BinaryServerFormatterSinkProvider binFormatterProvider = new BinaryServerFormatterSinkProvider(binFormatterProperties, null);
_serverChannel = new TcpServerChannel(channelProperties, binFormatterProvider);
// LEF: Only if we are coming form OUTSIDE the SERVICE do we want to register the channel, since the SERVICE already has this
// channel registered in this AppDomain.
ChannelServices.RegisterChannel(_serverChannel, false);
}
System.Diagnostics.Debug.Write(string.Format("Registering: {0}...\n", typeof(IPawnStatServiceStatus)));
RegisterType(typeof(IPawnStatServiceStatus),m_AdvertiseServer.RunningStatusURL.ToString());
System.Diagnostics.Debug.Write(string.Format("Registering: {0}...\n", typeof(IPawnStatService)));
RegisterType(typeof(IPawnStatService), m_AdvertiseServer.RunningServerURL.ToString());
System.Diagnostics.Debug.Write(string.Format("Registering: {0}...\n", typeof(IServiceConfiguration)));
RegisterType(typeof(IServiceConfiguration), m_AdvertiseServer.RunningConfigURL.ToString());
}
[SecurityPermission(SecurityAction.Demand, Flags=SecurityPermissionFlag.RemotingConfiguration, RemotingConfiguration=true)]
public static void RegisterType(Type type, string serviceUrl)
{
WellKnownClientTypeEntry clientType = new WellKnownClientTypeEntry(type, serviceUrl);
if(clientType != RemotingConfiguration.IsWellKnownClientType(type)) {
RemotingConfiguration.RegisterWellKnownClientType(clientType);
}
_wellKnownTypes[type] = clientType;
}
public static bool Connect()
{
// Init the Advertisement Service, and Locate any listening services out there...
m_AdvertiseServer.InitClient();
if(m_AdvertiseServer.LocateServices(iTimeout)) {
if(!Connected) {
bConnected = true;
}
} else {
bConnected = false;
}
return Connected;
}
public static void Disconnect()
{
if(_wellKnownTypes != null) {
_wellKnownTypes.Clear();
}
_wellKnownTypes = null;
if(_serverChannel != null) {
if(Environment.UserInteractive) {
// LEF: Don't unregister the channel, because we are running from the service, and we don't want to unregister the channel...
ChannelServices.UnregisterChannel(_serverChannel);
// LEF: If we are coming from the SERVICE, we do *NOT* want to unregister the channel, since it is already registered!
_serverChannel = null;
}
}
bConnected = false;
}
}
So, THAT is meat of my remoting code, and allowed me to write a client that didn't have to be aware of where the services was installed, or how many services were running on the network. This allowed me to communicate with it over the network, or on the local machine. And it wasn't a problem to have two or more people running the app, however, yours might. Now, I have some complicated callback code in mine, where I register events to go across the remoting channel, so I have to have code that checks to see if the client is even still connected before I send the notification to the client that something happened. Plus, if you are running for more than one user, you might not want to use Singleton objects. It was fine for me, because the server OWNS the objects, and they are whatever the server SAYS they are. So, my STATS object, for example, is a Singleton. No reason to create an instance of it for EVERY connection, when everyone is going to see the same data, right?
I can provide more chunks of code if necessary. This is, of course, one TINY bit of the overall picture of what makes this work... Not to mention the subscription providers, and all that.
For the sake of completeness, I'm including the code chunk to keep your service connected for the life of the process.
public override object InitializeLifetimeService()
{
ILease lease = (ILease)base.InitializeLifetimeService();
if(lease.CurrentState == LeaseState.Initial) {
lease.InitialLeaseTime = TimeSpan.FromHours(24);
lease.SponsorshipTimeout = TimeSpan.FromSeconds(30);
lease.RenewOnCallTime = TimeSpan.FromHours(1);
}
return lease;
}
#region ISponsor Members
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.Infrastructure)]
public TimeSpan Renewal(ILease lease)
{
return TimeSpan.FromHours(12);
}
#endregion
If you include the ISponsor interface as part of your server object, you can implement the above code.
Hope SOME of this is useful.
When you register your service, you can tell it to allow interactions with the desktop. You can read this oldie link http://www.codeproject.com/KB/install/cswindowsservicedesktop.aspx
Also, don't forget that you can have multiple users logged in at the same time.
Apparently on Windows Vista and newer interacting with the desktop has been made more difficult. Read this for a potential solution: http://www.codeproject.com/KB/cs/ServiceDesktopInteraction.aspx

Detecting an incoming call in Lync

I'm trying to detect an incoming call in the Lync client . This is done by subscribing to ConversationManager.ConversationAdded event in the Lync client as described in this post
However, by using this method I'm not able to detect incoming calls if a conversation window with the caller is already open before the caller is calling.
For instance if I'm chatting with a friend and therefore have a open conversation windows and this friend decides to call me, the ConversationAdded event is not triggered.
How would I detect incoming calls when I already have an active conversation with the caller?
Thanks,
Nicklas
You need to monitor the states of the modalities on the conversation. The two avaiable modalities are IM and AV, so you'll need to watch for state changes on these, like so:
void ConversationManager_ConversationAdded(object sender, Microsoft.Lync.Model.Conversation.ConversationManagerEventArgs e)
{
e.Conversation.Modalities[ModalityTypes.InstantMessage].ModalityStateChanged += IMModalityStateChanged;
e.Conversation.Modalities[ModalityTypes.AudioVideo].ModalityStateChanged += AVModalityStateChanged;
}
void IMModalityStateChanged(object sender, ModalityStateChangedEventArgs e)
{
if (e.NewState == ModalityState.Connected)
MessageBox.Show("IM Modality Connected");
}
void AVModalityStateChanged(object sender, ModalityStateChangedEventArgs e)
{
if (e.NewState == ModalityState.Connected)
MessageBox.Show("AV Modality Connected");
}
This sample is using the ConversationAdded event to wire up the event handlers for modality changes, so this will only work for conversations that are started while your application is running. To do the same for conversations that are already active before your application starts, you could add this code to your application's startup routine:
foreach (var conv in _lync.ConversationManager.Conversations)
{
conv.Modalities[ModalityTypes.InstantMessage].ModalityStateChanged += new EventHandler<ModalityStateChangedEventArgs>(IMModalityStateChanged);
conv.Modalities[ModalityTypes.AudioVideo].ModalityStateChanged += new EventHandler<ModalityStateChangedEventArgs>(AVModalityStateChanged);
}
You should subscribe to the ModalityStateChanged event on Conversation.Modalities[ModalityTypes.AudioVideo], this will give you events when the AV modality is created or changes state.

Posting to Twitter from Silverlight 4 app

I wrote a method to post to Twitter using webclient. Everything works fine when calling the method from a console app.
I migrated the method to Silverlight 4. Here is where the fun begins. After cleaning up the code, switching to an asynchronous method call, and getting rid of the red squiggled underlines, the code now runs inside my SL4 app. The tweets do not, however, actually post to my twitter page.
I wired up an event handler for the "_completed" event. It gets fired.
Also wired up an event handler for the "_uploadProgressChanged" event. It never gets fired. Could be upload is too quick?
Any suggestions for troubleshooting this?
Update #2-
Correction... the "_completed" event DOES NOT get fired. I also added Fiddler to the mix to watch the traffic. It does not appear the app is transmitting anything. Fiddler does show activity if I post to stackoverflow (so Fiddler is working).
public static void PostTwitterUpdate(string handle, string pwd, string tweet)
{
WebClient webClient = new WebClient();
webClient.Credentials = new NetworkCredential(handle, pwd);
Uri uriString = new Uri("http://twitter.com/statuses/update.xml", UriKind.Absolute);
try
{
// event handlers added tongiht for debugging...
webClient.UploadProgressChanged += webClient_UploadProgressChanged;
webClient.UploadStringCompleted += webClient_UploadStringCompleted;
webClient.UploadStringAsync(uriString, "It's just me testing...");
}
catch (Exception ex)
{
throw;
}
}
static void webClient_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
{
// breakpoint set here for debugging...
}
static void webClient_UploadProgressChanged(object sender, UploadProgressChangedEventArgs e)
{
// breakpoint set here for debugging...
}
This only would work in an elevated trust Out-of-Browser application because the Twitter Cross Domain Policy File at http://twitter.com/crossdomain.xml does not permit the calls for web page based apps.
Michael

how to get an event whenever the network cable is connected or disconnected

im doing an application in which im transfering file through FTP.i succesfully done all
the things to transfer files and folders.now i want to know how to get an event whenever the
the network cable is connected or disconnected while im transfering a file.
im using SYSTEM.NET NAMESPACE,FTPWEBREQUEST Class.
when will the event get raised i just run mi program and disconnected the network cable
but nothing happens.
im not able to raise the event will u send ur code .actually it is working in vb.net.it doesnt get raised in c# below is mycode:
public partial class Form1 : Form
{
public static event NetworkAvailabilityChangedEventHandler networkchanged;
string file_to_upload;
string serverip;
string username;
string password;
FileStream fstream;
Stream strem;
public Form1()
{
InitializeComponent();
networkchanged += new NetworkAvailabilityChangedEventHandler(Form1_networkchanged);
}
void Form1_networkchanged(object sender, NetworkAvailabilityEventArgs e)
{
//my implementations goes here
//throw new Exception("The method or operation is not implemented.");
}
i done it this is very useful.thank you very much
System.Net.NetworkInformation.NetworkChange.NetworkAvailabilityChanged event.
You don't really need to handled the "network cable is disconnected" case. The FTP library you are using should/would time-out or give an error. What library/class are you using?

Categories