I'm very new in C# world though I'm trying to modify an installer using custom action. What I'm trying to do is to run a batch script after installation finishes. I'm using the following Installer class:
namespace PostInstall
{
[RunInstaller(true)]
public partial class Installer1 : Installer
{
public Installer1()
{
InitializeComponent();
System.Diagnostics.Process.Start("PostInstall.bat");
}
}
}
A project named PostInstall contains a *.cs file with the code above. The project is created following this link's section "To create the custom action". In the setup project, I've added the primary output of PostInstall project in Install & Commit node as described in the link.
Yet at the end of the installation the following error is received:
Error 1001. Unable to create an instance PostInstall.Installer1
installer type -> Exception has been thrown by the target of an
invocation. -> The system can't find the file specified.
I verified that PostInstall.bat exists in the installation directory. Why the error is occurring and how to resolve it?
I think the installation directory is not automatically the directory in which the installer is run, so you cannot assume that Process.Start("PostInstall.bat") will find the batch file.
This DevCity article is a very good introduction to this topic, and tells you how to get the installation directory passed to your custom action objects so that you can create the full pathname for your batch file.
Have you thought about what will happen while your batch file is running? Do you want to wait until it is finished before proceeding to the next stage of your installation?
Ideally the custom actions should be written in native code, if it's not possible in your case try to run the .msi as Administrator
Related
I created a class library project and configured the properties section debug to start an exe (the.exe) located in the output directory of the build (as shown in the image).
It worked as long as we had a pre-build event copying the exe and all related files from one directory in the output directory of the build. Unfortunatly this is inconvinient and we do not have track which version of the exe is used.
So I created a versioned nuget package to place all the files in the output directory. I confirmed all the required files (I know of) are in the output directory. And since I created the nuget package manually with the CLI I can confirm they are exactly the same files.
But when I try to start the application from Visual Studio 2019 now I get the following error in the debug output:
The target process exited without raising a CoreCLR started event. Ensure that the target process is configured to use .NET Core. This may be expected if the target process did not run on .NET Core.
The program '[16616] the.exe' has exited with code -2147450749 (0x80008083).
Actually both (the.exe and the class library) are .NET 5.
Comparing the changes of the two setups via Git changes does not hold any clues beside adding the nuget and removing the pre-build events.
So any clue what could be the difference/problem and how to get the executable running? May I missed something?
Well, better check twice when you are stating "I confirmed all the required files (I know of) are in the output directory."
The problem was that not all files made it into the output directory.
In my case only the the.exe and the.dll were placed into the output directory. Once I checked again and ensured that also the.runtimeconfig.json (which was missing) were added it was running again and the exception were gone. Though I am not sure if there is a better way than distributing the.runtimeconfig.json.
update visual studio using Visual Studio installer worked for me. This link! helped for me.
I am developing a visual studio setup project. So far all has been good except uninstalling. The program did not create its own uninstaller, but instead the uninstall feature is inside of the setup.msi. So what I need to do is during the install, I need to copy the running setup.msi to the [TARGETDIR]. The easiest way I can think of is to use custom actions. I'm pretty lost on custom actions though, I don't understand where they go and every time I try to code one, its full of errors. Looking at other questions and answers, I have come up with the following:
[RunInstaller(true)]
public partial class CustomInstaller : System.Configuration.Install.Installer
{
public override void Install(System.Collections.IDictionary stateSaver)
{
base.Install(stateSaver);
string path = this.Context.Parameters["targetdir"];
// Do something with path.
}
}
But I don't understand it. I see how it gets targetdir as that gets passed via the customactiondata. But, RunInstaller isn't known, nor is System.COnfiguration.Install.Installer. Where am I supposed to put this .cs file to make it work? Very confused.
This class should be placed in your application project. I believe it can be included in any project whose DLL is packaged by the setup project, but it usually makes the most sense to put it in the application project.
Make sure your application project references System.Configuration.Install.dll. That will resolve the reference to Installer.
RunInstaller is in the System.ComponentModel namespace (System.dll), so make sure you have a using System.ComponentModel statement at the top of the class file.
This question may help you understand custom actions more:
Why won't my Setup Project Perform my Custom Registration Process
This might help you get started, although it doesn't cover installer classes.
https://www.simple-talk.com/dotnet/visual-studio/getting-started-with-setup-projects/
Error 2835 is a bogus error related to trying to show a dialog, probably the error dialog, so it's masking whatever went wrong, most likely your code.
Make a log using msiexec /I /l*v and look for your error before the 2835.
You pass that targetdir value to your custom action like an argument list, so you'd say /targetdir="[TARGETDIR]\" and that's case-sensitive and including the brackets. It's picky because it gets merged with other arguments.
Beware that your code is not running in an application context. It's a call from the msiexec process running with the system account and a working directory of sysetm32. That means full paths need to be specified and any use of a profile-specific item (like Desktop, user profile location) will fail.
I have the following problem. There is a custom build process which is using the custom build activity. I've been opening this build some time ago, and everything was good. But, after some time, the custom build activity and build process has changed, got new arguments and some other changes. This activity has been updated on the server source control path, which is set in build controller settings. But, it seems that this activity doesn't want to be downloaded on my desktop, because when I open build definition, I'm getting error that my new custom type couldnot be resolved.
I've tried to build this activity by myself and place it to the folder, which contains devenv.exe, and this "solved" problem - my build process has been opened. But It is not normal.
What should I do to normally open my build definitions?
The contents of custom assembly folder defined for controller is downloaded to temp folder and loaded by studio once (im not sure if proper version increments for dlls would solve this - haven't tried) when opening the process tab on build definition. You either have dlls somewhere that overrides this (GAC, VS private assemblies) or your studio has been running for long time.
Remove the one you put along devenv, restart studio, check GAC and private assemblies, you can use Studio and attach debuger to other instance and review loaded modules this can help you pinpoint where the item is comming from.
To remove assembly run following from Visual Studio command line: gacutil /u "YourAssembly"
For studio assemblies i believe this is the folder: Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies
I Need to develpe application for getting http website page
I found this tutorial for using curl in .Net
http://thedotnetframework.blogspot.com/2008/06/lets-talk-about-http-protocol-and-http.html
I downloaded the curl dll files and add reference (LibCurlNet.dll) to my project
and added the class in my project
but when I run my project, I have error message at line
Curl.GlobalInit((int)CURLinitFlag.CURL_GLOBAL_ALL);
the error message says
Unable to load DLL 'libcurl.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
it seems that ibcurl.dll has a problem
note : I can not add (ibcurl.dll) as reference in my project
please help ;
You're looking for the built-in WebClient class.
You don't need any third-party libraries.
The error you are seeing is that you need that file (and LibCurlShim.dll) present in your build directory (e.g. bin\debug) or wherever your exe is running from. There is no problem with the file - you just cannot add it as a reference in the usual way in Visual Studio.
You could right-click on Project Explorer and add Existing Files and select libcurl.dll and LibCurlShim.dll. Then in Solution Explorer, on the Properties of those two files make sure you set the Copy To Output Directory to something like Copy Always or Only If Newer
How do you detect that the install is running in silent mode?
I have a custom application that I've added a .msi setup project. I run the .msi file with the /qb switch, and in my custom installer c# code I would like to be able to detect this.
Edit: nobugs says to test the UILevel property. How do I access the UILevel property from a class derived from the System.Configuration.Install.Installer class?
Taking the hint from nobugz, I did the following:
On the Custom Actions view of the .msi setup project, I added the following to my CustomActionData (to pass the UILevel through to my custom installer):
/UILevel="[UILevel]"
Within my C# code for the code derived from base class Installer, I added code to get the value:
string uiLevelString = Context.Parameters["UILevel"];
It was then simple to parse the string for an int value. If the value is <= 3, it is a silent install.
First I would point out that InstallUtil is a very bad pattern. They run out of process, tatoo the process with a CLR version and when they fail they raise a 1001 error modal dialog even during a silent install.
Instead you should use WiX's DTF pattern.
MsiGetMode ( Session.Mode ) is limited during deferred execution so you will have to serialize and deserialize the UILevel.
http://www.msifaq.com/a/1044.htm