PDetsFromPath throwing ProductDetailsException on Mac

Hello,

I am integrating LimeLM in a Mac app which I am building using mono. I modified TurboActivate.cs file so that it imports functions from dylib file instead of dll. I am having trouble with PDetsFromPath throwing ProductDetailsException which means that either the file is missing or it is corrupt. However File.Exists() returns true for the path I use and I have also tried re-downloading the file.

Can anyone help with the issue?

Well, make sure you're calling PDetsFromPath() before you make any other TurboActivate calls. Also, since you're using Mono, and thus you've modified the P/Invoke TurboActivate calls, also make sure the strings are being passed as UTF-8 on non-Windows platforms. That is, if you've done what I've suggested above, and you still get this error, then the error is likely caused by Mono converting the string path to UTF-16 instead of UTF-8.

See: Interop with Native Libraries on Mono

I solved it by moving the file to the app directory and now it is detected automatically by the library.

Similar problem, can you tell me how you fixed it? I'm trying to add TA to a Xamarin bundle. I've tried with the dylib and dat files just about everywhere, I've set it to AnyCPU, x86 and 64. I've tried setting the PDetsFromPath and every time it says the same message - the dat file is either missing or corrupt.

Where exactly do the dylib, dat and TA.exe files go? Please.

N

The TurboActivate.dat file needs to be in the same folder as the executable file (which is inside the YourApp.app folder if you're building an "app package").

Does that make sense?

Yes, tried that. I have now manually added TurboActivate.dat into the MonoBundle folder alongside the exe file and the dylib file. Also in desperation I've put it in the MacOS folder, the Resources folder and the the Contents folder, and in the package alongside the Contents folder. It is a newly downloaded copy of our TurboActivate.dat. I still see the same message. Is there a particular dat file for OSX? What am I missing? The code is

namespace ISISVision{

static class MainClass { static TurboActivate ta; //readonly static bool isGenuine;

static void Main (string[] args) { // Don't use 0 for either of these values. // We recommend 90, 14. But if you want to lower the values we don't recommend going // below 7 days for each value. Anything lower and you're just punishing legit users. const uint DaysBetweenChecks = 90; const uint GracePeriodLength = 14; NSApplication.Init (); try { ta = new TurboActivate("our GUID");

Any ideas at all?Neil

Hey Neil,

Mono might not be playing by the same rules as native applications on macOS. So, use TurboActivate constructor to pass in an absolute location to the TurboActivate.dat file. You can use the C# classes to get the absolute path of your mono exe, and work from there.

Let me know if that helps.

Yep, tried that too. I even added a

string sFilename= <<code to access file path through NBundle>> + "/TurboActivate.dat"if (System.IO.File.Exists(sFilename)){ta = new TurboActivate("our GUID", sFilename);}else

and stepped through the code, and confirmed that the file exists and this line was being called. I am assuming it wants the filename too, not just the folder location.Neil

Try re-downloading your TurboActivate.dat from LimeLM. Does that work?

I downloaded and tried with a new copy yesterday. Is that current enough?

Neil

Yep, that's new enough.

I just realized what the problem is, our C# example is built for Windows, so the strings it passes are marshaled Wide-Strings. The problem is that only Windows uses Wide Strings. macOS and the other unix variants use UTF8 (multibyte char* strings).

This is a long way of saying you'll have to modify our TubroActivate.cs to pass in UTF8 strings to the native TurboActivate functions rather than WideStrings.

In the near future we'll add support for Mono and Microsoft's .NET framework on macOS.

fantastic thanks, Wyatt.

I changed two entries:[DllImport("libTurboActivate.dylib", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern UInt32 TA_GetHandle(string versionGUID);

[DllImport("libTurboActivate.dylib", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] public static extern int TA_PDetsFromPath(string filename);

I guess I may need to change others as I get to them but all works fine now. Thanks for the helpNeil 😀

Hello Wyatt, I think this is related. I'm trying to set some extra data, using the pc username but I only ever get the first letter.

ta.Activate(Environment.UserName);andta.UseTrial(trialFlags, Environment.UserName);wheretrialFlags = TA_Flags.TA_USER | TA_Flags.TA_VERIFIED_TRIAL;

I've changed the Unicode call to Ansi as worked before. Any words of wisdom?

Neil

Hey Neil,

It depends on the version of the .NET Framework. My guess is that the .NET Framework on your app is storing the strings internally as WideChar strings, but not correctly converting them to multi-byte strings when calling the DLL.

Right again, Wyatt.

Here is the code I used - probably not the most efficient (and grateful for any improvements):NSString ns = (NSString)Environment.UserName;NSData dValue = ns.Encode(NSStringEncoding.UTF8);string s = NSString.FromData(dValue, NSStringEncoding.UTF16LittleEndian);modDeclare.ta.UseTrial(trialFlags, s);

ThanksNeil

You're converting a string to UTF16 on macOS and then passing it to TurboActivate. That's the problem. Unix versions of TurboActivate use UTF8 strings. Windows version of TurboActivate uses Wide-Char (roughly UTF16) strings.