Home Posts

C# Installer Scripting for Nexus Mod Manager

For some reason there are no information about scripting your own installer in C# for Nexus Mod Manager, but you know what? This page will teach you to do that.

If you haven't used C# before, you can read a quick introduction into it.


First, grab this template and place it in your mod's fomod folder as script.cs.

using System;

class Script : BaseScript
{
    public bool OnActivate()
    {
        return true;
    }
}

What is happening here? Let's see.

System.dll
System.Drawing.dll
System.Windows.Forms.dll
System.Xml.dll

Down there is documentation with small samples, I hope you will understand how to use them properly. Also you can download sample installer script, which shows how to install mods from archive in NMM way, how to create user interface via Windows Forms, etc.

In next examples we will use Skyrim as game and this mod structure:

my-mod.7z
---------
fomod/images/test.png
fomod/script.cs
fomod/info.xml
README.txt
LokirsTomb.esp

Accessing your mod's files

NMM provides fewer methods to access your mod's files:

Basic installation

bool PerformBasicInstall();

This method just copies all files from your mod except fomod directory to game's data folder. Return value indicates success of operation (get error message by calling GetLastError()).

Example:

public bool OnActivate()
{
    return PerformBasicInstall();
}

Manual installation

bool InstallFileFromMod(string file);
bool InstallFileFromMod(string file, string to);
bool InstallFolderFromMod(string folder, bool recurse);
bool InstallFolderFromMod(string folder, string to, bool recurse)

Using first method extract's file from your archive to same path in Data folder, second method allows you to change path where file will be extracted. Return value indicates successful extracting. You can get error message by calling GetLastError(). These method can throw SecurityException if you chose not permitted destination directory (ex. "C:/mahfile.txt").

Third and fourth methods installs all files from mod's specified directory.

Examples:

// my-mod.7z/LokirsTomb.esp => ../Skyrim/Data/LokirsTomb.esp
InstallFileFromMod("LokirsTomb.esp");
// my-mod.7z/README.txt => ../Skyrim/Data/Readmes/LokirsTomb_Readme.txt
InstallFileFromMod("README.txt", "Readmes/LokirsTomb_Readme.txt");

You can also generate a file on fly:

bool GenerateDataFile(string path, byte[] data);

Writes the file represented by the given byte array to the given path.

Remarks: This method writes the given data as a file at the given path. If the file already exists the user is prompted to overwrite the file.

Accessing mod data

string[] GetModFileList();
string[] GetModFileList(string folder, bool recurse);

Retrieves the list of files in the specified folder in the mod. Second method allows to chose the folder whose file list should be rethieved and whether to return files that are in subdirectories of the given directory.

byte[] GetFileFromMod(string file);

Return's file content as byte array. Can return null when file doesn't exist (get error message by calling GetLastError()).

Example:

byte[] data = GetFileFromMod("README.txt");
string text = System.Text.Encoding.UTF8.GetString(data);
MessageBox(text, "You gotta read this.");

Game management

Game version

Version GetGameVersion();

Gets the version of the game that is installed or null if not installed.

Game data files

string[] GetExistingDataFileList(string path, string pattern, bool allFolders);

Gets a filtered list of all files in a user's Data directory.

Returns a filtered list of all files in a user's Data directory.

bool DataFileExists(string path)

Determines if the specified file exists in the user's Data directory.

Returns true if the specified file exists; false otherwise.

byte[] GetExistingDataFile(string path)

Gets the speified file from the user's Data directory as byte array.

The specified file, or null if the file does not exist.

Plugins

string[] GetAllPlugins();
string[] GetActivePlugins();

First method gets a list of all installed plugins, second retrieves a list of currently active plugins.

void SetPluginActivation(string path, bool activate);

Sets the activated status of a plugin (i.e., and esp or esm file).

Plugin load order

void SetPluginOrderIndex(string plugin, int newIndex);

Sets the load order of the specifid plugin.

void SetLoadOrder(int[] plugins);

Sets the load order of the plugins.

Remarks: Each plugin will be moved from its current index to its indices' position in plugins parameter.
plugins parameter defines new load order of the plugins. Each entry in this array contains the current index of a plugin. This array must contain all current indices.
void SetLoadOrder(int[] plugins, int position);

Moves the specified plugins to the given position in the load order.

Remarks: Note that the order of the given list of plugins is not maintained. They are re-ordered to be in the same order as they are in the before-operation load order.
void SetRelativeLoadOrder(string[] relativelyOrderedPlugins);

Orders the plugins such that the specified plugins are in the specified order.

Remarks: The given plugins may not end up consecutively ordered.

Mod Manager info

Version GetModManagerVersion();

Get's NMM version.

User interaction

Message dialogs

void MessageBox(string message);
void MessageBox(string message, string title);
DialogResult MessageBox(string message, string title, MessageBoxButtons buttons);

Shows a message box. First two methods shows a message with optional title and "OK" button. Third method, which returns DialogResult (see docs), can define it's own buttons for message box with MessageBoxButtons enumeration (see docs) and get result back.

You can also use message boxes from System.Windows.Forms namespace (see docs).

Example:

MessageBox("Here is your pizza.", "DELIVERY");
var result = MessageBox("Give him some money?", "title",
    System.Windows.Forms.MessageBoxButtons.YesNo);

if (result == System.Windows.Forms.DialogResult.Yes) {
    MessageBox("Have your pizza, dude!");
} else {
    MessageBox("God damn it, dude!");
}

User interface

// this is same as `Form form = new Form();`
System.Windows.Forms.Form CreateCustomForm();

Creates Windows Forms Form. This allows to create windows with textboxes, buttons, etc. Google how to use Windows Forms.

If you have Visual Studio, you can use it's visual form designer to create forms in drag-n'-drop way. You need to create new Windows Forms project, edit the form, then copy-paste form source code and code, generated by form designer into the script, and finally create your Form's instance from code.

Example:

public bool OnActivate() {
    var form = CreateCustomForm();
    form.Text = "Title";

    var button = new System.Windows.Forms.Button();
    button.Text = "hit me gently";
    button.Location = new System.Drawing.Point(30, 30);
    button.ClientSize = new System.Drawing.Size(100, 100);
    button.Click += (sender, args) => {
        MessageBox("oooh");
    };

    form.Controls.Add(button);

    form.ShowDialog();
    return true;
}

string[] Select(IList<SelectOption> options, string title, bool selectMany);
new SelectOption(string name, bool isDefault, string description, Image image);

Displays a selection form to the user (seems to be broken).

INI management

string GetIniString(string settingsFileName, string section, string key);

Retrieves the specified settings value as a string.

int GetIniInt(string settingsFileName, string section, string key);

Retrieves the specified settings value as an integer.

bool EditIni(string settingsFileName, string section, string key, string value);

Sets the specified value in the specified ini file to the given value. Returns true if the value was set; false if the user chose not to overwrite the existing value.

Fallout Base Script derived

You must inherit your Script class from one of these classes to use these methods: FalloutBaseScript, Fallout3BaseScript, FalloutNVBaseScript, Fallout4BaseScript or SkyrimBaseScript.

bool ScriptExtenderPresent();

Indicates whether or not a script extender is present. For Skyrim it is SKSE, for Fallout 3 — FOSE, for Fallout New Vegas — NVSE, for Fallout 4 — F4SE.

string[] GetBSAFileList(string bsa);

Retrieves the list of files in the specified BSA. Return list of files contained in the specified BSA.

byte[] GetDataFileFromBSA(string bsa, string file);

Gets the specified file from the specified BSA.

// Fallout.ini/Skyrim.ini/FalloutNV.ini
string GetFalloutIniString(string section, string key);
int GetFalloutIniInt(string section, string key);

// FalloutPrefs.ini/SkyrimPrefs.ini/FalloutNVPrefs.ini
string GetPrefsIniString(string section, string key);
int GetPrefsIniInt(string section, string key);

// GECKCustom.ini
string GetGeckIniString(string section, string key);
int GetGeckIniInt(string section, string key);

// GECKPrefs.ini
string GetGeckPrefsIniString(string section, string key);
int GetGeckPrefsIniString(string section, string key);

Retrieves the specified game ini value as a string/integer.

// Fallout.ini/Skyrim.ini/FalloutNV.ini
bool EditFalloutINI(string section, string key, string value, bool unused);

// FalloutPrefs.ini
bool EditPrefsINI(string section, string key, string value, bool unused);

// GECKCustom.ini
bool EditGeckINI(string section, string key, string value, bool unused);

// GECKPrefs.ini
bool EditGeckPrefsINI(string section, string key, string value, bool unused);

Sets the specified value in the game ini file to the given value. Returns true if the value was set; false if the user chose not to overwrite the existing value.

string GetRendererInfo(string value);

Gets the specified value from the RendererInfo.txt file. Returns specified value from the RendererInfo.txt file, or null if the value is not found.

bool IsAIActive();

Determines if archive invalidation is active.

bool EditShader(int package, string shaderName, byte[] data);

Edits the specified shader with the specified data. Returns true if the value was set; false if the user chose not to overwrite the existing value.

void SetupScriptCompiler(TesPlugin[] plugins);

Sets up the script compiler for the given plugins.

void CompileResultScript(SubRecord subrecord, out Record record, out string message);

Compiles the result script.

void CompileScript(Record record, out string message);

Compiles a script.

Fallout 3 Base Script derived

This method is only available when you inherit from Fallout3BaseScript.

Version GetFoseVersion();

Gets the version of FOSE that is installed. Returns null if FOSE is not installed.

Fallout NV Base Script derived

This method is only available when you inherit from FalloutNVBaseScript.

Version GetNvseVersion();

Gets the version of NVSE that is installed. Returns null if NVSE is not installed.

Skyrim Base Script derived

This method is only available when you inherit from SkyrimBaseScript.

Version GetSkseVersion();

Gets the version of SKSE that is installed. Returns null if SKSE is not installed.