New blog for Windows 8 app developers

    I am posting this on behalf of Ian LeGrow, Partner Group Program Manager here in Windows.

    As you may have heard, we now have a new Windows 8 app developer blog to help you build Metro style apps on our new Windows 8 platform.

    In the new blog, we share our learning and converse with you as you enter the new world of Windows Metro style app development. The blog complements the Windows Dev Center and community forums, and you’ll see a lot of pointers to content and samples to help you get going. We talk about our experiences building the platform and building apps, pitfalls to avoid, tips and tricks, why we made certain choices in the platform, and anything else we can pass along to help you create amazing apps.

    Developers, testers, and program managers from the Windows development team are posting to this blog regularly from now through the release of Windows 8 and beyond. We already have several great posts that you can check out for info on topics ranging from using the Live SDK in your apps to async patterns to ways to improve the performance of your apps, and much more.

    Come join us in the conversation on the Windows 8 app developer blog. We hope to see you there.

    Trigger-Start Services Recipe
    12

    Windows services enable code to run in the background, even if no user is logged on. These background services provide a lot of useful functionality while minimizing interference with the user’s desktop.

    Services have been around for a long time and have proven to be quite useful. Many application developers, OEMs, and IT organizations use services. On a typical system, this can result in a large number of services running at a given time. For example, my machine has about 110 services running right now. This large number of services is due to multiple beta products, different users, multiple desktop and everything running together at the same time.

    Running this many services can lengthen Windows startup time, increase the machine’s attack surface, takes a toll on memory, CPU, and power usage. While developers may have machines that can handle loads like these, my machine is a powerful enough (8G of RAM, 4 cores…) so I don’t really care, consumers probably do.

    If you are developing Windows services, be sure to write them in the most efficient way possible. The service should run only when it needs to be running. You could write an on-demand service that can be started and stopped by applications that need it, or configure the service as a delayed auto-start service. “Windows Services Enhancements” by Kenny Kerr covers these useful features, among others.

    However, Windows 7 and Windows Server 2008 R2provide a new mechanism for making sure services run only when needed. It is called Trigger-Started Service (TSS). Basically, TSS tells the operating system to start the service under certain conditions, such as when specific devices or types of devices are plugged into the computer, or when a computer is added or removed from a domain. Additional criteria are specified in the services documentation.

    So what is the problem?

    There is already good documentation for creating or enabling services to run like this, and it’s quite easy to do in C++. However, while there are several examples and code snippets for doing the same thing in managed code, none of these implementations provides a general purpose, easy-to-reuse solution that doesn’t, in most cases, ultimately require a lot of interoperability code to be written or modified.

    The Windows 7 Trigger-Start Services Recipe gives managed code developers an easier way to write TSS.

    In the recipe, you’ll find the Win7TriggerStartRecipe assembly, which provides a clean .NET interface that can be used to communicate with Windows Service Control Manager (SCM) to configure a service as a TSS. The SCM is a large tool, as it includes the Win 32 API, a command line interface, and reflects some of its functionality in the Windows Control Panel. You will use its API to configure services to use TSS.

    Usually, a service is configured to work as a TSS immediately after the service is installed. Since the recommended method of installing a .NET service is to use installutil.exe, bundled with the .NET framework, and this requires that the service have an Installer-derived class, the best place to use the trigger start assembly will be in an AfterInstall handler in the ServiceInstaller implementation. However, it can be used by any application with administrative privileges to register any service.

    To use the recipe, you’ll first need to add a reference to the Win7TriggerStartRecipe assembly in your project and then add the following Using statement:

    using WindowsRecipes.TriggerStartServices;

    Before you can start working, you need to double check that underlying operating system supports this feature. To do so, call the static method IsSupported in the TriggerStart class. This is currently supported only on Windows 7 and Windows Server 2008 R2.

    Next, create an instance of the TriggerStart class. You can use one of the three constructors, passing a reference to a specific service implementation to link (bind) the required service to the TriggerStart manager.

    After that, you can add (or remove) triggers as necessary from the Triggers collection, and then register these changes with the SCM by calling CommitChangesToService. The following code registers a service to start when a generic USB Drive is plugged into the PC.

       1: try
       2: {
       3:     if (!TriggerStart.IsSupported)
       4:     {
       5:         Console.WriteLine("The current system does not support trigger-start services.");
       6:         return;
       7:     }
       8:     //Without error checking and logging, the following lines of code are 
       9:     //everything necessary to register a service
      10:     TriggerStart ts = new TriggerStart(this.USBServiceInstaller.ServiceName);
      11:  
      12:     //Add a trigger that tells the SCM to start the service when USB device plugged in
      13:     Guid Guid_USBDevice = new Guid("53f56307-b6bf-11d0-94f2-00a0c91efb8b");
      14:     const string DeviceName = @"USBSTOR\GenDisk";
      15:  
      16:     ts.Triggers.Add(
      17:                 new DeviceInterfaceArrivalTrigger(
      18:                         ServiceTriggerAction.ServiceStart,
      19:                         Guid_USBDevice,DeviceName));
      20:     ts.Triggers.Add(
      21:                 new DeviceInterfaceArrivalTrigger(
      22:                         ServiceTriggerAction.ServiceStop, 
      23:                         Guid_USBDevice, 
      24:                         DeviceName));
      25:                                 
      26:     //Commit our changes (this registers these triggers with the SCM)
      27:     ts.CommitChangesToService();
      28:  
      29:     Console.WriteLine("Trigger registration successful.  
      30:                        To manually confirm this, type 'sc qtriggerinfo " 
      31:                        + this.USBServiceInstaller.ServiceName + "'.");
      32: }
      33: catch (Exception ex)
      34: {
      35:     Console.WriteLine("Registering the service for trigger starting failed:");
      36:     Console.WriteLine(ex.Message);
      37: }

    As you can see from the above code, after checking that TSS is supported, you create a new instance of the TriggerStart class, passing a specific service implementation – this.USBServiceInstaller.ServiceName.

    Next you define a GUID that is associated with a USB device, and provide a DeviceName. Then add specific triggers like DeviceInterfaceArrivalTrigger, passing a specific trigger action like ServiceTriggerAction.ServiceStart that starts the service when a generic USB storage device is plugged into the computer USB port. The DeviceInterfaceArrivalTrigger activates when the specified device or type of device is connected to the system or on startup if the device is already connected. You will need to specify the DeviceInterfaceClass GUID that identifies the class of device you are looking for, and at least one Hardware ID or Compatible ID that identifies a list of matching device names to watch for.

    The next trigger defines the stop condition when the USB key is pulled out, as there is no need to continue running the service if the USB is not plugged in and the service will start again the next time you plug in a generic USB storage device.

    Lastly, you need to call the CommitChangesToService method, to save any changes to the service configuration.

    That’s all there is to it. Again, when first associated with a service, the Triggers collection contains any triggers currently associated with the service. Modify this collection as necessary, commit the changes, and you’re done.

    DeviceInterfaceArrivalTrigger, is just one of many triggers that you can use, here is a list of the implemented triggers in this recipe:

    • DomainEventTrigger: This trigger activates when the computer joins or leaves a domain. All you need to do is specify which action in the constructor or by using the EventType member.
    • FirewallEventTrigger: This trigger activates when one of a group of specified ports is opened or closed on the firewall. You’ll start by specifying a list of the ports (FirewallPort) you’re interested in monitoring by using the Ports member. You’ll then specify whether you’d like the trigger to activate when they open or close with the EventType member. The FirewallPort structure contains optional ServiceName and ServicePath members if you’d like to specify the service listening in on the event.
    • GroupPolicyEventTrigger: This simple trigger fires when changes are made to group policy. The trigger simply needs to specify whether to monitor user or machine policy through the EventType member.
    • IPAddressAvailabilityTrigger: This trigger fires when the computer joins its first network, or leaves its last network. You specify which by using the EventType member.
    • CustomEventTrigger: This trigger mostly exists for the assembly to be able to modify services with existing triggers of this type. You can use it to add your own custom trigger, but because the expected data is unknown unmanaged data provided by a specified Events for Windows (EFW) provider, you’ll need to marshal it yourself. Still, if the data is easily marshaled, you may find this helpful for adding your own custom triggers.

    If you want to understand how the recipe works, please download and review the recipe code and documentation

    Here is a short video by Kate Gregory, explaining this in great detail.

    Follow Yochay on Twitter

    (Post edited by Barbara Alban)

    Windows Restart and Recovery Recipe
    12

    Vista introduced two closely related features: Application Restart and Application Recovery. These features are designed to eliminate much of the pain caused by the unexpected termination of your application, whether as a result of an unhandled exception, a “hard hang,” or any other crash.

    Application Recovery applies to applications that have a “document” or any other in-memory information that might be lost when the application closes unexpectedly. Application Restart applies to all applications, whether they might have unsaved data or not, and to more unexpected closes, including a DLL update or a system reboot. Today, a large number of applications such as Windows Office (Microsoft Word and friends) use these features. Even if something does go wrong (and when it comes to software, it is most likely that at some point something will go wrong), the application together with the operating system can provide a seamless recovery path that makes the user feel a little less frustrated.

    Basically, any Windows application can register with the operating system for restart and, optionally, for recovery.

    • To register for restart, the application provides a command line argument that will inform the application it is restarting. A restarted application that uses recovery can look in the known location for recovery data when it is restarted, and reload the unsaved data.
    • To register for recovery, the application provides a callback function. The operating system will call this function on a separate thread (remember, your main thread just threw an exception) if the application crashes or hangs. The callback function can save any unsaved data in a known location. It cannot access the UI thread, which is no longer running. Do note that the call back function can’t run forever. The operating system will not permit it to run more than few seconds.

    All this sounds great; what is the problem?

    The native Win32 API calls to register for restart and for recovery are fairly simple to use. The Windows API Code Pack includes a managed wrapper for the both recovery and restart functionality.

    However, the problem most developers experience is the degree of freedom allowed regarding the recovery method. Since the API requires a callback that the operating system calls when something bad happens to your application, developers can write out their unsaved data in any way they choose, and anywhere.

    While writing a file to the hard drive is an obvious choice, some might decide to add records to a database, upload a file to a network location, send an email message, print something, add an event to the event log, and so on. Since the application is in an unknown state during the recovery callback, these are actually poor choices. If you are looking to implement the recovery callback, you should choose a solution that is fast (quick code execution), and that relies on the bare minimum of available resources. Therefore writing to the hard drive is probably your best choice.

    Once the decision is made to write a file to the hard drive, more questions arise. What folder should be used? Many developers use “the current directory” – which works great during development, but once the application is deployed and installed under Program Files (for example), the Windows UAC will prevent your application from writing to that folder through yet another exception on your recovery callback method… “The AppData (%AppData%) folder for the user is a much better choice.” – Not the ideal situation.

    But there are yet more questions; for example, what file format should be used? What should the file be named? How can the restarting application find the file if the filename is not hardcoded to be the same every time? What will happen if two instances, with different data, require restart at the same time – how will they each save their own data separately and find their own data on restart? Fortunately, we have a recipe for developers who need to cook this into their code.

    The Windows Restart and Recovery Recipe includes a library that solves all of the above mentioned problems for both managed (.NET) and native (C++) implementations. The recipe includes code samples that show how to use the library, and documentation explaining in detail how the library works.

    Our goal was to make using the Restart and Recovery features super easy and accessible.

    For example: The recipe is provided as a .NET assembly - WindowsRecipes.RestartManager. Projects that use the recipe must add a reference to the assembly. There is one class - RestartRecoveryHelper, with two methods, CheckForRestart and RegisterForRestartAndRecovery. Next, you’ll need to point to your data model class; any class that is serializable, using the Serializable attribute, can be used as data to be saved. Then all you need to do is simply call the RegisterForRestartAndRecovery method like the following snippet.

    doc = new SampleDocument();
    // initialize doc as required
    rrh = new WindowsRecipes.RestartManager.RestartRecoveryHelper<SampleDocument>();
    SampleDocument recovereddoc = rrh.CheckForRestart();
    if (recovereddoc != null)
    {
        doc = recovereddoc;
        //use contents of doc to set values of controls on the form
    }
    rrh.RegisterForRestartAndRecovery("TestHarness",doc,WindowsRecipes.RestartManager.FileType.Xml);

    This code includes registering to the recovery method as well as recovering from previous unexpected application terminations.

    The SampleDocument is a serializable class we use just for demo purposes. Next we create the helper class – RestartRecoveryHelper, that can handle the specific SampleDocument class type. You can create any number of such files for any data object that you want to save, or you can create one big nested data object. Both are valid, as long as the object is serializable.

    Next we check to see if the application was restarted due to an unexpected termination. If so, we then retrieve the data that was saved before the application terminated and use it in our application logic. For example, we can use the recovered data to set values on a few controls. This completes the recovery part.

    Now we want to register the app to restart and recovery in case it crashes again. Simply call the RegisterForRestartAndRecovery method by passing a string as the name of the app, the doc as the data object to save, and the file type to save.

    The recipe takes care of everything for you. The temporary recovery files are saved in the Roaming Application Data folder usually located at “C:\Users\<your user name>\AppData\Roaming”. The file names are guaranteed to be unique, the format is up to you, binary or XML. This way, we can make sure that a given application can handle multiple users and multiple crashes. Once recovered, the files are removed.

    Here is a short video by Kate Gregory, explaining this in great detail. You can also watch a video showing the native APIs.

    If you are interested, you can read more about this in the Windows Restart and Recovery Recipe and download the code and documentation.

    I want to thank Kate Gregory for her help with this recipe.

    Follow Yochay on Twitter

    (Post edited by Barbara Alban)

    Tasks.Show A Windows 7 Developers Resource
    16

    Are you still using yellow sticky notes to remember tasks on your to-do list? Did you ever need an easy, light and quick way to manage your to-do list? Well we have a solution for you. Tasks.Show is a simple Windows application that lets you manage your to-do list in an easy and intuitive manner. Simply create a new task, assign it to a project, give it a deadline, and you are set.

    Tasks.Show is a developer resource application, where you get the full source code of a complete and fully functional application that is using Windows 7 unique features like Windows Touch and the Windows Taskbar.

    image

     

     

     

     

     

     

     

     

     

     

     

     

     

    Tasks.Show provides you with a visual representation of how busy you are. Tasks display on a timeline according to project and size, and estimated amount of work. The timeline view at the bottom of the screen also gives you sense of how your to-do list looks over time, and just how busy you are?

    image

     

     

     

     

     

    Integrated with Windows to easily manage your tasks

    Use Ctrl + Alt + T from anywhere in Windows, even if you are a different application, to activate Tasks.Show and start entering a new task. Use special keywords while typing to place a given task in the right order and assign it a deadline. Use Windows Touch to easily interact with different tasks, sliding between tasks, assigning tasks to a project with a flick of your fingers. The application also interacts with Windows 7 Taskbar, allowing you to easily switch to your more important tasks or create new tasks directly from the Windows 7 Tasks.Show Taskbar icon.

    image

     

     

     

     

     

     

     

     

     

     

     

     

     

    Installing

    You can download the full MSI package (the installer). The installer installs the Tasks.Show application for you to use.

    Working with Visual Studio

    You can download the complete source code of the application. Make sure you install Tasks.Show before you run the application from Visual Studio. This way the installer sets up all the registry settings to allow your application to work with the Taskbar.

    The Visual Studio solution includes only two projects:

    • Tasks.Show.Data.VS2010 – Holds the data model for the application, basically all the tasks and any related date
    • Tasks.Show.VS2010 – Holds the main WPF application
    Windows 7 Recipe – Taskbar Single Instance
    7

    It has been a while since I posted anything on the Windows 7 for Developer blog, but it is good to be back. This is about the first of four recipes we are releasing in the upcoming weeks; the others will be about Restart and Recovery, Trigger Start Services, and Library Watcher.

    The purpose of this blog is to share a library we created specifically for the Windows 7 Taskbar scenario. The Windows 7 Taskbar includes many new features, one of which is the Taskbar Jump-List that allows users to perform various application-related tasks without ever switching to the application window. By now, there are many applications that uses the Taskbar—Office 2010, IE9, other browsers, Messenger, and Microsoft Zune, among many other Microsoft and non-Microsoft applications.

    The taskbar jump list task is nothing but a simple command line call. The API lets you specify a command line type string with any number of arguments you want to pass. The Windows shell simply executes this command line and, in most cases, launches another instance of the application. You can read more about Developing for the Windows 7 Taskbar – Jump into Jump Lists – Part 1, Part 2, and Part 3.

    However, some applications use the Windows 7 Taskbar jump list tasks as “commands” to the application to change the application status. For example, Windows Media Player surfaces a few tasks (Resume Previous Play List is one example) that, when the user activates them, instead of launching a second instance of media player, they execute the task itself. Windows Live Messenger exposes few tasks that let you control your availability status as illustrated in the following figure

    image

     

     

     

     

     

     

     

     

     

     

     

    Windows Live Messenger allows users to change their status without switching to the application.

    The Taskbar Single Instance Recipe allows developers to easily develop applications that use Messenger-like tasks that change the state of the currently running instance, allowing it to react to incoming state-change notifications and act accordingly.

    This blog shows you how to use the Windows 7 Taskbar Single Instance recipe. If you are interested in how the library works you’ll have to download the library and its documentation. You can download the native C++ implementation, or .NET one.

    Some technical background

    The Windows 7 Taskbar jump list tasks API is simple. All you need to do is populate a list of IShellItems or IShellLinks. Each entry contains a “command” line with an optional argument. However, it should be noted that simply activating an IShellItem or an IShellLink from the Windows 7 Taskbar results in a new process being launched (usually seen by the user as a new instance of the application). If the shell link references your own executable, then activating it would result in the launching of a new instance of your process. Sometimes this is the required result (for example, when opening a new document in a new Notepad window). However we may want to use the Taskbar tasks to affect our current instance's state (for example, by changing the status of a messenger application).

    Just to be clear, every time you click a Windows 7 jump list task, Windows creates a new process and runs the command line. There is no API for you to “communicate” through the Windows 7 Taskbar jump list tasks. In order to “communicate” with your application from the Taskbar jump list tasks, you’ll need to run some code in your application that upon application startup checks if the application is already running and, if it is running, notifies the currently executing application instance of the required task clicked by the user, and then closes the new instance that was just created.

    This would usually involve some sort of synchronization object to check if an instance is already running (for example, a Mutex) and a communication mechanism to perform the notification itself. Basically, this is an implementation of a singleton pattern.

    The code for accomplishing this task is usually quite similar for many application types, and is usually written over and over again. Therefore, the goal of the Taskbar Single Instance recipe is to provide a simple, reusable code library for both native code and managed code developers that, on the one hand, can be easily used with default settings, but also can be easily customized and extended if required on the other hand.

    You can download the recipe code and documentation to fully understand how to implement the singleton pattern and see some examples. For now, let’s focus on how to use the library.

    What Does the Recipe Do to My Applications?

    Now that we understand the problem, let’s see the solution in action and then dive into the actual code. When you run any of the samples in the recipe and use the jump list tasks to change the status of the application, you’ll notice that the currently running application changes it status, but you will not see a second instance of the application launch. To see what happens behind the scenes you’ll need to use Process Explorer (part of System Internals). With this tool, you are able to see each process in your system. New processes are highlighted in green for few seconds, and processes that are being closed are highlighted in red.

    With that in mind let’s review how the taskbar singleton recipe works. Our starting point is an application that is already running. As you can see from the following figure, the small top window is our sample application, and the bigger window is Process Explorer. In the box outlined in red, you can see two separate lines of the WpfSample.exe process. One is highlighted in yellow – this is our main process or the running application as you can see in the small green Window1 at the top of the figure.

    image

     

     

     

     

     

     

     

     

     

     

    The second WpfSample.exe process, highlighted in green, is the new process that was created as a result of pressing the jump list “Online” task to change the application status from its previous state to “Online.” As you can see, Windows launched a second instance of the application, but you can’t see it in the window – the application is not visible yet.

    Next, the recipe kicks in and will “send” the Online message from the newly created instance of the application to the already existing one. Then the recipe will make sure the newly created instance is terminated. As you can see from the following figure, the second line is highlighted in red, and the process is terminated.

    image

     

     

     

     

     

     

     

     

     

     

    I Am Convinced; How Can I Use This?

    The SingleInstanceManager class is the key class for using the recipe's code. In order to use the recipe, create an instance of the SingleInstanceManager using the static Initialize() method. This method accepts an object of type SingleInstanceManagerSetup that can be used to customize the behavior of the SingleInstanceManager. If you don’t customize, the SingleInstanceManager will use the default value provided in this blog. At a minimum, this setup object should be given an application ID that will be used to identify the application as a single instance.

    The SingleInstanceManager supports both Managed and Native code. The samples I’ll be showing are in native (C++ code).

       1: SingleInstanceManagerSetup simSetup(L"MyApp");
       2: g_SIM = SingleInstanceManager::Initialize(&simSetup);
       3:  
       4: /* Your application code here */
       5:  
       6: // Free memory
       7: delete g_SIM;

    As long as the SingleInstanceManager object is kept alive, no other instance of the application will be executed in parallel to the first instance. If and when you try to launch a second application instance, by default the process of the second application will exit before executing any of you application code. If you prefer, you can set up the SingleInstanceManager to throw an exception instead of exiting the process (see section "Additional Configuration Options").

    Accepting Notifications from Other Application Instances

    In order to receive incoming arguments from additional launched application instances, you need to specify an arguments handler when creating the SingleInstanceManagerSetup object.

       1: void ArgsHandler(LPCWSTR* pArguments, DWORD dwLength, LPVOID pContext)
       2: {
       3:     // Handle incoming arguments
       4: }
       5:  
       6: int _tmain(int argc, _TCHAR* argv[])
       7: {
       8:     // The NULL argument is the context passed to the handler (e.g. an object
       9:     // instance to call one of it's methods).
      10:     SingleInstanceManagerSetup simSetup(L"MyApp", ArgsHandler, NULL);
      11:     g_SIM = SingleInstanceManager::Initialize(&simSetup);
      12:  
      13:     /* Your application code here */
      14:  
      15:     // free memory
      16:     delete g_SIM;
      17:     return 0;
      18: }

    By default, whenever trying to initialize a SingleInstanceManager object in a second process (as part of launching a new instance of an application) while the first application’s instance already exists, the command line arguments of the second instance will be sent to the first instance which will be notified of the arguments by the handler it has configured. The arguments sent to the first instance can be customized via the setup object (see section "Additional Configuration Options"). This setup object gives you full control over the how the parameters are being sent between applications, as well as other notifications.

    Additional Configuration Options

    The SingleInstanceManager behavior can be customized via various properties of the setup object (SingleInstanceManagerSetup). These properties are outlined in this section. Note that in Native C++, these properties are accessible via "Set…()" and "Get…()" methods and can also be set via the class constructor.

    • The ApplicationId property is used to identify an application and is used as the key by which the application's single instance will be identified. Note that an application ID is unique to each logged on user (that is, if two application instances are running under different users on the same machine, the application IDs will not match). The ApplicationId is the only mandatory property when constructing a SingleInstanceManagerSetup object.
    • The ArgumentsHandler property is used to specify a handler method to receive notifications of incoming arguments (for an example, see section "Accepting Notifications from other Application Instances").
    • The Context property is available only in native code, and is used to specify a context object to be passed to the arguments handler.
       1: void ArgsHandler(LPCWSTR* pArguments, DWORD dwLength, LPVOID pContext)
       2: {
       3:     MyClass *pClass = (MyClass *) pContext;
       4:     pClass->SomeMethod(...);    // Handle incoming arguments
       5: }
       6:  
       7: int _tmain(int argc, _TCHAR* argv[])
       8: {
       9:     MyClass *pClass = new MyClass();
      10:     SingleInstanceManagerSetup simSetup(L"MyApp", ArgsHandler, pClass);
      11:     g_SIM = SingleInstanceManager::Initialize(&simSetup);
      12:  
      13:     // Your application code here
      14:  
      15:     delete g_SIM;
      16:     delete pClass;
      17:     return 0;
      18: }
    • The TerminationOption property allows the user to choose a course of action in cases where an application instance is already running and the current instance needs to be closed (after notifying the original instance of the arguments). The enum allows two possible values:
    • Exit (default) – Exit the current process without returning to the user code. The managed code calls "System.Environment.Exit()" and the native code calls "ExitProcess()", and both use the specified exit code in the ExitCode property.
    • Throw –Throws an exception indicating that another application instance is already running. The user is then able to catch the exception and exit gracefully.
    • The ExitCode property allows specifying the exit code to be used in case the TerminationOption property is set to "Exit" and an application instance is already running. The default value is 0.
    • The ArgumentsProvider property allows you to override the default response for the arguments passed to the first application instance. By default, the arguments passed are the command line arguments of the current process, which uses "Environment.GetCommandLineArgs()" for managed code and "GetCommandLineW()" and "CommandLineToArgvW()" for native code.
    • The Factory property allows the user to customize the argument delivery strategy that is used by the SingleInstanceManager. By default, the "RemotingStrategyFactory" is used for managed code and "NamedPipeStrategyFactory" is used for native code. These factory objects produce "RemotingStrategy" strategy objects and "NamedPipeStrategy" strategy objects respectively.

    The delivery strategy factory is the class used by the SingleInstanceManager to both:

    • Notify the original application instance of the command line arguments, if this application instance is not the first one
    • Receive notification of incoming command line arguments from other application instances if the current instance is the first one

    The specific strategy implementation contains all the logic and code that is required to enable the communication between the two processes. If the default supplied strategy does not meet the user's needs, the user can supply another implementation that can be easily plugged in.

    • The ArgumentsHandlerInvoker is the object used by the SingleInstanceManager to invoke the registered argument handler. By default, the handler is invoked on the thread pool in managed code and directly on the incoming thread in native codeInstance Notification Option
    • The InstanceNotificationOption property is used to determine the behavior when the first application instance is launched under elevated security rights (that is, run as administrator), and the second instance is not an administrator. This enum has two options:
    • NotifyAnyway (default) – Notifies the original application instance anyway.
    • NotifyOnlyIfAdmin – Notifies the first application instance only if the second application instance is also run as an administrator.
    • The DeliveryFailureNotification is used to provide the SingleInstanceManager with a callback method if the delivery of the arguments from the second process to the first one was unsuccessful.

    Follow Yochay on Twitter

    (Post edited by Barbara Alban)

Page 1 of 15 (75 items) 12345...Last