ActCtx + manifest + comhost + .NET 6.0: does it work, does anyone has a working example? - manifest

My goal is to expose a .NET 6.0 library to COM, in order to use it from VBA in MS Access. And to use the manifest approach rather than using the registry.
Got article "Exposing .NET Core components to COM" working, using their "COM server sample" example code.
This example however requires that a manifest file is present in the folder containing the executable. When using the COM object from MS Access we do not want to place the manifest file and other files in the MS installation folders.
The suggested solution is to create an Microsoft.Windows.ActCtx object and let that object create my COM object, using the Manifest property of the ActCtx object to specify the manifest file.
This is the part that continues to fail. actCtx.CreateObject("") gives an Invalid Cast exception, even without assignment of the result to a variable, hence it is an internal issue. No additional details, no information in the event log. Tried this in C# and from VBA.
I have a few questions:
Is ActCtx the way to specify the manifest path, or is there a better way to do this from VBA in MS Office?
The example uses a COM host, which seems to be some COM class / object factory, which in turn helps creating my COM object. As opposed to .NET Framework this COM host seems to be introduced for .NET Core; .NET 6.0 in my case. Is the COM host required? Is the simpler direct instantiation possible?
Does anyone has answers to these questions, tips, or even better: a working example?

Some progress but I am still not happy. Abandoned the ActCtx approach for a while and tried to create the COM server object of the sample directly in MS Access VBA. Added a reference to the com host, say COMServer.comhost.dll, as opposed to the implementation COMServer.dll. Created the object, simply with New. Error: class not registered. Performed a regsvr32 COMServer.comhost.dll and the sample works.
Although the sample works there are now again registry entries: the guid of the server class has been added to the registry. Regfree COM not achieved.
This is despite COMServer.comhost.dll looking promising. A tlb type library built separately and embedded in the .dll is seen by VBA: intellisense works and the object browser works. The manifest seems to be correctly embedded in the .dll too, and takes precedence over the manifest on disk.
The question remains how to avoid the regsvr32 step and make the solution working by just adding the reference to COMServer.comhost.dll, in MS Access VBA.

Related

How to programmatically convert Access 1997 .mdb to Access 2007 .accdb

I'm in the starting process of building an application that walks through a folder structure, starting at a given root path, and converts all found Access 1997 .mdb files into the newer Access 2007/2010 .accdb format. However, I'm running into some troubles when doing to actual file conversion.
I'm using Microsoft's Access Interop API (https://msdn.microsoft.com/en-us/library/office/ff193465.aspx) to handle the conversion, so this has to be written in VBScript. Script is below:
Dim app
Set app = CreateObject("Access.Application")
app.ConvertAccessProject "C:\Users\[User]\Access Conversion Utility\sample.mdb", "C:\Users\[User]\Access Conversion Utility\converted.accdb", acFileFormatAccess12
When run, I get the error "The project cannot be converted into this format. The project can only be converted to Access 2000 or newer format." Yet, this same error message shows up regardless of the file parameter enum value, be it 'acFileFormatAccess97' or 'acFileFormatAccess2000'. Does anyone know the details of this error and what a possible solution could be? I've tried changing the extension of the second parameter, thinking that was part of the issue, but this made no changes to the error message.
The sample file I'm using is able to be opened in Access just fine, it's just the conversion itself that fails.
By all means, if anyone has a better idea or approach to do the conversion programatically, I would love to hear it, but this is the only one I was able to find. The plan is to run this script from a GUI application written in C#, but also allow for the application to be run via the command line as well.
I'm using Microsoft's Access Interop API ... so this has to be written in VBScript.
Nonsense. I just tried this in C# (Visual Studio 2010) and it worked fine for me with Access 2010:
// COM reference required for project
// Microsoft Access 14.0 Object Library
var app = new Microsoft.Office.Interop.Access.Application();
app.ConvertAccessProject(
#"C:\Users\Public\test\a97test.mdb",
#"C:\Users\Public\test\a2007converted.accdb",
Microsoft.Office.Interop.Access.AcFileFormat.acFileFormatAccess2007);
app.Quit();
Note that this will almost certainly not work with Access 2013 and later, but neither would a VBScript implementation of COM Interop for those versions of Access since they absolutely refuse to open Access_97 (and earlier) databases.
Problem is twofold.
First, Access 2007 and later won't read older formats than the JET 4 format of Access 2000.
Second, the constant for the 2007 format is acFileFormatAccess2007, not acFileFormatAccess12, it's the numeric value of the constant that is 12.
On this point, the documentation is wrong:
AcFileFormat Enumeration (Access)
So you will have to obtain an older version of Access for the first conversion to JET 4, then another step to convert to 2007 format.
Edit:
Or, of course, do as Gord shows.
Plain VBScript does not know about the ac* constants. So define them properly.

Error accessing WinRT sensors in C++ desktop application

I am trying to access the WinRT sensors from a Win32 desktop application using C++/CX as mentioned here: https://software.intel.com/en-us/articles/using-winrt-apis-from-desktop-applications
When I include the C++/CX header file it causes an error when building the Win32 project.
Exact error text: "error C1190: managed targeted code requires a '/clr' option."
Since I am not using /clr code at all, this is a confusing error.
Any suggestions? Please educate me if there is a better way to do this.
The error you are getting is because you are compiling some files without /ZW option for compiler. Since you are able compile at least some files with WinRT extensions, but not others, your project configuration is inconsistent.
The option /ZW (enable WinRT extensions) has to be configured on the level of project (and not on the level of individual files). There are two ways to ensure your settings are consistent. First method is through UI in Visual Studio -- you have to go through all platforms/configurations on the project and ensure /ZW is enabled, then got through all indivudual .cpp files, and ensure they don't override project level settings. This is tedious and error prone. The easier method is to open .vcxproj in notepad and do the following:
Add this section at the beginnig of the file, under root Project node:
<ItemDefinitionGroup>
<ClCompile>
<CompileAsWinRT>true</CompileAsWinRT>
</ClCompile>
</ItemDefinitionGroup>
Search and remove any other places where <CompileAsWinRT> is defined.

Manifest for dependencies on items other than the main executable?

I'll explain what i'm trying to do (and why) first and then get more into the details.
I'm trying to get Registration Free COM activation working in the context of a language that is compiled JIT. I use Reg-Fre COM because i would like to avoid having to register my COM component and would like this application to be installable without administrative rights.
The JIT compiler is the main executable is signed and contains an embeded manifest. Latest versions of Windows prefer the embeded manifest over an external one, by default (it was the opposite on Windows XP).
Since the JIT is signed, i cannot extract/modify/update it's manifest without breaking the signing. Also, this would introduce complexity in the maintenance of our application (always making sure we embed a new manifest). And there's are also the legal implications of modifying a program for which i don't own the rights.
So, my idea was to try to get the WinSxS activation going thru a Win32 wrapper library for which i would provide a manifest that lists the dependencies. As a proof of concept, i decided to make a simple VB6 app, a C++ Wrapper Library and two COM library (1 in .NET and 1 in VB6).
The wrapper contains 3 methods, one that calls the VB6 COM, one that calls the .NET COM and one that returns a simple string.
As long as everything as my COM are registered, it works, of course.
If i unregister them, provide manifests for the COMs and add them as dependencies to the main executable's manifest, it works.
If i unregister them, provide manifests for the COMs and the C++ Wrapper and add the com as dependencies for the C++ Wrapper and then add the C++ Wrapper as the only dependency in the main executable's manifest, it works.
If i delete my main executable's manifest, the COM calls stop working but the simple string method still works.
Please note that for all my tests, i run a Powershell script that changes the Modified Date of all my files, making sure to trip the activation context cache (manifest).
From there, i started debugging using SXSTrace.exe and setting the COMPlus_LoadLogDir variable. I found out that if my manifest is external, it never gets taken into consideration. I also found out that if i embed it in the .DLL, sxstrace shows it is found, parsed and that the dependencies are found, their manifest found and i get the usual successful context activation lines in the log.
INFO: Parsing Manifest File C:\RegFreeComWrapper\bin\vbCom.MANIFEST.
INFO: Manifest Definition Identity is vbCom,type="win32",version="1.0.0.0".
INFO: Parsing Manifest File C:\RegFreeComWrapper\bin\netCom.MANIFEST.
INFO: Manifest Definition Identity is netCom,processorArchitecture="msil",version="1.0.0.0".
INFO: Activation Context generation succeeded.
End Activation Context Generation.
However, even tho the log says that, my COM calls still dont go thru.
When the call goes thru for the .NET COM call, i get some output in the COMPlus_CLRLoadLogDir configured path.
In this case, i don't get any output.
As soon as i add the manifest that only lists my C++ Wrapper as a dependency to my main executable, everything starts working again. I get a similar output from SXSTrace, but now the COM call works. As mentioned, in all cases, the C++ Wrapper's simple string method works. Meaning that even tho i have no manifest from my main executable, it can still find my .dll and call it.
Seems like the COMs don't work if i dont have the full manifest chain:
Application.Manifest > Wrapper.Manifest > COMs manifests
So, two things here...
1. Is the thing i'm trying to do even possible? (Having dependencies listed only in the manifest of a DLL that belongs to me, without touching the main executable's manifest)
2. If it is possible, i'm probably only missing a small thing to get everything going... what is it ? :)
I can provide all my code/executable as examples, should someone be interested in trying stuff with em.
Got it working!
I modified my C++ Wrapper to use the Activation Context API and force a context activation using 'ActivateActCtx'
http://msdn.microsoft.com/en-us/library/aa374151(v=vs.85).aspx
I wrapped my code with their example's code and made sure to reference my manifests and now all is working fine. No manifest on my main executable!

Building Windows Store app programmatically

We have a requirement of creating several Windows 8 apps for tablets. There is a common solution and news apps are created by passing different resource to the same code.
For Mobile it was a cakewalk - Used the Microsoft.Build.Evaluation.Project class to get the xap file.
But for Surface, building from code does not give the direct appx output, while building using MSBuild gives appx as the output.
I tried several methods to avoid calling MSBuild from C#(by creating a Command Process) like creating a zip file - myapp.appx - and then signing it using this c++ code. It didn't workout because of an extern reference and I gave up.
Then I tried to use SignTool.exe by creating a Command Process in C#. That too failed.
So, I am wondering if there is any way to build an appx directly from C# without MSBuild.
The reason why I am trying to avoid MSBuild is to get a status from the build process, which Microsoft.Build.Evaluation.Project.Build() provides.
First try adding a pfx key to your project and then try the build via Microsoft.Build.Evaluation.Project.Build() again. The pfx is required from what I read:
See Candy's answer here:
MSBuild target to create the .appx package
So then the trick would be to use SignTool to get the pfx in the first place and update the project with that pfx, but first see if the above works.

Found conflicts between different versions of the same dependent assembly.MVC3 -> MVC4 / EF4 -> EF5

The question is how to resolve conflicts between versions of assemblies in my project that was upgraded to MVC4 and EF5?
The problem is manifest in the fact that my controllers and models can include System.Data.Objects, but now my views.
I am using MVC 4, my project was upgraded from MVC 3.
Entity Framework is version 5.
I have a controller that is able to use objectcontext from System.Data.Objects.
My Usings:
using System.Data.Objects;
using System.Data.Entity;
When I try to include the using in the view form System.Data.Objects, I get :
CS0234: The type or namespace name 'Objects' does not exist in the namespace 'System.Data' (are you missing an assembly reference?)
I am targeting .net 4.5
My Build Displays this message:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets(1561,5): warning MSB3247: Found conflicts between different versions of the same dependent assembly.
You can build your solution in diagnostic mode to get more detailed information about the error.
Open the VS Options dialog (Tools > Options), navigate to the "Projects and Solutions" node and select "Build and Run". Change the MS Build project build output verbosity to Diagnostic.
Have a look here.
If you look at the build message, it states the 4.0 version of the .net framework is referenced... Is there a setting in your project file or web/app.config specifying a conflicting version of the .net framework?
Are you familiar with fuslog? you can set it up to log all assembly bindings that .net is doing while running your application. You should then be able to see detailed information on what is getting bound when. If you still can't figure it out, you can always do a binding redirect on that .dll in the web.config.
http://msdn.microsoft.com/en-us/library/eftw1fys.aspx -- binding redirects
http://msdn.microsoft.com/en-us/library/e74a18c4(v=vs.71).aspx -- fusion log viewer
Set up fusion logger and take a look at what the output is. If you don't get an answer from that, try the binding redirect (which would give you at least a temporary solution).
In the directory I was publishing to, there was a folder named aspnet_client. I moved it (instead of deleting it), republished, and it worked. I'm not sure why that folder decided to give me trouble out of the blue.