I'm building a c# console application that automatically finds updates, downloads them and installs them.
I'm using this method for the installation part:
public static void InstallUpdates(UpdateCollection DownloadedUpdates)
{
UpdateSession UpdateSession = new UpdateSession();
UpdateInstaller InstallAgent = UpdateSession.CreateUpdateInstaller() as UpdateInstaller;
InstallAgent.Updates = DownloadedUpdates;
//Starts a synchronous installation of the updates.
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa386491(v=VS.85).aspx#methods
IInstallationResult InstallResult = InstallAgent.Install();
}
According to this link, I can check whether or not a reboot is required. What I want to achieve is a system reboot that is done immediately when the RebootRequiredBeforeInstallation changes to true.
I thought of doing this, but that won't work because I can't use an else statement:
while (!InstallAgent.RebootRequiredBeforeInstallation)
{
} else
{
// Reboot
}
What would be the correct approach to this?
How about this:
while (!InstallAgent.RebootRequiredBeforeInstallation)
{
// Install things
// If the installer sets the RebootRequiredBeforeInstallation flag to
// true, the while loop will terminate and you can reboot.
}
if (InstallAgent.RebootRequiredBeforeInstallation)
{
// Reboot
}
Related
Very simply, I have created a simple shutdown timer with C# Forms that runs a shutdown command through the command prompt with an associated timer. I have noticed that Windows displays a notification indicating the computer is about to be shutdown just prior to the event (I think it appears no sooner than 15 min or so).
My question is this: Is there a way to stop that popup notification from appearing without interacting with the registry or making intrusive changes in Windows 7/8/10?
I haven't been able to find a good resource on interacting with native Windows (OS) elements like popups and notifications handed out by the OS for these kinds of events. Anyway to catch that event and modify it (like to not display the notification) would be great. But a more permanent solution such as disabling it through the registry or something is also fine. But I'm more interested in a programmatic solution.
Note: If there is no intrusive way of handling this, then I am really open to anything. I'm also trying to re-learn Forms so the exercise is worth it.
Edit: The code is on GitHub and pretty much completed but I would like to add this functionality to it.
Based upon what McNets said in his comment:
Why do not use the std. windows shutdown command? Add a scheduled task that shutdown the system immediately
I decided to leverage the Window's Task Scheduler. I decided to use Task Scheduler but there are others out there that do similar things.
Even though this approach is a bit more involved than just opening up a command prompt, it does everything I need including a circumvention of the shutdown banner that I noted in my question. Note, I can still give the user the option of running it with a banner like I did before but I have yet to implement that functionality. It is pretty trivial though (especially with the base code below). Simply add the timer to the shutdown args instead of /t 1 and set the task to run immediately.
This probably isn't the only solution but it is the least invasive that I could find. Thanks for all the help everyone. I appreciate it.
Full Source on GitHub.
Globals:
public const string DEFAULT_TASK_NAME = "ScheduledShutdownTimer";
private const string SHUTDOWN_COMMAND_ARGS = "/s /c \"Scheduled Computer shutdown via " +
"the Windows Shutdown Timer App\" /t 1";
Create a task:
using (TaskService ts = new TaskService())
{
// If the task doesn't exist, create it.
if (TimerExists(DEFAULT_TASK_NAME))
throw new TimerExists("The timer already exists in the task scheduler. You " +
"must modify it instead of attempting to create it!");
else
{
try
{
TaskDefinition td = ts.NewTask();
td.RegistrationInfo.Date = _currentTime; // DateTime.Now
td.RegistrationInfo.Source = "Windows Shutdown Timer";
td.RegistrationInfo.Description = "Shutdown Timer initiated Windows " +
"Shutdown Timer";
td.Settings.Enabled = true;
td.Triggers.Add(new TimeTrigger(_shutdownTime));
td.Actions.Add(new ExecAction("shutdown", SHUTDOWN_COMMAND_ARGS, null));
TaskService.Instance.RootFolder
.RegisterTaskDefinition(DEFAULT_TASK_NAME,td);
Properties.Settings.Default.ShutdownTimer = _shutdownTime;
Properties.Settings.Default.Save();
StartLocalTimer();
}
catch(Exception)
{
DialogResult alert = MessageBox.Show("The timer couldn't be set. ",
"Error - Couldn't Set Timer!", MessageBoxButtons.RetryCancel,
MessageBoxIcon.Error);
if (alert == DialogResult.Retry)
CreateShutdownTimer(numSeconds);
}
}
}
Modify a Task:
using (TaskService ts = new TaskService())
{
// If the task exists, update the trigger.
if (TimerExists(DEFAULT_TASK_NAME))
{
Task task = ts.GetTask(DEFAULT_TASK_NAME);
if (task.Definition.Triggers.Count == 1)
task.Definition.Triggers.RemoveAt(0);
else if (task.Definition.Triggers.Count > 1)
{
for (int index = 0; index < task.Definition.Triggers.Count - 1; index++)
{
task.Definition.Triggers.RemoveAt(index);
}
}
// Add the new trigger after making sure it is the only one.
task.Definition.Triggers.Add(new TimeTrigger(_shutdownTime));
if (task.Definition.Actions.Count == 1)
task.Definition.Actions.RemoveAt(0);
else if (task.Definition.Actions.Count > 1)
{
for (int index = 0; index < task.Definition.Actions.Count - 1; index++)
{
task.Definition.Actions.RemoveAt(index);
}
}
// Add the new action after making sure it is the only one.
task.Definition.Actions.Add(new ExecAction("shutdown", SHUTDOWN_COMMAND_ARGS,
null));
// Reset the status in case it was set as anything but "Ready"
task.Definition.Settings.Enabled = true;
task.RegisterChanges();
Properties.Settings.Default.ShutdownTimer = _shutdownTime;
Properties.Settings.Default.Save();
// Starts the timer display and enables/disables buttons.
StartLocalTimer();
}
else
throw new NoTimerExists("The timer doesn't exist in the task scheduler. You " +
"must create it instead of attempting to modify it!");
}
Stop a task:
using (TaskService ts = new TaskService())
{
// If the task exists, remove the trigger.
// Note: the included Stop() method doesn't work.
if (TimerExists(DEFAULT_TASK_NAME))
{
Task task = ts.GetTask(DEFAULT_TASK_NAME);
task.Definition.Triggers.RemoveAt(0);
task.RegisterChanges();
StopLocalTimer(); // Resets display timers in program
}
else
throw new NoTimerExists("The timer doesn't exist in the task scheduler. " +
"You must create it instead of attempting to modify it!");
}
I created an app in window phone 8 which could change the lockscreen images from background task. The app worked well in emulator and device when run through code. It contains the launchforTest() which makes lockscreen change every 30 sec.
I got some comments that told that launchforTest() don't work when app gets uploaded over store. its basically for the testing purpose.
So my problem is that When i install my app from the store which I have put for beta testing the background tasks don't work i,e lockscreen images don't change
What am I missing in the code which has made it not working pls help.
Here is my Code
private ResourceIntensiveTask resourceIntensiveTask;
private string resourceIntensiveTaskName = "SmartLockScreenScheduledTaskAgent";
private string resourceIntensiveTaskDescription = "Displays the latest deals.";
private StartTask()
{
LockScreenChange("ms-appdata:///Local/Image0.jpg", true);
}
private async void LockScreenChange(string filePathOfTheImage, bool isAppResource)
{
if (!LockScreenManager.IsProvidedByCurrentApplication)
{
// If you're not the provider, this call will prompt the user for permission.
// Calling RequestAccessAsync from a background agent is not allowed.
await LockScreenManager.RequestAccessAsync();
}
// Only do further work if the access is granted.
if (LockScreenManager.IsProvidedByCurrentApplication)
{
// At this stage, the app is the active lock screen background provider.
// The following code example shows the new URI schema.
// ms-appdata points to the root of the local app data folder.
// ms-appx points to the Local app install folder, to reference resources bundled in the XAP package
// var schema = isAppResource ? "ms-appx:///" : "ms-appdata:///Local/";
var uri = new Uri(filePathOfTheImage, UriKind.Absolute);
// Set the lock screen background image.
LockScreen.SetImageUri(uri);
// Get the URI of the lock screen background image.
var currentImage = LockScreen.GetImageUri();
System.Diagnostics.Debug.WriteLine("The new lock screen background image is set to {0}", currentImage.ToString());
UpdatePrimaryTile();
StartResourceIntensiveAgent();// StartPeriodicAgent();//
// MessageBox.Show("Lock screen changed. Click F12 or go to lock screen.");
}
else
{
MessageBox.Show("Background can't be updated as you clicked no!!");
}
}
public void RemoveResourceIntensiveAgent()
{
try
{
if (resourceIntensiveTask != null)
{
ScheduledActionService.Remove(resourceIntensiveTaskName);
}
}
catch (Exception)
{
}
}
/// <summary>
/// Code to start the resource intensive task
/// </summary>
private void StartResourceIntensiveAgent()
{
// Variable for tracking enabled status of background agents for this app.
agentsAreEnabled = true;
resourceIntensiveTask = ScheduledActionService.Find(resourceIntensiveTaskName) as ResourceIntensiveTask;
// If the task already exists and background agents are enabled for the
// application, you must remove the task and then add it again to update
// the schedule.
if (resourceIntensiveTask != null)
{
ScheduledActionService.Remove(resourceIntensiveTaskName);
}
resourceIntensiveTask = new ResourceIntensiveTask(resourceIntensiveTaskName);
// The description is required for periodic agents. This is the string that the user
// will see in the background services Settings page on the device.
resourceIntensiveTask.Description = (resourceIntensiveTaskDescription);
// Place the call to Add in a try block in case the user has disabled agents.
try
{
ScheduledActionService.Add(resourceIntensiveTask);
//ResourceIntensiveStackPanel.DataContext = resourceIntensiveTask;
resourceIntensiveTask.ExpirationTime = DateTime.Now.AddDays(14);
// If debugging is enabled, use LaunchForTest to launch the agent in one minute.
ScheduledActionService.LaunchForTest(resourceIntensiveTaskName, TimeSpan.FromSeconds(30));
}
catch (InvalidOperationException exception)
{
if (exception.Message.Contains("BNS Error: The action is disabled"))
{
MessageBox.Show("Background agents for this application have been disabled by the user.");
agentsAreEnabled = false;
}
}
catch (SchedulerServiceException)
{
// No user action required.
}
}
Your problem is that you have implemented your background agent as a ResourceIntensiveTask. ResourceIntensiveTasks run under the following very specific constraints:
Phone is plugged in
Lock screen is engaged
Wireless network (non-cellular) connectivity is available
Consider implementing this background agent as a PeriodicTask. If you are running up against runtime constraints, consider refactoring as much code as possible to preprocess what portions of the the lock screen image as you are able while the main application is running, or by creating static image assets in the package that can be used to convey the same information.
Ref: Background agents for Windows Phone: Constraints for Resource-intensive Agents
When I try to start my c# service it says:"starting" for a second and it turns back to being "stopped"
What can be the problem? I had the same code before, and it worked but made some changes in the code now and it stopped working. Here is what I added to my code:
App Config:
<add key="cut-copy" value="copy"/>
Normal code:
private void fileSystemWatcher1_Created(object sender, System.IO.FileSystemEventArgs e)
{
String cut_copy = ConfigurationManager.AppSettings[#"cut-copy"];
if (cut_copy == "copy")
{
cut = false;
}
else
{
cut = true;
}
if (WaitForFileAvailable(e.FullPath, TimeSpan.FromSeconds(10)))
{
var file = Path.Combine(source, e.Name);
var copy_file = Path.Combine(target, e.Name);
var destination = Path.Combine(target, Path.ChangeExtension(source, Path.GetExtension(source)));
if (File.Exists(file))// Check to see if the file exists.
{ //If it does delete the file in the target and copy the one from the source to the target.
File.Delete(copy_file);
File.Copy(e.FullPath, Path.Combine(target, e.Name));
}
else// If it doesn't, just copy the file.
{
if (cut == true)
{
if (File.Exists(file))// Check to see if the file exists.
{ //If it does delete the file in the target and copy the one from the source to the target.
File.Delete(copy_file);
File.Move(Path.Combine(e.FullPath, e.Name), target);
}
}
else
{
if (File.Exists(file))// Check to see if the file exists.
{ //If it does delete the file in the target and copy the one from the source to the target.
File.Delete(copy_file);
File.Copy(e.FullPath, Path.Combine(target, e.Name));
}
}
//under this is more code that didn't change
}
EDIT: ONSTART:
protected override void OnStart(string[] args)
{
base.OnStart(args);
this.fileSystemWatcher1 = new System.IO.FileSystemWatcher();
((System.ComponentModel.ISupportInitialize)(this.fileSystemWatcher1)).BeginInit();
fileSystemWatcher1.Path = source;
fileSystemWatcher1.Changed += new FileSystemEventHandler(fileSystemWatcher1_Changed);
fileSystemWatcher1.Created += new FileSystemEventHandler(fileSystemWatcher1_Created);
fileSystemWatcher1.Deleted += new FileSystemEventHandler(fileSystemWatcher1_Deleted);
fileSystemWatcher1.Renamed += new RenamedEventHandler(fileSystemWatcher1_Renamed);
this.fileSystemWatcher1.EnableRaisingEvents = true;
this.fileSystemWatcher1.IncludeSubdirectories = true;
((System.ComponentModel.ISupportInitialize)(this.fileSystemWatcher1)).EndInit();
logger("Service started "+ DateTime.Now);
}
What am I doing wrong?
Usually this behavior indicates that the OnStart method ends without leaving any threads running. I have experienced that if an unhandled exception is thrown starting the service, the service doesn't go into Stopped state, but the service manager shows the "Starting service" window for 30 seconds and then fails saying it can't determine the service's state.
I'm not sure whether the FileSystemWatcher actually spawns a new thread that keeps running. You could (just to try it), also create a System.Timers.Timer that fires every 30 seconds in OnStart and stop that timer in OnStop. If the service keeps running then, you have to spawn a new thread for the FileSystemWatcher.
Usually, in OnStart you'd spawn a separate thread that does the service's work. Be it waiting for TCP connections, a timer that does things on a regular basis or any other kind of thread. If you don't do that, the service just stops as soon as there are no more threads active.
For the code, the only answer that anyone could give you are just "guessing". You better debug it yourself.
The easiest way to hit a break-point in a Windows Service is to put this line of code at the beginning of the OnStart method:
Debugger.Break();
Compile your service in Debug mode, so you can have all the necessary symbols in your executable.
Install your service
Start it from the service list.
You will get a prompt for debugging the "yourservicename.exe" program.
Say Yes-debug, Choose debugger.
Choose the correct Visual Studio version as your debugger.
Now you will be in the Debugger.Break line
Have fun
I would like to handle situation in such case, user performs purchasing in this machine, but which to run the feature in another machine.
I know I have to check for receipt. I was wondering, is this the correct way to do so? Note that, I bypass signature check. As, I need to setup a backend system which I do not want to consider at this moment. I can't even perform signature check locally, as Windows 8 Store App doesn't provide System.Security.Cryptography API.
I was wondering, whether the following code snippet is good enough to handle most of the cases? Note, I unable to test the code, as I need to publish a new version, in order for me to test the code.
private async void history_Click(object sender, RoutedEventArgs e)
{
bool OK = true;
// The next line is commented out for production/release.
LicenseInformation licenseInformation = CurrentApp.LicenseInformation;
if (!licenseInformation.ProductLicenses["PremiumFeatures"].IsActive)
{
try
{
// The customer doesn't own this feature, so
// show the purchase dialog.
String receipt = await CurrentApp.RequestProductPurchaseAsync("PremiumFeatures", true);
// the in-app purchase was successful
licenseInformation = CurrentApp.LicenseInformation;
if (licenseInformation.ProductLicenses["PremiumFeatures"].IsActive || receipt.Length > 0)
{
// In some situations, you may need to verify that a user made an in-app purchase.
// For example, imagine a game that offers downloaded content. If the user who
// purchased the content wants to play the game on another PC, you need to verify
// that the user purchased the content.
//
// Receipt is used to handle such situation.
//
// Validate receipt is complicated, as it requires us to setup a backend system.
// http://msdn.microsoft.com/en-US/library/windows/apps/jj649137
//
// I will just assume non empty receipt string means valid receipt.
OK = true;
}
else
{
OK = false;
}
}
catch (Exception)
{
// The in-app purchase was not completed because
// an error occurred.
OK = false;
}
}
else
{
// The customer already owns this feature.
OK = true;
}
if (OK)
{
// Launch premium feature.
Frame.Navigate(typeof(HistoryPage));
}
}
You can test your code using CurrentAppSimulator instead of CurrentApp. It looks ok to me.
the problem only appears when making Release build and running exe file ( not from visual studio )
in all other combination either it's running from visual studio or running exe everything works fine
I'm running Function Load using backgroundWorker
Load:
while (!Request.GAMELIST.XMLReceived) ;
GameEngine.ParseGameList( Request.GAMELIST.XML );
Request.GAMELIST.XMLReceived = false;
while loop in this fragment works like delay
it should wait till XML is received from server and then continue
but it stucks in above specified situation
if I'll put MessageBox.show("here we go"); after while loop
messageBox will not appear
but if I'll put MessageBox.show("here we go"); before while loop
application will receive data until I click messagebox ok
and then everything will work fine
here is GAMELIST class implementation
public class RequestGAMELIST
{
public string XML;
public bool XMLReceived = false;
public void ParseRequest( string request )
{
int index = request.IndexOf(':') + 2;
XML = request.Substring(index, request.Length - index);
XMLReceived = true;
}
}
please provide help if you can
this is really strange thing which I can't figure out by my self
Thanks.
Yes, this code has very good odds to hang in the Release build. The JIT optimizer doesn't know that the variable might be set to true by code outside of the method. You need to tell it that, like this:
public class RequestGAMELIST
{
public volatile bool XMLReceived = false;
// etc..
}
The volatile keyword ensures that the jitter won't store the variable value in a CPU register.
That solves your problem, it is still not the right way to do it. You should use an AutoResetEvent instead. It ensures that the thread responds to the variable change is quickly as possible. And most importantly, it lets the thread block so it doesn't burn any cpu cycles.
public class RequestGAMELIST
{
public AutoResetEvent XMLReceived = new AutoResetEvent();
public void ParseRequest( string request )
{
int index = request.IndexOf(':') + 2;
XML = request.Substring(index, request.Length - index);
XMLReceived.Set();
}
}
In your thread:
XMLReceived.WaitOne();
GameEngine.ParseGameList( Request.GAMELIST.XML );
This is a bad idea:
while (!Request.GAMELIST.XMLReceived) ;
At least you should be doing something like:
while (!Request.GAMELIST.XMLReceived) {
System.Threading.Thread.Sleep(100); // Don't hog the CPU!
}
Your program runs fine in debug mode perhaps due to certain debug routines added inside the while loop which makes it run slower...