text:
using System;
using System.Windows.Forms;

namespace Universal_THCRAP_Launcher
{
    internal static class Program
    {
        /// <summary>
        ///     The main entry point for the application.
        /// </summary>
        [STAThread]
        private static void Main()
        {
            try
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);

                var mainForm = new MainForm();
                if (!mainForm.InitChecks())
                {
                    return;
                }

                Application.Run(mainForm);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
            }
        }
    }
}


text:
<?xml version="1.0" encoding="utf-8"?>
<root>
  <!--
    Microsoft ResX Schema

    Version 2.0

    The primary goals of this format is to allow a simple XML format
    that is mostly human readable. The generation and parsing of the
    various data types are done through the TypeConverter classes
    associated with the data types.

    Example:

    ... ado.net/XML headers & schema ...
    <resheader name="resmimetype">text/microsoft-resx</resheader>
    <resheader name="version">2.0</resheader>
    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
        <value>[base64 mime encoded serialized .NET Framework object]</value>
    </data>
    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
        <comment>This is a comment</comment>
    </data>

    There are any number of "resheader" rows that contain simple
    name/value pairs.

    Each data row contains a name, and value. The row also contains a
    type or mimetype. Type corresponds to a .NET class that support
    text/value conversion through the TypeConverter architecture.
    Classes that don't support this are serialized and stored with the
    mimetype set.

    The mimetype is used for serialized objects, and tells the
    ResXResourceReader how to depersist the object. This is currently not
    extensible. For a given mimetype the value must be set accordingly:

    Note - application/x-microsoft.net.object.binary.base64 is the format
    that the ResXResourceWriter will generate, however the reader can
    read any of the formats listed below.

    mimetype: application/x-microsoft.net.object.binary.base64
    value   : The object must be serialized with
            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
            : and then encoded with base64 encoding.

    mimetype: application/x-microsoft.net.object.soap.base64
    value   : The object must be serialized with
            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
            : and then encoded with base64 encoding.

    mimetype: application/x-microsoft.net.object.bytearray.base64
    value   : The object must be serialized into a byte array
            : using a System.ComponentModel.TypeConverter
            : and then encoded with base64 encoding.
    -->
  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
    <xsd:element name="root" msdata:IsDataSet="true">
      <xsd:complexType>
        <xsd:choice maxOccurs="unbounded">
          <xsd:element name="metadata">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" />
              </xsd:sequence>
              <xsd:attribute name="name" use="required" type="xsd:string" />
              <xsd:attribute name="type" type="xsd:string" />
              <xsd:attribute name="mimetype" type="xsd:string" />
              <xsd:attribute ref="xml:space" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="assembly">
            <xsd:complexType>
              <xsd:attribute name="alias" type="xsd:string" />
              <xsd:attribute name="name" type="xsd:string" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="data">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
              <xsd:attribute ref="xml:space" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="resheader">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" />
            </xsd:complexType>
          </xsd:element>
        </xsd:choice>
      </xsd:complexType>
    </xsd:element>
  </xsd:schema>
  <resheader name="resmimetype">
    <value>text/microsoft-resx</value>
  </resheader>
  <resheader name="version">
    <value>2.0</value>
  </resheader>
  <resheader name="reader">
    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <resheader name="writer">
    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  <data name="BuildDate" type="System.Resources.ResXFileRef, System.Windows.Forms">
    <value>..\Resources\BuildDate.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;windows-1250</value>
  </data>
  <data name="BuildUser" type="System.Resources.ResXFileRef, System.Windows.Forms">
    <value>..\Resources\BuildUser.txt;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
  </data>
  <data name="Custom" type="System.Resources.ResXFileRef, System.Windows.Forms">
    <value>..\Resources\Custom.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
  </data>
  <data name="Dice" type="System.Resources.ResXFileRef, System.Windows.Forms">
    <value>..\Resources\Dice.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
  </data>
  <data name="Favorite" type="System.Resources.ResXFileRef, System.Windows.Forms">
    <value>..\Resources\Favorite.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
  </data>
  <data name="Game" type="System.Resources.ResXFileRef, System.Windows.Forms">
    <value>..\Resources\Game.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
  </data>
  <data name="GameAndCustom" type="System.Resources.ResXFileRef, System.Windows.Forms">
    <value>..\Resources\GameAndCustom.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
  </data>
  <data name="Shinmera_Banner_5_mini_size" type="System.Resources.ResXFileRef, System.Windows.Forms">
    <value>..\Resources\Shinmera_Banner_5_mini_size.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
  </data>
  <data name="Shinmera_Banner_5_mini_size_hover" type="System.Resources.ResXFileRef, System.Windows.Forms">
    <value>..\Resources\Shinmera_Banner_5_mini_size_hover.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
  </data>
  <data name="Sort_Ascending" type="System.Resources.ResXFileRef, System.Windows.Forms">
    <value>..\Resources\Sort-Ascending.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
  </data>
  <data name="Sort_Decending" type="System.Resources.ResXFileRef, System.Windows.Forms">
    <value>..\Resources\Sort-Descending.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
  </data>
  <data name="Star" type="System.Resources.ResXFileRef, System.Windows.Forms">
    <value>..\Resources\Star.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
  </data>
  <data name="Star_Hollow" type="System.Resources.ResXFileRef, System.Windows.Forms">
    <value>..\Resources\Star_hollow.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
  </data>
  <data name="Trash" type="System.Resources.ResXFileRef, System.Windows.Forms">
    <value>..\Resources\Trash.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
  </data>
</root>

repo_name: thpatch/Universal-THCRAP-Launcher

repo_language: C#

mime_type: text/plain


text:
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.42000
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace Universal_THCRAP_Launcher.Properties {
    using System;

    /// <summary>
    ///   A strongly-typed resource class, for looking up localized strings, etc.
    /// </summary>
    // This class was auto-generated by the StronglyTypedResourceBuilder
    // class via a tool like ResGen or Visual Studio.
    // To add or remove a member, edit your .ResX file then rerun ResGen
    // with the /str option, or rebuild your VS project.
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    internal class Resources {

        private static global::System.Resources.ResourceManager resourceMan;

        private static global::System.Globalization.CultureInfo resourceCulture;

        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
        internal Resources() {
        }

        /// <summary>
        ///   Returns the cached ResourceManager instance used by this class.
        /// </summary>
        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
        internal static global::System.Resources.ResourceManager ResourceManager {
            get {
                if (object.ReferenceEquals(resourceMan, null)) {
                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Universal_THCRAP_Launcher.Properties.Resources", typeof(Resources).Assembly);
                    resourceMan = temp;
                }
                return resourceMan;
            }
        }

        /// <summary>
        ///   Overrides the current thread's CurrentUICulture property for all
        ///   resource lookups using this strongly typed resource class.
        /// </summary>
        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
        internal static global::System.Globalization.CultureInfo Culture {
            get {
                return resourceCulture;
            }
            set {
                resourceCulture = value;
            }
        }

        /// <summary>
        ///   Looks up a localized string similar to 2021. 04. 05.  0:13:35,51
        ///Central Europe Standard Time.
        /// </summary>
        internal static string BuildDate {
            get {
                return ResourceManager.GetString("BuildDate", resourceCulture);
            }
        }

        /// <summary>
        ///   Looks up a localized string similar to Tudi20
        ///tudorkae@gmail.com
        ///.
        /// </summary>
        internal static string BuildUser {
            get {
                return ResourceManager.GetString("BuildUser", resourceCulture);
            }
        }

        /// <summary>
        ///   Looks up a localized resource of type System.Drawing.Bitmap.
        /// </summary>
        internal static System.Drawing.Bitmap Custom {
            get {
                object obj = ResourceManager.GetObject("Custom", resourceCulture);
                return ((System.Drawing.Bitmap)(obj));
            }
        }

        /// <summary>
        ///   Looks up a localized resource of type System.Drawing.Bitmap.
        /// </summary>
        internal static System.Drawing.Bitmap Dice {
            get {
                object obj = ResourceManager.GetObject("Dice", resourceCulture);
                return ((System.Drawing.Bitmap)(obj));
            }
        }

        /// <summary>
        ///   Looks up a localized resource of type System.Drawing.Bitmap.
        /// </summary>
        internal static System.Drawing.Bitmap Favorite {
            get {
                object obj = ResourceManager.GetObject("Favorite", resourceCulture);
                return ((System.Drawing.Bitmap)(obj));
            }
        }

        /// <summary>
        ///   Looks up a localized resource of type System.Drawing.Bitmap.
        /// </summary>
        internal static System.Drawing.Bitmap Game {
            get {
                object obj = ResourceManager.GetObject("Game", resourceCulture);
                return ((System.Drawing.Bitmap)(obj));
            }
        }

        /// <summary>
        ///   Looks up a localized resource of type System.Drawing.Bitmap.
        /// </summary>
        internal static System.Drawing.Bitmap GameAndCustom {
            get {
                object obj = ResourceManager.GetObject("GameAndCustom", resourceCulture);
                return ((System.Drawing.Bitmap)(obj));
            }
        }

        /// <summary>
        ///   Looks up a localized resource of type System.Drawing.Bitmap.
        /// </summary>
        internal static System.Drawing.Bitmap Shinmera_Banner_5_mini_size {
            get {
                object obj = ResourceManager.GetObject("Shinmera_Banner_5_mini_size", resourceCulture);
                return ((System.Drawing.Bitmap)(obj));
            }
        }

        /// <summary>
        ///   Looks up a localized resource of type System.Drawing.Bitmap.
        /// </summary>
        internal static System.Drawing.Bitmap Shinmera_Banner_5_mini_size_hover {
            get {
                object obj = ResourceManager.GetObject("Shinmera_Banner_5_mini_size_hover", resourceCulture);
                return ((System.Drawing.Bitmap)(obj));
            }
        }

        /// <summary>
        ///   Looks up a localized resource of type System.Drawing.Bitmap.
        /// </summary>
        internal static System.Drawing.Bitmap Sort_Ascending {
            get {
                object obj = ResourceManager.GetObject("Sort_Ascending", resourceCulture);
                return ((System.Drawing.Bitmap)(obj));
            }
        }

        /// <summary>
        ///   Looks up a localized resource of type System.Drawing.Bitmap.
        /// </summary>
        internal static System.Drawing.Bitmap Sort_Decending {
            get {
                object obj = ResourceManager.GetObject("Sort_Decending", resourceCulture);
                return ((System.Drawing.Bitmap)(obj));
            }
        }

        /// <summary>
        ///   Looks up a localized resource of type System.Drawing.Bitmap.
        /// </summary>
        internal static System.Drawing.Bitmap Star {
            get {
                object obj = ResourceManager.GetObject("Star", resourceCulture);
                return ((System.Drawing.Bitmap)(obj));
            }
        }

        /// <summary>
        ///   Looks up a localized resource of type System.Drawing.Bitmap.
        /// </summary>
        internal static System.Drawing.Bitmap Star_Hollow {
            get {
                object obj = ResourceManager.GetObject("Star_Hollow", resourceCulture);
                return ((System.Drawing.Bitmap)(obj));
            }
        }

        /// <summary>
        ///   Looks up a localized resource of type System.Drawing.Bitmap.
        /// </summary>
        internal static System.Drawing.Bitmap Trash {
            get {
                object obj = ResourceManager.GetObject("Trash", resourceCulture);
                return ((System.Drawing.Bitmap)(obj));
            }
        }
    }
}


text:
//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by a tool.
//     Runtime Version:4.0.30319.42000
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

namespace Universal_THCRAP_Launcher.Properties {

    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0")]
    internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {

        private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));

        public static Settings Default {
            get {
                return defaultInstance;
            }
        }
    }
}


text:
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
  <Profiles />
  <Settings />
</SettingsFile>


text:
using System.Reflection;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Universal THCRAP Launcher")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Tudi20 @ THPATCH")]
[assembly: AssemblyProduct("Universal THCRAP Launcher")]
[assembly: AssemblyCopyright("Copyright © THPATCH 2020")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components.  If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("e8802a2f-80f1-4727-a97d-78ded7f24e92")]

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.2.5.*")]


native: Magyar

english: Hungarian

settings: Beállítások

closeOnExit: Bezárás a futtatható indulásakor

langCredits: Fordította: {0}

and: és

downloadAll: Összes nyelv letöltése

downloading: Letöltés...

hidePatchExtension: Futtatási konfiguráció (patch stack) kiterjesztésének elrejtése

showVanilla: Mutassa a Szűz (THCRAP nélküli) indítási lehetőséget futtatási konfigurációk között

onlyOneExe: Csak egyetlen futtathatót engedélyezzen futtatni

label_gameNaming: Futtathatók elnevezési módszere:

onlyOneUTL: Csak egyetlen UTL futtatásának engedélyezése

showGameId: Mutassa a játék azonosítóját (thXX)

general: Átlagos

namingType:
thXX
Kezdőbetük
Rövid név
Hosszú név

error: Hiba

thcrap_loader:
thcrap_loader.exe nem található.
Bizonyosodj meg róla, hogy az alkalmazás mellette van!

gamesJs:
games.js nem található.
Bizonyosodj meg róla, hogy elöször a(z) thcrap_configure.exe fájlt futtatod!

patchStacks:
Futtatási konfigurációkból (patch stack) álló konfig fájlok nem találhatóak.
Bizonyosodj meg róla, hogy elöször a(z) thcrap_configure.exe fájlt futtatod!

jsonParser: A Newtonsoft.Json.dll hiányzik. Bizonyosodj meg róla, hogy azt is átmásoltad.

file: A(z) {0} fájl hiányzik. Bizonyosodj meg róla, hogy ez nem így van.

oops: Valami hiba történt...

noneSelected:
Egy futtatási konfiguráció (patch stack) vagy futtatható (executable) sincs kiváalasztva!
Kérlek, válassz ki egyet!

downloadError:
Nem sikerült a nyelvi fájlok letöltése a GitHubról.
Ennek lehetséges indokai:
- Nem vagy csatlakozva az Internethez.
- A program annyira elavult, hogy már nem létezik a GitHub repo.
- Egy olyan jövőben vagy, ahol nincs GitHub vagy Internet.

alreadyRunning: A program már fut. Vagy kapcsold ki a beállításd, hogy ezt ellenőrize, vagy zárd be a másik programot.

caption: Megjegyzés

text: Az indító eltűnik konfigurálás közben...

caption: Gyorsgombok

text:
Alt + F4: Alklamazás bezárása (alapértelmezett Windows rövidítés)
Ctrl + R: Alkalmazás újraindítása
Ctrl + O: Kiválasztott futtatási konfiguráció (patch stack) megnyitása
F1: Gyorsgombok mutatása (ez az ablak)
F2: Kiválasztott elem kedvencnek jejölése a kiválasztott listán

file: Univerzális THCRAP Indító

desc: Parancsikon UTL-hez

utl: Univerzális THCRAP Indító

running: Fut:

menuStrip:
Alkalmazás
Parancsikon létrehozása az asztalon
Parancsikon létrehozása a Start menüben
Beállítások...
Újraindítás
Kilépés

menuStrip:
Visszajelzés
Hiba jelentése
Egyéb

menuStrip: Súgó Gyorsgombok

vanilla: Szűz

custom: Környezet Egyedi Program

hided: A program minimalizálva lett az értesítési területre és futni fog a háttérben.

startButton: Futtatható indítása a kiválasztott beállításokkal

sortAZ: Rendezés ábécésorrendbe

filterFav: Szűrés kedvencek alapján

filterByType: Szűrés típus alapján

patchLB: Futtatási konfiguráció (patch stack) kiválasztása

gameLB: Futtatható (executable) kiválasztása

patchFav: Futtatási konfiguráció (patch stack) hozzáadása a kedvencekhez (vagy használd az F2-t, ha akítvan ki van választva)

gamesFav: Futtatható (executable) hozzáadása a kedvencekhez (vagy használd az F2-t, ha aktívan ki van választva)

random: Véletlenszerű elem kiválasztása

delete: Kiválasztott konfiguráció törlése a lemezről


text:
/* Copyright 2012 Marco Minerva, marco.minerva@gmail.com

   From code written by Michael Potter
   More information here: http://www.codeproject.com/KB/cs/cssingprocess.aspx

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;

namespace JumpListHelpers
{
    ///
    /// SingleProgamInstance uses a mutex synchronization object
    /// to ensure that only one copy of process is running at
    /// a particular time. It also allows for UI identification
    /// of the intial process by bring that window to the foreground.
    ///
    internal sealed class SingleProgramInstance : IDisposable
    {
        #region Platform Invoke

        [DllImport("user32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);
        [DllImport("user32.dll")]
        private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
        [DllImport("user32.dll")]
        private static extern bool IsIconic(IntPtr hWnd);

        private const int SW_RESTORE = 9;

        #endregion

        private Mutex processSync = null;

        ///
        /// Initializes a new instance of the <see cref="SingleProgramInstance"/> class.
        ///
        public SingleProgramInstance()
            : this(string.Empty)
        { }

        ///
        /// Initializes a new instance of the <see cref="SingleProgramInstance"/> class using the specified string as the process identifier.
        ///
        /// <param name="identifier">The string that represents the process identifier.</param>
        public SingleProgramInstance(string identifier)
        {
            processSync = new Mutex(false,
                Assembly.GetExecutingAssembly().GetName().Name + identifier);
        }

        ///
        /// Gets a value indicating whether this instance is single instance.
        ///
        /// <value>
        ///     <c>true</c> if this instance is single instance; otherwise, <c>false</c>.
        /// </value>
        public bool IsSingleInstance
        {
            get
            {
                if (processSync.WaitOne(0, false))
                    return true;
                else
                    return false;
            }
        }

        ///
        /// If another instance of the application is already running, raises the other process.
        ///
        public IntPtr RaiseOtherProcess()
        {
            Process proc = Process.GetCurrentProcess();
            // Using Process.ProcessName does not function properly when
            // the name exceeds 15 characters. Using the assembly name
            // takes care of this problem and is more accruate than other
            // work arounds.
            string assemblyName = Assembly.GetEntryAssembly().GetName().Name;
            foreach (Process otherProc in Process.GetProcessesByName(assemblyName))
            {
                //ignore this process
                if (proc.Id != otherProc.Id)
                {
                    // Found a "same named process".
                    // Assume it is the one we want brought to the foreground.
                    // Use the Win32 API to bring it to the foreground.
                    IntPtr hWnd = otherProc.MainWindowHandle;
                    if (IsIconic(hWnd))
                        ShowWindowAsync(hWnd, SW_RESTORE);
                    SetForegroundWindow(hWnd);
                    return hWnd;
                }
            }

            return IntPtr.Zero;
        }

        #region Implementation of IDisposable

        ///
        /// Releases unmanaged resources and performs other cleanup operations before the
        /// <see cref="SingleProgramInstance"/> is reclaimed by garbage collection.
        ///
        ~SingleProgramInstance()
        {
            //Release mutex (if necessary)
            //This should have been accomplished using Dispose()
            this.FreeResources();
        }

        private void FreeResources()
        {
            try
            {
                if (processSync.WaitOne(0, false))
                {
                    //If we own the mutex than release it so that
                    //other "same" processes can now start.
                    processSync.ReleaseMutex();
                }
                processSync.Close();
            }
            catch { }
        }

        ///
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        ///
        public void Dispose()
        {
            //release mutex (if necessary) and notify
            //the garbage collector to ignore the destructor
            this.FreeResources();
            GC.SuppressFinalize(this);
        }

        #endregion
    }
}


text:
/* Copyright 2012 Marco Minerva, marco.minerva@gmail.com

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System;
using System.Linq;
using System.Windows.Forms;

namespace JumpListHelpers
{
    public static class ProgramManager
    {
        public static void Run(Type formType, string mainFormTitle)
        {
            JumpListHelpers.WindowsMessageHelper.MainFormName = mainFormTitle;
            using (SingleProgramInstance spi = new SingleProgramInstance())
            {
                if (spi.IsSingleInstance)
                {
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);

                    Form form = (Form)Activator.CreateInstance(formType);
                    JumpListMainFormBase mainForm = form as JumpListMainFormBase;
                    if (mainForm != null)
                    {
                        var args = string.Join(" ", Environment.GetCommandLineArgs().Skip(1).ToArray());
                        mainForm.OnStartupInstance(new StartupEventArgs(true, args));
                    }
                    Application.Run(form);
                }
                else
                {
                    // The program has already been started, so pass the arguments to it.
                    IntPtr handle = spi.RaiseOtherProcess();
                    HandleCommand(handle);
                }
            }
        }

        private static void HandleCommand(IntPtr handle)
        {
            var commandLineArgs = Environment.GetCommandLineArgs();
            if (commandLineArgs.Length > 1 && commandLineArgs[1].StartsWith(WindowsMessageHelper.COMMAND_PREFIX))
            {
                // It is a Jump List command.
                string temp = commandLineArgs[1].Split(':').LastOrDefault();
                int commandNumber;
                if (int.TryParse(temp, out commandNumber))
                    WindowsMessageHelper.SendMessage(handle, commandNumber);
            }
            else
            {
                var args = string.Join(" ", commandLineArgs.Skip(1).ToArray());
                WindowsMessageHelper.SendMessage(handle, args);
            }
        }
    }
}


text:
using System;
using System.Windows.Forms;

namespace JumpListHelpers
{
    public partial class JumpListMainFormBase : Form
    {
        public JumpListMainFormBase()
        {
            InitializeComponent();
        }

        public event EventHandler<CommandEventArgs> JumpListCommandReceived;
        public event EventHandler<StartupEventArgs> StarupInstance;

        internal void OnStartupInstance(StartupEventArgs e)
        {
            if (StarupInstance != null)
                StarupInstance(this, e);
        }

        internal void OnJumpListCommandReceived(CommandEventArgs e)
        {
            if (JumpListCommandReceived != null)
                JumpListCommandReceived(this, e);
        }

        protected override void WndProc(ref Message m)
        {
            if (WindowsMessageHelper.WindowMessages.ContainsKey(m.Msg))
            {
                OnJumpListCommandReceived(new CommandEventArgs(WindowsMessageHelper.WindowMessages[m.Msg]));
            }
            else if (m.Msg == WindowsMessageHelper.WM_COPYDATA)
            {
                string arguments = WindowsMessageHelper.GetArguments(m.LParam);
                OnStartupInstance(new StartupEventArgs(false, arguments));
            }
            else
            {
                base.WndProc(ref m);
            }
        }
    }
}


text:
namespace JumpListHelpers
{
    partial class JumpListMainFormBase
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.Text = "JumpListMainFormBase";
        }

        #endregion
    }
}


text:
<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Windows7APICodePack-Core" version="1.1.0.0" />
  <package id="Windows7APICodePack-Shell" version="1.1.0.0" />
</packages>


text:
/* Copyright 2012 Marco Minerva, marco.minerva@gmail.com

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace JumpListHelpers
{
    internal class WindowsMessageHelper
    {
        #region Platform Invoke

        internal const int WM_COPYDATA = 0x004A;

        private struct CopyDataStruct : IDisposable
        {
            public IntPtr dwData;
            public int cbData;
            public IntPtr lpData;

            public void Dispose()
            {
                if (lpData != IntPtr.Zero)
                {
                    LocalFree(this.lpData);
                    lpData = IntPtr.Zero;
                }
            }
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll")]
        private static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, ref CopyDataStruct lParam);

        [DllImport("user32.dll")]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll")]
        private static extern int RegisterWindowMessage(string msgName);

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern IntPtr LocalAlloc(int flag, int size);

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern IntPtr LocalFree(IntPtr p);

        #endregion

        public static string MainFormName { get; set; }

        public static Dictionary<int, string> WindowMessages { get; set; }
        internal const string COMMAND_PREFIX = "__JumpListCommand:";

        static WindowsMessageHelper()
        {
            WindowMessages = new Dictionary<int, string>();
        }

        public static int RegisterCommand(string commandName)
        {
            int command = RegisterWindowMessage(commandName);
            WindowMessages[command] = commandName;
            return command;
        }

        public static bool SendMessage(IntPtr handle, int msgId)
        {
            if (handle == IntPtr.Zero)
            {
                handle = FindWindow(null, MainFormName);
                if (handle == IntPtr.Zero) return false;
            }

            long result = SendMessage(handle, msgId, IntPtr.Zero, IntPtr.Zero);

            if (result == 0) return true;
            else return false;
        }

        public static bool SendMessage(IntPtr handle, string args)
        {
            if (handle == IntPtr.Zero)
            {
                handle = FindWindow(null, MainFormName);
                if (handle == IntPtr.Zero) return false;
            }

            WindowsMessageHelper.CopyDataStruct cds = new WindowsMessageHelper.CopyDataStruct();
            try
            {
                cds.cbData = (args.Length + 1) * 2;
                cds.lpData = WindowsMessageHelper.LocalAlloc(0x40, cds.cbData);
                Marshal.Copy(args.ToCharArray(), 0, cds.lpData, args.Length);
                cds.dwData = (IntPtr)1;
                WindowsMessageHelper.SendMessage(handle, WindowsMessageHelper.WM_COPYDATA, IntPtr.Zero, ref cds);
                return true;
            }
            catch
            {
                return false;
            }
            finally
            {
                cds.Dispose();
            }
        }

        public static string GetArguments(IntPtr lParam)
        {
            string arguments = null;
            try
            {
                CopyDataStruct st = (CopyDataStruct)Marshal.PtrToStructure(lParam, typeof(CopyDataStruct));
                arguments = Marshal.PtrToStringUni(st.lpData);
            }
            catch { }

            return arguments;
        }
    }
}


text:
/* Copyright 2012 Marco Minerva, marco.minerva@gmail.com

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

   THIS FILE IS MODIFIED TO FIT THE PURPOSE OF THIS PROGRAM.
*/

using System;
using System.Collections.Generic;
using System.Reflection;

namespace JumpListHelpers
{
    public static class JumpListManager
    {
        private static Microsoft.WindowsAPICodePack.Taskbar.JumpList list;
        private static Dictionary<string, Microsoft.WindowsAPICodePack.Taskbar.JumpListCustomCategory> categories;

        public static bool AutoRefresh { get; set; }

        static JumpListManager()
        {
            list = Microsoft.WindowsAPICodePack.Taskbar.JumpList.CreateJumpList();
            list.ClearAllUserTasks();
            list.Refresh();
            categories = new Dictionary<string, Microsoft.WindowsAPICodePack.Taskbar.JumpListCustomCategory>();
        }

        #region AddUserTask overloads

        public static void AddTaskLink(string title, string path)
        {
            AddTaskLink(title, path, null, null, 0);
        }

        public static void AddTaskLink(string title, string path, string arguments, string iconPath)
        {
            AddTaskLink(title, path, arguments, iconPath, 0);
        }

        public static void AddTaskLink(string title, string path, string iconPath, int iconNumber)
        {
            AddTaskLink(title, path, null, iconPath, iconNumber);
        }

        public static void AddTaskLink(string title, string path, string iconPath)
        {
            AddTaskLink(title, path, null, iconPath, 0);
        }

        public static void AddTaskLink(string title, string path, string arguments, string iconPath, int iconNumber)
        {
            var icon = CreateIconReference(iconPath, iconNumber);
            AddTaskLink(title, path, arguments, icon);
        }

        private static void AddTaskLink(string title, string path, string arguments, Microsoft.WindowsAPICodePack.Shell.IconReference? icon)
        {
            var task = CreateJumpListLink(title, path, arguments, icon);
            list.AddUserTasks(task);

            if (AutoRefresh)
                list.Refresh();
        }

        #endregion

        #region Add Custom Links

        public static void AddCategoryLink(string categoryName, string title, string path)
        {
            AddCategoryLink(categoryName, title, path, null, null, 0);
        }

        public static void AddCategoryLink(string categoryName, string title, string path, string arguments, string iconPath)
        {
            AddCategoryLink(categoryName, title, path, arguments, iconPath, 0);
        }

        public static void AddCategoryLink(string categoryName, string title, string path, string iconPath, int iconNumber)
        {
            AddCategoryLink(categoryName, title, path, null, iconPath, iconNumber);
        }

        public static void AddCategoryLink(string categoryName, string title, string path, string iconPath)
        {
            AddCategoryLink(categoryName, title, path, null, iconPath, 0);
        }

        public static void AddCategoryLink(string categoryName, string title, string path, string arguments, string iconPath, int iconNumber)
        {
            var icon = CreateIconReference(iconPath, iconNumber);
            AddCategoryLink(categoryName, title, path, arguments, icon);
        }

        private static void AddCategoryLink(string categoryName, string title, string path, string arguments, Microsoft.WindowsAPICodePack.Shell.IconReference? icon)
        {
            var task = CreateJumpListLink(title, path, arguments, icon);
            Microsoft.WindowsAPICodePack.Taskbar.JumpListCustomCategory category;
            if (!categories.TryGetValue(categoryName, out category))
            {
                category = new Microsoft.WindowsAPICodePack.Taskbar.JumpListCustomCategory(categoryName);
                categories[categoryName] = category;
                list.AddCustomCategories(category);
            }

            category.AddJumpListItems(task);

            if (AutoRefresh)
                list.Refresh();
        }

        #endregion

        #region Add Category Self Links

        public static void AddCategorySelfLink(string categoryName, string title, string commandName)
        {
            AddCategorySelfLink(categoryName, title, commandName, null, 0);
        }

        public static void AddCategorySelfLink(string categoryName, string title, string commandName, string iconPath)
        {
            AddCategorySelfLink(categoryName, title, commandName, iconPath, 0);
        }

        public static void AddCategorySelfLink(string categoryName, string title, string commandName, string iconPath, int iconNumber)
        {
            if (string.IsNullOrWhiteSpace(commandName))
                throw new ArgumentNullException("commandName");

            var icon = CreateIconReference(iconPath, iconNumber);

            // Register the command and get the associated number.
            int command = WindowsMessageHelper.RegisterCommand(commandName);
            AddCategoryLink(categoryName, title, Assembly.GetEntryAssembly().Location, WindowsMessageHelper.COMMAND_PREFIX + command.ToString(), icon);
        }

        #endregion

        #region Add Task Self Links

        public static void AddTaskSelfLink(string title, string commandName)
        {
            AddTaskSelfLink(title, commandName, null, 0);
        }

        public static void AddTaskSelfLink(string title, string commandName, string iconPath)
        {
            AddTaskSelfLink(title, commandName, iconPath, 0);
        }

        public static void AddTaskSelfLink(string title, string commandName, string iconPath, int iconNumber)
        {
            if (string.IsNullOrWhiteSpace(commandName))
                throw new ArgumentNullException("commandName");

            var icon = CreateIconReference(iconPath, iconNumber);

            // Register the command and get the associated number.
            int command = WindowsMessageHelper.RegisterCommand(commandName);
            AddTaskLink(title, Assembly.GetEntryAssembly().Location, WindowsMessageHelper.COMMAND_PREFIX + command.ToString(), icon);
        }

        #endregion

        public static void AddTaskSeparator()
        {
            list.AddUserTasks(new Microsoft.WindowsAPICodePack.Taskbar.JumpListSeparator());
        }

        private static Microsoft.WindowsAPICodePack.Taskbar.JumpListLink CreateJumpListLink(string title, string path, string arguments, Microsoft.WindowsAPICodePack.Shell.IconReference? icon)
        {
            var task = new Microsoft.WindowsAPICodePack.Taskbar.JumpListLink(path, title);
            if (icon.HasValue)
                task.IconReference = icon.Value;
            task.Arguments = arguments;

            return task;
        }

        private static Microsoft.WindowsAPICodePack.Shell.IconReference? CreateIconReference(string iconPath, int iconNumber)
        {
            Microsoft.WindowsAPICodePack.Shell.IconReference? icon = null;
            if (!string.IsNullOrEmpty(iconPath))
                icon = new Microsoft.WindowsAPICodePack.Shell.IconReference(iconPath, iconNumber);

            return icon;
        }

        public static void Refresh()
        {
            list.Refresh();
        }

        public static void Clear()
        {
            list = Microsoft.WindowsAPICodePack.Taskbar.JumpList.CreateJumpList();
            list.ClearAllUserTasks();
            list.Refresh();
            categories = new Dictionary<string, Microsoft.WindowsAPICodePack.Taskbar.JumpListCustomCategory>();
        }

        public static void AddToRecent(string path)
        {
            Microsoft.WindowsAPICodePack.Taskbar.JumpList.AddToRecent(path);
        }

        public static bool ShowRecentFiles
        {
            get
            {
                if (list.KnownCategoryToDisplay == Microsoft.WindowsAPICodePack.Taskbar.JumpListKnownCategoryType.Recent)
                    return true;

                return false;
            }
            set
            {
                if (value)
                    list.KnownCategoryToDisplay = Microsoft.WindowsAPICodePack.Taskbar.JumpListKnownCategoryType.Recent;
                else
                    list.KnownCategoryToDisplay = Microsoft.WindowsAPICodePack.Taskbar.JumpListKnownCategoryType.Neither;
            }
        }

        public static bool ShowFrequentFiles
        {
            get
            {
                if (list.KnownCategoryToDisplay == Microsoft.WindowsAPICodePack.Taskbar.JumpListKnownCategoryType.Frequent)
                    return true;

                return false;
            }
            set
            {
                if (value)
                    list.KnownCategoryToDisplay = Microsoft.WindowsAPICodePack.Taskbar.JumpListKnownCategoryType.Frequent;
                else
                    list.KnownCategoryToDisplay = Microsoft.WindowsAPICodePack.Taskbar.JumpListKnownCategoryType.Neither;
            }
        }
    }
}


text:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>8.0.30703</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{4BFF1C22-01E4-4557-BFD6-F24325615599}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>JumpListHelpers</RootNamespace>
    <AssemblyName>JumpListHelpers</AssemblyName>
    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup>
    <SignAssembly>false</SignAssembly>
  </PropertyGroup>
  <PropertyGroup>
    <AssemblyOriginatorKeyFile>
    </AssemblyOriginatorKeyFile>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="Microsoft.WindowsAPICodePack">
      <HintPath>..\packages\Windows7APICodePack-Core.1.1.0.0\lib\Microsoft.WindowsAPICodePack.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.WindowsAPICodePack.Shell">
      <HintPath>..\packages\Windows7APICodePack-Shell.1.1.0.0\lib\Microsoft.WindowsAPICodePack.Shell.dll</HintPath>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Drawing" />
    <Reference Include="System.Windows.Forms" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Data" />
    <Reference Include="System.Xml" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="EventArgs\CommandEventArgs.cs" />
    <Compile Include="JumpListMainFormBase.cs">
      <SubType>Form</SubType>
    </Compile>
    <Compile Include="JumpListMainFormBase.Designer.cs">
      <DependentUpon>JumpListMainFormBase.cs</DependentUpon>
    </Compile>
    <Compile Include="JumpListManager.cs" />
    <Compile Include="ProgramManager.cs" />
    <Compile Include="SingleProgamInstance.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
    <Compile Include="EventArgs\StartupEventArgs.cs" />
    <Compile Include="WindowsMessageHelper.cs" />
  </ItemGroup>
  <ItemGroup>
    <None Include="packages.config" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
       Other similar extension points exist, see Microsoft.Common.targets.
  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
  -->
</Project>


text:
/* Copyright 2012 Marco Minerva, marco.minerva@gmail.com

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System;

namespace JumpListHelpers
{
    public class CommandEventArgs : EventArgs
    {
        public string CommandName { get; internal set; }

        public CommandEventArgs(string commandName)
        {
            CommandName = commandName;
        }
    }
}


text:
/* Copyright 2012 Marco Minerva, marco.minerva@gmail.com

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

using System;

namespace JumpListHelpers
{
    public class StartupEventArgs : EventArgs
    {
        public string CommandLineArgs { get; internal set; }
        public bool IsFirstInstance { get; internal set; }

        public StartupEventArgs(bool isFirstInstance, string commandLineArgs)
        {
            IsFirstInstance = isFirstInstance;
            CommandLineArgs = commandLineArgs;
        }
    }
}


text:
using System.Reflection;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("JumpListHelpers")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("JumpListHelpers")]
[assembly: AssemblyCopyright("Copyright © Marco Minerva [marco.minerva@gmail.com] 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Setting ComVisible to false makes the types in this assembly not visible
// to COM components.  If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("0f1339dd-b341-451e-9996-741cc8f484c0")]

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]


text:
pyxll-examples
==============

Example code to be used with PyXLL.

See http://www.pyxll.com for information about how PyXLL can be used to embed Python code in Excel.

repo_name: pyxll/pyxll-examples

repo_language: Python


text:
"""
An Excel function for creating new named Excel functions from
Python expressions.

Excel functions are created by building a new Python function that
evaluates the expression, exposed to Excel using the xl_func
decorator.

The 'recalc_on_open' option is used so that the functions are
available as soon as the workbook containing them is opened with
the need to recalculate.
"""
from pyxll import xl_func

@xl_func("str name, str[] args, str expr, str return_type, str[] imports: str", recalc_on_open=True)
def pylambda(name, args, expr, return_type="var", imports=[]):
    """
    Create a new Excel function that evaluates a Python expression.

    :param name: Name of the new Excel function.
    :param args: List of arguments with optional types.
    :param expr: Python expression that will be the body of the function.
    :param return_type: Return type of the Excel function.
    :param imports: List of Python packages to import.
    """
    # Get the argument names and types
    arg_names = []
    arg_types = []
    for arg in args:
        arg_name, *arg_type = map(str.strip, arg.split(":", 1))
        arg_type = arg_type[0] if arg_type else "var"
        arg_names.append(arg_name)
        arg_types.append(arg_type)

    # Build a signature string using the argument types
    signature = ", ".join([f"{t} {n}" for n, t in zip(arg_names, arg_types)])
    signature += f": {return_type}"

    # Build the Python function as a string using the @xl_func decorator
    func = f"""
@xl_func("{signature}", name="{name}")
def func({', '.join(arg_names)}):
    return {expr}
"""

    # Create a namespace dictionary to exec the code in
    namespace = {
        "xl_func": xl_func
    }

    # Import and add any modules to the namespace
    for module_name in imports:
        module = __import__(module_name)
        namespace[module.__name__] = module

    # Exec the string to build the function and register it
    exec(func, namespace, namespace)

    return f"[{name}]"


text:
# PyLambda

An example showing how to build new Excel functions using Python expressions
declared as data in an Excel workbook.

Inspired by the standard LAMBDA function added to Excel 365, but using Python
expressions instead of an Excel formula.

Defining functions in an Excel workbook shouldn't be considered "best practice" as
it limits the ability to test and version control code, but being able to
evaluate Python expressions entered in Excel may be useful when used sparingly!

See pylambda.xlsx in this folder for example usage.


text:
"""
Get BitMEX prices into Excel using websockets and PyXLL RTD functions.

Requires:
- Python 3.5 or higher
- websockets

>> pip install websockets

See https://pyxll.medium.com/live-streaming-crypto-prices-in-excel-aaa41628bc53
"""
from pyxll import xl_func, RTD, get_event_loop
import websockets
import asyncio
import json

class BitMex:
    """Class to manage subscriptions to instrument prices."""

    URI = "wss://www.bitmex.com/realtime"

    def __init__(self, loop=None):
        self.__websocket = None
        self.__running = False
        self.__running_task = None
        self.__subscriptions = {}
        self.__data = {}
        self.__lock = asyncio.Lock(loop=loop)

    async def __connect(self):
        # Connect to the websocket API and start the __run coroutine
        self.__running = True
        self.__websocket = await websockets.connect(self.URI)
        self.__connecting_task = None
        self.__running_task = asyncio.create_task(self.__run())

    async def __disconnect(self):
        # Close the websocket and wait for __run to complete
        self.__running = False
        await self.__websocket.close()
        self.__websocket = None
        await self.__running_task

    async def __run(self):
        # Read from the websocket until disconnected
        while self.__running:
            msg = await self.__websocket.recv()
            await self.__process_message(json.loads(msg))

    async def __process_message(self, msg):
        if msg.get("table", None) == "instrument":
            # Extract the data from the message, update our data dictionary and notify subscribers
            for data in msg.get("data", []):
                symbol = data["symbol"]
                timestamp = data["symbol"]

                # Update the latest values in our data dictionary and notify any subscribers
                tasks = []
                subscribers = self.__subscriptions.get(symbol, {})
                latest = self.__data.setdefault(symbol, {})
                for field, value in data.items():
                    latest[field] = (value, timestamp)

                    # Notify the subscribers with the updated field
                    for subscriber in subscribers.get(field, []):
                        tasks.append(subscriber(symbol, field, value, timestamp))

                # await all the tasks from the subscribers
                if tasks:
                    await asyncio.wait(tasks)

    async def subscribe(self, symbol, field, callback):
        """Subscribe to updates for a specific symbol and field.

        The callback will be called as 'await callback(symbol, field, value, timestamp)'
        whenever an update is received.
        """
        async with self.__lock:
            # Connect the websocket if necessary
            if self.__websocket is None:
                await self.__connect()

            # Send the subscribe message if we're not already subscribed
            if symbol not in self.__subscriptions:
                msg = {"op": "subscribe", "args": [f"instrument:{symbol}"]}
                await self.__websocket.send(json.dumps(msg))

            # Add the subscriber to the dict of subscriptions
            self.__subscriptions.setdefault(symbol, {}).setdefault(field, []).append(callback)

            # Call the callback with the latest data
            data = self.__data.get(symbol, {})
            if field in data:
                (value, timestamp) = data[field]
                await callback(symbol, field, value, timestamp)

    async def unsubscribe(self, symbol, field, callback):
        async with self.__lock:
            # Remove the subscriber from the list of subscriptions
            self.__subscriptions[symbol][field].remove(callback)
            if not self.__subscriptions[symbol][field]:
                del self.__subscriptions[symbol][field]

            # Unsubscribe if we no longer have any subscriptions for this instrument
            if not self.__subscriptions[symbol]:
                msg = {"op": "unsubscribe", "args": [f"instrument:{symbol}"]}
                await self.__websocket.send(json.dumps(msg))
                del self.__subscriptions[symbol]
                self.__data.pop(symbol, None)

            # Disconnect if we no longer have any subscriptions
            if not self.__subscriptions:
                async with self.__lock:
                    await self.__disconnect()

class BitMexRTD(RTD):
    """RTD class for subscribing to BitMEX prices using the
    BitMex class above.
    """

    # Use a single BitMex object for all RTD functions
    _bitmex = BitMex(get_event_loop())

    def __init__(self, symbol, field):
        super().__init__(value="Waiting...")
        self.__symbol = symbol
        self.__field = field

    async def connect(self):
        # Subscribe to BitMix updates when Excel connects to the RTD object
        await self._bitmex.subscribe(self.__symbol, self.__field, self.__update)

    async def disconnect(self):
        # Unsubscribe to BitMix updates when Excel disconnects from the RTD object
        await self._bitmex.unsubscribe(self.__symbol, self.__field, self.__update)

    async def __update(self, symbol, field, value, timestamp):
        # Update the value in Excel
        self.value = value

@xl_func("string symbol, string field: rtd", recalc_on_open=True)
def bitmex_rtd(symbol, field="lastPrice"):
    """Subscribe to BitMEX prices for a given symbol."""
    return BitMexRTD(symbol, field)

if __name__ == "__main__":

    async def main():
        # This is the callback that will be called whenever there's an update
        async def callback(symbol, field, value, timestamp):
            print((symbol, field, value, timestamp))

        bm = BitMex()

        await bm.subscribe("XBTUSD", "lastPrice", callback)

        await asyncio.sleep(60)

        await bm.unsubscribe("XBTUSD", "lastPrice", callback)

        print("DONE!")

    # Run the 'main' function in an asyncio event loop
    loop = asyncio.get_event_loop()
    loop.create_task(main())
    loop.run_forever()


text:
# Get BitMEX prices into Excel using websockets and PyXLL RTD functions.
#
# Requires:
# - Python 3.5 or higher
# - websockets
#
# pip install websockets
#

[PYXLL]
pythonpath = .
modules =
    bitmex


text:
# NLP.VLOOKUP

A more flexible VLOOKUP using Natural Language Processing
from scikit-learn.

The following video accompanies this code:

[![Improving VLOOKUP with NLP Video](http://img.youtube.com/vi/bqMH62QniC8/0.jpg)](https://www.youtube.com/watch?v=bqMH62QniC8 "Improving VLOOKUP with NLP Video")

To use in Excel add the folder this file is in to your pythonpath
in the pyxll.cfg file and add 'nlp_vlookup' to the modules list
in the same file.

Once installed you may use the "NLP.VLOOKUP" function in Excel

```
=NLP.VLOOKUP(
    lookup_value,
    table_array,
    col_index_num, (optional)
    include_score, (default is False)
    all_matches, (default is False)
    threshold (default is 0.5)
)
```

The NLP.VLOOKUP function works in a similar way to VLOOKUP but can match
similar words not just identical words.

There is an example workbook in this folder that demonstrates how to use
the NLP.VLOOKUP function.


text:
"""
A more flexible VLOOKUP using Natural Language Processing
from scikit-learn.

To use in Excel add the folder this file is in to your pythonpath
in the pyxll.cfg file and add 'nlp_vlookup' to the modules list
in the same file.
"""
from sklearn import feature_extraction, metrics
from pyxll import xl_func, xl_return
from typing import List, Any
import pandas as pd

@xl_func(name="NLP.VLOOKUP")
@xl_return("dataframe<index=False, columns=False>")
def nlp_vlookup(value: str,
                table: List[List[Any]],
                col_index: int = None,
                include_score: bool = False,
                all_matches: bool = False,
                threshold: float = 0.5) -> pd.DataFrame:
    """
    Do a 'VLOOKUP' for value in table and return the value at col_index
    of the matching row.

    :param value: Value to match.
    :param table: Table of input values with the candidates in the left most column.
    :param col_index: Index of column in the table to return.
    :param include_score: Include the score in the return value.
    :param all_matches: If True return a table of all matches.
    :param threshold: Exclude matches below this threshold (0-1).
    """
    # Get the first column in the table as the list of words to match.
    words = [str(x[0]) for x in table]

    # Vectorize all the strings by creating a Bag-of-Words matrix, which extracts
    # the vocabulary from the corpus and counts how many times the words appear in each string.
    vectorizer = feature_extraction.text.CountVectorizer()
    vectors = vectorizer.fit_transform([value]+words).toarray()

    # Then, we calculate the cosine similarity, a measure based on the angle between two
    # non-zero vectors, which equals the inner product of the same vectors normalized to both
    # have length 1.
    cosine_sim = metrics.pairwise.cosine_similarity(list(vectors))

    # Get the scores for each word and put them into a DataFrame.
    scores = cosine_sim[0][1:]
    scores_df = pd.DataFrame({"score": scores}, index=words)

    # Join the input table and the scores into a single DataFrame.
    table_df = pd.DataFrame(table, index=words)
    df = table_df.join(scores_df)

    # Filter out any with a score below the threshold.
    df = df[df["score"] >= threshold]

    # If there are no matches then raise an exception.
    if not len(df.index):
        raise ValueError("No matches found")

    # Sort by score.
    df = df.sort_values(by="score", ascending=False)

    # Get the top result if not returning all matches.
    if not all_matches:
        df = df.head(1)

    # Reindex to get only the columns we're interested in and put the score first.
    columns = table_df.columns.to_list() if col_index is None else [col_index-1]
    if include_score:
        columns = ["score"] + columns
    df = df.reindex(columns=columns)

    return df

if __name__ == "__main__":
    words = [
        ["Bridgewater Associates", "United States Westport, CT", "$98,918"],
        ["Renaissance Technologies", "United States East Setauket, NY", "$70,000"],
        ["Man Group", "United Kingdom London", "$62,300"],
        ["Millennium Management", "United States New York City, NY", "$43,912"],
        ["Elliott Management", "United States New York City, NY", "$42,000"],
        ["BlackRock", "United States New York City, NY", "$39,907"],
        ["Two Sigma Investments", "United States New York City, NY", "$38,842"],
        ["The Children's Investment Fund Management", "United Kingdom London", "$35,000"],
        ["Citadel LLC", "United States Chicago, IL", "$34,340"],
        ["D.E. Shaw & Co.", "United States New York City, NY", "$34,264"],
        ["AQR Capital Management", "United States Greenwich, CT", "$32,100"],
        ["Davidson Kempner Capital Management", "United States New York City, NY", "$31,850"],
        ["Farallon Capital", "United States San Francisco, CA", "$30,000"],
        ["Baupost Group", "United States Boston, MA", "$29,100"],
        ["Marshall Wace", "United Kingdom London", "$27,800"],
        ["Capula Investment Management", "United Kingdom London", "$23,000"],
        ["Canyon Capital Advisors", "United States Los Angeles, CA", "$22,800"],
        ["Wellington Management Company", "United States Boston, MA", "$21,000"],
        ["Viking Global Investors", "United States Greenwich, CT", "$19,950"],
        ["PIMCO", "United States Newport Beach, CA", "$17,453"],
    ]

    match = nlp_vlookup("Capital", words, include_score=True, all_matches=True, threshold=0.5)
    print(match)


text:
"""
Example code showing how to draw a matplotlib figure embedded
in an Excel worksheet.

Matplotlib is used to plot a chart to an image, which is then
displayed as a Picture object in Excel.
"""
from pyxll import xl_func, xlfCaller
from pandas.stats.moments import ewma
import os

# matplotlib imports
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure

# For interacting with Excel from Python
from pyxll import get_active_object
import win32com.client

@xl_func("string figname, "
         "numpy_column<float> xs, "
         "numpy_column<float> ys, "
         "int span: string",
         macro=True)
def mpl_plot_ewma_embedded(figname, xs, ys, span):
    # create the figure and axes for the plot
    fig = Figure(figsize=(8, 6), dpi=75, facecolor=(1, 1, 1), edgecolor=(0, 0, 0))
    ax = fig.add_subplot(111)

    # calculate the moving average
    ewma_ys = ewma(ys, span=span)

    # plot the data
    ax.plot(xs, ys, alpha=0.4, label="Raw")
    ax.plot(xs, ewma_ys, label="EWMA")
    ax.legend()

    # write the figure to a temporary image file
    filename = os.path.join(os.environ["TEMP"], "xlplot_%s.png" % figname)
    canvas = FigureCanvas(fig)
    canvas.draw()
    canvas.print_png(filename)

    # Show the figure in Excel as a Picture object on the same sheet
    # the function is being called from.
    xl = xl_app()
    caller = xlfCaller()
    sheet = xl.Range(caller.address).Worksheet

    # if a picture with the same figname already exists then get the position
    # and size from the old picture and delete it.
    for old_picture in sheet.Pictures():
        if old_picture.Name == figname:
            height = old_picture.Height
            width = old_picture.Width
            top = old_picture.Top
            left = old_picture.Left
            old_picture.Delete()
            break
    else:
        # otherwise place the picture below the calling cell.
        top_left = sheet.Cells(caller.rect.last_row+2, caller.rect.last_col+1)
        top = top_left.Top
        left = top_left.Left
        width, height = fig.bbox.bounds[2:]

    # insert the picture
    # Ref: http://msdn.microsoft.com/en-us/library/office/ff198302%28v=office.15%29.aspx
    picture = sheet.Shapes.AddPicture(Filename=filename,
                                      LinkToFile=0,  # msoFalse
                                      SaveWithDocument=-1,  # msoTrue
                                      Left=left,
                                      Top=top,
                                      Width=width,
                                      Height=height)

    # set the name of the new picture so we can find it next time
    picture.Name = figname

    # delete the temporary file
    os.unlink(filename)

    return "[Plotted '%s']" % figname

def xl_app():
    xl_window = get_active_object()
    xl_app = win32com.client.Dispatch(xl_window).Application
    return xl_app


text:
"""
Example code showing how to draw an interactive matplotlib figure
in Excel.

While the figure is displayed Excel is still useable in the background
and the chart may be updated with new data by calling the same
function again.
"""
from pyxll import xl_func
from pandas.stats.moments import ewma

# matplotlib imports
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt4agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure

# Qt imports
from PySide import QtCore, QtGui
import timer  # for polling the Qt application

# dict to keep track of any chart windows
_plot_windows = {}

@xl_func("string figname, numpy_column<float> xs, numpy_column<float> ys, int span: string")
def mpl_plot_ewma(figname, xs, ys, span):
    """
    Show a matplotlib line plot of xs vs ys and ewma(ys, span) in an interactive window.

    :param figname: name to use for this plot's window
    :param xs: list of x values as a column
    :param ys: list of y values as a column
    :param span: ewma span
    """
    # Get the Qt app.
    # Note: no need to 'exec' this as it will be polled in the main windows loop.
    app = get_qt_app()

    # create the figure and axes for the plot
    fig = Figure(figsize=(600, 600), dpi=72, facecolor=(1, 1, 1), edgecolor=(0, 0, 0))
    ax = fig.add_subplot(111)

    # calculate the moving average
    ewma_ys = ewma(ys, span=span)

    # plot the data
    ax.plot(xs, ys, alpha=0.4, label="Raw")
    ax.plot(xs, ewma_ys, label="EWMA")
    ax.legend()

    # generate the canvas to display the plot
    canvas = FigureCanvas(fig)

    # Get or create the Qt windows to show the chart in.
    if figname in _plot_windows:
        # get from the global dict and clear any previous widgets
        window = _plot_windows[figname]
        layout = window.layout()
        if layout:
            for i in reversed(range(layout.count())):
                layout.itemAt(i).widget().setParent(None)
    else:
        # create a new window for this plot and store it for next time
        window = QtGui.QWidget()
        window.resize(800, 600)
        window.setWindowTitle(figname)
        _plot_windows[figname] = window

    # create the navigation toolbar
    toolbar = NavigationToolbar(canvas, window)

    # add the canvas and toolbar to the window
    layout = window.layout() or QtGui.QVBoxLayout()
    layout.addWidget(canvas)
    layout.addWidget(toolbar)
    window.setLayout(layout)

    window.show()

    return "[Plotted '%s']" % figname

#
# Taken from the ui/qt.py example
#
def get_qt_app():
    """
    returns the global QtGui.QApplication instance and starts
    the event loop if necessary.
    """
    app = QtCore.QCoreApplication.instance()
    if app is None:
        # create a new application
        app = QtGui.QApplication([])

        # use timer to process events periodically
        processing_events = {}
        def qt_timer_callback(timer_id, time):
            if timer_id in processing_events:
                return
            processing_events[timer_id] = True
            try:
                app = QtCore.QCoreApplication.instance()
                if app is not None:
                    app.processEvents(QtCore.QEventLoop.AllEvents, 300)
            finally:
                del processing_events[timer_id]

        timer.set_timer(100, qt_timer_callback)

    return app


text:
# Python Plotting in Excel with Matplotlib

**THIS EXAMPLE IS OUT OF DATE**

For details of how to use matplotlib in Excel with PyXLL please refer to the offical PyXLL docs https://www.pyxll.com/docs/userguide/plotting/index.html.

This example pre-dates plotting being added as a feature to PyXLL and should no longer be used, but is intetionally left here in case it is of interest.
The code relies on an old version of pandas and will not work with the latest version.


text:
"""
Uninstall PyXLL from all Excel installations.

This script modifies the registry directly to remove references
to PyXLL from Excel.

Close all Excel sessions before running this script, as otherwise
Excel will re-write its settings when it closes so PyXLL will
still be installed.

PyXLL is removed from the following registry keys (both 32 and 64 bit):

- HKLM|HKCU/Software/Microsoft/Office/*/Excel/Options
- HKLM|HKCU/Software/Microsoft/Office/*/Excel/Add-in Manager
- HKLM|HKCU/Software/Microsoft/Office/*/Excel/Resiliency/DisabledItems

"""
import sys, os
import re
import logging

try:
    import winreg
except ImportError:
    import _winreg as winreg

logging.basicConfig(level=logging.INFO)
_log = logging.getLogger(__name__)

_root_keys = {
    winreg.HKEY_CURRENT_USER : "HKEY_CURRENT_USER",
    winreg.HKEY_LOCAL_MACHINE : "HKEY_LOCAL_MACHINE",
}

def uninstall_all():
    """uninstalls PyXLL from all installed Excel versions"""
    for wow64_flags in (winreg.KEY_WOW64_64KEY, winreg.KEY_WOW64_32KEY):
        for root in _root_keys.keys():
            try:
                flags = wow64_flags | winreg.KEY_READ
                office_root = winreg.OpenKey(root, r"Software\Microsoft\Office", 0, flags)
            except WindowsError:
                continue

            # look for all installed versions of Excel and uninstall PyXLL
            i = 0
            while True:
                try:
                    subkey = winreg.EnumKey(office_root, i)
                except WindowsError:
                    break

                match = re.match("^(\d+(?:\.\d+)?)$", subkey)
                if match:
                    office_version = match.group(1)
                    uninstall(office_root, office_version, wow64_flags)
                i += 1

            winreg.CloseKey(office_root)

def uninstall(office_root_key, office_version, wow64_flags):
    """Uninstalls PyXLL from a single Excel install"""
    # uninstall entries from \Software\Microsoft\Office\<version>\Excel\Options
    # (this is what Excel uses to determine what to load on start-up)
    options_key = None
    try:
        flags = wow64_flags | winreg.KEY_READ
        subkey = r"%s\Excel\Options" % office_version
        options_key = winreg.OpenKey(office_root_key, subkey, 0, flags)
    except WindowsError:
        pass

    if options_key:
        _log.debug("Found %s Excel %s options keys" % (_get_arch(wow64_flags), office_version))
        pyxll_values = []
        try:
            i = 0
            while True:
                name, data, dtype = winreg.EnumValue(options_key, i)
                if "OPEN" in name and dtype == winreg.REG_SZ \
                and data.rstrip('"\'').lower().endswith("pyxll.xll"):
                    pyxll_values.append(name)
                i += 1
        except WindowsError:
            pass
        winreg.CloseKey(options_key)

        # if there were any pyxll keys found delete them
        if pyxll_values:
            _log.debug("Found PyXLL in %s Excel %s's options keys" % (_get_arch(wow64_flags), office_version))
            try:
                flags = wow64_flags | winreg.KEY_WRITE
                subkey = r"%s\Excel\Options" % office_version
                options_key = winreg.OpenKey(office_root_key, subkey, 0, flags)
                for value in pyxll_values:
                    winreg.DeleteValue(options_key, value)
                winreg.CloseKey(options_key)
                _log.info("Deleted PyXLL from %s Excel %s's options" % (_get_arch(wow64_flags), office_version))
            except WindowsError:
                _log.error("Couldn't delete PyXLL keys from %s Excel %s's options; Write access not allowed." %
                           (_get_arch(wow64_flags), office_version))

    # uninstall entries from \Software\Microsoft\Office\<version>\Excel\Add-in Manager
    # (this is what Excel uses to list addins in the addin manager)
    addins_key = None
    try:
        flags = wow64_flags | winreg.KEY_READ
        subkey = r"%s\Excel\Add-in Manager" % office_version
        addins_key = winreg.OpenKey(office_root_key, subkey, 0, flags)
    except WindowsError:
        pass

    if addins_key:
        _log.debug("Found %s Excel %s Addins" % (_get_arch(wow64_flags), office_version))
        pyxll_values = []
        try:
            i = 0
            while True:
                name, data, dtype = winreg.EnumValue(addins_key, i)
                filename = os.path.basename(name)
                if filename.lower() == "pyxll.xll":
                    pyxll_values.append(name)
                i += 1
        except WindowsError:
            pass
        winreg.CloseKey(addins_key)

        # if there were any pyxll keys found delete them
        if pyxll_values:
            _log.debug("Found PyXLL in %s Excel %s's Addins" % (_get_arch(wow64_flags), office_version))
            try:
                flags = wow64_flags | winreg.KEY_WRITE
                subkey = r"%s\Excel\Add-in Manager" % office_version
                addins_key = winreg.OpenKey(office_root_key, subkey, 0, flags)
                for value in pyxll_values:
                    winreg.DeleteValue(addins_key, value)
                winreg.CloseKey(addins_key)
                _log.info("Deleted PyXLL from %s Excel %s's addins list" % (_get_arch(wow64_flags), office_version))
            except WindowsError:
                _log.error("Couldn't delete PyXLL keys from %s Excel %s's addins; Write access not allowed." %
                           (_get_arch(wow64_flags), office_version))

    # uninstall entries from \Software\Microsoft\Office\<version>\Excel\Resiliency\DisabledItems
    # (this is what Excel uses to list blacklist badly behaving addins)
    disabled_key = None
    try:
        flags = wow64_flags | winreg.KEY_READ
        subkey = r"%s\Excel\Resiliency\DisabledItems" % office_version
        disabled_key = winreg.OpenKey(office_root_key, subkey, 0, flags)
    except WindowsError:
        pass

    if disabled_key:
        _log.debug("Found %s Excel %s disabled addins" % (_get_arch(wow64_flags), office_version))
        pyxll_values = []
        try:
            i = 0
            while True:
                name, data, dtype = winreg.EnumValue(disabled_key, i)
                if dtype == winreg.REG_BINARY:
                    value = data.decode("utf-16", "ignore")
                    if "pyxll.xll" in value:
                        pyxll_values.append(name)
                i += 1
        except WindowsError:
            pass
        winreg.CloseKey(disabled_key)

        # if there were any pyxll keys found delete them
        if pyxll_values:
            _log.debug("Found PyXLL in %s Excel %s's disabled addins" % (_get_arch(wow64_flags), office_version))
            try:
                flags = wow64_flags | winreg.KEY_WRITE
                subkey = r"%s\Excel\Resiliency\DisabledItems" % office_version
                disabled_key = winreg.OpenKey(office_root_key, subkey, 0, flags)
                for value in pyxll_values:
                    winreg.DeleteValue(disabled_key, value)
                winreg.CloseKey(addins_key)
                _log.info("Deleted PyXLL from %s Excel %s's disabled addins" % (_get_arch(wow64_flags), office_version))
            except WindowsError:
                _log.error("Couldn't delete PyXLL keys from %s Excel %s's disabled addins; Write access not allowed." %
                           (_get_arch(wow64_flags), office_version))

def _get_arch(flags):
    if flags & winreg.KEY_WOW64_64KEY:
        return "64 bit"
    elif flags & winreg.KEY_WOW64_32KEY:
        return "32 bit"
    return "unknown"

def main():
    uninstall_all()

if __name__ == "__main__":
    sys.exit(main())


text:
"""
Custom cell formatting example.

This example shows how to write a custom formatter that copies the
cell formatting for an array function when the result of the
array function expands.

This can be useful where the Excel user applies their own formatting
to a range, but that range can change shape as the inputs to the
function change.

As array data often contains cell headers, the first n rows are
treated separately from the rest of the range to allow column
headers to be formatted differently from the rest of the data.

This example requires the 3rd party package pywin32 to be installed.

This code accompanies the blog post
https://www.pyxll.com/blog/custom-fill-formatter
"""
from pyxll import Formatter, xl_func
from win32com.client import constants

class FillFormatter(Formatter):
    """FillFormatter is a custom cell formatter used to apply
    formatting to data returned from an Excel array function.

    To use a formatter, pass it to the @xl_func decorator using
    the 'formatter' kwarg, for example::

        fill_formatter = FillFormatter()

        @xl_func(formatter=fill_formatter)
        def your_function(...):
            return an_array
    """

    def __init__(self, num_headers=1):
        """FillFormatter constructor.

        :param num_headers: Number of column header rows to treat
                            separately from the rest of the data
                            when formatting.
        """
        super().__init__()
        self.__num_headers = num_headers
        self.__prev_cell = None

    def clear(self, cell):
        """The clear method is called by PyXLL as part of the formatting.
        It is always immediately followed by a call to the 'apply' method.

        Here, rather than clear any formatting we store the cell that should
        be cleared to use in the apply method.
        """
        # Don't clear the previous cell(s) yet
        self.__prev_cell = cell

    def apply(self, cell, *args, **kwargs):
        """The apply method is called immediately after the clear method
        has been called.

        It's here were we can apply any custom formatting to the cell(s) that
        the array function has been returned to.

        We use the previously stored 'prev_cell' to copy the formatting from
        the previous range to the new range.
        """
        if self.__prev_cell is None:
            return

        # Reset prev_cell ahead of any future calls.
        prev_cell = self.__prev_cell
        self.__prev_cell = None

        # Get the previous and new Range objects from the cells as win32com objects.
        prev_range = prev_cell.to_range(com_package="win32com")
        new_range = cell.to_range(com_package="win32com")

        # Check if the range is shrinking and clear the formatting if it is.
        if prev_range.Rows.Count > new_range.Rows.Count:
            num_rows = prev_range.Rows.Count - new_range.Rows.Count
            rows = prev_range.GetOffset(RowOffset=new_range.Rows.Count)
            rows = rows.GetResize(RowSize=num_rows)
            rows.ClearFormats()

        if prev_range.Columns.Count > new_range.Columns.Count:
            num_cols = prev_range.Columns.Count - new_range.Columns.Count
            cols = prev_range.GetOffset(ColumnOffset=new_range.Columns.Count)
            cols = cols.GetResize(ColumnSize=num_cols)
            cols.ClearFormats()

        # Copy the formatting if the range has expanded.
        if new_range.Columns.Count > prev_range.Columns.Count \
        or new_range.Rows.Count > prev_range.Rows.Count:
            prev_rows = prev_range
            new_rows = new_range

            # If we have header rows then copy those separately from the rest.
            if self.__num_headers > 0:
                prev_header = prev_range.GetResize(RowSize=self.__num_headers)
                new_header = new_range.GetResize(RowSize=self.__num_headers)

                prev_header.Copy()
                new_header.PasteSpecial(Paste=constants.xlPasteFormats,
                                        Operation=constants.xlNone)

                if prev_range.Rows.Count > self.__num_headers:
                    prev_rows = prev_rows.GetOffset(RowOffset=self.__num_headers)
                    prev_rows = prev_rows.GetResize(RowSize=prev_range.Rows.Count - self.__num_headers)

                    new_rows = new_rows.GetOffset(RowOffset=self.__num_headers)
                    new_rows = new_rows.GetResize(RowSize=new_range.Rows.Count - self.__num_headers)

            # Copy for the formatting from the previous range to the new one.
            prev_rows.Copy()
            new_rows.PasteSpecial(Paste=constants.xlPasteFormats,
                                  Operation=constants.xlNone)

            # End copy/paste mode.
            new_rows.Application.CutCopyMode = False

@xl_func("int rows, int columns: var[][]", auto_resize=True, formatter=FillFormatter())
def fill_formatter_example(rows, columns):
    """Sample function that simply returns a table of data for
    the purpose of demonstrating the FillFormatter class.
    """
    header = [f"COL{i+1}" for i in range(columns)]
    rows = [[c + r * columns for c in range(columns)] for r in range(rows)]
    return [header] + rows


text:
; Example showing how to write customer formatters using PyXLL.
;
; Formatters can be used to apply formatting to results returned
; from user defined worksheet functions (UDFs) using PyXLL's
; xl_func decorator.
;
; To try this out, add this file to your existing pyxll.cfg
; file using the 'external_config' option.
;
[PYXLL]
modules =
    fill_formatter

[PYTHON]
pythonpath =
    .


text:
# Custom Formatters Examples

Example showing how to write customer formatters using PyXLL.

Formatters can be used to apply formatting to results returned
from user defined worksheet functions (UDFs) using PyXLL's
xl_func decorator.

To try this out, add the pyxll.cfg from this folder to your
existing pyxll.cfg file using the 'external_config' option.


text:
"""
Facebook AI powered chatbot in Excel.

There are two functions:
  - parlai_create_world creates a world containing two agents (the AI and the human).
  - parlai_speak takes an input from the human and runs the model to get the AI response.

The entire conversation is returned by parlai_speak so it can be viewed in Excel
rather than just the last response.

See https://parl.ai/projects/blender/
"""
from pyxll import xl_func
from parlai.core.params import ParlaiParser
from parlai.core.agents import create_agent
from parlai.core.worlds import create_task
from excel_agent import HumanExcelAgent

@xl_func("str: object")
def parlai_create_world(model="zoo:blender/blender_90M/model"):
    parser = ParlaiParser(True, True, 'Interactive chat with a model')
    parser.add_argument(
        '-it',
        '--interactive-task',
        type='bool',
        default=True,
        help='Create interactive version of task',
    )
    parser.set_defaults(interactive_mode=True, task='interactive')
    args = ['-t', 'blended_skill_talk', '-mf', model]
    opt = parser.parse_args(print_args=False, args=args)

    agent = create_agent(opt, requireModelExists=True)
    human_agent = HumanExcelAgent(opt)
    world = create_task(opt, [human_agent, agent])
    return world

@xl_func("object, str, int: str[][]")
def parlai_speak(world, input, limit=None):
    human, bot = world.get_agents()[-2:]
    human.set_input(input)
    world.parley()

    messages = [[x.get('id', ''), x.get('text', '')] for x in human.get_conversation()]

    if limit:
        messages = messages[-limit:]
        if len(messages) < limit:
            messages = ([['', '']] * (limit - len(messages))) + messages

    return messages

if __name__ == "__main__":
    world = parlai_create_world()
    conversation = parlai_speak(world, "Hello")
    for id, msg in conversation:
        print(f"{id}: {msg}")


text:
[PYTHON]
pythonpath =
    ./

[PYXLL]
modules =
    parlai_excel


text:
"""
A ParlAI agent that takes input from a human Excel user.
Input is set using 'set_input' before calling world.parle.
"""
from parlai.core.agents import Agent
from parlai.core.message import Message

class HumanExcelAgent(Agent):

    def __init__(self, opt):
        super().__init__(opt)
        self.id = 'localExcelHuman'
        self.episodeDone = False
        self.finished = False
        self.__input = ""
        self.__conversation = []

    def set_input(self, input):
        self.__input = input or ""

    def get_conversation(self):
        return self.__conversation

    def epoch_done(self):
        return self.finished

    def observe(self, msg):
        self.__conversation.append(msg)

    def act(self):
        reply = Message()
        reply['id'] = self.getID()
        reply_text = self.__input.replace('\\n', '\n')
        reply['episode_done'] = False
        reply['text'] = reply_text
        self.__conversation.append(reply)
        return reply

    def episode_done(self):
        return self.episodeDone


text:
# Facebook AI Blender Chatbot

This example requires the 'ParlAI' package from Facebook AI which can be cloned
from https://github.com/facebookresearch/ParlAI.

Check that ParlAI is working correctly by running the following script

```bash
python -Xutf8 parlai/scripts/safe_interactive.py -t blended_skill_talk -mf zoo:blender/blender_90M/model
```

In the example `parlai_excel.py` There are two functions:

- parlai_create_world creates a world containing two agents (the AI and the human).
- parlai_speak takes an input from the human and runs the model to get the AI response.

The entire conversation is returned by parlai_speak so it can be viewed in Excel
rather than just the last response.

## References

https://parl.ai/projects/blender/
https://github.com/facebookresearch/ParlAI


text:
from pyxll import xl_func, xl_app, async_call
import matplotlib.pyplot as plt
import win32gui, win32ui, win32con
import torch.nn as nn
import numpy as np
import tempfile
import torch
import os

class NN(nn.Module):
    """Neural network with Sequential layers"""

    def __init__(self, layers):
        super(NN, self).__init__()
        print(layers)
        self.layers = nn.Sequential(*layers)

    def forward(self, x):
        return self.layers(x)

@xl_func
def nn_Linear(in_features: int, out_features: int, bias: bool=True):
    """Create a linear transformation layer."""
    return nn.Linear(in_features, out_features, bias)

@xl_func
def nn_Tanh():
    """Create a Tanh transformation layer."""
    return nn.Tanh()

@xl_func
def nn_Sigmoid():
    """Create a Sigmoid transformation layer."""
    return nn.Sigmoid()

@xl_func("object[]: object")
def nn_Sequential(layers):
    """Create a neural network from a list of layers."""
    # remove any empty cells passed in
    layers = [layer for layer in layers if layer is not None]
    return NN(layers)

@xl_func
def nn_Run(net, image_name, scale=1, offset=-0.5, seed=None):
    """Run the neural network with random weights"""

    # See the seed for the RNG
    seed = int(seed) if seed is not None else torch.random.initial_seed()
    torch.manual_seed(seed)

    # Initialize the weights
    def init_weights(m):
        if isinstance(m, nn.Linear):
            nn.init.normal_(m.weight)

    net.apply(init_weights)

    # Find the Excel image
    xl = xl_app()
    sheet = xl.Caller.Worksheet
    image = sheet.Pictures(image_name)

    # Get the image size in pixels
    size_x, size_y = get_image_size(image)

    # Create the inputs
    inputs = np.zeros((size_y, size_x, 2))
    for x in np.arange(0, size_x, 1):
        for y in np.arange(0, size_y, 1):
            scaled_x = scale * ((float(x) / size_x) + offset)
            scaled_y = scale * ((float(y) / size_y) + offset)
            inputs[y][x] = np.array([scaled_x, scaled_y])

    inputs = inputs.reshape(size_x * size_y, 2)

    # Compute the results
    result = net(torch.tensor(inputs).type(torch.FloatTensor)).detach().numpy()
    result = result.reshape((size_y, size_x, 3))

    # Create a temporary file to write the result to
    file = create_temporary_file(suffix=".png")

    # Write the image to the file
    plt.imsave(file, result)
    file.flush()

    # Replace the old image with the new one
    new_image = sheet.Shapes.AddPicture(Filename=file.name,
                                        LinkToFile=0,  # msoFalse
                                        SaveWithDocument=-1,  # msoTrue
                                        Left=image.Left,
                                        Top=image.Top,
                                        Width=image.Width,
                                        Height=image.Height)

    image_name = image.Name
    image.Delete()
    new_image.Name = image_name

    return f"[{new_image.Name}]"

def get_image_size(image):
    """Return the size of an image in pixels as (width, height)."""
    # Get the size of the input image in pixels (Excel sizes are in points,
    # or 1/72th of an inch.
    xl = xl_app()
    dc = win32gui.GetDC(xl.Hwnd)
    pixels_per_inch_x = win32ui.GetDeviceCaps(dc, win32con.LOGPIXELSX)
    pixels_per_inch_y = win32ui.GetDeviceCaps(dc, win32con.LOGPIXELSY)
    size_x = int(image.Width * pixels_per_inch_x / 72)
    size_y = int(image.Height * pixels_per_inch_y / 72)

    return size_x, size_y

def create_temporary_file(suffix=None):
    """Create a named temporary file that is deleted automatically."""
    # Rather than delete the file when it's closed we delete it when the
    # windows message loop next runs. This gives Excel enough time to
    # load the image before the file disappears.
    file = tempfile.NamedTemporaryFile(suffix=suffix, delete=False)

    def try_delete(filename):
        try:
            os.unlink(filename)
        except PermissionError:
            # retry if Excel is still accessing it
            async_call(os.unlink, filename)

    # Make sure the file gets deleted after the function is complete
    async_call(try_delete, file.name)

    return file


text:
; To try this out, add this file to your existing pyxll.cfg
; file using the 'external_config' option.
;
; This code accompanies the Medium article
; https://medium.com/8bad2b3a5d9d

[PYTHON]
pythonpath = .

[PYXLL]
modules =
    pytorch_abstract_art


text:
# Interactive Neural Network Fun in Excel

This code accompanies the medium article https://towardsdatascience.com/interactive-neural-network-fun-in-excel-8bad2b3a5d9d.

It shows how it is possible to construct neural networks with PyTorch in Excel using PyXLL.

To try out the code, add the included pyxll.cfg file to your own pyxll.cfg file, by adding
it to the "external_config" setting in the PYXLL section. Alternatively, simply add the
`pytorch_abstract_art` module to your list of modules and ensure it's on your Python path.


text:
# Cached objects are now part of PyXLL

This example is obsolute as of PyXLL 4.0.

For passing Python objects between functions see https://www.pyxll.com/docs/userguide/udfs.html#cached-python-objects.