I'm writing a .NET 4.0 based ActiveX control for IE7+. I have to manage an interface with a key-reader device. I followed some great tutorials and articles about "how to do" it, and currently is working well.
My problems started when I wanted to deploy an other version of my control.
I'm using VS2010 with setup deployment project and cabarc for the .CAB. The 1.0.0.0 version went well. Currently I would like to get the 1.0.2.0 version working, and it is doing its job well, but IE always prompting for an install. Again and again.
What I did:
1: Changed the AssemblyInfoVersion.cs to version 1.0.2.0
2: Changed the .inf file according version to 1.0.2.0
3: Changed the .msi version to 1.0.2
And I changed the OBJECT tag in the HTML page to #version=1,0,2,0
So far so fine. It is installed! I can see it under the "Uninstall Programs", the version of the control is 1,0,2 ! Great, but the IE still wants me to donwload and install it every time when I open the page.
I saw a thread connected with Excel: How to get COM Server for Excel written in VB.NET installed and registered in Automation Servers list?
And I got usefull information about I should change something in the registry. I did some search there, and I fould my classId under :
HKLM\SOFTWARE\Wow6432Node\Classes\CLSID{GUID}
I have here the following subkeys:
InstalledVersion
Implemented Categories
InprocServer32
ProgId
I was happy, because I saw, that in the InstalledVersion part the version still 1,0,1,0. I changed it to 1,0,2,0 and... it did not worked. I serched through the registry, now everywhere the InstalledVersion is 1,0,2,0. The .dll version is 1,0,2,0. The installed control's version is 1,0,2. Under the InprocServer32 I have all three 1,0,0,0 ; 1,0,1,0; 1,0,2,0 versions. And of course in the HTML code the version is also 1,0,2,0.
(My machine is 64 bit Win7, IE9)
Could anybody help in this, what I missed?
Other problem with this whole scenario: After the version increase by the first install my dev machine is rebooting without any question. Do you have any idea what kind of settings can make this behavior?
UPDATE:
The problem solved. I'm kind of blind or just a bit tired because of this.
But the problem is may important for the future:
First a summary about the issue:
After a new version was deployed (installed well on client) the IE was always propting for install the version.
The problem source is in the registry. You should have the rigth version number in the InstalledVersion(Default) registry key.
I had a very special case here (and I don't know the cause yet), but I had two entries with (Default) under the SubKey InstalledVersion. The firs one was empty, the second one contained the rigth value. I could not delete the first one, but the second one only. After I changed the first (Default) everything worked find!
The second problem with the automatic restart solved too.
This thread helped: MSI installer with Silent or Passive mode will automatically restart computer without prompt for user sometimes
Have to add the /qn /norestart or /promptrestart to end of an msiexec call, because without this flag the windows automatic restarts itself without questioning.
If somebody has a similiar issue, then here is the solution in my case:
[RunSetup]
run="""msiexec.exe""" /i """%EXTRACT_DIR%\KeyReaderEngineInstaller.msi""" /qn /promptrestart
According to Microsoft Documentatation:
/promptrestart
Prompt before restarting option. Displays a message that a restart is required to complete the installation and asks the user whether to restart the system now. This option cannot be used together with the /quiet option.
You can either use /qn /norestart or just /promptrestart. In my case, just the IE had to be restarted, instead of the whole operational system. Therefore, I use /qn /norestart
Related
I have a windows application installed and working perfectly fine.
Something weird came up, the test scenario is if I rename the config file from the original name which is:
Model Label PC Client.exe.config
...to:
xxxModel Label PC Client.exe.config
...and click the .EXE file on the application folder / path where i installed it, it works as expected.
But when I clicked the shortcut icon of this application on the desktop, it shows a pop up that installs a new copy of the correct config file name.
please refer to the screenshot , any idea how to prevent this from happening? or is this really the behavior?
OP:
"any idea how to prevent this from happening?"
For installed apps, it is by design. Essentially you have removed an installed file and so the installer tech will kick in to recover it as if nothing happened.
Now technically you could get around that auto-recovery by not using MSI tech to install your app trusting instead on good-ol' XCOPY but then again, renaming/moving/deleting the file may break the app because this time there is no auto-recovery!
Additionally .NET apps expect to find a .config file matching the same name as the executable so you shouldn't go renaming/deleting/moving it in most scenarios.
Since a while I am facing the following error when trying to launch any kind of application with the Azure Emulator:
Microsoft Azure Tools: Method not found: 'Void Microsoft.WindowsAzure.ServiceModel.Service.set_IsSLBPartialGS(Microsoft.WindowsAzure.ServiceModel.Expression)'.
A restart of my machine usually solves this for a while, but I tend to run into this problem daily, and if I see this warning once, there's no way to get around it without a reboot.
Sadly, I can also not find a lot of documentation, if any.
I am using the Azure Tools V2.9.
Does anyone have a solution, or at least a hint as to what this could be?
Problem:
The Azure SDK v2.9 is shipped with a mismatched version of assemblies. One of the assemblies is missing a setter for the property called IsSLBPartialGS.
Fix:
Copy the 2 assemblies Microsoft.WindowsAzure.ServiceModel.dll and Microsoft.WindowsAzure.ServiceModel.Comon.dll from:
"C:\Program Files\Microsoft SDKs\Azure\Emulator"
to:
"C:\Program Files\Microsoft SDKs\Azure\Emulator\devfabric"
Note that you'll need admin rights for this operation. I recommend making a backup before overwriting any assemblies.
How the I found the fix:
I wrote my own decompiler and symbol inspector to in order to compare assemblies and their contents. After comparing multiple folders, I found that the Microsoft.Windows.Azure.ServiceModel.dll in the Emulator folder has the AssemblyFileVersion:
1.0.6696.103 (rd_sm.180206-1102)
while the one in the DevFabric folder is version:
1.0.6696.47 (rd_sm.160421-1505)
Note that both AssemblyVersion's are the same (as shown in .NetReflector to be 1.0.0.0), however the AssemblyFileVersions are different. Looking further between the differences in the decompiled code from my program, I found that the assembly in the DevFabric (which is a slightly older version) is missing some key classes/methods/properties including the following:
See picture of code difference
I experienced this issue starting recently, and was able to resolve it by reverting Azure Data Lake and Stream Analytics Tools to version 2.3.3000.2 -- the update to 2.3.7000.2 on 3/25/19 seems to have introduced the issue.
For me, it was just because I didn't start VS2019 as Administrator. Closed the solution and started it with Admin privilege then error went away.
Only Visual Studio Repairing resolved the problem for me.
I had the same eror, but it shows me the error when I tried to start debugging 2 and more applications at the same time.
To perform the repairing open Visual Studio Installer and find Repair option there.
Updated:
when I installed Resharper back - I started to get the error, after I uninstalled - everything started to work.
The problem is following: I have my custom uninstaller called before MSI uninstall. After shutting down my application properly it calls msiexec to use Windows Installer to uninstall MSI.
It's done by executing something like "msiexec /x{PRODUCT_CODE} /promptrestart".
And here is important thing - if the system is not restarted after uninstallation, and then the user installs the app again, some of its files will be deleted after next restart, so it's not acceptable. The restart is required, however, I need prompt, automatic and unconditional restart is evil and should never ever be used.
So, the invocation above displays STUPID "uninstall / repair" dialog. I do not want it. When I use "msiexec /x{PRODUCT_CODE} /qr /promptrestart" - then it uninstalls nicely, however it refuses propt for restart afterwards.
I have read about setting ARPNOREPAIR property.
But the idiots who gave that answer wouldn't care to say WHERE and HOW that property could be set. Even... Where the property belongs, it's the property of what? MSI file?
Then, maybe is it another way to achieve this, like invoke the prompt for restart from my code, but... how? The uninstaller should remove all my files until that moment. Maybe it's possible to execute a kind of script after the uninstallation process is complete?
(One more problem, the Windows Installer doesn't delete ALL files and directories created by my app. It would be nice if I could execute some code to clean up better.)
UPDATE
I see 2 paths ahead: make a script to be run once the uninstallation ends (like using Registry or Task Scheduler or IDK), use Win32 API to modify MSI file, because AFAIK it's possible to change its properties that way.
Questions: Some questions first.
Restart Manager: Are you familiar with the Restart Manager feature of MSI? Intended to help shut down and restart
applications without the need for reboots. I would give it a quick
skim? I think this is your real solution?
Alternative MSI Tools: There are many tools available for creating MSI setups. This link also contains further links to a summary of the shortcomings of Visual Studio Installer Projects.
Using the free, open-source WiX toolset - for example - you can change MSI dialogs. Github sample. SO question 1. SO question 2. And here is the official WiX toolset site.
Adding my own answer from SO: Changing text color to Wix dialogs (please do skim)
I am not familiar with how to change dialogs in Visual Studio Installer Projects. Commercial products Advanced Installer and Installshield can certainly change dialogs.
Services: What is the nature of the product you are installing? Does it has a lot of services for example? Services can be shut down and restarted via MSI tables if you use a proper tool to build the MSI.
REINSTALLMODE: Do you use a custom REINSTALLMODE for your setup? (some settings can cause more reboot prompts).
Custom Uninstaller: How do you invoke that custom uninstaller of yours? Manually or do you register an uninstall command line with Add / Remove Programs? (this latter approach is not recommended).
ARP Applet vs MSI Dialogs: The ARPNOREPAIR property is set in the MSI itself - in the property table. It affects only what is seen in Windows' Add / Remove Programs applet (ARP = Add / Remove Programs), and not what you see when your MSI is invoked via command line. Then you see the dialogs defined in that MSI itself (which can be changed - not entirely trivial to do).
ARP / Add Remove Programs Applet: A quick review of this applet below:
Hold Windows Key and Tap R. Type: appwiz.cpl and press Enter. This opens the Add /Remove Programs Applet.
Select the different package entries in the list to see different settings for ARPNOREPAIR, ARPNOMODIFY, etc...
If ARPNOREPAIR is set in the MSI's property table then the Repair entry is missing.
If ARPNOMODIFY is set in the MSI's property table then the Change entry is missing.
If ARPNOREMOVE is set in the MSI's property table then the Remove entry is missing.
If the special ARPSYSTEMCOMPONENT property is set, then the MSI will be missing from ARP altogether.
Links:
In-use files not updated by MSI-installer (Visual Studio Installer project)
So, there is an "ugly hack" which solves the exact problem:
First - we need an executable, that isn't affected by the installer. This one is easy, we just copy that one installed exe to a TEMP directory and run it from there.
The next step is to that file must wait unit the uninstall phase is done. There are a couple of ways of doing so. You can observe the installer process, you can observe the file system if main program file is deleted. Considering the pace of common installer operations, polling once a second is a good enough option.
The next step is optional - you remove remaining files created by application, empty directories and such.
The next step is reboot itself, MessageBox.Show() from PresentationFramework is fine to ask user, when user answer OK or YES, then reboot itself can be performed in many ways, I use ExitWindowsEx() from user32.dll since it's probably what msiexec calls internally.
Here's example code:
if (MessageBox.Show(RestartPromptMsg, "", MessageBoxButton.OKCancel, MessageBoxImage.Exclamation) == MessageBoxResult.OK) {
NativeMethods.ExitWindowsEx(
NativeMethods.Flags.Reboot,
NativeMethods.Reason.MajorApplication | NativeMethods.Reason.MinorInstallation | NativeMethods.Reason.FlagPlanned
);
}
Of course some parameters could be passed to our special clean up executable, so it could do some extra things, like skip the restart prompt if it's not really required.
The last step is to delete our executable itself. It's easy, but it's tricky. Again I hope my example code would help:
var cleanUpTempPath = Path.Combine(Path.GetTempPath(), CleanUpExe);
File.Copy(CleanUpPath, cleanUpTempPath, overwrite: true);
Process.Start(new ProcessStartInfo {
FileName = "cmd",
Arguments = $"/c (\"{cleanUpTempPath}\" -purge \"{InstallerDir}\") & (del \"{cleanUpTempPath}\")",
UseShellExecute = false,
CreateNoWindow = true
});
We use cmd.exe special feature, the power of & and (). Commands separated with & gets executed when previous command exits. So when our clen up exe completes, it's gets deleted by the same cmd instance which called it. Remember to quote all paths, they can contain spaces. Remember to enclose a command with arguments in parentheses, because otherwise the & operator would be seen as a parameter to the previous command, not the cmd.exe.
I tested it in my big production application and it works as charm. The code examples don't work when just pasted, if you're looking for complete code, just google for it, there are plenty of working examples on pinvoke.net and StackOverflow.
I created an installer and custom actions for a service.
On first install I managed to install the service , but when I tried running the service I got
an Error :Windows installer service cant start Error 193:0xc2
I have tried deleting this service in myriad of ways, yet on install I am still getting an error message 1001 The specified service already exists.
I deleted the service directly from the registry , but this does not seem to have worked.
I have tried
sc delete [service] --> The specified service does not exist as an installed service.
The service is not showing up in the registry nor is it present in installed services.
Any other thoughts or options would be appreciated
I have used this commands in a bat file that runs every time reinstalling. Try this and see.
set path=%path%;%SystemRoot%\Microsoft.NET\Framework\vXXX
InstallUtil /u YourService.exe
InstallUtil /i YourService.exe
net start "Service name"
If you want to delete/uninstall/remove a Windows service, perhaps left from an incomplete installer, you can use the sc command from an Administrator control prompt:
sc delete [servicename]
"sc delete" Deletes a service subkey from the registry. If the service is running or if another process has an open handle to the service, then the service is marked for deletion.
EDIT
I have tried sc delete [service] The specified service does not exist
as an installed service.
Probably restarting the machine would fix this.
sc.exe stop serviceName
sc.exe delete serviceName
and reboot the your VM\PC
This complaint may be coming from the installer, not from Windows.
I had this same issue earlier this year, I installed a service from an MSI file, which fouled up somewhere along the line. I uninstalled the package and tried reinstalling through the installer and got the same message as you did, that the service already existed. Frustrating. It didn't show up as an installed package at all anymore, nor did it show up in the service list.
It ended up that the MSI file did not clean up after itself properly during uninstall, but that I could manually manipulate this database and remove the information myself using MSIZap.exe. You need the Windows SDK to get at this program. There may be other ways, but I don't know of them.
You will need the package guid of your installation package to remove it using MSIZap. In the same directory as MsiZap.exe, you will find another application, MsiDb.exe. Run that, point it at your MSI file, point it to some empty directory to store some exports select the "Property" table, select the "Export" radio button and hit the "OK" button. Open the "Property.idk" file that was generated by MsiDb.exe in any text editor. Look in your text for a line that says "ProductCode". The GUID that follows is what you will feed into MsiZap, brackets and all. Now you will simply (bwahaha... yeah right) enter:
msizap T {product code}
Where "{product code}" is replaced by the GUID you found. This removes all traces of your product from the MSI database in windows, which should shut the installer up.
I realize that all of this is a ridiculous pain in the butt. I don't understand why finding a product code is such a trial. But, I suppose if the uninstaller worked, you wouldn't have to do its job for it now. There really might be a simpler way to do all of this, but I haven't found one. Once I found something that worked, I was over it.
As a final note, what caused this error for me was leaving the services list open during uninstall. An uninstaller which isn't paying attention could ignore some exceptions and leave pieces of itself lying about. I was lucky, the poorly behaving uninstaller was my own. And by the way, to appreciate just how much garbage is left over from uninstallation, check out this article.
I'm not sure if I had the same problem that you had, but if so, I hope this helps. If you need clarification, ask and I'll update the answer. If I'm up a tree and this has nothing to do with your problem, I apologize.
Try with Powershell and Wmi:
(gwmi win32_service -filter "name='yourservicename'").delete()
Make sure services.msc window is closed. Sometime that messes up the service deletion. I am not sure if this will help, you should not have touched the registry!
Perhaps you tried to delete the service while it's running? In that case you might need to reboot to clear things up.
I am desperately trying to deploy an ActiveX for IE developed in C# as a CAB archive. I have read many resources (some of them from StackOverflow) and it appears a lot of people are having the same problems. I have tried 3 solutions: a) creating a CAB VS project, b) manually creating a CAB using CABARC with a COM registration in INF and c) manually creating a CAB with launching msiexec. None of them worked. I even tried d) creating a bootstrapper which launches msiexec to no avail (because some people suggested simply launching msiexec on Vista can't work).
I am running Windows Vista but my project fails to run even on IE6 on XP.
When I install ActiveX using MSI, all is fine on ALL Windows. Apparently CAB thing is not working and I could not find a proper way to debug this whole process yet.
Any help is appreciated.
Update: Note that this old but excellent answer is still a very good outline for how to approach solving this problem, at least as along the evolutionary scale as Win7 and IE11. I just succeeded making it all work using the Answerer's Firebreath.org toolset as a jumping off point. It's not simple but it can be done. I've added a reference to that project to the reference list below since it may make a more logical jumping off point for current developers than this overview is.
Hooray - I have just finished an identical project, so you'll be pleased to know that it's actually possible. I have only tested this on XP - I understand there may be issues where Vista/7 don't allow msiexec to be called.
Given that you have an assembly correctly exposing a COM interface, I did the following:
Strong-named the assembly.
Created an INF file
Created an MSI using the Visual Studio 2008 "Setup Project" template.
Created a CAB file using "iexpress.exe" bundled with Windows XP.
Create INF file
The *.inf file I used looks like:
[version]
signature="$CHICAGO$"
AdvancedINF=2.0
[Setup Hooks]
install=install
[install]
run=msiexec.exe /package """%EXTRACT_DIR%\SampInst.msi""" /qn
The only bit you should need to change is the SampInst.msi. Note I would use an 8.3 filename, as long filenames can cause issues. While testing, I would not use the qn switch either, as that is a silent install.
Create the Installer
The installer has to do only one thing, and that is register the assembly by calling RegAsm on it. Most installers will provide some method to easily do this. For example, an installer created through VS 2008 will simply need to have the “Register” property of the assembly set to “vsdrpCOM”. Note that vsdrpCOM should be chosen as it generates the appropriate registry entries at build-time. The vsdrpCOMSelfRegistration setting is likely to fail as it calls RegAsm at run-time, and will thus not work for non-administrators.
Package the installer into a CAB file
This can be done by any cab archiver. Windows XP contains iexpress.exe, a wizard driven archiver, while Microsoft’s CAB SDK contains cabarc.exe. Other 3rd-party tools are also available.
Note that you will need to reserve space in the CAB file for code-signing if you are going to sign the CAB.
You will need to CAB the INF file, and the MSI file. You will not need to CAB the Setup.Exe file.
Handy hint: The VS2008 Setup Project project type allows you to set a post-build step in the properties, so you can build and CAB in a single step. My post-build step looks like:
cd "$(ProjectDir)"
"%WINDIR%\System32\Makecab.exe" /f "VboCslib.ddf"
The DDF file format is documented.
Sample HTML page
The object tag is used to point to the cab file containing the installer. A very simple HTML page which would deploy an ActiveXControl would be:
<html>
<head></head>
<body>
<!--
ID : The id of the ActiveX control to be used in JavaScript.
CLASSID : The GUID associated with the ActiveX control.
CODEBASE: The location containing the CAB installer for the ActiveX
control. This could be a URL, or a relative path.
-->
<OBJECT ID="MyActiveXControl"
CLASSID="CLSID:FC36FAE1-48E0-4f6b-B469-E1B5A8C6D1AC"
CODEBASE="cabfiles\SampleCabFile.CAB#version=1,0,0,0">
</OBJECT>
<script>
MyActiveXControl.SomeMethod();
</script>
</body>
</html>
Handy hints
Ensure your installer installs on a "per-user" basis, not a "per-machine" basis. This will make it more likely to install if the user does not have admin privileges.
Trouble-shooting
Internet Explorer 6 actually provides a really useful diagnostic aid. Clear your Temporary Internet Files, then navigate to the web-page. If the installation does not work, go to your temporary internet files and you will see a couple of files in there. One of these will be an error log starting ?CodeDownloadErrorLog. Drag it to your desktop and open it in notepad, and it will give details on what it was trying to do when it failed.
References
Microsoft KB247257 – Steps for signing a .cab file
MSDN – About INF File Architecture
SN.EXE - Code Strong Programs with Strong Names
Nikolkos Craft – How To: Deploy .NET ActiveX Control
CodeProject – Create ActiveX .NET Step by Step
CodeProject – Downloading C# ActiveX Components through CAB file
MSDN - ALLUSERS Property (Windows)
MSDN – Non-Admin ActiveX Controls
MSDN – Microsoft Cabinet Format
Update: Firebreath.org has a toolset for generating browser plugins for many platforms. The IE/ActiveX code to solve the problem posed here is just a subset. But as of 6 Nov 2014, I found it easier to start with Firebreath and its instructions than to try to build up my dev environment and roll all my own solutions from scratch.