Using Self Code Signing Certificates for Publish purpose - vb.net

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".

Related

Weird Issue With Windows Service - Service Timing Out

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.

VB.Net - Elevate Privileges

How can I elevate my program on demand? (For example when clicking a button).
I don't like to set the privileges in the manifests file, I am talking about
elevating my VB.Net program at runtime.
Does anyone know how to do this?
I appreciate every helpful answer :)
You can't elevate your program on demand as such. Your options are:
Restart your application using the RunAs verb (see start batch file from within vb.net as admin)
Start your application with the required privileges in the first place
Okay, using the RunAs-Method to elevate it. (This requires a restart tho)
Private Sub RestartElevated()
Dim startInfo As New ProcessStartInfo()
startInfo.UseShellExecute = True
startInfo.WorkingDirectory = Environment.CurrentDirectory
startInfo.FileName = Application.ExecutablePath
startInfo.Verb = "runas"
Try
Dim p As Process = Process.Start(startInfo)
Catch ex As System.ComponentModel.Win32Exception
Return
End Try
Application.[Exit]()
End Sub

An issue with reading DB when program runs at startup in vb.net

I'm new here and to vb.net and I'm stuck on something that I feel SHOULD be simple to resolve. I setup my program to let the user decide if he or she wants to have the program run at windows start. It actually works fine as it is assigning the registry value to CurrentUser instead of Local Machine because of admin rights needing to be bypassed. However, when I restart my computer the program comes up like normal, but it will not read my access db that is located in the same folder as the program; it tries to read the DB from Windows\System32.
Is there a way to force it to read from the executablepath instead of System32?
Here is my simple code:
Private Sub startup()
If cbStartup.Checked = True Then
My.Computer.Registry.CurrentUser.OpenSubKey("Software").OpenSubKey("Microsoft").OpenSubKey("Windows").OpenSubKey("CurrentVersion").OpenSubKey("Run", True).SetValue("CC_List", System.Windows.Forms.Application.ExecutablePath)
ElseIf cbStartup.Checked = False Then
My.Computer.Registry.CurrentUser.OpenSubKey("Software").OpenSubKey("Microsoft").OpenSubKey("Windows").OpenSubKey("CurrentVersion").OpenSubKey("Run", True).DeleteValue("CC_List", False)
End If
End Sub
So when the O/S starts your program the Current Directory is %windir%\System32.
You need to either adjust all your existing paths to be explicitly relative to Application.ExecutablePath, or put
My.Computer.FileSystem.CurrentDirectory = My.Application.Info.DirectoryPath
at the start of your program (which is the modern version of ChDir ...).

Unable to execute SQL command in windows service

I'm working on creating a windows service that will send emails to a customer when they are within a month of having their submission expire. I'm using vb.net in Visual Studios 2008
Because it's a windows service it's very difficult to debug. Trying to narrow down my error I created a "sendDebugEmail" method that sends me an email if it gets to a certain line. The emails never make it past "dr = cmd.ExecuteReader()"
I'm wondering what I am doing wrong. My SQL statement should work fine. I've tested it in my SQL server database.
I've created a dummy_database that I just made in sql server as well. I added an INSERT sql statement for the dummy table i have in there just to see if i could actually access a database. All the table takes in is the line number and time it was sent. When I run my windows service that database updates just fine.
Any help would be appreciated. Thanks
Dim conn As New SqlConnection(connString2)
sendDebugEmail("134")
SQL = "Select email FROM _Customer WHERE custID in (SELECT custID FROM _OnlineCustomer WHERE ExpirationDate <= '6-20-12' AND ExpirationDate >= '6-10-12')"
Dim cmd As New SqlCommand(SQL, conn)
sSubject = "hello"
sBody = "This is test data"
Dim dr As SqlDataReader
sendDebugEmail("143")
Try
dr = cmd.ExecuteReader() // This is were it stops
sendDebugEmail("147")
While dr.Read
sendDebugEmail("152")
Try
LogInfo("Service woke up")
Dim i As Integer = 0
' Prepare e-mail fields
sFrom = "test#gmail.com"
sTo = "test1#gmail.com"
sCc = "test2#gmail.com"
Dim oMailMsg As MailMessage = New MailMessage
oMailMsg.From = sFrom
oMailMsg.To = sTo
oMailMsg.Cc = sCc
' Call a stored procedure to process the current item
' The success message
oMailMsg.Subject = sSubject + "(Success)"
oMailMsg.Body = sBody + "Email has been sent successfully."
' Send the message
If Not (oMailMsg.To = String.Empty) Then
SmtpMail.Send(oMailMsg)
End If
Catch obug As Exception
LogEvent(obug.Message)
Finally
End Try
End While
Catch ex As Exception
Finally
dr.Close()
cmd.Dispose()
conn.Close()
conn.Dispose()
End Try
End Sub
/////////////////////////////////////////////////////////////////////////////////
Problem Solved: I set up my connection but I never opened it.
I needed conn.open()
The thing that helped me most was adding this code into my last catch statement:
sendDebugEmail(ex.Message & vbcrlf & ex.stackTrace)
It send me an email of the stackTrace and made it very easy to debug
Are you trapping and swallowing exceptions? If you are, stop. Let exceptions service crash the service: the exception will be logged in the Event log. The only exceptions you should trap are those you can actually recover from (though its valid to catch the exception, log it and rethrow it via throw;).
Have you instrumented your code with log4net (http://logging.apache.org/log4net/), or something similar? You should be, especially for a daemon like a Windows service — how else are you (or operations) going to diagnose problems with the service when the occur (as they will).
Edited to note:
You should be using using statements: all those ADO.Net objects are IDisposable. It makes for cleaner code.
Consider using a SqlDataAdapter to fill a DataTable or DataSet with your results set. The pattern you're using:
read a row from SQL
while read was successful
send an email
read a row from SQL
will ultimately lead to blocking in your database. Talking to a mail server has the potential for a high latency. If the mail server doesn't answer, or you have network congestion, or any of a number of other reasons, you're going to be left hanging until the mail is sent or an exception is thrown due to timeout. And your SQL Query is going to be sitting there with read locks on the table and indices from which you're reading data, blocking people attempting to do updates, inserts or deletes. Your production DBAs will be...vexed. You want to keep your locks moving and get the locks released as quick as you can.
If you are sure about your code (with no exceptions) i think you should check the authentication you are using to connect the SQL server(inside the connection string within the app.config file/inline code of the windows service).
If you are using SQL authentication for this (check the connection string for user name sa and its password) setting the account type of the windows service to LocalService will help you.
If the SQL connection is using windows authentication then setting the account type of the windows service to LocalSystem will help you.
The Account type modification can be done after installation also. For this go to Control panel->Administrative tools->Services->YourService right click and select Propertes->Logon and perform it there. If you are selecting the LocalSystem (windows authentication) you will be asked to enter the login credentials of the account in which the service is running.
In the case of windows authentication in SQL connection the credentials of the account in which the service is running will be taken for SQL connectivity also.
Hope this helps ...
One more suggestion put a sleep statement on your process when it starts so oyu have time to attach to it
Problem Solved: I set up my connection but I never opened it.
I needed conn.open()
The thing that helped me most was adding this code into my last catch statement:
sendDebugEmail(ex.Message & vbcrlf & ex.stackTrace)
It send me an email of the stackTrace and made it very easy to debug

Reset IIS on multiple servers at once instead of looping through

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