private static extern Error vbaiSetVariables(NativeSession session, VariableUpdateMode updateMode, VariableValuePriv[] variableArray, int size);
public void SetVariables(VariableUpdateMode updateMode, VariableValue[] variableArray) { if (variableArray == null) { throw new ArgumentException("variableArray"); } if (variableArray.Length == 0) { throw new ArgumentException("variableArray is empty"); } VariableValuePriv[] variables = new VariableValuePriv[variableArray.Length]; List <IntPtr> HandlesToDispose = new List <IntPtr>(); for (int i = 0; i < variableArray.Length; i++) { VariableValueUnion val = new VariableValueUnion(); variables[i].name = variableArray[i].name; variables[i].type = variableArray[i].type; switch (variableArray[i].type) { case VariableDataType.BooleanVariableType: val.boolValue = variableArray[i].boolValue; break; case VariableDataType.NumericVariableType: val.numValue = variableArray[i].numValue; break; case VariableDataType.StringVariableType: val.strValue = Marshal.StringToHGlobalAnsi(variableArray[i].strValue); HandlesToDispose.Add(val.strValue); break; case VariableDataType.PointVariableType: val.pointValue = variableArray[i].pointValue; break; case VariableDataType.ImageVariableType: val.imgValue = variableArray[i].imgValue._image; break; case VariableDataType.Numeric1DVariableType: val.num1DValue = Marshal.AllocHGlobal(sizeof(double) * variableArray[i].num1DValue.Length); Marshal.Copy(variableArray[i].num1DValue, 0, val.num1DValue, variableArray[i].num1DValue.Length); variables[i].arraySize = variableArray[i].num1DValue.Length; HandlesToDispose.Add(val.num1DValue); break; case VariableDataType.Boolean1DVariableType: // Unmanaged code has 4 bytes for bool and managed code only has 1 byte. // When copying 1 byte into 4 byte data space, need to make sure memory is initialized to all zeros so when we set one byte to false (0), // we don't have to worry about remaining 3 bytes possibly having data that would make the False look like a True in C code. int boolSizeinBytes = Marshal.SizeOf(new bool()) * variableArray[i].bool1DValue.Length; IntPtr currentLocation = val.bool1DValue = Marshal.AllocHGlobal(boolSizeinBytes); byte[] emptyByteArray = new byte[boolSizeinBytes]; Marshal.Copy(emptyByteArray, 0, currentLocation, boolSizeinBytes); for (int j = 0; j < variableArray[i].bool1DValue.Length; j++) { Marshal.WriteByte(currentLocation, Convert.ToByte(variableArray[i].bool1DValue[j])); currentLocation = new IntPtr(currentLocation.ToInt64() + Marshal.SizeOf(new bool())); } variables[i].arraySize = variableArray[i].bool1DValue.Length; HandlesToDispose.Add(val.bool1DValue); break; case VariableDataType.String1DVariableType: IntPtr[] stringArray = new IntPtr[variableArray[i].str1DValue.Length]; for (int j = 0; j < variableArray[i].str1DValue.Length; j++) { stringArray[j] = Marshal.StringToHGlobalAnsi(variableArray[i].str1DValue[j]); HandlesToDispose.Add(stringArray[j]); } val.str1DValue = Marshal.AllocHGlobal(Marshal.SizeOf(new IntPtr()) * stringArray.Length); Marshal.Copy(stringArray, 0, val.str1DValue, variableArray[i].str1DValue.Length); HandlesToDispose.Add(val.str1DValue); variables[i].arraySize = variableArray[i].str1DValue.Length; break; default: break; } variables[i].value = val; } Error err = vbaiSetVariables(_session.nativeSession, updateMode, variables, variables.Length); if (err != Error.Success) { ExceptionBuilder.CheckErrorAndThrow(err); } // Free allocated data for (int i = 0; i < HandlesToDispose.Count; i++) { Marshal.FreeHGlobal(HandlesToDispose[i]); } HandlesToDispose.Clear(); }