Use SetThreadExecutionState with app that doesn't already prevent sleep mode - c#

On Windows 7 & 10, the Spotify app doesn't prevent the display from turning off or the system going into Sleep mode (at least on the 3 windows machines I'm using). Is there a way to launch the app and incorporate the SetThreadExecutionState function into that thread to prevent the display sleeping while the app is running? Or any other function that will achieve that outcome?
I currently launch and close the app with two separate .bat files that change the sleep timers, but this is pretty clunky so I'd prefer a proper application to do it.

This c# solution doesn't use SetThreadExecutionState function, but you mentioned you already have .bat files to change the sleep timers, so you can copy the commands from them into here.
C# console application:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var spotify = new Process();
spotify.StartInfo.FileName = "Spotify.exe";
spotify.StartInfo.Arguments = "-v -s -a";
Process.Start("powercfg", "-CHANGE -monitor-timeout-ac 0");
spotify.Start();
spotify.WaitForExit();
var exitCode = spotify.ExitCode;
spotify.Close();
Process.Start("powercfg", "-CHANGE -monitor-timeout-ac 1");
}
}
}
Put more Process.Start lines to alter hibernate, etc.

Related

Calling C# program from another C# program [duplicate]

This question already has answers here:
How to start a c# program from another c# program in the same map?
(3 answers)
Closed 8 years ago.
I have 3 C# programs that need to be executed in an order(TestCSharp1, TestCSharp2 and TestCSharp3).2nd program should be executed only after first completes and 3 should execute only after 1 and 2 finish. How can I do this. Right now, I have them as scheduled tasks and I manually check if they have finished and then start others.
Use the Proccess Class (Documentation) to start a process from inside your program. Here is an example from the documentation:
using System;
using System.Diagnostics;
using System.ComponentModel;
namespace MyProcessSample
{
class MyProcess
{
public static void Main()
{
Process myProcess = new Process();
try
{
myProcess.StartInfo.UseShellExecute = false;
// You can start any process, HelloWorld is a do-nothing example.
myProcess.StartInfo.FileName = "C:\\HelloWorld.exe";
myProcess.StartInfo.CreateNoWindow = true;
myProcess.Start();
myProcess.WaitForExit(); //use this if you want to pause execution of your program till the process you have started closes.
// This code assumes the process you are starting will terminate itself.
// Given that is is started without a window so you cannot terminate it
// on the desktop, it must terminate itself or you can do it programmatically
// from this application using the Kill method.
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
Assuming you are running command line programs you can create a batch file with the three executables in it and run the batch file as a scheduled task. As you'll see in the comments, if there are Windows programs this approach will not work.
E.g.
#echo off
cd \ToTheRightPlace
TestCSharp1
TestCSharp2
TestCSharp3
You'll want to check return values, etc.

C#: close process on app's process' killing (with taskman)

I'm very new to C# so my question may sound rediculous. I'm developing an application which sometimes need to run ffmpeg. As you guess, this ffmpeg process must be killed when it's host app was closed. I use such code for this task:
AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnProcessExit);
private void OnProcessExit(object sender, EventArgs e)
{
proc.Kill();
}
This works fine, when the app is closed correctly (via it's interface or with Taskman - Applications). The problem is that OnProcessExit event won't trigger, if the program's process was killed (with Taskman - Processes). As far as I know, killing process and closing program actions are not the same on the low level, but I guess, killing process is a command to it and it can be handled with C# tools. So, is it possible, to close child process in this case?
I think Try this
Application.Exit();
I recommend to use job objects (as per Scott Miller suggestion).
Another option can be have special helper app for your app, which does following:
Start your app
When your app crashed, clean up after it.
But job objects is definitely better option, it specifically made for this
let your host program submit its program ID as parameter,
and then listen if the program exits.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
static class Program
{
[STAThread]
static void Main(string[] args)
{
if (args.Length != 0)
new System.Threading.Thread( new System.Threading.ParameterizedThreadStart(handelexit)).Start(args[0]);
// your code here
}
static void handelexit(object data)
{
int id = System.Convert.ToInt32(data.ToString());
System.Diagnostics.Process p = System.Diagnostics.Process.GetProcessById(id);
while (!p.HasExited)
System.Threading.Thread.Sleep(100);
System.Environment.Exit(0);
}
}
}

Visual Studio delay between multiple startup projects?

how to add some delay between startup projects in solution?
I want Client project to be started after 2-3 seconds from starting WindowsService.
Why I need this?
WindowsService runs socket server and Client runs socket to connect to server. WindowsService loads slowly than Client, and this causes an exception on client side when connecting to server which is not run yet
I would probably add a retry mechanism within the client. That way not only does it help in the "starting up from Visual Studio" case - it also helps if the server happens to be restarting while the real client connects. The fact that the server is on a faster machine doesn't mean the server will never need to restart, does it?
Indeed, you may well want to add this retry mechanism in such a way that the client can recover even if the server is restarted while it's connected. It depends on what the project is doing, of course.
You can use Mutex locking to sync the two startup project.
Program 1 (StartUp Project 1):
namespace ConsoleApplication1
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
class Program1
{
private static bool isNewMutexCreated = true;
private static Mutex mutex;
static void Main(string[] args)
{
mutex = new Mutex(true, "Global\\ConsoleApplication1", out isNewMutexCreated);
AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
Console.WriteLine("Application1 executed on " + DateTime.Now.ToString());
Console.ReadKey();
}
static void CurrentDomain_ProcessExit(Object sender, EventArgs e)
{
if (isNewMutexCreated)
{
Console.WriteLine("Mutex Released");
mutex.ReleaseMutex();
}
}
}
}
Program 2 (StartUp Project 2):
namespace ConsoleApplication2
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
class Program2
{
static void Main(string[] args)
{
Mutex mutex = null;
Thread.Sleep(5000);
while (mutex == null)
{
try
{
mutex = Mutex.OpenExisting("Global\\ConsoleApplication1");
}
catch (Exception)
{
Console.WriteLine("Mutex not found on " + DateTime.Now.ToString());
Thread.Sleep(3000);
}
}
Console.WriteLine("Application2 executed on " + DateTime.Now.ToString());
Console.ReadKey();
}
}
}
Another simpler option for testing is to just delay the client if the debugger is attached like this:
if (System.Diagnostics.Debugger.IsAttached)
{
System.Threading.Thread.Sleep(2000);
}
You might wrap that in an #if DEBUG block if you like. Anyway I think this should be the least amount of work :)
In case of multiple start-up projects, they are loaded in the order they are specified neither simultaneously nor randomly. http://msdn.microsoft.com/en-us/library/09138bex(v=vs.90).aspx
So ,may be if you specify "client" after "window service", then it may workout fine. And if you don't want to got the coded way suggested above, then (for testing only) you can manually attach the "client" process to you solution from a different solution after your desired delay.
http://msdn.microsoft.com/en-us/library/c6wf8e4z(v=vs.100).aspx
If the client needs to be started after, you need to adjust your list, as at the moment its started before!
I would also code a "/wait" which on loading app if it finds that flag, waits for it maybe useful in use too.
You can set the server project as the single startup project and use this macro to launch the server and the client with a delay:
Sub DebugServerAndClientWithDelay()
DTE.Debugger.Go(False)
System.Threading.Thread.Sleep(2000)
DTE.Windows.Item(Constants.vsWindowKindSolutionExplorer).Activate()
DTE.ActiveWindow.Object.GetItem("SolutionName\ClientProjectName").Select(vsUISelectionType.vsUISelectionTypeSelect)
DTE.ExecuteCommand("ClassViewContextMenus.ClassViewProject.Debug.Startnewinstance")
End Sub
You can add a button to your toolbar or use a shortcut key to run this macro.
Just add a procedure to check whether the socket is open or not. If the socket is open continue executing your code and try checking again if the socket is not open. This way even if you start the windows service later there will be no problem.
For the n-tier application I am currently working on, I combined the Mutex method suggested by Romil (slightly different code but same principle) and encapsulated it within a method with a [Conditional("DEBUG")] attribute applied (so it gets stripped out in release mode). We also surround the mutex logic with if (System.Diagnostics.Debugger.IsAttached) {...} since QA builds use Debug mode.
We originally just used a Thread.Sleep with a wait period that worked for most developers machines, but we ran into problems because devs' computer speeds vary and as we added more and more to the server bootstrapper, we had to keep increasing the wait period.
Why don't you just pass an argument to the client application which sets the delay?
static void main(string[] args)
{
// Sleep some time
int delay;
if (args.Length > 0 && int.TryParse(args, out delay))
{
Thread.Sleep(delay);
}
// Initialize client
}
Now you can add the delay in milliseconds to the command-line arguments for the project startup.
I also agree that if possible, it's better to solve your problem structurally, so it doesn't matter when your client and server start.

Windows Services - operating system is shutting down too quickly

Firstly I would like to apologize for my English language. I try to create a Windows Service which run program for BuckUp data when the computer is shutting down.
Problem is that the operating system during shutdown to kill my Windows Service before BackUp data is executed by to the end of. I changed the registry value HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\WaitToKillServiceTimeout to 3600000 but it didn't help, my Windows Service is killed before it is executed. Maybe someone knows how to make the operating system does't kill the Windows Service as quickly to BackUp data could be made. Please help me, I'm waiting for your response. Below I include my code Windows Service:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.IO;
namespace backUp_ser
{
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
this.CanShutdown = true;
}
protected override void OnStart(string[] args)
{
}
protected override void OnStop()
{
}
protected override void OnShutdown()
{
ProcessStartInfo stratInfo = new ProcessStartInfo();
stratInfo.WindowStyle = ProcessWindowStyle.Hidden;
stratInfo.FileName = "C:\\Program Files\\Cobian Backup 10\\Cobian.exe";
stratInfo.Arguments = "list:C:\\Program Files\\Cobian Backup 10\\DB\\MainList.lst -bu -nogui -autoclose";
Process process = Process.Start(stratInfo);
process.WaitForExit(360000);
}
}
}
Apart from your query, I want to remind you that the services are running in a separate logon session and the services won't interact with the logged in desktop session (mostly).
So, you need to intercept the shutdown event in your service code. Then, you need to hold the shutdown event till you complete your backup process. You can hook those Windows events through message pumps/queues. You need to intercept the WM_ENDSESSION/ WM_QUERYENDSESSION events.
This query is already discussed in this post. You can refer that.

Windows Shell Integration with multiple files

I'm making a program that is using Windows Shell Integration, and the registry changes I do are these:
For example, for .txt, I see that the value for HKEY_CLASSES_ROOT\.txt > (Default) is txtfile. I add to HKEY_CLASSES_ROOT\txtfile\shell the key myprogram > (Default) with the value Open with MYPROGRAM. to myprogram I add command > (Default) with the value *path-to-my-program* %1. Now when I right click a .txt file there is an option to open it with my program.
But when I do that with multiple .txt files Windows opens my program many times with each time another file as argument. But I want to open my program one time with all the files as many arguments. Is there an option to do that with changing stuff in registry?
If not, I also could not find a way to make a program that can be opened multiple times and combine all of them to one, so I can also do it that way if someone can help me with it. I'm making this program with C#, by the way.
You have to make your application "Single Instance".
Something like this should do the trick:
(untested code, just for reference)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
namespace YourApp
{
class Program
{
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
[STAThread]
static void Main()
{
bool createdNew = true;
using (Mutex mutex = new Mutex(true, "MyApplicationName", out createdNew))
{
if (createdNew)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Form1 frm = new Form1();
frm.SetNewData("send command line here");
Application.Run(frm);
}
else
{
Process current = Process.GetCurrentProcess();
foreach (Process process in Process.GetProcessesByName(current.ProcessName))
{
if (process.Id != current.Id)
{
SetForegroundWindow(process.MainWindowHandle);
// send message to that form or use .Net remoting
break;
}
}
}
}
}
}
}
For a better example see this CodeProject solution.
The standard way to handle this is to use a mutex to ensure that only a single instance of your program runs. Then when the shell attempts to start up a new instance to open each file, the new instance simply passes the message on to the already running instance and lets it open the file.
One possible option is to check if another instance of your program is already running. If so, you pass the file path to that instance to open. For program inter-communication you can use whatever you like, e.g.: .NET remoting, named pipes, DDE, custom window messages, etc..
That's the default. you have told the shell that when clicking 'open with MYPROGRAM' invoke application %1 for each file that is selected.
The simplest way to fix this is to make your application single instance, and to send messages to the instance that is already running when another file is selected. This way one instance of your application is launched to open one file and it receives a request to open each of the other files. This is how it is generally accomplished using C++
if you look at the Developer Documentation there is also the recommendation to use DDE. I don't know how accessible DDE is from within C#, and it's use is deprecated.

Categories

Resources