Has anyone actually managed to accomplish this?
I tried the approach suggested here, but no matter how i generate the precompiled serializer, mtouch fails to copy it to the app bundle, thus resulting in a runtime exception. I think this happens because the resulting binary may not be compatible with MonoTouch.
I have tried the following:
1) I used the provided iOs and Mono binaries included in the latest (r450 as this time) build in order to generate the precompiled serializer.
2) I used the source code to produce two different assemblies, built for MonoTouch. The first assembly is built using the symbols FEAT_SAFE;MONOTOUCH;NO_RUNTIME and the second is built using the symbols FEAT_SAFE;MONOTOUCH;FEAT_COMPILER. I have defined the symbol MONOTOUCH and used it the same as MONODROID symbol is used (see file CallbackAttribute.cs and Helpers.cs in the protobuf-net source).
I the used this two assemblies and tried to generate the precompiled serializer from a MonoTouch application in the simulator.
But no matter which version of the precompiled serializer i use, the assembly is still not included in the app bundle, with mtouch issuing: "Warning: Library 'MyLibrary.dll' missing in app bundle, cannot extract content", despite the fact that i do reference it in my code.
I finally got it. It seems that when the actual assembly name is different from the file name that contains it mtouch will not include it in the application bundle. And that was happening in my case. I am generating the assembly like this:
model.Compile("Taxi.ProtoBufSerializers.MQTTContractsSerializer", "MQTTContractsSerializer.dll");
So, given that Protobuf-Net sets the assembly name to the first parameter of this method and saves it in the file name given by the second parameter, mtouch will fail to include it in the application bundle.
However, i wanted to keep my namespace so i fiddled with Protobuf-Net's source code to generate the assembly like this:
File path: Given as the second parameter;
Assembly name: Path.GetFileNameWithoutExtension(path);
Module name: Path.GetFileName(path).
I am not performing any validations on the path at this time, but i don't need to do this just yet.
And voila: The sample works both on the simulator and the device.
Last but not least, i don't know if this is the way mtouch is supposed to behave or if it is a bug. I will however file a bug report against it.
I have only gotten it to work on the simulator. I created the custom serialization assembly on VS.NET 2010. One issue I had was that the IL/DLL that gets created had the wrong namespace. I did something like this:
model.Compile("X.Y.Serializer.MySerializer", "X.Y.Serializer.dll")
But the IL was something like:
.assembly X.Y.Serializer.MySerializer
{
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module X.Y.Serializer.MySerializer
I.e. the class name was in the assembly name.
So I wrote a perl program to:
Decompile DLL -> IL
Fix IL
Compile IL -> DLL
Here is the script:
#!/usr/bin/perl
# Usage: fix-protobuf-assembly assembly bad-namespace
#
# Example: fix-protobuf-assembly X.Y.Serializer.dll X.Y.Serializer.MySerializer
# X.Y.Serializer.MySerializer gets converted to X.Y.Serializer
use strict;
use File::Slurp;
use Cwd;
print "Current directory is " . getcwd() . "\n";
my $asm_file = shift || die "missing assembly file";
my $bad_ns = shift || die "missing namespace";
die "no such file '$asm_file'" if (! -f $asm_file);
my $il_file = $asm_file;
$il_file =~ s#dll$#il#;
Run("ildasm /out=$il_file $asm_file");
my $il = read_file($il_file) || die "error reading $il_file: $!";
my $ns = $bad_ns;
$ns =~ s#\.[^.]+$##;
if (($il =~ s#(\.assembly|module) $bad_ns#$1 $ns#g) == 0)
{
die "$bad_ns not found in input dll; aborting";
}
write_file($il_file, $il);
Run("ilasm /dll $il_file");
sub Run
{
my($command) = #_;
warn "Running $command ...\n";
system($command) && die "error running last command; bailing out";
}
Maybe I just missed the proper way to call Compile() and my hack is unnecessary.
The assembly worked fine on Windows and iOS simulator. But it then gave a runtime JIT compile violation error on the device. I just created a SO question:
JIT compile error with protobuf-net on MonoTouch/iOS device (iPhone/iPad)
I did try using MonoDevelop on Mac w/ standard console project to first create the serialization assembly. I had some issues, but to be honest I was sleepy and grumpy and it could have been user error, and quickly decided to jump over to Windows since my project has other components that I develop there.
I used .NET 4.0 projects on Windows and everything worked OK. I just had to create a lightweight version of two MT-only libraries so that I could access the classes that would be serialized.
Yes, we have been using it on a project since 2012 to improve performance over XML serialization. Mostly because the RESTFul services we had at the time could not do JSON over 1MB in size for some of the files. At this point in 2017, it would be a lot easier for us to use JSON now, instead of the extra hassle of building the custom serializers for each object.
Related
HOW I CAME ACROSS THIS
I wrote code for a simple stopwatch which can also double up as a Rubik's cube timer. The source code and the executable are here:
Cube timer
Anyway my doubt is not regarding this code(It works fine).
I downloaded the executable that I had uploaded to check if it worked fine and at that time I was greeted with this screen:
Open file - security warning
And under this dialogue box there was a field that said:
Publisher : Unknown Publisher
SCREEN SHOT:
DOUBT
Is there some way programatically or otherwise by which I can change the publisher field?
SPECS
I have compiled the code with Microsoft Visual C++ 2010 Express.
You can easily change the publisher, either when linking/compiling by setting the appropriate resources for your project (e.g. CompanyName), or modifying the resources with a resource editor.
Your problem is really that there is no signature, so even if a publisher field is present it cannot be trusted.
You can find an example resource rc file near the end of http://msdn.microsoft.com/en-us/library/windows/desktop/aa381058%28v=vs.85%29.aspx.
To add resources to your VC project check:
How do I embed version information into a windows binary?
VC++ 2012: How to include version info from version.inc (maintained separately) into the .rc file
The .rc file(s) will be compiled to binary (.res) and linked into your final executable.
To add or modify an existing executable, you should be able to use this tool (login required, this will cause the signature to be invalid in an already signed binary of course).
The Microsoft Authenticode documentation includes tutorials.
CAcert.org will sign a certificate you can use, and have instructions for getting started with Authenticode.
Sorry I can't be more helpful with VC, I don't use it, I usually using mingw and make, from some time ago targetting win32:
given a VERSIONINFO in a text version.rc file use mingw32-windres to compile it to a .o file (I actually had a bunch of .rc files, they were each #include-d in a single resources.rc so I only needed to run windres on that single file, and link a single extra object file)
include that version.o (or combined resources.o) in the final CC command, assuming compile and link to executable in one step
I also included -lversion when linking, AFAIR this was just because I used GetFileVersionInfo() for the code to check and display its own version in the 'About' dialog.
Make your program in a batch file, then using Advanced BAT to EXE Converter, convert it to EXE & fill out all of the fields. This sure helped me! :)
I'm currently trying to load a plugin assembly dynamically in a monotouch app.
To do this, I'm referencing the plugin dll in my app project, setting the limker to 'sdk only' and then i'm trying to call Assembly.Load(filename) within my app when the plugin is required.
This is the same approach that I've previously successfully used in monodroid. However currently, this is failing in monotouch with a FileLoadException.
Is this approach possible in monotouch? Is there a special file path you need to include? Or is this not supported in the aot environment?
Note: Obviously there are other ways I can achieve a similar effect - and I do have a backup plan... but this is my preferred route (if I can make it work)
Code like:
var a = Assembly.Load ("mscorlib.dll");
Assert.NotNull (a);
works fine with both the simulator and devices. However the parameter for Load is assemblyString which is not a filename (even if the exception thrown make you think it is).
Many other overloads exists (for Load) and other methods too (e.g. LoadFrom) but they might not all work inside MonoTouch (since some runtime support might be missing).
NOTE
Handling of mscorlib.dll is special (and works in more cases than other assembles, i.e. shortcuts). However the reflection-based methods seems to work as expected in more cases, e.g.:
string filename = System.IO.Path.GetFileName (GetType ().Assembly.Location);
Assembly assembly = Assembly.ReflectionOnlyLoadFrom (filename);
Assembly.Load (or any other way of loading code dynamically) is not supported in MonoTouch.
This is an iOS restriction - all the executable code has to be in the app (and it has to be native code, which is why we use AOT to generate native code at compile time).
I am using .Net 3.5/4.0 with code in C#.
I am trying to get a version number of an exe file on my C: drive.
For example path is: c:\Program\demo.exe. If the version number of demo.exe is 1.0.
How can i use this path to grab version number?.
You can use FileVersionInfo.FileVersion to fetch this from a path.
var versionInfo = FileVersionInfo.GetVersionInfo(pathToExe);
string version = versionInfo.FileVersion; // Will typically return "1.0.0.0" in your case
Updated and modernized 2018 (e.g. string interpolation of C#6):
The accepted answer is partly not correct (ProductVersion is not typically returning three-part version) and a bit misleading:
Here is a more complete answer. To get the main text not too lengthy I splitted it in a short(er) summary which may be "enough" for a lot of people. You are not obliged to read the detailed second part, so please no tl;dr :-)
Short summary:
There are different versions (assembly version, file version, product version) of each file, but normally you will have them all equal to not get "version hell" already on file level (it will come early enough).
The file version (which is visible in Explorer and used in setups/installations) is, what I would name the most important to bother.
To achieve this, simply comment out fileversion in AssemblyInfo.cs file as below. This assures that the three possible different versions of one file are the same!
[assembly: AssemblyVersion("1.1.2.")]
//[assembly: AssemblyFileVersion("1.1.2.")]
E.g. for Semantic versioning you want to get only 3 version parts out of possible 4 :
Having an automatic build counting for every Visual Studio build is useful. But this build counting is not always useful to tell your customers, internal or external. So for mentioning the file version to windows, in title dialogs, I would advice to show only three parts v1.2.3 (and of course with semantic versioning):
using System.Diagnostics;
...
var versInfo= FileVersionInfo.GetVersionInfo(pathToVersionedFile);
string fileVersionFull = versInfo.FileVersion; // No difference here for versinfo.ProductVersion if recommendation in AssemblyInfo.cs is followed
string fileVersionSemantic = $"V{versInfo.FileMajorPart}.{versInfo.FileMinorPart}.{versInfo.FileBuildPart}";
string fileVersionFull2 = $"V{versInfo.FileMajorPart}.{versInfo.FileMinorPart}.{versInfo.FileBuildPart}.{versInfo.FilePrivatePart}";
FileVersionFull2 is just showing how to handle all 4 parts, except the "V" it contains the same as FileVersionFull .
Details:
First is a cheat sheet about how to get and set the three versions:
File version: [assembly: AssemblyFileVersion(..)] => System.Diagnostics.FileVersionInfo.FileVersion
Product version: [assembly: AssemblyInformationalVersion(..)] => System.Diagnostics.FileVersionInfo.ProductVersion
Assembly version: [assembly: AssemblyVersion(..)] => System.Reflection.Assembly.Version
Especially the defaulting may be confusing. Recommended SO link to understand details: FileVersionInfo and AssemblyInfo
EntryAssembly vs. ExecutingAssembly
For fully considering every case for getting the version of the running app, search elsewhere for more details, e.g. here:
Which is better for getting assembly location , GetAssembly().Location or GetExecutingAssembly().Location
Especially, there can be confusion, if EntryAssembly or ExecutingAssembly should be used. They both have advantages and caveats.
If you have the following code not in the same assembly as the .exe, e.g. in a helper assembly, things get more complicated. Usually you would use EntryAssembly then, to get the version of the .exe.
But: For unit tests in Visual Studio to test routines in a parallel .exe project, GetEntryAssembly() doesn´t work (my env: NUnit, VS2017). But GetExecutingAssembly() doesn´t crash at least, only during unit test you get the assembly version of the test project. Fine enough for me.There may be situations which are not as simple.
If wanted, you can omit the declaration as static making it really possible to get versions of several different assemblies in one program.
public static class AppInfo
{
public static string FullAssemblyName { get; }
..
static AppInfo()
{
Assembly thisAssembly = null;
try
{
thisAssembly = Assembly.GetEntryAssembly();
}
finally
{
if (thisAssembly is null)
thisAssembly = Assembly.GetExecutingAssembly();
}
FullAssemblyName = thisAssembly.Location;
var versInfo = FileVersionInfo.GetVersionInfo(FullAssemblyName);
..
}
}
Product version vs. file version:
ProductVersion of a file is shown in Windows Explorer too. I would recommend to maximally differentiate ProductVersion and FileVersion in the most "customer-visible" file (mostly the main .exe of application). But it could be of course a choice to differentiate for every file of the "main" app and let them all have them all the "marketing" ProductVersion which is seen by customer.
But experience shows that it is neither necessary nor cheap to try to synchronize technical versions and marketing versions too much. Confusion doesn´t decrease really, costs increase. So the solution described in the first part here should do it mostly.
History: Assembly version vs. file version:
One reason for having different versions is also that one .NET assembly can originally consist of several files (modules)- theoretically. This is not used by Visual Studio and very seldom used elsewhere. This maybe one historical reason of giving the possibility to differentiate these two versions.
Technically the assembly version is relevant for .NET related versioning as GAC and Side-by-side versions, the file version is more relevant for classic setups, e.g. overwriting during updates or for shared files.
In the accepted answer a reference is made to "pathToExe".
This path can be retrieved and used as follows:
var assembly = Assembly.GetExecutingAssembly();
var fvi = FileVersionInfo.GetVersionInfo(assembly.Location);
var version = fvi.FileVersion; // or fvi.ProductVersion
Hope this saves someone from doing some unnecessary extra steps.
Where Program is your class name:
Console.WriteLine("Version = " + typeof(Program).Assembly.GetName().Version.ToString()) ;
I'm not sure if this is what you are looking for, but:
http://www.daniweb.com/software-development/csharp/threads/276174/c-code-to-get-dll-version
It says,
// Get the file version info for the notepad.
FileVersionInfo myFileVersionInfo = FileVersionInfo.GetVersionInfo(Environment.SystemDirectory + "\\notepad.exe");
// Print the file name and version number.
Console.WriteLine("File: " + myFileVersionInfo.FileDescription + '\n' + "Version number: " + myFileVersionInfo.FileVersion);
Use this, it works:
using System.Reflection;
string v = AssemblyName.GetAssemblyName("Path/filename.exe").Version.ToString();
This works good and returns the version provided in AssemblyVersion:
using System.Reflection;
infoFileVersionInfo versInfo = FileVersionInfo.GetVersionInfo("path.exe");
string version = $"v{versInfo.FileMajorPart}.{versInfo.FileMinorPart}.{versInfo.FileBuildPart}";
Solution 1
Dim fileVer As FileVersionInfo = FileVersionInfo.GetVersionInfo(Environment.CurrentDirectory + "\yourExe.exe")
yourLabel.Text = fileVer.FileVersion
Solution 2
Get File Version Number
yourLabel.Text = Application.ProductVersion
Both solutions will give 1.0.0.0
I developed an application using a recent Glade, so I need it to load the UI from XML at runtime, using the GtkBuilder. If I try to run this on a distro which has too old a Gtk (e.g. RHEL 5), it will fail like this
undefined symbol: gtk_builder_new
which is normal and expected. But I wonder if there is a way to catch that error and instead display a GUI error dialog saying something like "your version of Gtk is not new enough"? This is an error that happens before my main() starts, so really the question is, is there a way to handle runtime linking errors? While googling, I found a mention of the concept of a linker plugin but I didn't find details about that yet. It sounds like something which would have to exist outside my application anyway, so maybe that's going a bit far.
I could use dlopen() to load Gtk, but that's ridiculous because I'd have to give the full path to it, and then I'd have to call dlsym() a lot to link every function that I need. ld-linux.so does the search for me. Is there a way I can use ld-linux.so to tell me the path to libgtk without actually loading it, then I check whether the version is new enough (or just whether gtk_builder_new exists), then finish the runtime linking if it's OK?
Well, it doesn't work that way on a Linux distro. What you're basically doing is bypassing the package manager.
The good way is to build your software on the target distro. At configuration time (call to ./configure) you will see that the requirements to use your software are not met. Or if you have no configure script, the compiler will yell at link time.
Then, it's the packager's job to fill in the requirement of the package. If in the .spec file of your RPM package you require gtk >= 2.16, then at installation time, the user will be shown the dialog telling him that some dependencies are missing, and he will see that his GTK version is too old.
You seem to be talking about the situation where you have compiled against headers with a recent enough version, but are running on a system where your library is not recent enough.
GTK provides a facility for checking that you have linked against a new enough version of the library. For example, if you need at least GTK 2.12 (which is the version in which GtkBuilder was introduced) you can use this code which will even display a nice GUI error dialog:
if (gtk_major_version < 2 || gtk_minor_version < 12) {
GtkWidget *dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL,
GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE,
"Your version of GTK is too old to run this program.");
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
"You need at least version 2.12.0; your version is %d.%d.%d.",
gtk_major_version, gtk_minor_version, gtk_micro_version);
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
exit(-1);
}
Here is a workaround which might help: Rename your exe and create a bash script which calls it.
Now you can do this:
EXE=...name-of-your-real-executable...
LOG=logfile
$EXE > "$LOG" 2>&1 || {
if grep "undefined symbol: gtk_builder_new" "$LOG" ; then
... show error message ...
fi
}
[EDIT] Alternatively, you can create a really small test program which just contains a call to gtk_builder_new and run that during installation or in the test script.
That way, you don't need to check for a specific error message (which might get translated on non-English systems). If this small test program fails, you can be sure it's because of this missing symbol and nothing else.
I am trying to build an old version of an application which consists of VC++ projects that were written in Visual Studio 2003.
My OS is Windows 7 Enterprise (64-bit).
When I try and build the solution I get the following errors:
error C4772: #import referenced a type from a missing type library; '__missing_type__' used as a placeholder
fatal error C1084: Cannot read type library file: 'Smegui.tlb': Error loading type library/DLL.
They both complain about the following import statement:
#import "Smegui.tlb" no_implementation
This is not a case of the file path being incorrect as renaming the Smegui.tlb file causes the compiler to throw another error saying it cannot find the library.
Smegui is from another application that this one depends on. I thought perhaps I was missing a dll but there is no such thing as Smegui.dll.
All I know about .tlb files is that they are a type library and you can create them from an assembly using tlbexp.exe or regasm.exe (the later also registers the assembly with COM)
There is also an Apache Ant build script which uses a custom task to invoke devenv.com to build the projects. This is the same script that the build server originally used to build the application. It gives me the same errors when I try and run it.
The strangest thing about this is that I knew it ought to work seeing as it is all freshly checked out from subversion. I tried many different combinations of admin vs user elevation, VS vs Ant build, cleaning, release.
I have got it to build successfully about 5 times but the build seems to be non-deterministic.
If anyone can shed some light on how this tlb stuff even works or what this error might mean I would greatly appreciate it.
I found a far more reliable solution: open the tlb with oleview.exe and then close it.
Not sure what this actually does but it works every time.
I think oleview is actually one of the samples included with Visual Studio but I haven't had the time to debug it and see what it is doing.
I ran into this error because one type library was trying to load a dependent type library, which it could not find. Even though the dependent type library was in the same directory, and even though that directory was in the searchable path, the compiler would error loading the first type library, but not mention the dependent type library in the error.
To find the pseudo-missing type library, I ran Process Monitor (procman64.exe) during the compile. This showed that after the reported type library had successfully loaded, a dependent type library could not be found. It even showed all of the places that it was looking for the dependent type library, none of which were where it should have been looking (e.g.: ).
The fix was to add a <PreBuildEvent> to the project to copy the dependent .tlb file to one of the directories that was actually being searched.
<PreBuildEvent>
<Command>copy /Y ..\Lib\Interop\CWSpeechRecLib.tlb .\</Command>
</PreBuildEvent>
http://msdn.microsoft.com/en-us/library/sce74ah7%28VS.71%29.aspx
smegui.tlb is referencing some other tlb that the compiler can't find. If you have the .idl for smegui you might be able to figure out what the other is. I suspect the missing tlb is something that original build machine had registered but that your machine doesn't have registered.
A type library is a binary description of a set of interfaces, coclasses and enums. They're usually generated for COM components, in the case of tlbexp and regasm the tlb is created from the assembly metadata. For native COM components they are usually generated from an idl (Interface Description Language) file by the midl tool.
Edit:
I just noticed you're on x64 Windows. Are you building the project with a new version of Visual Studio? If so, are you targeting x86 or x64? If the latter, it may simply be a 32bit component that the compiler can't find (or less likely, a x64 component the x86 compiler can't find if you are targeting x86), for WOW64 the registry is virtualized for x86 vs. x64 applications.
Well I finally found out why I managed to get it to build sometimes and not others... sort of.
So long as I ran the build script with elevated administrator permissions and let that get as far as it could until that error occurred, then run the build script again as a protected administrator succeeded. Those steps must be done in that exact order with no other steps in between. If I try build in Visual Studio it does not work (although I did get it to succeed once). Probably some kind of virtualisation issue although it still doesn't quite make sense.
Well I don't need help on this any more and I know it's probably impossible to fully answer this question without knowing exactly what the build is doing. However if anyone does have any more thoughts I would happily receive them.
Cheers,
Steiny