User Profile
AharonBensadoun
Copper Contributor
Joined Nov 01, 2021
User Widgets
Recent Discussions
How to add a timer to C# Service
Hi everyone I am new to coding in c # and trying to write a windows service in c #, my service seems to be working fine except for one thing: I try to make it run in a loop, say every 30 seconds, another program. But for the moment when I launch my service, it executes the program only once. My code: using System; using System.Runtime.InteropServices; using System.Diagnostics; // SET STATUS using System.ComponentModel;// SET STATUS using System.ServiceProcess; using System.Timers; //using System.ServiceProccess;// SET STATUS public enum ServiceType : int { // SET STATUS [ SERVICE_WIN32_OWN_PROCESS = 0x00000010, SERVICE_WIN32_SHARE_PROCESS = 0x00000020, }; // SET STATUS ] public enum ServiceState : int { // SET STATUS [ SERVICE_STOPPED = 0x00000001, SERVICE_START_PENDING = 0x00000002, SERVICE_STOP_PENDING = 0x00000003, SERVICE_RUNNING = 0x00000004, SERVICE_CONTINUE_PENDING = 0x00000005, SERVICE_PAUSE_PENDING = 0x00000006, SERVICE_PAUSED = 0x00000007, }; // SET STATUS ] [StructLayout(LayoutKind.Sequential)] // SET STATUS [ public struct ServiceStatus { public ServiceType dwServiceType; public ServiceState dwCurrentState; public int dwControlsAccepted; public int dwWin32ExitCode; public int dwServiceSpecificExitCode; public int dwCheckPoint; public int dwWaitHint; }; // SET STATUS ] public enum Win32Error : int { // WIN32 errors that we may need to use NO_ERROR = 0, ERROR_APP_INIT_FAILURE = 575, ERROR_FATAL_APP_EXIT = 713, ERROR_SERVICE_NOT_ACTIVE = 1062, ERROR_EXCEPTION_IN_SERVICE = 1064, ERROR_SERVICE_SPECIFIC_ERROR = 1066, ERROR_PROCESS_ABORTED = 1067, }; public class Service_PSTest : ServiceBase { // PSTest may begin with a digit; The class name must begin with a letter private System.Diagnostics.EventLog eventLog; // EVENT LOG private ServiceStatus serviceStatus; // SET STATUS public Service_PSTest() { ServiceName = "Test2"; CanStop = true; CanPauseAndContinue = false; AutoLog = true; eventLog = new System.Diagnostics.EventLog(); // EVENT LOG [ if (!System.Diagnostics.EventLog.SourceExists(ServiceName)) { System.Diagnostics.EventLog.CreateEventSource(ServiceName, "Application"); } eventLog.Source = ServiceName; eventLog.Log = "Application"; // EVENT LOG ] EventLog.WriteEntry(ServiceName, "Test2.exe Test2()"); // EVENT LOG } [DllImport("advapi32.dll", SetLastError = true)] // SET STATUS private static extern bool SetServiceStatus(IntPtr handle, ref ServiceStatus serviceStatus); protected override void OnStart(string[] args) { EventLog.WriteEntry(ServiceName, "Test2.exe OnStart() // Entry. Starting script 'c:\\temp\\Test.exe\\Test1.ps1' -SCMStart"); // EVENT LOG // Set the service state to Start Pending. // SET STATUS [ // Only useful if the startup time is long. Not really necessary here for a 2s startup time. serviceStatus.dwServiceType = ServiceType.SERVICE_WIN32_OWN_PROCESS; serviceStatus.dwCurrentState = ServiceState.SERVICE_START_PENDING; serviceStatus.dwWin32ExitCode = 0; serviceStatus.dwWaitHint = 2000; // It takes about 2 seconds to start PowerShell SetServiceStatus(ServiceHandle, ref serviceStatus); // SET STATUS ] // Start a child process with another copy of this script try { Process p = new Process(); // Redirect the output stream of the child process. p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.FileName = "PowerShell.exe"; p.StartInfo.Arguments = "-ExecutionPolicy Bypass -c & 'c:\\temp\\Test.exe\\Test1.ps1' -SCMStart"; // Works if path has spaces, but not if it contains ' quotes. p.Start(); // Read the output stream first and then wait. (To avoid deadlocks says Microsoft!) string output = p.StandardOutput.ReadToEnd(); // Wait for the completion of the script startup code, that launches the -Service instance p.WaitForExit(); if (p.ExitCode != 0) throw new Win32Exception((int)(Win32Error.ERROR_APP_INIT_FAILURE)); // Success. Set the service state to Running. // SET STATUS serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING; // SET STATUS } catch (Exception e) { EventLog.WriteEntry(ServiceName, "Test2.exe OnStart() // Failed to start 'c:\\temp\\Test.exe\\Test1.ps1' " + e.Message, EventLogEntryType.Error); // EVENT LOG // Change the service state back to Stopped. // SET STATUS [ serviceStatus.dwCurrentState = ServiceState.SERVICE_STOPPED; Win32Exception w32ex = e as Win32Exception; // Try getting the WIN32 error code if (w32ex == null) { // Not a Win32 exception, but maybe the inner one is... w32ex = e.InnerException as Win32Exception; } if (w32ex != null) { // Report the actual WIN32 error serviceStatus.dwWin32ExitCode = w32ex.NativeErrorCode; } else { // Make up a reasonable reason serviceStatus.dwWin32ExitCode = (int)(Win32Error.ERROR_APP_INIT_FAILURE); } // SET STATUS ] } finally { serviceStatus.dwWaitHint = 0; // SET STATUS SetServiceStatus(ServiceHandle, ref serviceStatus); // SET STATUS EventLog.WriteEntry(ServiceName, "Test2.exe OnStart() // Exit"); // EVENT LOG } } protected override void OnStop() { EventLog.WriteEntry(ServiceName, "Test2.exe OnStop() // Entry"); // EVENT LOG // Start a child process with another copy of ourselves try { Process p = new Process(); // Redirect the output stream of the child process. p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.FileName = "PowerShell.exe"; p.StartInfo.Arguments = "-ExecutionPolicy Bypass -c & 'c:\\temp\\Test.exe\\Test1.ps1' -SCMStop"; // Works if path has spaces, but not if it contains ' quotes. p.Start(); // Read the output stream first and then wait. (To avoid deadlocks says Microsoft!) string output = p.StandardOutput.ReadToEnd(); // Wait for the PowerShell script to be fully stopped. p.WaitForExit(); if (p.ExitCode != 0) throw new Win32Exception((int)(Win32Error.ERROR_APP_INIT_FAILURE)); // Success. Set the service state to Stopped. // SET STATUS serviceStatus.dwCurrentState = ServiceState.SERVICE_STOPPED; // SET STATUS } catch (Exception e) { EventLog.WriteEntry(ServiceName, "Test2.exe OnStop() // Failed to stop 'c:\\temp\\Test.exe\\Test1.ps1'. " + e.Message, EventLogEntryType.Error); // EVENT LOG // Change the service state back to Started. // SET STATUS [ serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING; Win32Exception w32ex = e as Win32Exception; // Try getting the WIN32 error code if (w32ex == null) { // Not a Win32 exception, but maybe the inner one is... w32ex = e.InnerException as Win32Exception; } if (w32ex != null) { // Report the actual WIN32 error serviceStatus.dwWin32ExitCode = w32ex.NativeErrorCode; } else { // Make up a reasonable reason serviceStatus.dwWin32ExitCode = (int)(Win32Error.ERROR_APP_INIT_FAILURE); } // SET STATUS ] } finally { serviceStatus.dwWaitHint = 0; // SET STATUS SetServiceStatus(ServiceHandle, ref serviceStatus); // SET STATUS EventLog.WriteEntry(ServiceName, "Test2.exe OnStop() // Exit"); // EVENT LOG } } public static void Main() { Timer timer = new Timer(); // name space(using System.Timers;) void OnElapsedTime(object source, ElapsedEventArgs e) { System.ServiceProcess.ServiceBase.Run(new Service_PSTest()); } timer.Elapsed += new ElapsedEventHandler(OnElapsedTime); timer.Interval = 5000; //number in milisecinds timer.Enabled = true; } } Help will be welcome16KViews0likes2CommentsRe: Disable \ Remove old computer accounts
dannytveria Ok , test it and let me know if this help: $Computers_For_Action = Search-ADAccount -AccountInactive -DateTime $InactiveDate -ComputersOnly -SearchBase "DC=staff ,DC=local" | Where-Object {($_.Enabled -eq $true) -and ($_.distinguishedname -notlike "*,OU=Servers,*") -and ($_.distinguishedname -notlike "*,OU=Test,*") -and ($_.distinguishedname -notlike "*,OU=IT,*") -and ($_.distinguishedname -notlike "*,OU=Laptops,*") -and ($_.distinguishedname -notlike "*,CN=Computers,*") -and ($_.distinguishedname -notlike "*,CN=Managed Service Accounts,*") }5.6KViews0likes1CommentRe: Creating Users with a CSV
Jord9857 Hi, Your script is correct but you are miss something: In your csv file you doesn't have DisplayName or SamAccountName value, so you can't check if user exist or not , see line 15 of your script: $ADUser = Get-AdUser -Filter {$displayname -eq $User.DisplayName} So you have the choice, or you adding this columns in the csv with the correct value or you check if user exist with other parameters, for example firstname or lastname combined together. Hope this help16KViews0likes6CommentsRe: Disable \ Remove old computer accounts
Hi, If you don't specify that you want to deactivate only the computers that are currently active, then the csv file will still contain the computers that have already been deactivated, so you must specify that you want to deactivate only the active computers with the filter ($ _. Enabled -eq $true)5.1KViews0likes5CommentsRe: Disable \ Remove old computer accounts
dannytveria When you use the command: Search-ADAccount -AccountInactive -DateTime $ InactiveDate -ComputersOnly This does not mean that the Enabled property is False, it only means that no one has logged in for a long time To have only the computers which are still activated add a filter to your command: $Computers_For_Action = Search-ADAccount -AccountInactive -DateTime $InactiveDate -ComputersOnly -SearchBase "DC=staff ,DC=local" | Where-Object {($_.Enabled -eq $true) -and ($_.distinguishedname -notlike "*,OU=Servers,*") -and ($_.distinguishedname -notlike "*,OU=Test,*") -and ($_.distinguishedname -notlike "*,OU=IT,*") -and ($_.distinguishedname -notlike "*,OU=Laptops,*") -and ($_.distinguishedname -notlike "*,CN=Computers,*") -and ($_.distinguishedname -notlike "*,CN=Managed Service Accounts,*") }5KViews0likes7Comments
Recent Blog Articles
No content to show