My code is listed below. When I click the button, it's supposed to look at the service and then determine what it needs to do. However, when it gets the part to check if it is stopped, it's getting an error because its trying to start it, even though it is already started. I don't know why its trying to start the service even though it should be returning a false for stopped.
Any Help would be appreciated.
Dim sc As New System.ServiceProcess.ServiceController("LPT:One Job Queue Engine")
'This sets the Machine Name/IP Address
'Removed machine name.
sc.MachineName = "**********"
'This tells the service to stop
If sc.Status = ServiceProcess.ServiceControllerStatus.Running Then
sc.Stop()
'This tells the program to wait until the service is stopped
sc.WaitForStatus(ServiceProcess.ServiceControllerStatus.Stopped)
'This starts the service once it has stopped
sc.Start()
End If
'Here is where the problem is!
**If sc.Status.Equals(System.ServiceProcess.ServiceControllerStatus.Stopped) Then
sc.Start()
End If**
If sc.Status = ServiceProcess.ServiceControllerStatus.StopPending Then
sc.ExecuteCommand("taskkill /F /IM lptjqe.exe")
sc.Start()
End If
Well, here is what I did to fix the issue.
Instead of having two different if statements, I combined it into one.
If sc.Status = ServiceProcess.ServiceControllerStatus.Running Then
sc.Stop()
'This tells the program to wait until the service is stopped
sc.WaitForStatus(ServiceProcess.ServiceControllerStatus.Stopped)
'This starts the service once it has stopped
sc.Start()
ElseIf sc.Status = System.ServiceProcess.ServiceControllerStatus.Stopped Then
sc.Start()
End If
Enjoy!
Related
Hi there I have piece of legacy (VS2010) Windows Service code that I have imported into VS2017 and is causing me severe frustration. This code has worked well for about the last 6 years, however when I carry out the install and attempt to start the service the SCM comes back with a timeout error. The OnStart code is as follows:
Protected Overrides Sub OnStart(ByVal args() As String)
'Instaniate the timer for the service
_serviceTimer = New Threading.Timer(New Threading.TimerCallback(AddressOf Tick), Nothing, 60000, 60000)
End Sub
The call back is:
Private Sub Tick(ByVal state As Object)
'Switch off the timer event whilst the code executes
_serviceTimer.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite)
If Not _started Then
Startup()
_started = True
End If
Call ServerProcess()
'Re-enable the timer now that application code has completed
_serviceTimer.Change(_longInterval, _longInterval)
End Sub
I originally had the Startup process in the OnStart method, however removed it as an attempt at resolving this issue, however it has not made any difference. Method Startup is as follows:
Public Sub Startup()
Try
'Source these settings from the local config file
_appDataFolder = Utilities.GetSetting("AppDataRoot")
_configPathMapped = _appDataFolder & Utilities.GetSetting("ConfigPathMapped")
_logPath = _appDataFolder & "\" & utl.GetSetting("LogPath")
'Instaniate the timer for the service - Commented out after moving startup code from OnStart method
' _serviceTimer = New Threading.Timer(New Threading.TimerCallback(AddressOf Tick), Nothing, Timeout.Infinite, Timeout.Infinite)
'Initialise logging architecture
_logger = New aslLog.Logger(_configPathMapped & "nlog.config", _logPath, My.Application.Info.ProductName, My.Application.Info.Version.ToString)
_logger.SendLog("Started PSALERTS Schedule Server Service", NLog.LogLevel.Info, _serviceTimer, _checkInterval, Nothing)
'Determine if the cloned config files exists in the mapped config file folder
'We clone these files to a writable destination to allow us to overcome write restrictions ot the C: drive on the SPEN PTI Desktop model
If Not System.IO.File.Exists(_configPathMapped & "psaservermachine.config") Then
'Clone the app.config file in the config folder as psaservermachine.config
Utilities.CloneFile(_programFileLocation & "PSALERTSScheduleServer.exe.config", _configPathMapped & "psaservermachine.config")
End If
If Not System.IO.File.Exists(_configPathMapped & "nlog.config") Then
'Clone the nlog.config file
Utilities.CloneFile(_programFileLocation & "PSALERTSScheduleServer.exe.config", _configPathMapped & "nlog.config")
End If
'Determine the Oracle TNS Environment
'Check for the existence of the environment variable 'TNS_ADMIN'
If Environment.GetEnvironmentVariable("TNS_ADMIN") IsNot Nothing Then
'If TNS_ADMIN exists then we can continue with the application session
Else
Dim oraTnsPath As String = ""
'If it doesn't exist then we need to determine the Oracle information from the PATH environment variable
oraTnsPath = GetOraTnsPath()
If oraTnsPath <> "" Then
'Then create the TNS_ADMIN environment variable
Environment.SetEnvironmentVariable("TNS_ADMIN", oraTnsPath)
Else
'If no oracle client information exists then raise an error to this effect and exit the app
'informing the user that they need to install the Oracle client in order to use PSALERTS
Beep()
Throw New PSALERTSOracleConfigException(
"PSALERTS Oracle Configuration Error. PSALERTS Did not find a valid Oracle Client." & vbCrLf & vbCrLf &
"Please install a valid Oracle Client and try again." & vbCrLf & vbCrLf &
"If a valid Oracle Client is installed then ensure that the PATH environment variable contains an entry for the Oracle Client." & vbCrLf & vbCrLf &
"For example - TNS_ADMIN=C:\oracle\12.1.0\Client_lite\NETWORK\ADMIN"
)
End If
End If
'Register the application
If Not Registered() Then
'Register the application
Register()
End If
If Registered() Then
'Clean/close any stray Excel processes from previous debug session
If _debugModeOn Then
CleanUpRedundantProcesses("EXCEL", "PSALERTS")
End If
'instantiate fresh excel session
_myXLApp = New Excel.Application
'Get the timer interval settings
_longInterval = CType(utl.GetSettingServerMachine(_configPath, "appSettings", "LongIntervalMillis"), Integer)
_initInterval = CType(utl.GetSettingServerMachine(_configPath, "appSettings", "InitialIntervalMillis"), Integer)
_refreshInterval = CType(utl.GetSettingServerMachine(_configPath, "appSettings", "InitialIntervalMillis"), Integer)
'Re-start the timer with periodic signalling as per the specified check interval
_serviceTimer.Change(_initInterval, _initInterval)
Else
_started = False
End If
Catch ex As Exception
_logger.SendLog("PSALERTS Schedule Server startup failure.", NLog.LogLevel.Error, ex)
Finally
End Try
End Sub
I use a similar technique for a number of similar services and they are running fine. Would appreciate some insight from any Windows Service gurus out there. Oh, I use WiX to carry out the install, again this is a well worn template for a number of similar such applications.
Kind Regards
Paul J.
Core: The very most typical errors:
Config problems: connection strings, faulty paths, etc...
Boot startup problem (good list - from FAQ)
Wrong password / login account when running as a real user with password.
Files missing or runtimes missing.
Permission problems (ACL / NT Privilege missing).
Maybe check this answer before the below.
UPDATE: Maybe have a look at this previous answer. Service startup timing issue. Also check my ad-hoc answer there in the same page.
Debugger: Other than that - nothing like stepping through the code with a debugger. I haven't done that in a long time. Deploy debug binaries and try? Windows 10 now hides messages from services - not sure how that affects debuggers: No more switching to Session 0.
I am not a service guru, but a deployment specialist. I'll just provide some links and see if that helps. Maybe I have not fully understood the whole problem. I tend to focus on the deployment side and not so much development side.
Ideas List / Debugging Check List: These are "ideas lists" for what could be wrong for applications in general - not just services (two first lists are similar - created some time apart):
Crash on launch
Desktop application won't launch
General purpose WiX / MSI links
Yes, these lists are very generic - too large to digest. Just skim the first two I think.
Debugging Tools: Also a reminder of the most useful service debugging tools: Event Viewer, Task Manager, Services.msc, Process Explorer (system internals), The NET command and SC.exe.
Good Service FAQ: https://www.coretechnologies.com/WindowsServices/FAQ.html
Your startup method should fire up a background worker and quickly return to the SCM that it has started. There is a system wide default setting of 30 seconds but honestly a proper service should respond in a few seconds.
Looking though your code, your connection to the database is probably the long pole causing the problem.
I searched many times in this topic but with no luck, I have an application on WPF that use Click Once to published and there fore I can't use Admin Privilege, and I need to implement some actions in the installation Process like restart SQL server for example and for that I need Admin Privilege and since i start publishing using click once I had to remove Admin Privilege now, i tried restart my application to force Admin rights using the following code but didn't work
Public Function IsRunAsAdmin() As Boolean
Try
Dim id As WindowsIdentity = WindowsIdentity.GetCurrent()
Dim principal As WindowsPrincipal = New WindowsPrincipal(id)
Return principal.IsInRole(WindowsBuiltInRole.Administrator)
Catch __unusedException1__ As Exception
Return False
End Try
End Function
Public Sub AdminRelauncher()
If Not IsRunAsAdmin() Then
Dim proc As ProcessStartInfo = New ProcessStartInfo()
Dim procExecuting As New Process
proc.UseShellExecute = True
proc.WorkingDirectory = Environment.CurrentDirectory
proc.FileName = Assembly.GetEntryAssembly().CodeBase
proc.Verb = "runas"
Try
procExecuting = Process.Start(proc)
Application.ExitThread()
Application.Exit()
Catch ex As Exception
Console.WriteLine("This program must be run as an administrator! " & vbLf & vbLf & ex.ToString())
End Try
End If
End Sub
I still get the Error "Can not open MSSQL$****** on computer" after i searched of course i found the cause is admin rights needed.
So now i'm working on Code Signing Certificates as some one advise me that this will work for me.
but i'm an individual and my application price is not high enough to buy a paid certificate so i was wondering if i can make a self Code Signing Certificate and use it with click once.
Thank you.
I finally manged to figure out the problem my self, it was the admin rights.
The problem was that the code simply need like 2-3 mile seconds to execute so when i tracked the code i found that my code manged to stop the service indeed but wasn't able to start it again as it didn't take the time for the service to fully stop.
The solution was simple as it just needed couple of seconds to after it execute the code to stop the service.
So simply need to add a code in between.
First
Imports System.Threading
Then use the code as following
Dim service As ServiceController = New ServiceController("SQL Server (SQLEXPRESS)")
service.Stop()
Thread.Sleep(10000)
service.Start()
You see the code where Thread.sleep is make the application wait 10 seconds before it complete to execute the code.
This time is depends on the machine it self, 2-3 sec was enough but some other machine needed more time so to be in the safe side just add more seconds as I did.
Thank you, and "Stay Safe".
Recently I've created a windows service which can help to trace the process start time and exit time, but I found that whenever the addhandler [process].exited executed, the windows service will stop
Here are my codes for the handler
For Each chrome_p As Process In NewChromeProccess
chrome_p.EnableRaisingEvents = True
AddHandler chrome_p.Exited,
Sub()
Using sw As StreamWriter = New StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "\MonitoringApplication.txt", True)
ChromeEndTime.Add(chrome_p.ExitTime)
sw.WriteLine($"Process: {chrome_p.ProcessName}, Exit Time: {chrome_p.ExitTime}")
End Using
End Sub
Next
The description for Event ID 0 from source Service1 cannot be found. Either the component that raises this event is not installed on your local computer or the installation is corrupted. You can install or repair the component on the local computer.
If the event originated on another computer, the display information had to be saved with the event.
The following information was included with the event:
Service cannot be started. An instance of the service is already running
After some investigation I think the problem you are encountering is due to the line
sw.WriteLine($"Process: {chrome_p.ProcessName}, Exit Time: {chrome_p.ExitTime}")
And, specifically, the chrome_p.ProcessName part. When I had the line as you wrote it above, I was getting the error message: Process has exited, so the requested information is not available. Switching that out with a string constant, I get the line Process: chrome_p.ProcessName, Exit Time: 5/2/2019 8:05:46 PM in the text log file.
It's works in my PC but when i put into another machine i got an error "source: system process has exited, so the requested information is not available" & the exe doesnt came out. Any experienced bro can help? Appreciated!
p = New Process
With p
.EnableRaisingEvents = True
.StartInfo.FileName = Application.StartupPath & "\EXE\CDMObjectSelection\CDMObjectSelection.exe"
.StartInfo.Arguments = strArgs
.StartInfo.ErrorDialog = True
.StartInfo.WindowStyle = ProcessWindowStyle.Normal
.StartInfo.UseShellExecute = True
.Start()
End With
p.WaitForInputIdle()
While (ginthwnd = IntPtr.Zero)
System.Threading.Thread.Sleep(100)
p.Refresh()
ginthwnd = p.MainWindowHandle
End While
If you follow this code in a debugger or wrap it in a try/catch block you'll probably find that the exception happens on the line p.WaitForInputIdle(). As MSDN states: this exception is thrown when the process has already exited. Try wrapping your call in a try/catch and dealing with the InvalidOperationException.
MSDN also says "If a process does not have a message loop, WaitForInputIdle throws an InvalidOperationException". Make sure the process you're calling has a message loop.
See this answer for how to properly shut down your process.
Make sure you build your application on the right architecture.
For example, if you build your app as 64bit application and running on a 32bit operation system, you'll get this error. If you can, build your application as both 32bit and 64bit (Any CPU) and you won't need to worry about it.
I am trying to reset IIS on a set of servers all at one time instead of looping through and resetting each one individually, but I can't seem to figure out how to do it. Could someone please give me an example? Thank you
I am using System.Diagnostics
With m_Process.StartInfo
.FileName = strFileName
.Arguments = String.Format("{0}{1}", server, strArguements)
.UseShellExecute = False
.CreateNoWindow = True
.RedirectStandardError = True
.RedirectStandardOutput = True
End With
I've seen a few questions today with similar conditions ("instead of looping") and I've been trying to figure out what the big deal is about looping. Since iisreset (what I am guessing is assigned to strFileName in your example) takes a single machine name, you are out of luck in that department.
I would assume that iisreset connects to the SCM on the target server and does a restart of the IIS Admin and dependent services.
I suppose you could roll your own iisreset.exe that took multiple servers on the command line, but internal to that you would have to use some kind of iteration.
Could you maybe explain why you can't or don't want to loop?
At some level you have to loop over the list of servers and send some message to each to instruct them to reset. Whether you do that by running iisreset with each server name or by some other means, you can't really make the loop go away.
However, if you're just saying that you want to start resetting all the servers as fast as possible rather than waiting for the first to finish resetting before you start resetting the second, it looks like you already have that. When you call m_Process.Start(), it should return as soon as the new iisreset process has started. As far as I can see, it doesn't block and wait until iisreset exits. Therefore, your iisreset processes should already run in parallel.
If I understand what you're asking, you're okay looping throught he servers, but you just don't want to wait for each server to complete before proceeding to the next one. Since ProcessStartInfo doesn't allow any way to detach from a process you're starting (be nice if it did), you can do it like this (obviously, missing your parameters and such):
Imports System.Threading
Class Restarter
Sub Main()
Dim ServerList As New List(Of String)
For Each server As String In ServerList
ThreadPool.QueueUserWorkItem(AddressOf RestartServer, server)
Next
End Sub
Sub RestartServer(ByVal Server As String)
Dim m_Process As System.Diagnostics.Process
With m_Process.StartInfo
.FileName = strFileName
.Arguments = String.Format("{0}{1}", Server, strArguements)
.UseShellExecute = False
.CreateNoWindow = True
.RedirectStandardError = True
.RedirectStandardOutput = True
End With
m_Process.Start()
End Sub
End Class