I have implemented Stephany's suggestion, at least I think I have. :)
I now have a single process, Service A, and a "controller " executeable.
The controller code looks like this...
if (File.Exists(s_ downloadFile))
{
alterProcessSta tus("stop");
File.Replace(s_ downloadFile, s_installFile,
s_backupFile);
alterProcessSta tus("start");
}
Where alterProcessSta tus does...
ServiceControll er sc = new ServiceControll er("Service A");
sc.Refresh();
/** all my logic to handle stopping/starting the service
* depending on the process current state along with some
* sc.WaitForStatu s() just to make sure it works.
**/
Service A now handles downloading new copies of "itself" when updates
are ready. When an update is successfully downloaded I kick off a
System.Diagnost ic.Process.Star t(s_controllerP ath); and it does manage
to stop the service and replace the ServiceA.exe with the downloaded
version, however when starting the function I still get..
System.InvalidO perationExcepti on: Cannot start service Service A on
computer '.'. ---System.Componen tModel.Win32Exc eption: Access is
denied
--- End of inner exception stack trace ---
at System.ServiceP rocess.ServiceC ontroller.Start (String[] args)
at System.ServiceP rocess.ServiceC ontroller.Start ()
at Controller.Prog ram.alterProces sStatus(String arg)
at Controller.Prog ram.Main(String[] args)
Trying to use the Start in the Service Manager gives me the same Access
Denied, the event viewer said "The Service A service failed to start
due to the following error: Access is denied."
I created a rollback function in Controller and it is able to copy the
files back to how they were before the update and restart the process.
This got me thinking, it's obviously not the controllers fault since it
is able to manipulate the service and overwrite the files just fine. If
I manually put my downloaded file in the download location (instead of
letting the service download it) and then let the service run (it
doesn't download a new file if there is already a patch file waiting)
it is able to spawn the process to update itself just fine.
It would seem this is more about how the file is being delivered, not
how the update happens. So, maybe the way I go about downloading a new
file is the issue...
HttpWebRequest webrequest =
(HttpWebRequest )WebRequest.Cre ate(uri_newFile );
WebResponse wr_response = webrequest.GetR esponse();
StreamReader sr_response = new
StreamReader(wr _response.GetRe sponseStream()) ;
StreamWriter sw_out = new StreamWriter(ne w FileStream(s_do wnloadFile,
FileMode.Create ));
sw_out.Write(sr _response.ReadT oEnd());
wr_response.Clo se();
sr_response.Clo se();
sw_out.Close();
There is no difference byte wise between this code downloading a file
from my webserver and me placing the file directly in the
s_downloadFile location. This still leads me to believe it's all about
the permissions on the downloaded file. Anyone have any clues? What
tools are there to compare the permissions between two files on XP?
Stephany Young wrote:
If service B does nothing more than what you have said then I would suggest
that having that functionality as a seperate service is overkill.
A solid technique is to have service A monitor the need for an upgrade aand
download the upgraded executable as a temporary file. When it has completed
this step, have it use Process.Start to spawn a 'stub' program.
The stub program stops service A, replaces the executable with the
downloaded (upgraded) version and starts service A. Because the 'stub'
program is spawned by service A, it runs under thae same account
(LocalSystem) and so, for the short period of time involved, it needs to
impersonate an account with the necessary permissions.
This means that the 'stub' program only runs when it needs to and you don't
have the overhead of running a extra service.
The logic for the 'stub' program is relatively simple:
static void Main()
{
// Start impersonating a priviledged account
// Stop Service A
// Replace the executable for Service A
// Start Service A
// Cease impersonation
}
<ca****@carsone vans.comwrote in message
news:11******** *************@l 53g2000cwa.goog legroups.com...
I have written two windows services:
- service A does some crunching of local data files and uploads them to
a central processing computer via http.
- service B monitors a manifest file on a webserver to see if service A
needs to be updated.
What service B does if it sees their is an update for service A is to
download a new copy of the service A executable, stop service A,
replace the executable with the new copy, and start service B back up.
Everything works fine until that very last step. I can programatically
stop and start the service just fine, if the service A executable was
placed their manually. If service B downloads and replaces the service
A executable, it can't then restart service A. When starting service A
it dies with
System.InvalidO perationExcepti on: Cannot start service Service A on
computer '.'. ---System.Componen tModel.Win32Exc eption: Access is
denied
--- End of inner exception stack trace ---
at System.ServiceP rocess.ServiceC ontroller.Start (String[] args)
at System.ServiceP rocess.ServiceC ontroller.Start ()
at namespace.Servi ceB.t_update_El apsed(Object sender,
ElapsedEventArg s e)
I am assuming this is just a permissions issue somwhere. Service A and
Service B are both installed with ServiceProcessI nstaller.Accoun t =
ServiceAccount. LocalSystem and Username and Password = null;
Any thoughts? Thanks in advance for your help, i'm a general newb at
windows application development.