Question Help with duplicate code

colins5286

Member
Joined
Nov 8, 2018
Messages
12
Programming Experience
Beginner
I have written some code with alters the power settings on Windows computers. I am no software dev, but I suspect there is a better way of coding than what I have written. Basically the code is duplicated 6 times to run each alteration to the system. I am sure there must be a way to write one block of code and just pass the amended parameters to it 6 times...

I have copied the first two sections, but it repeats a further 4 times, just with different arguments.

Duplicate Code:
using System.Diagnostics;

namespace VolatileDataCapture.Services
{
    class PowerControlService
    {
        public void ChangePowerSettings()
        {
            ChangeStandbyTimeAC();
            ChangeStandbyTimeDC();
            ChangeHibernateTimeAC();
            ChangeHibernateTimeDC();
            ChangeMonitorTimeAC();
            ChangeMonitorTimeDC();
        }
        private void ChangeStandbyTimeAC()
        {
            using (var cmdPwrCfg = new Process())
            {
                cmdPwrCfg.StartInfo.FileName = "powercfg";
                cmdPwrCfg.StartInfo.UseShellExecute = false;
                cmdPwrCfg.StartInfo.CreateNoWindow = true;
                cmdPwrCfg.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                cmdPwrCfg.StartInfo.Arguments = "-change -standby-timeout-ac 0";
                cmdPwrCfg.StartInfo.RedirectStandardOutput = true;
                cmdPwrCfg.Start();
            }
        }
        private void ChangeStandbyTimeDC()
        {
            using (var cmdPwrCfg = new Process())
            {
                cmdPwrCfg.StartInfo.FileName = "powercfg";
                cmdPwrCfg.StartInfo.UseShellExecute = false;
                cmdPwrCfg.StartInfo.CreateNoWindow = true;
                cmdPwrCfg.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                cmdPwrCfg.StartInfo.Arguments = "-change -standby-timeout-dc 0";
                cmdPwrCfg.StartInfo.RedirectStandardOutput = true;
                cmdPwrCfg.Start();
            }
        }
 
The only difference in those methods is a string value, so you can add a string parameter to a method for that value to be passed in. Passing Parameters - C# Programming Guide | Microsoft Docs

Quick tip, if you change the string assignment to a new variable name you can use the quick actions menu to let it generate the parameter for you:

1572529614475.png
 
Last edited:
I have written some code with alters the power settings on Windows computers. I am no software dev, but I suspect there is a better way of coding than what I have written. Basically the code is duplicated 6 times to run each alteration to the system. I am sure there must be a way to write one block of code and just pass the amended parameters to it 6 times...

I have copied the first two sections, but it repeats a further 4 times, just with different arguments.
Welcome to refactoring, if you see that two or more routines are pretty close in code what do you think you would need to do to make it so it's 1 call with parameter(s)?
Look at the two you've provided here already, what do you think the parameter(s) should be to make them be identical calls?
 
It seems to me that with all those settings, you are just trying to prevent the screensaver from kicking in, and letting the machine go to sleep. There is a more efficient way to prevent this from happening. Use SetThreadExecutionState(). This is the same API that PowerPoint and various media players use to prevent the screensaver from kicking in, or from letting the machine go to sleep.

See ThreadExecutionState.cs and NativeMethods.cs from my Awake repo.
 
Last edited:
It seems to me that with all those settings, you are just trying to prevent the screensaver from kicking in, and letting the machine go to sleep. There is a more efficient way to prevent this from happening. Use SetThreadExecutionState(). This is the same API that PowerPoint and various media players use to prevent the screensaver from kicking in, or from letting the machine go to sleep.

See ThreadExecutionState.cs and NativeMethods.cs from my Awake repo.
I doubt he's changing the Power Options settings in Windows just for his app. I think he's putting together an app to change these settings in a more automated manor, this is actually something I do every time I install Windows (XP and newer) too.

I've always known you can change stuff like this in code instead of opening the Control Panel and clicking everywhere to change it all so I might grab this code as a starting point for making my own script I can run after each clean install.
 
If this is for changing a machine image, then just change the image once and deploy. If this is for existing environment of already deployed machines, then use a group policy. Based on the OP's other thread about dumping the registry, though, it looks like the OP needs this as another aspect of his pre and post installation testing of some product/software.

Anyway, the better way to change all those power settings through code is to call the Power Management API's directly instead of firing off a process. That or just use a batch file.
 
Right now, y'all are all summarising what you think the code is for, instead of asking the OP what he is actually trying to accomplish with the code they have.

Of course most of us know that there are better ways to achieve certain things, but unless we actually know what the OP is trying to do, then it's rather pointless pondering between each other what the code should do. Don't you think its better to just ask for clarity?

@colins5286 Can you explain what you're trying to do? What is your code meant to do and why?

Answering those questions will help the guys give you a better clearer answer.
 
I have written a small utility that extracts various information from a computer. Some of the data collected requires third party applications to run, this can take time and in some instances the machine will go to sleep or the disks will spin down etc...
I used to use various batch files to extract the data and amend the power settings, but now I have bundled them all together in one small C# application.

I accept there will be much better ways to do what I want - but these commands are the only way I know, having copied them from my batch files. I have done a crash course in coding to get my application to the place it is currently.

I just need to alter the times on Disk/Screen/Standby/Hibernate to Never. So that all the other processes can then run without the worry of the machine going to sleep. There isn't the option to set a group policy as these are individual machines and sometimes the application isn't open, so the API for PowerPoint wouldn't be effective. I am willing to try another way if someone can explain it to me, but otherwise the only way I can be sure it does what I need it to programatically change the values of the above settings.
Thanks
 
Ok that's a little clearer, except you're not going about it the correct way. Where are you assigning/acquiring the GUIDS? Where are you acquiring the list of power options?

Your attempt to execute these parameters are incorrect from a coding perspective. Doing this through execution of processes is just the wrong approach in my opinion, and if you have done a crash course, then this documentation will be easy for you to understand - Powercfg command-line options. However, another way would be to use pinvoke and manipulate the Win32 API calls through powrprof.dll which you can prevent a shutdown, and hibernation. See pinvoke.net: Search Results. NOTE : You could also do this using powershell. Since I am on my way out the door, I'll need to get back to you with some examples at a later point, or maybe the guys be kind enough to help you from here. :cool:
 
Invoking dll's is a bit out of my depth. I've tested the current code and it alters the correct power settings on the active GUID.
I was just hoping to clean the code up a little and not call the same code (bar the arguments) 6 times.
 
OK - I have read through some online tutorials and messed around. Here is my updated code. It does what I want and only has one instance of the actual code to execute, it calls it 6 times and passes different parameters each time. Probably still a very ugle way of doing it, but it reduces the lines of code by a few hundred.

Refactored Code:
using System;
using System.Diagnostics;
using System.IO;


namespace VolatileDataCapture.Services
{
    class PowerControlService
    {
        public void RunPowerSettingChanges()
        {
            File.AppendAllText(GlobalVariables.logFile, Environment.NewLine + "Windows Power Settings Changed " + DateTime.Now);
            CurrentPowerSettings();
            ChangePowerSettings(powerArgs: "-change -standby-timeout-ac 0");
            ChangePowerSettings(powerArgs: "-change -standby-timeout-dc 0");
            ChangePowerSettings(powerArgs: "-change -hibernate-timeout-ac 0");
            ChangePowerSettings(powerArgs: "-change -hibernate-timeout-dc 0");
            ChangePowerSettings(powerArgs: "-change -monitor-timeout-ac 0");
            ChangePowerSettings(powerArgs: "-change -monitor-timeout-dc 0");
            ChangePowerSettings(powerArgs: "-change -disk-timeout-ac 0");
            ChangePowerSettings(powerArgs: "-change -disk-timeout-dc 0");
        }

        private void ChangePowerSettings(string powerArgs)
        {
            using (var cmdPwrCfg = new Process())
            {
                cmdPwrCfg.StartInfo.FileName = "powercfg";
                cmdPwrCfg.StartInfo.UseShellExecute = false;
                cmdPwrCfg.StartInfo.CreateNoWindow = true;
                cmdPwrCfg.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                cmdPwrCfg.StartInfo.Arguments = powerArgs;
                cmdPwrCfg.StartInfo.RedirectStandardOutput = true;
                cmdPwrCfg.Start();
            }
        }

        private void CurrentPowerSettings()
        {
            using (var cmdPwrCfg = new Process())
            {
                cmdPwrCfg.StartInfo.FileName = "powercfg";
                cmdPwrCfg.StartInfo.UseShellExecute = false;
                cmdPwrCfg.StartInfo.CreateNoWindow = true;
                cmdPwrCfg.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                cmdPwrCfg.StartInfo.Arguments = "-query";
                cmdPwrCfg.StartInfo.RedirectStandardOutput = true;
                cmdPwrCfg.Start();
                string powerOutput = cmdPwrCfg.StandardOutput.ReadToEnd();
                File.AppendAllText(GlobalVariables.powerLogFile, powerOutput);
            }
        }
    }
}
 
sometimes the application isn't open, so the API for PowerPoint wouldn't be effective
You don't need the application to be installed. You just need to be able to run your code, the same way you need your current code to be able to run. There is no requirement that PowerPoint be installed. That API that I gave you is built into the operating system. You simply need to P/Invoke it since it's an unmanaged API as opposed to something that is in the managed .NET Framework library.
 
You don't need the application to be installed. You just need to be able to run your code, the same way you need your current code to be able to run. There is no requirement that PowerPoint be installed. That API that I gave you is built into the operating system. You simply need to P/Invoke it since it's an unmanaged API as opposed to something that is in the managed .NET Framework library.

OK - So if I invoke the API, then quite my app - will it still keep the machine awake?
 
I'm not sure. I've always called it when I needed the machine awake while I was running my code. I've never tried calling the API and then quitting out of my code.

On the other hand, why would you need to quit out of your app? You said the point of your app was supposed to collect information:
I have written a small utility that extracts various information from a computer. Some of the data collected requires third party applications to run, this can take time and in some instances the machine will go to sleep or the disks will spin down etc...
Wouldn't your app need to be running to collect the information?
 
I'm not sure. I've always called it when I needed the machine awake while I was running my code. I've never tried calling the API and then quitting out of my code.

On the other hand, why would you need to quit out of your app? You said the point of your app was supposed to collect information:

Wouldn't your app need to be running to collect the information?

My app also calls other executables, it maybe that a user closes the app then comes back to it later. I need to cover all my bases.
 
Back
Top Bottom