MathType in C# (OLE) - c#

I'm trying to run a MathType in a C# app... using OLE in forms to signify the equations/images.
This is how I started with the code.
I got the CLSID object for math type equation. I create a new instance and run a verb to start Math Type. This works good until I try to set or get data of the IDataItem attribute I have.
Code:
string progID = "Equation.DSMT4";
comRetVal= CLSIDFromProgID(progID, out eqContainerGUID);
Type t = Type.GetTypeFromProgID(progID); //ok-> MT6 Equation
Object instance = Activator.CreateInstance(t);
IDataObject oleDataObject = instance as IDataObject;
MTSDKDN.MathTypeSDK.IOleObject oleObject = instance as IDataObject;
//run verb Run For Conversion - I'm not sure what this verb does
oleObject.DoVerb(2, (IntPtr)0, activeSite, 0, (IntPtr)this.Handle, new MathTypeSDK.COMRECT());
//up to here everything is find
//Now say I want to put a MathML string into the IDataObject
//set format
formatEtc.cfFormat = (Int16)dataFormatMathMLPres.Id; //<-this overflows. I verified that the only format that works is Presentation MAthML
formatEtc.dwAspect = System.Runtime.InteropServices.ComTypes.DVASPECT.DVASPECT_CONTENT;
formatEtc.lindex = -1;
formatEtc.ptd = (IntPtr)0;
formatEtc.tymed = TYMED.TYMED_HGLOBAL;
//set medium
ConnectSTGMEDIUM stgMedium = new ConnectSTGMEDIUM();
string mathEqn = "<math><mi>x</mi></math>";
stgMedium.unionmember = Marshal.StringToHGlobalAuto(mathEqn);
stgMedium.pUnkForRelease = 0;
//if now i write the equation to console from STGMEDIUM i see that after each char there is a null. Is this normal?
//now I try to set data in IDataObject and the OLE object
//I thought this set the data of the ole object to the MathML string I put in STGMEDIUM
oleDataObject.SetData(ref formatEtc, ref stgMedium, false);
The app now crashes with this exception:
System.Runtime.InteropServices.COMException was unhandled Message="Invalid FORMATETC structure (Exception from HRESULT: 0x80040064 (DV_E_FORMATETC))" Source="System" ErrorCode=-2147221404 StackTrace: at System.Runtime.InteropServices.ComTypes.IDataObject.GetData(FORMATETC& format, STGMEDIUM& medium)
I'm not sure what this means, but I think it might have to do with
formatEtc.cfFormat = (Int16)dataFormatMathMLPres.Id;
because that ID is 50000 and does not fit in a short (cfFormat is a short) so it overflows to something like -15000.

I have solved similar issue by converting it from unsigned to signed value. it means that if the value (dataFormatMathMLPres.Id) is grater than 32767. Use (dataFormatMathMLPres.Id - 65536) instead. It will fit signed short.

Related

.NET COM Object Performance In Lotus Notes 8.5

First let me tell you I'm new to the .NET world, but have been Software Emgineer for 16 years, so I'm not new to coding. I ran across something that has me baffled, and maybe a more seasoned .NET developer might know what is causing a perfomance issue of my COM object. I have spent days browsing through forums with no luck, I decide to seek help by putting this post together. I have developed my .NET code in VS 2010 using C#. I know, the IDE is little aged. The code is pretty simple. The main method takes the Certificates encoded string, converts it to a byte format, and passes that to the X509Certificate object. I then use the objects method to get the expiration date. I also added a memory clean-up class hoping it would solve my problem. It did not.
using System;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Runtime.InteropServices; //Need for API
namespace CertificationInfo
{
//Certification Class
public class CertificateInformation
{
//[DllImport("kernel32.dll")]
//public static extern bool SetProcessWorkingSetSize(IntPtr proc, int min, int max);
//Class Attributes
//private X509Certificate CertificateObject;
public string CertificateData;
public string ExpirationDate;
private MemoryManagement MemMngr;
//Constructor
public CertificateInformation()
{
//Reset Expiration Date
this.ExpirationDate = "";
MemMngr = new MemoryManagement();
}
//Method
public string GetCertExpirationDate(string rawdata)
{
try
{
//Clean Up Memory
this.MemMngr.ReleaseMemory();
//Reset Expiration Date Property
this.ExpirationDate = "";
//Check for data
if (rawdata == "" && this.CertificateData == "")
{
//Nothing is passed & property is blank
this.ExpirationDate = "";
}
else
{
//Check for Raw Data value
if (rawdata != "")
{
this.CertificateData = rawdata;
}
//Convert Property Array
//Might be best to use unicode Under Encoding namespace
//System.Text.UnicodeEncoding Encoding0=new System.Text.UnicodeEncoding();
//Byte[] bytedata0=Encoding0.GetBytes(rawdata);
//Convert Property to byte array
System.Text.ASCIIEncoding Encoding = new System.Text.ASCIIEncoding();
Byte[] bytedata = Encoding.GetBytes(this.CertificateData);
//Create Encoding Object
X509Certificate CertificateObject = new X509Certificate(bytedata);
//this.CertificateObject = new X509Certificate(bytedata);
//Might have to check to see iff cert object is null though catch should pick it up
//Get Expiration date
this.ExpirationDate = CertificateObject.GetExpirationDateString();
//Reset Object & Certificate Data Property
CertificateObject = null;
Encoding = null;
this.CertificateData = "";
//Clean Up Memory
this.MemMngr.ReleaseMemory();
}
}
//Error Trapping in case of error still returns something
catch
{
this.ExpirationDate = "";
}
return this.ExpirationDate;
}
}
//API Class to Clean up Memory threads
public class MemoryManagement
{
//Memory Management API
[DllImport("kernel32.dll")]
public static extern bool SetProcessWorkingSetSize(IntPtr proc, int min, int max);
//Method
public void ReleaseMemory()
{
GC.Collect();
GC.WaitForPendingFinalizers();
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
}
}
}
}
I moved it into the GAC, and registered it as a DLL on my local machine. I then created a Lotus Script agent, that loops through all my documents(records). In the iteration it pulls a field into a string, passes it to method, and returns the expiration date as a string
%REM
Agent TestDLL
Created Jan 13, 2014 by Keith Wiwel/TPS/PGH/PNC
Description: Comments for Agent
%END REM
Option Public
Option Declare
Sub Initialize
Dim Session As New NotesSession
Dim db As NotesDatabase
Dim view As NotesView
Dim document As NotesDocument
Dim COMObj As Variant
'Counts
Dim TotalCount As Long
Dim MissingDataCount As Long
Dim COMErrorCount As Long
Dim COMSuccessCount As Long
Print "ETH - GetExpirationDLL: Initializing Notes Objects"
Set db=Session.Currentdatabase
Set view=db.Getview("Active Certificates - By Web Site")
Print "ETH - GetExpirationDLL: Initializing COM Object"
Set COMObj=CreateObject("CertificationInfo.CertificateInformation")
TotalCount=0
MissingDataCount=0
COMErrorCount=0
COMSuccessCount=0
Print "ETH - GetExpirationDLL: Start Processing"
Set document=view.Getfirstdocument()
Do Until document Is Nothing
TotalCount=TotalCount+1
Print "Processing..."+CStr(TotalCount)
'Expiration Variables
Dim expirationdate As String
Dim rawdata As String
Dim legacyexpirationdate As String
'Get data & Legacy Values
'rawdata
rawdata=CStr(Trim(document.Getitemvalue("CRT_File")(0)))
legacyexpirationdate=CStr(document.expirationdate(0))
If rawdata="" Then
'Capture Certificates with No CSR Data
document.ExpirationDate=""
If LegacyExpirationDate="" Then
document.LegacyExpirationDate=legacyexpirationdate
End If
document.COMError="Missing CSR"
Call document.Save(True,False)
MissingDataCount=MissingDataCount+1
Else
'Capture Legacy & Certificate Expiration Date
If legacyexpirationdate="" Then
document.LegacyExpirationDate=legacyexpirationdate
End If
Dim Certificatedat As String
CertificateDat=ComObj.CertificateData
'expirationdate=ComObj.ExpirationDate
expirationdate=COMObj.GetCertExpirationDate(rawdata)
Dim CertDate As String
CertDate=ComObj.ExpirationDate
Dim Debug As String
Debug=ComObj.xx
Print "Com expiration:" +CStr(ComObj.ExpirationDate)
If CStr(expirationdate)<>"" Then
'Success - Processing Expiration date
document.ExpirationDate=CStr(expirationdate)
COMSuccessCount=COMSuccessCount+1
Else
'Failed - Processing Expiration date
document.ExpirationDate=CStr(expirationdate)
document.COMError="COM Expiration Failed"
COMErrorCount=COMErrorCount+1
End If
Call document.Save(True,False)
End If
Set document=view.getnextdocument(document)
Loop
'Log Report
Print "ETH - GetExpirationDLL: Processed "+CStr(TotalCount)+" certificates."
Print "ETH - GetExpirationDLL: "+CStr(MissingDataCount)+" certificates had missing CSR data."
Print "ETH - GetExpirationDLL: "+CStr(COMErrorCount)+" certificates failed in the COM Object."
Print "ETH - GetExpirationDLL: "+CStr(COMSuccessCount)+" certificates were succesfully processed."
Print "ETH - GetExpirationDLL: End Processing"
'Delete COMObj
End Sub
The two main lines of code above are:
Set COMObj=CreateObject("CertificationInfo.CertificateInformation")
which creates the COM object. The other is:
expirationdate=expirationdate=COMObj.GetCertExpirationDate(rawdata)
which uses the method to pull the expiration date. As you might have expected, it works fine, however this is where my problem occurs. When I first ran the code it flew, it took roughly 10 minutes to go through 4,000+ records. I had a few anomalies that I wanted to check, so I ran it a couple more times. Each time it degraded, and enventually started crawling. My first thought was it was a memory leak. Since I was running it locally, I decided to turn off the power to the pc see if it cleared. It did not. I also installed it on my laptop to prove to myself it ran smotthly on it's first run. Ran fine on the first one, then perfomance started degrading on consecutive runs. Last day it was running so slow it was over 8+ hours. This is local machine testing so there are is no servers to contend with network traffic. I am at a complete loss, can anyone tell me what is going on? CPU is at 20% when running, and Mem usage for notes2.exe growsa little each time. It slows down when it enters:
expirationdate=expirationdate=COMObj.GetCertExpirationDate(rawdata)
That's the bottleneck. I am completely stuck, does anyone know what is going on?

CryptographicException - Unable to update the password

I have some data I wish to protect, so I am using ProtectedData to encrypt it onto a file.
When I am attempting to read and decrypt the data I am getting the strangest exception:
CryptographicException - Unable to update the password. The value provided for the new password does not not meet the length, complexity, or history requirements of the domain.
This is where it is thrown:
byte[] decryptedData = ProtectedData.Unprotect(Encoding.UTF8.GetBytes(fileContent),
Encoding.UTF8.GetBytes(entropy),
DataProtectionScope.LocalMachine);
It also happens when using DataProtectionScope.CurrentUser.
I haven't found any information about this exception online so I'm pretty much clueless.
Some generic errors won't generate an exception and that last error is thrown.
From inside System.Security.Cryptography.ProtectedDate.Unprotect:
throw new CryptographicException(Marshal.GetLastWin32Error());
More specifically it is most like failing because of on of the default flags using the System.Security.Cryptography implementing crypt32.dll:CryptUnprotectData - CRYPTPROTECT_UI_FORBIDDEN - "This flag is used for remote situations where presenting a user interface (UI) is not an option. When this flag is set and a UI is specified for either protection or unprotection, the call fails and GetLastError() returns the ERROR_PASSWORD_RESTRICTION status code." Windows Data Protection
I found a workaround that works for me is to not use the Base64 converter, I use the same script that PowerShell uses:
static byte[] ByteArrayFromString(string s)
{
int length = s.Length / 2;
byte[] numArray = new byte[length];
if (s.Length > 0)
{
for (int i = 0; i < length; i++)
{
numArray[i] = byte.Parse(s.Substring(2 * i, 2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture);
}
}
return numArray;
}

Exception from HRESULT: 0xFFFFFFF8

I keep getting this error in my controller during verification of fingerprint. And I can't seem to understand why. I'm using digitalPersona SDK Fingerprint reader, asp.netc#. I already tried googling but with no success. T_T
This is my codes in my controller
void verificationControl_OnComplete(object Control, DPFP.FeatureSet FeatureSet, ref DPFP.Gui.EventHandlerStatus EventHandlerStatus)
{
clearInfoBoxTimer.Stop();
DateTime entryTime = DateTime.Now;
DPFP.Verification.Verification ver = new DPFP.Verification.Verification();
DPFP.Verification.Verification.Result res = new DPFP.Verification.Verification.Result();
employee employees = null;
foreach (fingerprint fingerPrint in this.db.fingerprints)
{
DPFP.Template template = new DPFP.Template();
template.DeSerialize(fingerPrint.data);
ver.Verify(FeatureSet, template, ref res); //I GETTING AN ERROR HERE
if (res.Verified)
{
employees = fingerPrint.employee;
break;
}
}
}
Full Error:
System.Runtime.InteropServices.COMException (0xFFFFFFF8): Exception
from HRESULT: 0xFFFFFFF8
at DPFP.Verification.Verification.MC_verifyFeaturesEx(SafeHandle
mcContext, Int32 templateSize, Byte[] templatePt, Int32
featureSetSize, Byte[] featureSet, Int32 reserved0, IntPtr reserved1,
IntPtr reserved2, IntPtr reserved3, Double& achievedFar)
at DPFP.Verification.Verification.Verify(FeatureSet FeatureSet, Template Template, Int32 FARRequested)
at DPFP.Verification.Verification.Verify(FeatureSet FeatureSet, Template Template, Result& Result)
at Timee.BundyForm.verificationControl_OnComplete(Object Control, FeatureSet FeatureSet, EventHandlerStatus&
EventHandlerStatus) in
C:\Users\MyName\Desktop\Time\Timee\BundyForm.cs:line 79
at DPFP.Gui.Verification.VerificationControl.<>c_DisplayClass2.b_0()
Does anyone knows why I'm getting this error? or perhaps knows something about the error and share it? Thank you.
Well ... I had that problem today, but the detail was that I was comparing the features with an '' in the database, i change the '' by a null value and voilĂ 
I'm not really sure about this but I think my error has something to do with the datatype that I use. I use previously binary(255) to insert a long binary fingerprint data in mysql. I think binary(255) is not enough to store the long binary value of fingerprint.In my previous server which is sql server, I use binary(1632) to store the fingerprint binary data. So I changed it to BLOB datatype. So now it doesn't get an error.

Can anyone explain the major features of a VDPROJ file?

I'm sure there must be some documentation on MSDN somewhere, but I couldn't find it. It looks like some subset/variation of JSON. Really, this question grew out of something that has always bugged me: what do all the 8:s and 3:s mean? Is this some a version number of some kind? Maybe a typing scheme? Every VDPROJ excerpt I've ever seen is filled with these "eight-colon" and "three-colon" prefixes, but this is not the sort of question search engines are really good for.
"DeployProject"
{
"VSVersion" = "3:800"
"ProjectType" = "8:{978C614F-708E-4E1A-B201-565925725DBA}"
"IsWebType" = "8:FALSE"
"ProjectName" = "8:ProjectNameRedacted"
"LanguageId" = "3:1033"
"CodePage" = "3:1252"
"UILanguageId" = "3:1033"
"SccProjectName" = "8:"
"SccLocalPath" = "8:"
"SccAuxPath" = "8:"
"SccProvider" = "8:"
"Hierarchy"
{
"Entry"
{
"MsmKey" = "8:_02F97BB7BD104F1AAA1C97C854D5DC99"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
...
If anyone just wants to berate my pitiful Google-fu, that's fine too.
As #R. Matveev pointed out, the prefix numbers likely indicate the type of data stored in the property. This would be useful when deserializing the file into an object structure.
I doubt the source code which Visual Studio used to read/write the files was ever made open source, so it's no wonder that web searches returned nothing.
The best I could find was this page on OLE Automation data types, which may not have been the actual constants, but the data types seem to match the values in the *.vdproj file.
2.2.7 VARIANT Type Constants
typedef enum tagVARENUM
{
VT_EMPTY = 0x0000,
VT_NULL = 0x0001,
VT_I2 = 0x0002,
VT_I4 = 0x0003, // 4-byte signed integer
VT_R4 = 0x0004,
VT_R8 = 0x0005,
VT_CY = 0x0006,
VT_DATE = 0x0007,
VT_BSTR = 0x0008, // BSTR (string data)
VT_DISPATCH = 0x0009,
VT_ERROR = 0x000A,
VT_BOOL = 0x000B, // Boolean value
VT_VARIANT = 0x000C,
VT_UNKNOWN = 0x000D
...
} VARENUM;

Embedding Mono in Objective-c project: How to handle returned List<>

I'm embedding Mono in an MacOSX app written in Objective-c.
I'm accessing a C# lib (DDL), which only contains a bunch of static methods returning different types.
So far I can successfully get returned int, double and string, but I'm having trouble retrieving a returned array...
For exemple, here's how I retrieve an int:
MonoDomain *domain = mono_jit_init("TestDomain");
NSBundle* mainBundle = [NSBundle mainBundle];
NSString* dll = [mainBundle pathForResource:#"TestLib86" ofType:#"dll"];
MonoAssembly* assembly = mono_domain_assembly_open(domain, [dll UTF8String]);
MonoImage* image = mono_assembly_get_image(assembly);
// Get INTEGER
// get a method handle to whatever you like
const char* descAsString = "MiniLib86.Show:GetInt()";
MonoMethodDesc* description = mono_method_desc_new(descAsString,TRUE);
MonoMethod* method = mono_method_desc_search_in_image(description, image);
// call it
void* args[0];
MonoObject *result = mono_runtime_invoke(method, NULL, args, NULL);
int int_result = *(int*)mono_object_unbox (result);
// See the result in log
NSLog(#"int result %i", int_result);
The method in C# that returns an List looks like this:
public static List<int> GetListInt()
{
return new System.Collections.Generic.List<int>{1,2,3,4,5};
}
Any help would be really appreciated !
Take a look at mono_runtime_invoke_array.

Categories