PowerPoint.Application not raising events in C# - c#

I have a simple application written in C# and .Net 2.0 that displays several PowerPoint 2003 files in a loop. (It is going to be used for a information board in our cafeteria) The application works fine on my development machine but when I deploy it to another machine the events I have registered for SlideShowNextSlide and PresentationClose are never fired. I have tried registering the events with this method.
private void InitPPT()
{
app.SlideShowNextSlide += new Microsoft.Office.Interop.PowerPoint.EApplication_SlideShowNextSlideEventHandler(app_SlideShowNextSlide);
app.PresentationClose += new Microsoft.Office.Interop.PowerPoint.EApplication_PresentationCloseEventHandler(app_PresentationClose);
app.SlideShowEnd += new Microsoft.Office.Interop.PowerPoint.EApplication_SlideShowEndEventHandler(app_PresentationClose);
}
And with this method that I found here:
private void InitPPT()
{
IConnectionPointContainer oConnPointContainer = (IConnectionPointContainer)app;
Guid guid = typeof(Microsoft.Office.Interop.PowerPoint.EApplication).GUID;
oConnPointContainer.FindConnectionPoint(ref guid, out m_oConnectionPoint);
m_oConnectionPoint.Advise(this, out m_Cookie);
}
Do I need to register some dll's on the client machine or am I missing something.

I think this was due to the fact that I was trying to run my application from a local user account but impersonate a domain account so I could access network drives. I have changed my application so it only impersonates the domain account while preforming network operations and not at application startup.

Related

CreateEventSource doesn't create event log entry and windows service can't be launched

I'm developing a new windows service and I follow the steps provided in this instruction.
In the service class, I do pretty much the same things as the article
static EventLog _eventLog;
public CMSMetadata()
{
InitializeComponent();
_eventLog = new EventLog();
if (!EventLog.SourceExists("CMSMetadata_Processing"))
{
EventLog.CreateEventSource(new EventSourceCreationData("CMSMetadata_Processing", "CMSMetadata"));
}
_eventLog.Source = "CMSMetadata_Processing";
_eventLog.Log = "CMSMetadata";
}
protected override void OnStart(string[] args)
{
_eventLog.WriteEntry("In OnStart.", EventLogEntryType.Information);
}
After I installed and try to start the service, it shows me the following error
Error 1053: the service did not respond to the start or control
request in a timely fashion
And I also notice CreateEventSource() does not create the event log entry when I look for it in the event viewer.
I found this SO post is discussing the 1053 error I'm facing but none of the solutions works for me.
I have confirmed/tried
The service is built by release mode.
Install by both InstallUtil and ManagedInstallerClass.InstallHelper()
The framework version matches what I have installed, actually, I
tried 4.5.2 and 4.7.2 in case somehow it really has something to do with
the framework.
The service is running as local system.
The config is alright.
If I remove every code related to event log the service can be launched successfully.
Then I think fine if the service somehow can't create event log entry properly maybe I can create the entry in advance as a workaround.
However, in this way, I won't even able to install the service.
The install log (CMSMetadata.InstallLog) as below indicates somehow the installation will create the event source no matter I'm using CreateEventSource() or not.
Installing assembly 'C:\temp\GisSoftware\CMSMetadata\CMSMetadata.exe'.
Affected parameters are:
logtoconsole =
logfile = C:\temp\GisSoftware\CMSMetadata\CMSMetadata.InstallLog
assemblypath = C:\temp\GisSoftware\CMSMetadata\CMSMetadata.exe
Installing service CMSMetadata...
Service CMSMetadata has been successfully installed.
Creating EventLog source CMSMetadata in log Application...
Rolling back assembly 'C:\temp\GisSoftware\CMSMetadata\CMSMetadata.exe'.
Affected parameters are:
logtoconsole =
logfile = C:\temp\GisSoftware\CMSMetadata\CMSMetadata.InstallLog
assemblypath = C:\temp\GisSoftware\CMSMetadata\CMSMetadata.exe
Restoring event log to previous state for source CMSMetadata.
Service CMSMetadata is being removed from the system...
Service CMSMetadata was successfully removed from the system.
To conclude my question, What did I miss to use the event log in windows service?
It seems the service does create an event log by default. I should probably set AutoLog property of Service to false before generate the Installer.
Find the EventLogInstaller insides the ServiceInstaller and modify the log and source fixed my problem(also remember to remove the eventlog entry creation in service ctor).
public ProjectInstaller()
{
InitializeComponent();
EventLogInstaller installer = this.Installers.OfType<ServiceInstaller>().First()
.Installers.OfType<EventLogInstaller>().First();
installer.Source = _source;
installer.Log = _logName;
}
Moreover, it seems better to create eventlog during the installation instead of service ctor since it appears the permission of LocalSystem to access registry is limited.
ref: Easiest language for creating a Windows service

Check that application is not running on other user account c#

I am trying to restrict my application from having multiple instances at machine level, i.e. A computer will have multiple users logging into it and this application is required to have only one instance for performance reasons. So if User A starts the application, User B should simply get a message that this application is already running on User A's account. Now before you start schooling me on processes, I already tried that, and it doesn't work because for my application to check if a similar process is running, it needs to start the process(the application), in this case, the application will never start.
I am using this to restrict multiple instances, and it works great but it only works at user level.
Microsoft.VisualBasic.ApplicationServices
public class SingleInstanceApplication : WindowsFormsApplicationBase
{
private SingleInstanceApplication()
{
base.IsSingleInstance = true;
}
public static void Run(Form f, StartupNextInstanceEventHandler startupHandler)
{
SingleInstanceApplication app = new SingleInstanceApplication();
app.MainForm = f;
app.StartupNextInstance += startupHandler;
app.Run(Environment.GetCommandLineArgs());
}
}
Any help or advice will be much appreciated...
How are users accessing the application? You could create batch script that checks the process, if one is running then the script simply won't start the application. Not sure if you want to solve this programatically inside your application or through other means. But if you don't want a second instance of said application running your best bet would be outside of your application such as a batch script.
There is also this: cross-user C# mutex.
Where I work we have flags set to specific SQL tables that prevent multiple users from editing records at the same time. Or you could create a hidden lock file when a user logs in and than remove said file once the user logs out.

How to detect Windows Logon event using OnSessionChange in C#

I am not able to detect this Logon event in Windows.
Here is my code:
namespace ConsoleApplication2
{
public class MyService: ServiceBase
{
public MyService()
{
CanPauseAndContinue = true;
CanHandleSessionChangeEvent = true;
}
protected override void OnSessionChange(SessionChangeDescription changeDescription)
{
base.OnSessionChange(changeDescription);
}
}
class Program
{
static void Main(string[] args)
{
MyService tpl = new MyService();
Thread t = new Thread(delegate()
{
while (true) { }
});
t.Start();
}
}
}
How do I test run this app and then remote desktop into my laptop? I can see the event generated in Windows EventViewer, but my OnSessionChange is never called (I added a breakpoint inside).
Is my code wrong or is the way I am testing wrong?
Normally multiple concurrent remote desktop sessions are not allowed on any of Windows desktop systems. So to use RDP to login as a different user then I assume that you have hacked this, or are using windows server (which rules out XP!).
Regardless, each user logged into the system will therefore have their own applications running and each set of applications are unique to that user. So App1 could be run independently by each user.
That means that your console application cannot detect the other user that is logged on.
To do this you must use a Windows Service. This runs in the background and can detect and work for multiple users and also detect login and logout. See this SO link
This is the purpose of inheriting MyService from ServiceBase. If you are not running the application as a service, then you are not running it correctly!
You need to first install your application as a service and then run it like a service.
You say that you don't think your application can run as a service. I'm not sure why, but if this is the case then you would have to instead look at creating some kind of script to run your application upon start-up/login.
This way, every time somebody logs in then your application would run. This might anyway be simpler for you.

C# DCOM event binding Unathorized Execption

For a project I am working on I have to interface with a third-party DCOM library. I started with COM interop and this worked just fine locally, then I switched to DCOM and now I keep getting an unauthorized access exception (0x80070005) when trying to bind an event handler to the exposed event. Below is a summary of what I do in code:
public void connect(string server)
{
object dcomObj = null;
var guidB = Guid.Parse("c8c1f57f-0d7c-40b3-b17c-2eac12512006");
var typ = Type.GetTypeFromCLSID(guidB, server, true);
object[] url = { new UrlAttribute(server) };
dcomObj = Activator.CreateInstance(typ, null, url);
user = (RemoteObjectInterface)dcomObj ;
user.getState(); //works fine locally and remotely
user.stateChange += this.User_StateChange; //only works locally
}
I tried setting every permission I could find on the web but I without success. Does anyone have an Idea as to why only the binding of events fails?
RemoteObjectInterface inherits from both the IRemoteObjectEvents and the IRemoteObject. These interface come from the interop ms generated for me when I imported the original dll.
The server is a windows server 2003 VM in virtual box with a bridged network adapter. On the server Everyone is admin (including guest) and limits are set to full access and defaults are set to full access. I am building and running my code on c# .net 4.5.2 from a Windows 10 machine using visual studio 2015.
The sample application that comes with the SDK also fails when I try to use it remotely, the server registers the user but the sample application never realizes that it logged in successfully, I suspect that this behaviour is related to the failing of event binding.
TL;DR I can get and use a remote object but when I try to add an event handler I get an unauthorized exception (0x80070005), why does this happen on event binding? And how do I fix it?
I had the same problem.
For me the issue was I had a AD running on the same device and had to disable the loopback check in the registry. Other solution could be better I assume, but for me the registry hack will do.

Process.Start won't work

I am trying to launch a process from a web page's back-end code/app pool. This process will launch an App that i built myself.
For some reason, the process only works / runs when i start it from VS2013... it never works when i launch it from IIS(7.5) itself.
I am on a Windows 7 machine (both IIS host, and App location), and I've setup my web site to only be accessible via internal network.
Here's the code, followed by the config / attempts to fix the issue:
protected void btn_DoIt_Click(object sender, EventArgs e)
{
string file_text = this.txt_Urls.Text;
if (!String.IsNullOrWhiteSpace(file_text))
File.WriteAllText(ConfigurationManager.AppSettings["filePath"], file_text);
ProcessStartInfo inf = new ProcessStartInfo();
SecureString ss = GetSecureString("SomePassword");
inf.FileName = #"........\bin\Release\SomeExecutable.exe";
inf.Arguments = ConfigurationManager.AppSettings["filePath"];
inf.UserName = "SomeUserName";
inf.Password = ss;
inf.UseShellExecute = false;
//launch desktop app, but don't close it in case we want to see the results!
try
{
Process.Start(inf);
}
catch(Exception ex)
{
this.txt_Urls.Text = ex.Message;
}
this.txt_Urls.Enabled = false;
this.btn_DoIt.Enabled = false;
this.txt_Urls.Text = "Entries received and process started. Check local machine for status update, or use refresh below.";
}
Here are the things I've tried to resolve the issue:
Made sure the executing assembly was built with AnyCPU instead of
x86
Ensured that the AppPool that runs the app, also runs under the same account (SomeUsername) as the ProcessStartInfo specified.
Ensured that the specific user account has full access to the executable's folder.
Ensured that IIS_USR has full access to the executable's folder.
Restarted both the app pool and IIS itself many times over implementing these fixes
I am now at a loss as to why this simply will not launch the app... when i first looked into the event log, i saw that the app would die immediately with code 1000:KERNELBASE.dll, which got me on the AnyCPU config instead of X86 fix... that fixed the event log entries but the app still doesn't start (nothing comes up in task manager), and i get no errors in the event log...
if someone could help me fix this problem i would really appreciate it. This would allow me to perform specific tasks on my main computer from any device on my network (phone, tablet, laptop, etc etc) without having to be in front of my main PC...
UPDATE
The comment to my OP, and ultimate answer from #Bradley Uffner actually nailed the problem on the head: My "app" is actually a desktop application with a UI, and in order to run that application, IIS would need to be able to get access to the desktop and the UI, just like if it were a person sitting down in front of the PC. This of course is not the case since IIS is running only as a service account and it makes sense that it shouldn't be launching UI programs in the background. Also see his answer for one way of getting around this.
Your best bet might be to try writing this as 2 parts. A web site that posts commands to a text file (or database, or some other persistent storage), and a desktop application that periodically polls that file (database, etc) for changes and executes those commands. You could write out the entire command line, including exe path command arguments, and switches.
This is the only way I can really think of to allow a service application like IIS to execute applications that require a desktop context with a logged in user.
You should assign a technical user with enough high priviliges to the running application pool. By default the application pool is running with ApplicationPoolIdentity identy which has a very low priviliges.

Categories