Problems with de-registering of COM (advanced installer) - c++

Definition of problem:
Hangs up for sometime during COM de-registering and says The setup was unable to automatically close all requested applications. Please ensure that the applications holding files in use are closed before continuing with the installation. But actually my extension is successfully unloaded and uninstalled.
Definition of environment:
I created some kind of dummy shell namespace extension for tests. It implements IContextMenu and all methods returnS_OK and do nothing else and rgs file is
HKCR
{
xxx.sergz.dummyShellExt.1 = s 'DummyNSE Class'
{
CLSID = s '{6C0FBE00-9898-4BB0-806F-3ED7D2F1170D}'
}
xxx.sergz.dummyShellExt = s 'DummyNSE Class'
{
CurVer = s 'xxx.sergz.dummyShellExt.1'
}
NoRemove CLSID
{
ForceRemove {6C0FBE00-9898-4BB0-806F-3ED7D2F1170D} = s 'DummyNSE Class'
{
ProgID = s 'xxx.sergz.dummyShellExt.1'
VersionIndependentProgID = s 'xxx.sergz.dummyShellExt'
ForceRemove Programmable
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Apartment'
}
TypeLib = s '{3DC947F0-6691-4043-B414-29F749209905}'
Version = s '1.0'
}
}
NoRemove Directory
{
NoRemove Background
{
NoRemove ShellEx
{
NoRemove ContextMenuHandlers
{
ForceRemove DummyShellExt = s '{6C0FBE00-9898-4BB0-806F-3ED7D2F1170D}'
}
}
}
}
}
HKLM
{
NoRemove Software
{
NoRemove Microsoft
{
NoRemove Windows
{
NoRemove CurrentVersion
{
NoRemove Shell Extensions
{
NoRemove Approved
{
val '{6C0FBE00-9898-4BB0-806F-3ED7D2F1170D}' = s 'xxx.sergz Dummy shell extension.'
}
}
}
}
}
}
}
I choose Professional installer and added only my dll file. On file properties Registration tab I choose Auto register file..., Extract registration info... and Synchronization is Enabled. In Product Information->Install Parameters->PackageType I choose 64-bit package for x64....
Now I build the MSI and install the extension.
Launch explorer and do right click somewhere on folder background. According to my log my extension is loaded and is DLL_PROCESS_ATTACH and a few times DLL_THREAD_ATTACH.
I launch the MSI again and choose Remove. It says that you have to close ... applications are using files... and there is only Windows Explorer in the list. I choose Automatically close ... and press OK.
All Explorer windows are closed but it seems that Explorer was not shutdown.
The status is "Shutting down applications", according to my log the dll is already unloaded. The problem is here. The dll is already unloaded but the MSI is still waiting for something and then it says The setup was unable to automatically close all requested applications. Please ensure that the applications holding files in use are closed before continuing with the installation.
I click OK and the process continues and my DLL is successfully removed in the end.
I use windows 8 64bit.
What are the reasons of this waiting and the message that applications can not be closed. How can I figure it out?

Right, this isn't going to work, the shell extension is very likely to be loaded and MSI isn't going to kill Explorer.exe. Nor would you want it to, it is rather a ghastly sight to the user.
You'll need to use an alternative way to un/register the extension. It isn't clear what "Professional installer" might mean. But you can always un/register a COM server by modifying the registry yourself rather than leaving it up to the DLL to do so. It is in fact the recommended way. You already know the registry keys from your .rgs file. You can also use the Heat.exe harvester from the WiX toolset. The DLL needs to be removed by delay-deleting it at the next user login, done by adding it to the PendingFileRenameOperations registry key. Check your installer creator tool for the proper procedure.

Related

Is it possible to create a windows installer for combine an application built with Electron Framework and AutoHotkey Tool?

I have try many way to built the electron app with AutoHotKey tool as one exe file but still it's didn't work, if you find any way please help me. Here is the build.js code:
// C:\Users\sdkca\Desktop\electron-workspace\build.js
var electronInstaller = require('electron-winstaller');
// In this case, we can use relative paths
var settings = {
// Specify the folder where the built app is located
appDirectory: './KIT Online Examination System-win32-x64',
// Specify the existing folder where
outputDirectory: './KIT-online-exam-installers',
// The name of the Author of the app (the name of your company)
authors: 'Kirirom Institute of Technology.',
// The name of the executable of your built
exe: './KIT Online Examination System.exe',
exe: './AutoHotKey.exe'
};
resultPromise = electronInstaller.createWindowsInstaller(settings);
resultPromise.then(() => {
console.log
("The installers of your application were succesfully created !");
}, (e) => {
console.log(`Well, sometimes you are not so lucky: ${e.message}`)
});

how to display the virtual folder only when user open the windows explorer from an app on win 7?

--------------------------------second updates------------------------
I tried:
STDAPI_(BOOL) DllMain(HINSTANCE hInstance, DWORD dwReason, void *)
{
// Get the path and module name.
WCHAR szModulePathAndName[MAX_PATH];
GetModuleFileName(hInstance, szModulePathAndName, ARRAYSIZE(szModulePathAndName));
std::ofstream outfile("DllMain.txt");
outfile << szModulePathAndName << std::endl;
outfile.close();
if (dwReason == DLL_PROCESS_ATTACH)
{
g_hInst = hInstance;
DisableThreadLibraryCalls(hInstance);
}
return TRUE;
}
This doesn't work. The content to be print in the txt file is:
00000000000CDEE0
And it only print once when I register the dll. After that, no matter how many times I browse the virtual folder , open it, it never eneter DllMain to print the string again.
I am using Microsoft windows 7.0 SDK sample ( ExplorerDataProvider ) to create a virtual folder on "My Computer", like following:
When I open the file browser dialog, it displays this virtual folder.
When I click "Save as" from Microfost office, the windows file explorer dialog pops up and still display this virtual folder.
I wrote a C++ application, which can also save the file when clicks "export".
It will open the windows file explorer dialog and when the user selects the directory and click save, it can save the file.
My problem is: I hope the virtual folder can be only displayed when I use my C++ program to open the file dialog. If I open the windows explorer outside my application, the virtual folder is invisible. How could I do that?
It seems that once I register the dll for the virtual folder, the virtual folder is always there.
One possible solution for me is to register the virtual folder dll when my application is opening windows file explorer and then unregister it when the user closes it in the application, but the user can still see it if the user opening the windows explorer outside of the application when the windows file explorer is showing up in the application.
I didn't find anything like SetVisible function in IShellFolder.
You can return false in DLLMain if the file name returned by GetModuleFileName(NULL) is anything other than your C++ program.

Need to Programmatically Recompile all Script Tasks in DTSX Packages after Mass Find-And-Replace

An upcoming move of our Data Warehouse has us needing to change many Connection Strings and UNC File Paths located in VBA Script Tasks within DTSX Packages.
We've performed a mass find-and-replace but when changing Script Tasks using this method, the binaries run during DTSX Package execution don't get recompiled at run time, resulting in the find-and-replaced changes not being reflected in the Script Task's execution.
I've found some articles on how to do it in SQL Server 2008 and 2012, but we're using SQL Server 2014 and the code examples here aren't working for me:(https://blogs.msdn.microsoft.com/jason_howell/2013/03/05/script-component-recompile-in-sql-server-2012-integration-services-ssis-to-refresh-metadata/).
Some of the questions in the comments speak to my problem but none of the "I fixed this this way [navigate to path and include references]" are working for me -- I don't see these assemblies, and with the changes between 2008 to 2012, and now us on 2014, I'm uncertain whether these libraries are even included in my distribution...
So, I have a whole bunch of DTSX files in various sub directories that require their script tasks be recompiled in order for us to go live with these changes.
I'm hoping to not-have to open every script task in every package manually to force the build of each task.
Thanks in advance for any potential solutions!
I create a Console application with the code necesary to recompile every ScriptTask inside a dtsx package, using Visual Studio 2013 and C# up to two levels. Path for every assembly that needs to be referenced are included as comments in the code. pkgLocation is the path to the package(in the ends I build a Windows Form app, but this is the base and working code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.SqlServer.Dts.Design;
using Microsoft.SqlServer.Dts.Runtime;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Pipeline;
using Microsoft.SqlServer.VSTAHosting;
using Microsoft.SqlServer.IntegrationServices.VSTA;
using Microsoft.SqlServer.Dts.Tasks.ScriptTask;
using System.IO;
//Libraries
//C:\windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.SqlServer.Dts.Design\v4.0_12.0.0.0__89845dcd8080cc91\Microsoft.SqlServer.Dts.Design.dll
//C:\Program Files (x86)\Microsoft SQL Server\120\SDK\Assemblies\Microsoft.SqlServer.DTSPipelineWrap.dll
//C:\Program Files (x86)\Microsoft SQL Server\120\SDK\Assemblies\Microsoft.SQLServer.DTSRuntimeWrap.dll
//C:\windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.SqlServer.IntegrationServices.VSTA\v4.0_12.0.0.0__89845dcd8080cc91\Microsoft.SqlServer.IntegrationServices.VSTA.dll
//C:\Program Files (x86)\Microsoft SQL Server\120\SDK\Assemblies\Microsoft.SQLServer.ManagedDTS.dll
//C:\windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.SqlServer.PipelineHost\v4.0_12.0.0.0__89845dcd8080cc91\Microsoft.SQLServer.PipelineHost.dll
//C:\windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.SqlServer.ScriptTask\v4.0_12.0.0.0__89845dcd8080cc91\Microsoft.SqlServer.ScriptTask.dll
//C:\windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.SqlServer.TxScript\v4.0_12.0.0.0__89845dcd8080cc91\Microsoft.SqlServer.TxScript.dll
//C:\windows\Microsoft.NET\assembly\GAC_MSIL\Microsoft.SqlServer.VSTAScriptingLib\v4.0_12.0.0.0__89845dcd8080cc91\Microsoft.SqlServer.VSTAScriptingLib.dll
namespace recompApp
{
class Program
{
static void Main(string[] args)
{
string pkgLocation;
Package pkg;
Application app;
//This is the folder where the test package lives!!
pkgLocation =
#"C:\TestPackage.dtsx";
app = new Application();
pkg = app.LoadPackage(pkgLocation, null);
//It's Alive!!!!!!!
try
{
Executables pExecs = pkg.Executables;
foreach (Executable pExec in pExecs)
{
switch (pExec.GetType().Name)
{
case "TaskHost":{
TaskHost taskHost = (TaskHost)pExec;
Console.WriteLine("Executable name = " + taskHost.Name);
//Script Task Outside of a Sequence
if (taskHost.InnerObject.ToString().Equals("Microsoft.SqlServer.Dts.Tasks.ScriptTask.ScriptTask"))
{
ScriptTask task = (ScriptTask)taskHost.InnerObject;
//Load the script project, build and save
task.ScriptingEngine.LoadProjectFromStorage();
task.ScriptingEngine.VstaHelper.Build("");
task.ScriptingEngine.SaveProjectToStorage();
//Cleanup
task.ScriptingEngine.DisposeVstaHelper();
}
break;
}
case "Sequence":{
Executables seqExecs = ((Microsoft.SqlServer.Dts.Runtime.Sequence)(pExec)).Executables;
foreach(Executable seqExec in seqExecs){
switch (seqExec.GetType().Name)
{
case "TaskHost":
{
TaskHost taskHost = (TaskHost)seqExec;
//Script Task inside a Sequence Container
if (taskHost.InnerObject.ToString().Equals("Microsoft.SqlServer.Dts.Tasks.ScriptTask.ScriptTask"))
{
Console.WriteLine("Executable name = " + taskHost.Name);
ScriptTask task = (ScriptTask)taskHost.InnerObject;
//Load the script project, build and save
task.ScriptingEngine.LoadProjectFromStorage();
task.ScriptingEngine.VstaHelper.Build("");
task.ScriptingEngine.SaveProjectToStorage();
//Cleanup
task.ScriptingEngine.DisposeVstaHelper();
}
break;
}
}
}
break;
}
}
}
//Save the updated xml in the package
string xml;
pkg.SaveToXML(out xml, null);
File.WriteAllText(pkgLocation, xml);
}
catch (Exception e)
{
Console.WriteLine(e.Message.ToString());
}
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
}
I hope this helps a lots of people outside. I also have the Visual Basic version if you need it.

ADO objects instance creation failed on the target computer

I created an MFC application using VC++ 6.0 on my development computer installing Windows XP SP3. In this application, I used ADO objects to access SQL database server :
CoInitialize (NULL);
try
{
_ConnectionPtr pConn;
HRESULT hr = pConn.CreateInstance (__uuidof (Connection));
if (FAILED (hr))
{
AfxMessageBox ("Can't create intance of Connection");
}
//...
}
//...
Of course, the app works fine on my computer. However, I copied the whole Release folder of the app and then run it on another computer with Windows XP SP3 installed, the app failed at creating the Connection object with hr = -2147467262.
I searched on the internet much but don't see any resolution.
Does anyone know this issue and could you give me some guides on that?

OLE/COM Object Viewer reports STG_E_FILENOTFOUND

I have created simple COM DLL using ATL and have added "ATL Simple Object" after that. To be sure server is registering I have placed messagebox:
STDAPI DllRegisterServer(void)
{
MessageBoxA ( NULL, "Hello World!", "Test", MB_OK );
HRESULT hr = _AtlModule.DllRegisterServer();
return hr;
}
Registering does fine. I decided to look how this object looks with OLE-COM Object Viewer that is part of SDK. Viewer reports error:
"LoadTypelib'(c:\pr\ILight.dll) failed.
<No system message defined> STG_E_FILENOTFOUND ($800300002)
Does it means my COM dll corrupted? How to make VIewer to show my dll information?
P.S.
Project RC file contians:
"REGISTRY"
IDR_ILIGHT
HKCR{}
IDR_LIGHT
HKCR
{
AboutiLight.1 = s 'Light Class'
{
CLSID = s '{DBC53EA8-A51E-4374-B104-06A834273B0C}'
}
AboutiLight = s 'Light Class'
{
CurVer = s 'AboutiLight.1'
}
NoRemove CLSID
{
ForceRemove {DBC53EA8-A51E-4374-B104-06A834273B0C} = s 'Light Class'
{
ProgID = s 'AboutiLight.1'
VersionIndependentProgID = s 'AboutiLight'
ForceRemove Programmable
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Apartment'
}
TypeLib = s '{1D9F859D-10FF-4827-A341-4A8B8E318A61}'
Version = s '1.0'
}
}
}
String table
String table
ID=IDS_PROJNAME Value=100 Caption ILight
Version
VS_VERSION_INFO
FILEVERSION 1,0,0,1
PRODUCTVERSION 1,0,0,1
FILEMASK 0x3fL
FILEFLAGS 0x0L
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_DLL
FILESUBTYPE VFT2_UNKNOWN
After having received the same error (STG_E_FILENOTFOUND), and seeing Joe Willcoxson's comment about 64-bit and 32-bit, I was able to find a solution.
If you are using OleView.exe, the OLE/COM Object Viewer, there are actually two versions of it: 32-bit, and 64-bit. Ensure that you are launching with the proper version of OleView. The version in the base "BIN" folder of the SDK will be the 32-bit version. The "x64" folder will have the 64-bit version of the application, which is not fully compatible with older binaries and their typelibs (made in a 32-bit world).
On the other hand, if your new DLL is actively being compiled for x64, then it's highly likely 32-bit OleView will not be able to read the data properly, either.
1) Check to make sure that is the right path to your DLL.
2) Open the DLL itself from Visual Studio and check to be sure that a type library is embedded in the resources. If a typelib isn't found, add one.
3) If all that fails, did you register it under an administrator account/shell. If you call regsvr32.exe on it, make sure you are running with elevated privileges.