winax (node-activex)

repository·master·Indexed 18 days ago

https://github.com/durs/node-activex

A Windows C++ Node.js addon that provides Windows COM bindings and an ActiveXObject implementation similar to cscript.exe. It allows for the instantiation of COM objects, explicit management of COM variant types via the winax.Variant class, and the ability to run legacy JScript files using the nodewscript command.

Tokens
2.3K
Snippets
9
Records
11
Agent score
13%

What's inside winax

  1. Run WScript scripts with nodewscript

    master

    If you install winax globally (npm install -g winax), you get access to the nodewscript command. This allows you to run legacy JScript files designed for the Windows Scripting Host (WSH) within a Node.js runtime, enabling the use of npm modules alongside WScript features.

    Usage:

    nodewscript [options] <Filename.js>

    Key Differences & Limitations:

    • Execution Model: Node.js is non-blocking/async, while WScript is linear. Node.js execution completes when the last statement is done AND all pending promises/callbacks are resolved.
    • Implicit Properties: Unlike MS JScript, V8 (Node.js) does not support dynamic property checks on objects that aren't defined in ITypeInfo. An if (a.Prop) check might fail even if a.Prop is null or false if it's not explicitly marked as a property.
    • Function Setters: The JScript syntax object("key") = "value" for setters will throw a syntax error in V8. You must use standard assignment object.key = "value".
    • Bitness: nodewscript uses the same bitness as your installed Node.js version. If your scripts require 32-bit COM objects, use a 32-bit Node.js installation.
  2. Use winax as a library in native Node.js addons

    master

    You can include winax as a dependency in your own native C++ Node.js addon. This provides access to utility functions like Variant2Value and Value2Variant for translating between COM VARIANTs and Node.js types.

    Setup:

    1. Add winax to the dependencies section of your binding.gyp file:
    "dependencies": [
      "<!(node -p \"require.resolve('winax/lib_binding.gyp')\"):lib_node_activex"]
    ]
    1. Include the header in your C++ code:
    #include <node_activex.h>

    Note: Importing this library declares all methods in the global namespace and opens the v8 and node namespaces.

  3. Configure TypeScript for winax

    master

    To use winax with TypeScript, your tsconfig.json must be configured to avoid conflicts with the built-in ScriptHost library which contains a conflicting global ActiveXObject type.

    1. Set moduleResolution to something other than classic (e.g., nodenext).
    2. Explicitly exclude ScriptHost from your lib array.
    {
    	"compilerOptions": {
    		"target": "esnext",
    		"module": "nodenext",
    		"lib": [ "ESNext" ]
    	}
    }
  4. Install winax via npm

    master

    You can install the winax package using npm. If you are using a specific version of Visual Studio, you can specify it during installation to ensure compatibility with your build environment.

    npm install winax
    npm install winax --msvs_version=2015
    npm install winax --msvs_version=2017
  5. Work with Excel ranges using 2D arrays

    master

    You can assign values to Excel ranges using two-dimensional JavaScript arrays.

    Behavioral Rules:

    • The second dimension is automatically deduced from the first array.
    • To explicitly pass VT_EMPTY (empty cells), use null in the array.
    • If the provided array dimensions are smaller than the target range, the missing cells will be emptied.
    • If a single-row array is provided (e.g., [[1, 2, 3]]), it will duplicate across the rows/columns of the target range based on the range size.
    var excel = new winax.Object("Excel.Application", { activate: true });
    var wbk = excel.Workbooks.Add(template_filename);
    var wsh = wbk.Worksheets.Item(1);
    
    // Standard 2D assignment
    wsh.Range("C3:E4").Value = [ ["C3", "D3", "E3" ], ["C4", "D4", "E4" ] ];
    
    // Using null to leave cells empty
    wsh.Range("C3:E4").Value = [ [null, "D3", "E3" ], "C4" ];
    
    // Duplicating values across a range
    wsh.Range("C3:F4").Value = [ [100, 200, 300, 400] ];
  6. Create a COM object from a JavaScript object

    master

    You can pass a plain JavaScript object to the ActiveXObject constructor to create a COM object. This is useful for sending complex data structures (including nested objects, arrays, and functions) to COM procedures like those in Excel.

    var com_obj = new ActiveXObject({
    	text: test_value,
    	obj: { params: test_value },
    	arr: [ test_value, test_value, test_value ],
    	func: function(v) { return v*2; }
    });
  7. Use and manipulate COM Variants

    master

    The winax.Variant class allows you to explicitly manage COM variant types. This is necessary for precise type control when interacting with COM APIs.

    Supported Type Strings:

    • int, uint, int8, char, uint8, uchar, byte, int16, short, uint16, ushort, int32, uint32, int64, long, uint64, ulong, currency, float, double, string, date, decimal, variant, null, empty.
    • Use the prefix p (e.g., pshort) or the string 'byref' to indicate a reference to the current type.

    Key Methods:

    • new Variant(value, type): Creates a new variant.
    • v.assign(value): Changes the content.
    • v.cast(type): Casts the variant to a new type.
    • v.clear(): Clears the variant content.
    • winax.cast(value, type): A utility function to cast a value directly.
    var winax = require('winax');
    var Variant = winax.Variant;
    
    // Create variant instance 
    var v_short = new Variant(17, 'short');
    var v_short_byref = new Variant(17, 'pshort');
    var v_int_byref = new Variant(17, 'byref');
    var v_byref = new Variant(v_short, 'byref');
    
    // Create variant arrays
    var v_array_of_variant = new Variant([1,'2',3]);
    var v_array_of_short = new Variant([1,'2',3], 'short');
    var v_array_of_string = new Variant([1,'2',3], 'string');
    
    // Change variant content
    var v_test = new Variant();
    v_test.assign(17);
    v_test.cast('string');
    v_test.clear();
    
    // Using cast function
    var v_short_from_cast = winax.cast(17, 'short');
  8. Create an ActiveXObject

    master

    You can instantiate COM objects in two ways: using the global ActiveXObject constructor or using the winax.Object prototype.

    When using the constructor, you can pass an optional configuration object:

    • activate: (boolean, default false) If true, allows activating an existing object instance (via CoGetObject).
    • getobject: (boolean, default false) If true, allows using the name of the file in the ROT (via GetAccessibleObject).
    • type: (boolean, default true) If true, allows using type information to resolve conflicts between properties and methods (e.g., resolving rs.EOF).
    // Using global function
    var con = new ActiveXObject('ADODB.Connection');
    
    // Using Object prototype
    var winax = require('winax');
    var con = new winax.Object('ADODB.Connection');
    
    // With configuration options
    var con = new ActiveXObject("Object.Name", {
    	activate: false,
    	getobject: false,
    	type: true
    });
  9. Inspect COM objects with diagnostic properties

    master

    The library provides several diagnostic properties to inspect the members and identity of a dispatch object:

    • __id: The dispatch identity (e.g., ADODB.Connection.@Execute.Fields).
    • __value: The value of the dispatch object (equivalent to valueOf()).
    • __type: An array of all member items with their properties.
    • __methods: A list of member methods by name (via ITypeInfo::GetFuncDesc).
    • __vars: A list of member variables by name (via ITypeInfo::GetVarDesc).
  10. Import the node-activex module

    master

    To use the node-activex library, require the module in your Node.js application. This provides access to the ActiveXObject constructor, which allows you to instantiate and interact with COM/ActiveX objects within a Node.js environment.

    const activex = require('node-activex');
    // The exported object contains the ActiveXObject constructor and related functionality