void updateHelper_PipeServerDisconnected(object sender, UpdateHelperData e) { // wyUpdate should only ever exit after success or failure // otherwise it is a premature exit (and needs to be treated as an error) if (UpdateStepOn == UpdateStepOn.Checking || UpdateStepOn == UpdateStepOn.DownloadingUpdate || UpdateStepOn == UpdateStepOn.ExtractingUpdate || e.UpdateStep == UpdateStep.RestartInfo) { if (e.UpdateStep == UpdateStep.RestartInfo) { if (ClosingAborted != null) { ClosingAborted(this, EventArgs.Empty); } ClosingForInstall = false; } // wyUpdate premature exit error UpdateStepFailed(UpdateStepOn, new FailArgs { wyUpdatePrematureExit = true, ErrorTitle = e.ExtraData[0], ErrorMessage = e.ExtraData[1] }); } }
void SafeProcessReceivedMessage(byte[] message) { // Cast the data to the type of object we sent: UpdateHelperData data = UpdateHelperData.FromByteArray(message); if (BufferResponse) { lock (receivedBuffer) { // only buffer important messages if (data.ResponseType != Response.Progress) { receivedBuffer.Add(data); } } // checks if we're still buffering responses, if so don't process it now if (BufferResponse) { return; } } ProcessReceivedMessage(data); }
void SendAsync(UpdateHelperData uhd) { lock (_lock) { if (isDisposed) { return; } // if currently working, add the new message to the stack if (bw != null) { sendBuffer.Push(uhd); } else { RecreateBackgroundWorker(); // process immediately UpdateStep = uhd.UpdateStep == UpdateStep.ForceRecheckForUpdate ? UpdateStep.CheckForUpdate : uhd.UpdateStep; // begin sending to the client bw.RunWorkerAsync(uhd); } } }
public void RestartInfo(string fileToExecute, string autoUpdateID, string argumentsForFiles, bool isAService) { lock (_lock) { if (isDisposed) { return; } UpdateHelperData uhd = new UpdateHelperData(UpdateStep.RestartInfo); uhd.ExtraData.Add(fileToExecute); uhd.ExtraDataIsRTF.Add(isAService); if (!string.IsNullOrEmpty(autoUpdateID)) { uhd.ExtraData.Add(autoUpdateID); uhd.ExtraDataIsRTF.Add(false); if (!string.IsNullOrEmpty(argumentsForFiles)) { uhd.ExtraData.Add(argumentsForFiles); uhd.ExtraDataIsRTF.Add(false); } } SendAsync(uhd); } }
bool StartClient() { if (string.IsNullOrEmpty(m_CompleteWULoc)) { throw new Exception("The wyUpdate executable path supplied is not valid. Make sure wyUpdate exists on disk."); } // get the unique pipe name (the last 246 chars of the complete path) string pipeName = UpdateHelperData.PipenameFromFilename(m_CompleteWULoc); // first try to connect to the pipe if (!pipeClient.Connected) { pipeClient.Connect(pipeName); } if (pipeClient.Connected) { // request the processId if (!RetrySend((new UpdateHelperData(UpdateAction.GetwyUpdateProcessID)).GetByteArray())) { throw new Exception("Failed to get the wyUpdate Process ID."); } return(true); } if (!File.Exists(m_CompleteWULoc)) { throw new Exception("The wyUpdate executable was not found: " + m_CompleteWULoc); } ClientProcess = new Process { StartInfo = { FileName = m_CompleteWULoc, // start the client in automatic update mode (a.k.a. wait mode) Arguments = "/autoupdate", WindowStyle = ProcessWindowStyle.Hidden } }; if (!string.IsNullOrEmpty(ExtraArguments)) { ClientProcess.StartInfo.Arguments += " " + ExtraArguments; } ClientProcess.Start(); TryToConnectToPipe(pipeName); return(pipeClient.Connected); }
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { lock (_lock) { if (isDisposed) { return; } bw.DoWork -= bw_DoWork; bw.RunWorkerCompleted -= bw_RunWorkerCompleted; bw.Dispose(); bw = null; // error occurs when a message fails to send or wyUpdate fails to start if (e.Error != null) { // if the process is running - try to kill it try { if (ClientProcess != null && !ClientProcess.HasExited) { ClientProcess.Kill(); } } catch { } // set the client process to null so it can be restarted // when the user retries. ClientProcess = null; // clear the to-send stack sendBuffer.Clear(); // inform the AutomaticUpdater that wyUpdate is no longer running if (PipeServerDisconnected != null) { PipeServerDisconnected(this, new UpdateHelperData(Response.Failed, UpdateStep, AUTranslation.C_PrematureExitTitle, e.Error.Message)); } } else { // process the next in stack if (sendBuffer.Count > 0) { RecreateBackgroundWorker(); UpdateHelperData uhd = sendBuffer.Pop(); UpdateStep = uhd.UpdateStep; // begin sending to the client bw.RunWorkerAsync(uhd); } } } }
void updateHelper_PipeServerDisconnected(object sender, UpdateHelperData e) { // wyUpdate should only ever exit after success or failure // otherwise it is a premature exit (and needs to be treated as an error) if (UpdateStepOn == UpdateStepOn.Checking || UpdateStepOn == UpdateStepOn.DownloadingUpdate || UpdateStepOn == UpdateStepOn.ExtractingUpdate) { // wyUpdate premature exit error UpdateStepFailed(UpdateStepOn, new FailArgs { wyUpdatePrematureExit = true, ErrorTitle = e.ExtraData[0], ErrorMessage = e.ExtraData[1] }); } }
void SendAsync(UpdateHelperData uhd) { // if currently working, add the new message to the stack if (bw.IsBusy) { sendBuffer.Push(uhd); } else { // process immediately UpdateStep = uhd.UpdateStep == UpdateStep.ForceRecheckForUpdate ? UpdateStep.CheckForUpdate : uhd.UpdateStep; // begin sending to the client bw.RunWorkerAsync(uhd); } }
void ProcessReceivedMessage(UpdateHelperData data) { if (data.Action == UpdateAction.GetwyUpdateProcessID) { ClientProcess = Process.GetProcessById(data.ProcessID); return; } if (data.Action == UpdateAction.NewWyUpdateProcess) { // disconnect from the existing pipeclient pipeClient.Disconnect(); CreateNewPipeClient(); try { ClientProcess = Process.GetProcessById(data.ProcessID); } catch (Exception) { // inform the AutomaticUpdater that wyUpdate is no longer running if (PipeServerDisconnected != null) { PipeServerDisconnected(this, new UpdateHelperData(Response.Failed, UpdateStep, AUTranslation.C_PrematureExitTitle, "Failed to connect to the new version of wyUpdate.exe")); } } TryToConnectToPipe(data.ExtraData[0]); // if the process is running - try to kill it if (!pipeClient.Connected) { // inform the AutomaticUpdater that wyUpdate is no longer running if (PipeServerDisconnected != null) { PipeServerDisconnected(this, new UpdateHelperData(Response.Failed, UpdateStep, AUTranslation.C_PrematureExitTitle, "Failed to connect to the new version of wyUpdate.exe")); } } // begin where we left off // if update step == RestartInfo, we need to send the restart info as well if (ResendRestartInfo != null && UpdateStep == UpdateStep.RestartInfo) { ResendRestartInfo(this, EventArgs.Empty); } else { SendAsync(new UpdateHelperData(UpdateStep)); } return; } if (data.UpdateStep != UpdateStep) { // this occurs when wyUpdate is on a separate step from the AutoUpdater UpdateStep prev = UpdateStep; // set new update step UpdateStep = data.UpdateStep; // tell AutoUpdater that the message we sent didn't respond in kind // e.g. we sent RestartInfo, and wyUpdate responded with DownloadUpdate // meaning we can't update yet, we're just begginning downloading the update if (UpdateStepMismatch != null) { UpdateStepMismatch(this, data.ResponseType, prev); } } // wyUpdate will give us its main Window Handle so we can pass focus to it if (data.Action == UpdateAction.UpdateStep && data.UpdateStep == UpdateStep.RestartInfo) { ClientWindowHandleToShow = data.ProcessID; } if (data.ResponseType != Response.Nothing && ProgressChanged != null) { ProgressChanged(this, data); } }
void StartNewSelfAndClose() { bool checkForClients = false; // when this function is called in the constructor // (i.e. before the handle for the form is created) // then the pipeserver will not have yet been created if (!updateHelper.RunningServer) { checkForClients = true; updateHelper.StartPipeServer(this); } Process clientProcess = new Process { StartInfo = { FileName = newSelfLocation, //NOTE: (Very goddamn important - change this and die) // Arguments must have the "clear space" before the closing quote after // baseDirectory. "Why?" you ask, because Windows is the offspring // of a Unicorn and an Angel. Everyone knows that Angels don't // respect backslash-quote combos. // And Unicorns are racists. // The non-absurd reason is that if you have a baseDirectory variable with // a trailing slash then a quote character adjacent to this slash (i.e. // with no space between the slash and quote) the commandline args // get fubar-ed. A base directory with a trailing slash is valid // input, thus the slash-space-quote combo must remain. // start the client in automatic update mode (a.k.a. wait mode) Arguments = "-cdata:\"" + clientFileLoc + "\" -basedir:\"" + baseDirectory + " \" /autoupdate /ns", WindowStyle = ProcessWindowStyle.Hidden } }; clientProcess.Start(); if (checkForClients) { // there must be at least one client running to receive this message int timeSpent = 0; while (updateHelper.TotalConnectedClients == 0) { // if we've already waited 30 seconds, we've wait long enough // something has gone wrong with the AutomaticUpdater control // no point in waiting around any longer. if (timeSpent == 30000) { break; } // wait 1/3 of a second timeSpent += 300; Thread.Sleep(300); } } // tell all the clients that there's a new wyUpdate updateHelper.SendNewWyUpdate(UpdateHelperData.PipenameFromFilename(newSelfLocation), clientProcess.Id); CancelUpdate(true); }
void updateHelper_ProgressChanged(object sender, UpdateHelperData e) { switch (e.ResponseType) { case Response.Failed: // show the error icon & menu // and set last successful step UpdateStepFailed(UpdateStepToUpdateStepOn(e.UpdateStep), new FailArgs { ErrorTitle = e.ExtraData[0], ErrorMessage = e.ExtraData[1] }); break; case Response.Succeeded: switch (e.UpdateStep) { case UpdateStep.CheckForUpdate: AutoUpdaterInfo.LastCheckedForUpdate = DateTime.Now; // there's an update available if (e.ExtraData.Count != 0) { version = e.ExtraData[0]; // if there are changes, save them if (e.ExtraData.Count > 1) { changes = e.ExtraData[1]; changesAreRTF = e.ExtraDataIsRTF[1]; } // save the changes to the AutoUpdateInfo file AutoUpdaterInfo.UpdateVersion = version; AutoUpdaterInfo.ChangesInLatestVersion = changes; AutoUpdaterInfo.ChangesIsRTF = changesAreRTF; } else { // Clear saved version details for cases where we're // continuing an update (the version details filled // in from the AutoUpdaterInfo file) however, // wyUpdate reports your app has since been updated. // Thus we need to clear the saved info. version = null; changes = null; changesAreRTF = false; AutoUpdaterInfo.ClearSuccessError(); } break; case UpdateStep.DownloadUpdate: UpdateStepOn = UpdateStepOn.UpdateDownloaded; break; case UpdateStep.RestartInfo: // show client & send the "begin update" message updateHelper.InstallNow(); // close this application so it can be updated // use either the custom handler or Environment.Exit(); if (CloseAppNow != null) { CloseAppNow(this, EventArgs.Empty); } else { Environment.Exit(0); } return; } StartNextStep(e.UpdateStep); break; case Response.Progress: // call the progress changed event if (ProgressChanged != null) { ProgressChanged(this, e.Progress); } break; } }