Enums don't equal on different machines? - c#

I'm using the Wix Bootstrapper Enum LaunchAction:
Microsoft.Tools.WindowsInstallerXml.Bootstrapper.LaunchAction
On my machine, a different laptop and a virtual machine when I do:
var m_state = LaunchAction.Install;
And then later on:
if(m_state == LaunchAction.Install)
It passes. Looking in the debugger m_state has the value Install. However on my colleagues machine the if statement does not pass. Looking in the debugger the values are exactly the same. My thoughts are that he might have an outdated / updated version of the WixBootstrapper DLL however that shouldn't actually have any effect because it would use that DLL when compiling.
Edit:
Comparing them as int values, on my machine and the laptop both values are 5. On my colleagues machine m_state is 5 and LaunchAction.Install is 4.
Edit 2:
So what we believe is happening is that the DLL he has on his machine is from the Wix toolset 3.9 whilst the other machines are using 3.10. In 3.9 the LaunchAction.Install is 4, whereas in 3.10 it is 5.
The custom bootstrapper has this DLL as a payload file. What we think has happened is that the payload file being added is a 3.10 version but when its originally compiled it's using the 3.9. Resulting the in the comparison being:
if(m_state == 4)
The answer being false because the value of m_state is using the 3.10 version so it reads 5.

You must rebuild bootstrapper applications and bundles when you switch versions of WiX. They're source-compatible buts BAs are not guaranteed binary-compatible.

Related

How can I conditionally run my program in 64 bit or 32 bit mode based on external resources?

There are a few questions (and unwanted answers) all over the forums about Microsoft.ACE.OLEDB.12.0 provider not being registered on the local machine, like this one. The gist of the problem, how I understand it, is that the application will look for the provider on the same platform as what the application is running on. So if your computer is 64 bit and the provider 32 bit, then there will be a mismatch if you don't compile the application to run in 32 bit mode.
Most answers effectively deal with this by installing the appropriate data components for the current platform. Other suggestions are to compile for whichever platform the data components are available.
I am developing an app using PCs running Windows 7, 8 and 10, all 64 bit, depending on where I am, but some have older versions of Office and others newer versions. This causes me to have to change the platform for which I compile depending on the PC I currently work on. While this is no problem for me, personally, I foresee this causing headaches for the end users not being able to run the program.
Trying to avoid asking users to install other components on their computers; is there a way I can tell the program to check the platform availability of the database provider and then run in that mode? Might it be possible to create 32 bit and 64 bit extensions of the database module and load the appropriate one regardless of the mode the main program is running in?
EDIT:
I just tried to compile my database extensions on different platforms Whichever one that is not the same platform as the application causes an exception when being loaded saying that I am attempting to load an assembly from a different platform. So I guess I'm out of luck with my option 2...
You can use CorFlags utility to modify your executable on target machine, after you will detect which mode it needs to run.
First ensure that your main exe is compiled under any cpu with Prefer 32 bit flag not set. Now when application is started you need to check if we are in 64-bit process or not, and also check your dependencies (this I won't cover - I don't work with OLEDB). If you found mismatch (say you are running in 64-bit process but your dependencies are 32-bit) - you need to run external process to modify your main executable and then restart it. Easiest way to do it is via simple cmd script, like this (in this example my main exe is called ConsoleApplication3.exe):
:start
start /wait "" "C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\CorFlags.exe" ConsoleApplication3.exe /32BIT+
if errorlevel 1 (
goto start
)
start "" ConsoleApplication3.exe
Note that this is just example and if something goes wrong it will fall into endless loop, adjust to your requirements. What this script does is just updates your exe using CorFlags tool to run in 32-bit mode, then starts your main exe.
Right after starting your application, you might do the following check:
static void Main() {
if (Environment.Is64BitProcess) {
// here you also check if you have dependency mismatch, and then:
Console.WriteLine("Running in 64-bit mode. Press any key to fix");
Console.ReadKey();
// run script (here we assume script is in the same directory as main executable, and is called fix-mode.cmd
var process = new Process() {
StartInfo = new ProcessStartInfo("cmd.exe", "/c call fix-mode.cmd")
};
process.Start();
// here you should exit your application immediatly, so that CorFlags can update it (since it cannot do that while it is running)
}
else {
// after restart by our script - we will get here
Console.WriteLine("Running in 32bit mode");
}
}
Note that this tool (CorFlags) is available only with Visual Studio so you may want to pack it together with your application (might be not available on remote machine).

Beginner ILNumerics: install under VS2012

I am very much interested in ILNUmerics and would like to try the free version, but I am having troubles.
I have started with a console application and was trying to run the 'hello ilnumerics'console application but I noticed that VS fails to find MKL libraries.
I am using VS2012 under Windwos 8 (through Bootcamp on a MacBook Pro mid 2010; should it be relevant); I have installed the NuGet Packages extension from the Project solution. Then right-click on references in the solution explorer, 'Manage Nu Get Packages', fron online/search found ilnumerics in various versions. I chose 'ILNumerics' and install. I got 'ILNumerics' and 'ILNumerics.Native' added to my project. Then I can see ILNumerics under 'References' in Solution Explorer and also get two new folders /bin32/ and /bin64/ they both contain two DLLs named: libiomp5md.dll and mkl_custom.dll. I have checked their
'Copy to Ouput Directory' property and they are all set to 'Copy if newer'.
Apparently mkl_custom is not found. I write the following code, taken from the quickstart guide:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ILNumerics;
namespace ConsoleApplication3
{
class Program : ILMath
{
static void Main(string[] args)
{
ILArray<double> A = array<double>
(new double[] { 1,1,1,1,1,2,3,4,1,3,6,10,1,4,10,20} ,4, 4);
ILArray<double> B = counter(4, 2);
ILArray<double> Result = linsolve(A, B);
Console.Out.WriteLine("A: " + Environment.NewLine +
A.ToString());
Console.Out.WriteLine("B: " + Environment.NewLine + B.ToString());
Console.ReadKey();
}
}
}
and I get this exception:
An unhandled exception of type 'System.DllNotFoundException' occurred in ILNumerics.dll
Additional information: Unable to load DLL 'mkl_custom': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
If I do not invoke linsolve the ToString method of ILArray does work: if I comment // ILArray Result = linsolve(A, B);
I get the two matrices printed on the screen.
I have also tried to compute the determinant of a matrix and got the same exception: apparently any time I call mkl_custom VS is not capable to find it.
Any help/hint, please?
Also, is it necessary to install ILNumerics through NuGet on any project added to the solution? Would it be possible to install it locally once for all and then add the reference if necessary?
Two options:
1) Make sure, all binaries are accesible as intended: ILNumerics uses AnyCPU targets and chooses the platform dependend subfolder by adding the "bin32" / "bin64" directories to the PATH envoronment variable on startup. Possibly there is something failing on your machine? You can make sure by placing the correct binaries (depending on your platform) directly into the output path manually.
2) In case the error persists: mkl_custom.dll depends on some other dlls itself. One (libiomp5md.dll) is delivered with the ILNumerics nuget package. Others are expected to exist on your system: KERNEL32.DLL and MSVCR110.DLL. Make sure, you have these! If the kernel dll was missing -> call it a miracle and reinstall your system. If the msvcr110 is missing -> go here and install the "Visual C++ Redistributable for Visual Studio 2012".
In case the problem persists, you may file a bug on the ILNumerics bugtracker, because, the runtime should be there, as you wrote you are using VS2012. Possibly it is a versioning problem though.
EDIT: Since version 4.0 ILNumerics does not deploy the native binaries in bin32/ bin64/ subfolder anymore but installs all native dependencies systemwide into the GAC and System32/WOW folders. The old scheme will still work (for compatibility with old projects) though. But it is not necessary anymore to deal with any dependancies for ILNumerics explicitly. They should simply be found at runtime.
Like numbers303 said, ILNumerics.dll can't find a required dependency. You can brute force fixing this dependency by copying the required DLLs to the same directory as the ILNumerics.dll as a post build step, but I think there's a more elegant solution.
A VS2010 .NET console solution gets created by default with the x86 configuration. Compiling and running the ILNumerics example Hello ILNumerics! code with this configuration results in a DLL not found exception (mkl_custom.dll).
Re-targeting the solution via configuration manager to 'Any CPU' fixed the issue for me:
In Solution Explorer, right click on the solution and select properties. Select Configuration Properties and click on the Configuration Manager... button in the upper right hand corner. Make sure that the project that uses ILNumerics has the 'Any CPU' selected. If 'Any CPU' isn't available as a selection, select '' from the pulldown and create an 'Any CPU' platform based on your current platform. Usually this just means accepting the default in the 'New Project Platform' dialog. You'll probably also want to modify the 'Active solution platform:' to contain an 'Any CPU' target as well.
Rebuild/run.
In my case it helped to install "Visual C++ Redistributable for Visual Studio 2012" although I work with Visual Studio 2010 with the corresponding "Visual C++ Redistributable for Visual Studio 2010" installed. Which worked fine as long as the mkl_custom.dll is not needed. But colleagues of mine dosn't have this problem without having the 2012 Redistributable installed.

Class not registered error from PHP

We've created a C# class library assembly and made it COM visible to be able to call its methods from PHP. This used to work fine, but now we wanted to install it on a Windows Server 2008 server and we keep walking into the error "Class not registered".
To rule out any dependency problems I made a tiny little test class library in C#. The class library is built for Any CPU and it is COM visible (also set COMVisible to true in AssemblyInfo.cs). The test class library only contains one class with one method. The class is called TestLib and the namespace is also called TestLib. The method is called Test and only returns a string.
What we have done is the following:
- built the TestLib.dll
- copied it to the Windows Server 2008 machine
- registered the dll with: regasm /codebase TestLib.dll
- the regasm tool returns a success message
- in PHP we simply try to create a new COM instance:
try
{
$test = new COM("TestLib.TestLib");
}
catch (Exception $e)
{
die($e->getMessage());
}
when we call this test script from either the browser or the commandline (php -f test.php) we get the error "Class not registered" in both cases
I also tried adding TestLib to the GAC by using gacutil -i, but to no avail; still the class not registered error.
Then I tried compiling the testlibrary with .NET 2.0 instead of 4.0 as the target framework, same result. The .NET framework 4.0 is installed on the server by the way.
Any ideas?
Okay, so after some more research I figured it out. The php.exe process is 32 bit. The COM visible assembly is compiled for Any CPU so it should be accessible to both 32 and 64 bit applications.
The problem is that on a 64 bit OS php.exe, and any 32 bit process for that matter, searches in HKEY_CLASSES_ROOT\Wow6432Node\CLSID instead of HKEY_CLASSES_ROOT\CLSID and in HKEY_LOCAL_MACHINE\Software\Classes\Wow6432Node\CLSID instead of HKEY_LOCAL_MACHINE\Software\Classes\CLSID. The registry entries in the Wow6432 keys aren't created by regasm that is shipped with .NET framework v4 on Windows Server 2008. On Windows 7 they are created, don't ask me why.
It also turned out that if I create a little test assembly for .NET v2.0 and register it with regasm that ships with .NET framework v2.0 that it does create the Wow6432Node entries on Windows 2008. Strange.
So my solution is to create a basic registry file on the server using:
regasm /regfile MyClassLib.dll
This creates a file MyClassLib.reg with only the 'normal' 64 bit entries. Then I exported the Wow6432Node keys from a Windows 7 machine and added it to that .reg file. Now when I import that reg file into the registry on Windows 2008 everything works fine.
For more info on the Wow6432Node entries check out: http://msdn.microsoft.com/en-us/library/windows/desktop/ms724072%28v=vs.85%29.aspx
Hope this saves someone else some time and headaches.
If you are trying to call a 32-bit COM DLL on 64-bit Windows, you will need to register it.
Copy your 32-bit DLL to C:\Windows\sysWOW64
Run C:\Windows\sysWOW64\regsvr32.exe your_com_32.dll
A bit more info with screenshots.

PerformanceCounters on .NET 4.0 & Windows 7

I have a program that works fine on VS2008 and Vista, but I'm trying it on Windows 7 and VS2010 / .NET Framework 4.0 and it's not working. Ultimately the problem is that System.Diagnostics.PerformanceCounterCategory.GetCategories() (and other PerformanceCounterCategory methods) is not working. I'm getting a System.InvalidOperationException with the message "Cannot load Counter Name data because an invalid index '' was read from the registry."
I can reproduce this with the very simple program shown below:
class Program
{
static void Main(string[] args)
{
foreach (var pc in System.Diagnostics.PerformanceCounterCategory.GetCategories())
{
Console.WriteLine(pc.CategoryName);
}
}
}
I did make sure I'm running the program as an admin. It doesn't matter if I run it with VS/Debugger attached or not. I don't have another machine with Windows 7 or VS2010 to test it on, so I'm not sure which is complicating things here (or both?). It is Windows 7 x64 and I've tried forcing the app to run in both x32 and x64 but get the same results.
It seems performance counters were corrupted on my system. Although I didn't follow this post exactly, it led me to the solution. Here is what I did:
In an command prompt with administrator/elevate privileges typed the following:
lodctr /?
Useful stuff in there...
Then typed:
lodctr /R
According to the docs from the prior step, this gets windows to rebuild the perf registry strings and info from scratch based on the current registry settings and backup INI files. I have a feeling this is what did the magic. However, next I noticed the .NET performance counters were not there anymore so based on this I typed the following to reload them:
lodctr "C:\Windows\Microsoft.NET\Framework64\v4.0.20506\corperfmonsymbols.ini"
Note that this path is for .NET Framework 4.0 on x64. You can imagine the path for other variations of the framework/platform. I'm guessing you should always load the counters from the highest version of the .NET framework that you have installed, but that is just a guess.
I hope this helps someone else someday!

C# for 64bit OS?

How can I make my compilation optimized for Windows 64 bit?
You might also want to do a check at runtime, just to be sure:
using System;
using System.Runtime.InteropServices;
class SystemChecker
{
static bool Is64Bit
{
get { return Marshal.SizeOf(typeof(IntPtr)) == 8; }
}
}
A managed project is automatically built according to the architecture selected => default C# project created on AMD64 will be AMD64, X86 on X86. The native one is always 32-bit by default.
To explicitly set a platform:
1 open the solution explorer, select solution, right click->Configuration Manager.
2 go to 'Active Solution Platform', click New.
3 in the 'New Solution Platform' dialog that comes up select the new platform say Itanium. Set 'Copy Settings From' to 'Any CPU' which was the default setting in the 'Active Solution Platform'.
4 click OK.
This is from WebLog
As Patrick Desjardins said, with a little addition.
Beware if you have third party DLL which uses Interop and is compiled with 32 bit. In that case, you will specifically have to set all your assemblies which uses it to use x86 or all manner of weird things will happen.
You can compile for 64bit through the /platform-flag. Note that visual studio Express has no straightforward 64bit compile setting.
See here for more information, and here. Taken from the second source is the following information:
On a 64-bit Windows operating system:
Assemblies compiled with /platform:x86 will execute on the 32 bit CLR running under WOW64.
Executables compiled with the /platform:anycpu will execute on the 64 bit CLR.
DLLs compiled with the /platform:anycpu will execute on the same CLR as the process into which it is being loaded.
Runtime Check:
You can check the execution bit environment at runtime through one of the following options
bool is64BitProcess = IntPtr.Size == 8;
int bitProcess = IntPtr.Size*8;
//C# 4 provides System.Environment.Is64BitProcess
//TimothyP's solution:
bool is64BitProcess = Marshal.SizeOf(typeof(IntPtr)) == 8;

Categories