log4net used in VSTO Add-In will not write to file if the Add-In is under HKLM - vsto

ENVIRONMENT
VS2022
OFFICE 365
log4net 2.0.15
ISSUE:
I wrote a VSTO Add-In for Outlook and installed log4net as a NuGet package.
What I noticed is that when the Add-In is installed under HKCU, log4net writes to my log files just fine;
this includes internal debugging.
However, we would like to have the Add-In installed on a per-machine basis (HKLM). Under HKLM log4net does not write anywhere; even when I turn on the internal debugging.
NOTE: The following snippet works fine when the VSTO Add-In is installed under HKCU
<log4net>
<appender name="RollingFileAppenderAddin" type="log4net.Appender.RollingFileAppender">
<file type="log4net.Util.PatternString" value="%envFolderPath{UserProfile}\\MyLogs\\MyLog.txt" />

Related

Outlook 2007 add-in refuses to load when deployed to all-users via MSI/WiX

I've been trying to do this seemingly simple task for over a day now. So I would appreciate if someone can shed some light on what am I missing here?
I wrote an Outlook 2007 add-in (in Visual Studio 2008, C# project) and now I'm trying to write an MSI installer for it (using WiX). The installation process also requires VS Tools For Office Runtime to be installed, which I do separately.
Then, the following are registry keys, that I've been testing it with for the current user. Using WiX mark-up:
<Component Id="RegistryRegAddin" Guid="{GUID}">
<RegistryKey Id="RegKey_AddIn" Root="HKCU" Key="Software\Microsoft\Office\Outlook\Addins\$(var.ProductThis)" ForceCreateOnInstall="yes" ForceDeleteOnUninstall="yes">
<RegistryValue Type="string" Name="Description" Value="$(var.AppDescr)" />
<RegistryValue Type="string" Name="FriendlyName" Value="$(var.ProductThis)" />
<RegistryValue Type="integer" Name="LoadBehavior" Value="3" />
<RegistryValue Type="string" Name="Manifest" Value="[INSTALLFOLDER]AddInName.vsto|vstolocal" />
</RegistryKey>
</Component>
So this works just fine for the current user.
But now I'm trying to change it so that the add-in is installed for all users. I modified HKCU to HKLM in the WiX registry markup above. But in that case, the MSI installs fine (on a 32-bit Windows 7 Pro), but my add-in doesn't load into Outlook.
Why!????
Then if I go in Outlook to Tools -> Trust Center -> Add-ins -> my add-in is in the "Inactive Application Add-ins" but when I try to check it to enable it, Outlook shows this message:
The connected state of Office Add-Ins registered in HKEY_LOCAL_MACHINE
cannot be changed.
Argh!!!!
But in that case, the MSI installs fine (on a 32-bit Windows 7 Pro), but my add-in doesn't load into Outlook.
There are multiple reasons why your add-in may not be loaded. Among them you can find the following points and possible diagnostic ways:
Make sure all the prerequisites were installed correctly.
No exceptions are thrown at startup. Microsoft Office applications can disable VSTO Add-ins that behave unexpectedly. If an application does not load your VSTO Add-in, the application might have hard disabled or soft disabled your VSTO Add-in.
Hard disabling can occur when a VSTO Add-in causes the application to close unexpectedly. It might also occur on your development computer if you stop the debugger while the
Startup event handler in your VSTO Add-in is executing.
Soft disabling can occur when a VSTO Add-in produces an error that does not cause the application to unexpectedly close. For example, an application might soft disable a VSTO Add-in if it throws an unhandled exception while the Startup event handler is executing.
When you re-enable a soft-disabled VSTO Add-in, the application immediately attempts to load the VSTO Add-in. If the problem that initially caused the application to soft disable the VSTO Add-in has not been fixed, the application will soft disable the VSTO Add-in again.
Use the Fuslogvw.exe utility for checking whether the right assemblies are loaded. See Assembly Binding Log Viewer for more information.
The MSI engine failure. Try to take a look at the MSI log files.
You may also find a similar case described on the VSTO AllUser addIn fails to load on several clients page.
I think this is specific to Office 2007. Try adding the following code fragment to your code:
<Component Id="EnableLocalMachineVSTO" Permanent="yes">
<Condition>ALLUSERS=1</Condition>
<RegistryKey Root="HKLM" Key="Software\Microsoft\Office\12.0\Common\General">
<RegistryValue Name="EnableLocalMachineVSTO" Value="1" Type="integer" KeyPath="yes" />
</RegistryKey>
</Component>
The EnableLocalMachineVSTO is the keyword you can put in the search box to learn more. This is one of the common issues with "my add-in works when installed as current user but doesn't when installed as local machine", AFAIK.

How to allow Outlook Add-In read the config file

We are developing an Outlook Add-In VSTO using C#, it reads a configuration by using ConfigurationManager.AppSettings["key"].
We made a .msi installer by WIX and installed to Outlook, then the Add-In can't read the config value.
But when trying with Advanced Installer, the add-in works perfectly.
I'm not sure what the Advanced Installer does with my msi file (or registry), can you please help me to solve the problem with WIX because we want a free installer creator tool (Advanced Installer costs me 1500$).
Thanks a lot
Does the add-in assembly name correspond to the config file name? Are they located in the same folder? Is the config file deployed?
The Deploying an Office Solution by Using Windows Installer article provides all the required steps for creating Windows installer setup programs.

Install vsix package both on Visual Studio 2015 and Visual Studio 2017 with WIX

I have a WiX setup project that installs VSIX packages using the wix:VsixPackage element from the Vs extension.
I am trying to modify this setup project to support both Visual Studio 2015 and Visual Studio 2017. So I've modified the setup definition like this:
<Component Id="Modeling.Factory" Guid="1A5C7D5C-676E-46D9-9808-5FE79A51B8B3">
<File
Id="Modeling.Factory.vsix"
Name="Primavera.Modeling.Factory.Shell3.vsix"
Source="$(var.SolutionDir)\Bin\Primavera.Modeling.Factory.Shell3.vsix"
Vital="yes">
<wix:VsixPackage
PackageId="FA9F2DC1-30A2-4C88-AFC6-3CD5A49C39CB"
Target="Pro"
TargetVersion="14.0"
Permanent="no"
Vital="yes" />
<wix:VsixPackage
PackageId="FA9F2DC1-30A2-4C88-AFC6-3CD5A49C39CB"
Target="Pro"
TargetVersion="15.0"
Permanent="no"
Vital="yes" />
</File>
</Component>
Notice the two Target and TargetVersion settings.
The setup builds without any warning, both in VS2015 and VS2017.
When I run the setup it fails. The setup log file includes this line that identifies the problem:
MSI (s) (A0:3C) [11:36:57:314]: Executing op: CustomActionSchedule(Action=vim2916624A52A9C02C06B731DECBEAB911,ActionType=3122,Source=C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\VSIXInstaller.exe,Target=/q /skuName:Pro /skuVersion:15.0 "C:\Program Files (x86)\PRIMAVERA\Elevation SDK v3.00\Temp\Primavera.Modeling.Factory.Shell3.vsix" /admin,)
CustomAction vim2916624A52A9C02C06B731DECBEAB911 returned actual error code 2003 (note this may not be 100% accurate if translation happened inside sandbox)
So the problem is that the setup is trying to install the VSIX package to VS2017 using the VS2015 version of the VSIXnstaller.
What am I doing wrong? Is it possibly a bug in WiX?
I am using WiX v3.11.0.1507.
Thanks for any help.
The changes in VS2017 require changes in VsixInstaller that are apparently not feasible without further changes in VS2017: http://wixtoolset.org/development/wips/5433-add-support-to-detect-and-install-vsix-packages-into-vs15/

WIX Conditional Message on Exit

I have a WIX installer which I need to also install the VC++ 2015 runtime executable. I'm using the vcredist_x64.exe as opposed to the merge modules (see this thread). I can successfully launch the vcredist_x64.exe after my msi finishes installing my application by using a custom action... however, what I'd like to do is first check to see if the runtime files already exist. If they do, then I'll just finish without running the vcredist_x64.exe. Otherwise, I'll run the custom action to install the runtimes as well.
It took some digging, but I was able to find out that the 2015 runtimes have a registry key shown below:
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio\14.0\VC\Runtimes\x64
with an Installed value of 1 if they exist.
So, in my .wxs file I have the following registry search:
<!-- Visual C++ 2015 x64 -->
<Property Id="VCREDISTRUNTIMES2015INSTALLED">
<RegistrySearch Id="VCREDISTRUNTIMES2015SEARCH" Root="HKLM" Key="SOFTWARE\WOW6432Node\Microsoft\VisualStudio\14.0\VC\Runtimes\x64" Name="Installed" Type="raw" />
</Property>
Now, what I'd like to do is show a message on my exit dialog which says that if the runtimes aren't detected, then it will launch an installer to install them upon exit. Something like this:
<Property Id="WIXUI_EXITDIALOGOPTIONALTEXT" Value="Visual C++ Redistributable for Visual Studio 2015 is Required. Installation will proceed on exit.">
<Condition>VCREDISTRUNTIMES2015INSTALLED</Condition>
</Property>
However, this doesn't work. I get an error on the conditional tag and the project wont build. Assuming my registry search is setup correctly, can someone tell me how to properly add a conditional message on my exit dialog? Thanks!
Answering my own question... but here goes. It turns out that my registry search was just fine... but I needed to use "SetProperty" instead. So, something like this:
<SetProperty Id="WIXUI_EXITDIALOGOPTIONALTEXT" After="AppSearch" Value="The Visual C++ Redistributable Package for Visual Studio 2015 is Required. Installation will now install run-time components that are required to run C++ applications built using Visual Studio 2015.">
NOT VCREDISTRUNTIMES2015INSTALLED
</SetProperty>
Now, if the VCREDISTRUNTIMES2015INSTALLED is null (or false) then it will show the message on the exit dialog. Otherwise, there will be no message shown. Hope that helps.

Deploying and Registering Com Interop interfaces

I am attempting to deploy my new .net Com visible interfaces. After installation my new .dll could be loaded by my app. There is a requirement to cast one of the interfaces which is not working.
I am harvesting my wix xml with the use of Heat.
"C:\Program Files (x86)\WiX Toolset v3.10\bin\heat.exe" file "MYComConnect.dll" /out "dll_fragment_12_2015.wxs"
"C:\Program Files (x86)\WiX Toolset v3.10\bin\heat.exe" file "MYComConnect.tlb" -scom /out "tlb_fragment_12_2015.wxs"
To know that it is not a coding problem with my .dll I have registered my .dll and .tlb with regasm and everything works fine.
"C:\Windows\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe" "MYComConnect.dll" /tlb
I then did a registry comparison of what is added by regasm and what my wix installer adds.
I noticed that the following folders keys were added by regasm but were NOT added by my wix install (corresponding values were also added by regasm but I will not post it all)
HKLM\SOFTWARE\Classes\Interface\{6D8A24A9-9723-4934-9852-D8877BBBB9F6}
HKLM\SOFTWARE\Classes\Interface\{6D8A24A9-9723-4934-9852-D8877BBBB9F6}\ProxyStubClsid32
HKLM\SOFTWARE\Classes\Interface\{6D8A24A9-9723-4934-9852-D8877BBBB9F6}\TypeLib
HKLM\SOFTWARE\Classes\Interface\{721AE779-4A04-4FFE-B317-FE2355DE31FA}
HKLM\SOFTWARE\Classes\Interface\{721AE779-4A04-4FFE-B317-FE2355DE31FA}\ProxyStubClsid32
HKLM\SOFTWARE\Classes\Interface\{721AE779-4A04-4FFE-B317-FE2355DE31FA}\TypeLib
HKLM\SOFTWARE\Classes\Interface\{A001212B-8F67-42B6-BAA6-D61D6B34FC26}
HKLM\SOFTWARE\Classes\Interface\{A001212B-8F67-42B6-BAA6-D61D6B34FC26}\ProxyStubClsid32
HKLM\SOFTWARE\Classes\Interface\{A001212B-8F67-42B6-BAA6-D61D6B34FC26}\TypeLib
HKLM\SOFTWARE\Classes\Interface\{F293DBB5-471C-4D71-80CB-C3B30EBDFE10}
HKLM\SOFTWARE\Classes\Interface\{F293DBB5-471C-4D71-80CB-C3B30EBDFE10}\ProxyStubClsid32
HKLM\SOFTWARE\Classes\Interface\{F293DBB5-471C-4D71-80CB-C3B30EBDFE10}\TypeLib
It seems that my wix install only adds registry keys in Wow6432Node. Regasm adds keys to both.
HKLM\SOFTWARE\Classes\Wow6432Node\Interface\{6D8A24A9-9723-4934-9852-D8877BBBB9F6}
HKLM\SOFTWARE\Classes\Wow6432Node\Interface\{6D8A24A9-9723-4934-9852-D8877BBBB9F6}\ProxyStubClsid32
HKLM\SOFTWARE\Classes\Wow6432Node\Interface\{6D8A24A9-9723-4934-9852-D8877BBBB9F6}\TypeLib
HKLM\SOFTWARE\Classes\Wow6432Node\Interface\{721AE779-4A04-4FFE-B317-FE2355DE31FA}
HKLM\SOFTWARE\Classes\Wow6432Node\Interface\{721AE779-4A04-4FFE-B317-FE2355DE31FA}\ProxyStubClsid32
HKLM\SOFTWARE\Classes\Wow6432Node\Interface\{721AE779-4A04-4FFE-B317-FE2355DE31FA}\TypeLib
HKLM\SOFTWARE\Classes\Wow6432Node\Interface\{A001212B-8F67-42B6-BAA6-D61D6B34FC26}
HKLM\SOFTWARE\Classes\Wow6432Node\Interface\{A001212B-8F67-42B6-BAA6-D61D6B34FC26}\ProxyStubClsid32
HKLM\SOFTWARE\Classes\Wow6432Node\Interface\{A001212B-8F67-42B6-BAA6-D61D6B34FC26}\TypeLib
HKLM\SOFTWARE\Classes\Wow6432Node\Interface\{F293DBB5-471C-4D71-80CB-C3B30EBDFE10}
HKLM\SOFTWARE\Classes\Wow6432Node\Interface\{F293DBB5-471C-4D71-80CB-C3B30EBDFE10}\ProxyStubClsid32
HKLM\SOFTWARE\Classes\Wow6432Node\Interface\{F293DBB5-471C-4D71-80CB-C3B30EBDFE10}\TypeLib
The other difference I noted is that heat has the following entry for each class whereas Regasm does not have it
HKLM\SOFTWARE\Classes\Wow6432Node\CLSID\{FB1D6314-4409-46E9-BD92-DDD99D110CDE}\Implemented Categories\{62C8FE65-4EBB-45e7-B440-6E39B2CDBF29}\: ""
I have read that it does not matter where the interfaces are registered as they do not depend on bitness however after a comparison of what regasm does and what heat harvests it appears that if the interfaces are not added to both the x64 and x32 registry then it does not work.
Just the first RegistryValue element from my heat harvested interface fragment looks like this below. This adds the element to the Wow6432Node.
<Fragment>
<DirectoryRef Id="MYAPPCOMINTEROP">
<Component Id="Com_Interop_TLB" Guid="{F8F60B35-0270-4569-8F0F-9D09398C72D8}">
<File Id="fil460187E36ECD90A7A9A00591ADB1C5CB" Name="MYComConnect.tlb" KeyPath="yes" Source="..\..\MYComConnectReferencedDLL\MYComConnect.tlb" />
<RegistryValue Root="HKCR" Key="Interface\{6D8A24A9-9723-4934-9852-D8877BBBB9F6}" Value="_MYAppConnect" Type="string" Action="write" />
So in the absence of another solution I want to follow what regasm does with the registry entries, how can I achieve that with my Wix xml.
Edit - Further information
Target computer is Win 7 x64 with Office 2010 x86
My Main App has Target CPU x86
Com Visible .dll Target CPU is AnyCPU (the dll is used by Office and my App)
MSI is x64 (as I already have a context menu .dll which needs to write registry items to x64 so that Windows' x64 Explorer will read them.
I hope this does not complicate things but what my COM Visible dll does is allows me to call code in a VSTO addin. I dont think this code is necessary as I can get my custom object from Office and cast it to my custom interface with no problems if I use regasm to register my .dll and create the tlb file.
I actually unregistered everything on my development PC and installed my final MSI. My .dll works and I can cast my interface. What assumptions can I make from this? I am assuming that the problem lies with my Com .dll and building it and thus my problem has nothing to do with my heat harvesting and wix xml coding.
Update 2 of Problem
I obtained a second PC with Visual Studio on it. I Copied my Com .dll project on it and built it. I Created the .tlb file with Tlbexp.exe on this PC. I then installed this with my MSI and I can now cast the COM interface.
So I now have to work out why building it on one PC it works and on another it does not. The most major difference right now is that the PC that works has Win 7 on it, the one that does not work is Win 10.
It might help to know the bitness of your app and your MSI build(s).
A 32-bit app will have a 32-bit registry view, and will need CLSID references to 32-bit COM dlls. Interface entries may refer to a ProxyStub CLSID that will also need to be 32-bit and that means that the interface entries have bitness. That's my understanding anyway, so your COM Dll needs CLSID and Interface references in HKCR (HKL\Software\Classes) in both native and 32-bit WoW6432 if it has both 64 and 32-bit callers.
In WiX, you'd add Win64=yes to the component to make it 64-bit. If you have 32 and 64-bit callers to your COM, then in a 64-bit MSI you'd add both 32 and 64-bit components for your COM, and in a separate 32-bit MSI just the 32-bit components. Heat doesn't know the bitness of your final MSI, so it's up to you to use Win64 on components to target the required registry view.