I know
<Error... />
task can stop the running process but it will raise an error. How can I get rid of that error but still be able to quit the program?
Use
<Error Code="0" />
Related
One of my msbuild targets works as following:
get configuration files
start window service with those configuration files
exec service specific task
stop window service
repeat
The issue is that sometimes service stop executable task (Exec Command="sc stop myservice") takes longer time and when "sc start myservice" is called it says that service is already running. So my question is: how can I wait for "exec" command ot finish? I tried to put each executable in target and call with "CallTarget" and putting appropriate "DependsOnTargets" or "AfterTargets" and it didn't work. Can you help me? Thanks in advance.
The problem was that Exec actually did finished command execution (he simply thrown "sc stop myservice") and after that another exec started to work. I added timeout for the "sc start myservice" for a minute and it solved. The result looked like:
<Exec Command="sc stop myservice" ContinueOnError="true" />
<Exec Command="sc start myservice" ContinueOnError="true" Timeout="60000" />
I want to call a command line program of OpenOffice in WiX. To do so, I created a custom action, as seen below:
<CustomAction Id="ca_RunOpenOfficeProgram" Return="check" Directory="TARGETDIR" ExeCommand="cmd.exe /K "C:\OpenOffice.org3\program\unopgk.com list --shared"" />
The Custom Action is being run in an Install Execute Sequence:
<InstallExecuteSequence>
<Custom Action="ca_RunOpenOfficeProgram" Before="InstallFinalize" />
</InstallExecuteSequence>
When running the resulting MSI-File, I receive the following error message in a command line:
Invalid command 'C:\OpenOffice.org3\program\unopkg.com' could not be found.
Well, of course, the command is available and I may run it from command line. But it just doesnt work if the command line is being called by WiX.
It`s also notable that the part 'list --shared' is completely ignored.
Does anyone know what`s going on here?
I would recommend using the ShellExecute custom action from the WiX toolset.
Here is the sample code:
<Property Id="WixShellExecTarget" Value="[#myapplication.exe]" />
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
Change the Value of property WixShellExecTarget to cmd.exe /K "C:\OpenOffice.org3\program\unopgk.com list --shared" and it should work.
Are you sure that cmd.exe /K "C:\OpenOffice.org3\program\unopgk.com list --shared" works? It looks like you have the quotes in the wrong place.
And, do you really want the console window kept open (/k)? Does the user have to enter more commands before the installation continues? You might want /c instead. See the help with cmd /?.
But, if there is only one command needed, why not just run the program directly?
ExeCommand=""C:\OpenOffice.org3\program\unopgk.com" list --shared"
Finally, if the above is the only command needed and assuming C:\OpenOffice.org3\program\unopgk.com is a console application, a useless console window will be opened. This can be avoided with WiX's QtExecCmdLine custom action.
If you are running the program to gather information, and it is a console application, you could do:
cmd /c "C:\OpenOffice.org3\program\unopgk.com" list --shared >path\out.txt
and use another custom action to read the file and make decisions on it or show it to the user in a Windows Installer dialog. This would be a better experience than leaving the user with a console window with a blinking prompt that they have to exit out of.
Found the solution for my problem:
1) As written in my answer to Toms post, I had in typo in the command line ... stupid.
2) The quotes regarding the command line call had been misplaced (Toms answer)
3) I found out that running 'unopkg.com' with the 'shared' parameter is only executed when the command line is being run with administration rights. I thought that the attribute 'impersonated="yes"' in my CustomAction would be enough, but it didn`t help.
Guess I have to dig deeper into documentation of WiX regarding UAC.
Also thanks to Ralf. I didnt try his solutions, but you might give it a shot.
Setting LaunchTarget e.g. to "cmd.exe" works fine, after the installation of the burn package, the desired command line window pops up. However, setting LaunchTarget to for example "[InstallFolder]\Path\To\Postinstallexecutable.exe" yields an error:
Error 0x80070002: Failed to launch target: C:\Program Files (x86)\Path\To\Postinstallexecutable.exe
The path is correct, executing "C:\Program Files (x86)\Path\To\Postinstallexecutable.exe" at the command line works fine. Is this a bug or am I missing something? WiX toolset version is 3.8.309.0.
Update: After a little more testing, the problem seems to occur only when you try to pass a parameter to the command in LaunchTarget. So for example using
<Variable Name="LaunchTarget" Value="[InstallFolder]\Basiskomponenten\Allgemein\test.cmd" />
works, while
<Variable Name="LaunchTarget" Value="[InstallFolder]\Basiskomponenten\Allgemein\test.cmd Test123" />
results in an 0x80070002 error.
The LaunchTarget variable points only to the executable that should be launched, it cannot be provided the command-line arguments. It wasn't until a very recent build of WiX v3.8 that you could set a second variable called LaunchArguments that provides the arguments. So, try upgrading to yesterday's WiX v3.8 build (or newer) and do:
<Variable Name="LaunchTarget" Value="[InstallFolder]\Basiskomponenten\Allgemein\test.cmd" />
<Variable Name="LaunchArguments" Value="Test123" />
As part of sql server 2005, there is the bulk copy command "bcp.exe" (http://msdn.microsoft.com/en-us/library/ms162802%28SQL.90%29.aspx)
We are running the bcp command from our msbuild script using the exec task. Unfortunately, when bcp fails to load a row of data, the build still succeeds.
I tried (per build script snippet below) specifying an error file, and checking for its existence, unfortunately that means the build always fails even if bcp completely succeeds, because it appears that bcp will always create the error file even if there are no errors.
<ItemGroup>
<bcpFiles Include="$(DataPath)\*.txt" />
</ItemGroup>
<Delete Files="BcpErrors.txt" />
<Message Text="bcp $(DatabaseName).dbo.%(bcpFiles.FileName) in %(bcpFiles.FullPath) -eBcpErrors.txt -c -E -q -t"`" -r"`\n" $(bcpConnectionString)" />
<Exec Command="bcp $(DatabaseName).dbo.%(bcpFiles.FileName) in %(bcpFiles.FullPath) -eBcpErrors.txt -c -E -q -t"`" -r"`\n" $(bcpConnectionString)" />
<Error Condition="Exists('BcpErrors.txt')" Text="One or more bcp commands contained errors." />
Is there any way I can get msbuild to fail the build if bcp fails to load any of the data?
If BCP returns a non-zero error code for failure then the MSBuild Exec task should detect that and mark the task as failed.
You could use the MSBuild ExtensionPack "File" task to look for error text in the output file:
<MSBuild.ExtensionPack.FileSystem.File TaskAction="FilterByContent" RegexPattern="Error = " Files="BcpErrors.txt">
<Output TaskParameter="IncludedFileCount" PropertyName="ErrorFileCount"/>
</MSBuild.ExtensionPack.FileSystem.File>
<Error Condition="$(ErrorFileCount) != 0" Text="One or more bcp commands contained errors." />
Ok, so it's not exactly using bcp.exe, but BULK INSERT is very similar to bcp.exe, can take the same format of files, and has most of the same options. The Sql.Execute task will also fail if the BulkInsert query fails. So I ended up with
<ItemGroup>
<bcpFiles Include="$(DataPath)\*.txt" />
</ItemGroup>
<Sql.Execute ConnectionString="$(ConnectionString)" Sql="BULK INSERT [$(DatabaseName)].dbo.[%(bcpFiles.FileName)] FROM '%(bcpFiles.FullPath)' WITH (DATAFILETYPE='char', KEEPIDENTITY, FIELDTERMINATOR='`', ROWTERMINATOR='`\n', MAXERRORS=1)" />
(Sql.Execute task is defined in Microsoft.Sdc.Common.tasks)
I'm trying to decide which side I'm on in the MsBuild vs. Nant war. I'm starting with: stop a service, deploy some files, restart the service. Just from looking at these two links, that is much easier to do in Nant.
MSBuild: Example of using Service Exists MSBuild task in Microsoft.Sdc.Tasks?
<target name="service_exists">
<script language="C#">
<references>
<include name="System.ServiceProcess.dll" />
</references>
<code><![CDATA[
public static void ScriptMain(Project project) {
String serviceName = project.Properties["service.name"];
project.Properties["service.exists"] = "false";
project.Properties["service.running"] = "false";
System.ServiceProcess.ServiceController[] scServices;
scServices = System.ServiceProcess.ServiceController.GetServices();
foreach (System.ServiceProcess.ServiceController scTemp in scServices)
{
etc...
Nant: http://ryepup.unwashedmeme.com/blog/2007/01/04/restart-a-windows-service-remotely/
<!-- Send the stop request -->
<exec program="sc.exe">
<arg line="\\server stop shibd_Default"/>
</exec>
<!-- Sleep a little bit, to give the service a chance to stop -->
<sleep seconds="5"/>
<!-- Send the start request -->
<exec program="sc.exe">
<arg line="\\server start shibd_Default"/>
</exec>
I wonder if the SO community agrees with me. Is it much easier to get basic things like this done in Nant? Sure looks that way. C# code in a CDATA block? WTF?
Our current build process is a) lots of bat files b) lots of cursing. I'd really like to find a good replacement, but that MsBuild stuff looks like a world of pain to my eyes. I'm thinking the way to go is to build scripts in Nant, then use MsBuild to do any .NET builds that need to be done.
One important question: which one is better at catching errors in the script before the script is run? I was thinking of rolling my own here and that was very important part of it: line up all your data and make sure that it makes sense before attempting to run.
In msbuild you could also use the ServiceController task that is packaged in the msbuild community tasks.
You can execute sc.exe using MSBuild every bit as easily ...
<Exec Command="sc.exe \\server stop shibd_Default" />
By default this will "fail" if the exit code (of sc.exe) is non-zero, but that can be customized.
With Nant, there are 2 other ways to stop a service, and one is able to track an error.
First one (using Net Stop):
<exec program="net" failonerror="false"><arg value="stop"/><arg value="${serviceName}"/></exec>
Second one (much cleaner):
<servicecontroller action="Stop" service="${serviceName}" if="${service::is-installed(serviceName,'.') and service::is-running(serviceName,'.')}" />
Note that the second line verifies that the service already exists and is running, which allows to track any weird error.
In addition to #nulpptr's answer for MSBuild, if you don't have the option of using the community tasks, you might have to resort to a hack to wait for your service to stop before moving on. If you have the resource kit you can use the EXEC task with the sleep command.
No resource kit? Use the ping trick...
However, if you don't have the resource kit, you can use the ping trick to force a delay. For instance, the following will stop your service using the sc command, and then pause for about 5 seconds:
<Exec Command="sc.exe \\server stop shibd_Default" ContinueOnError="true" />
<Exec Command="ping 127.0.0.1 -n 5 > nul" ContinueOnError="true" />