Running console app with parameters from NSIS installer - batch-file

I am creating one installer for my project. Deployment of project needs some changes that are too complex with NSIS.
So for making it easy I have written one console app in C#. This app will do all the complex changes required with use of some parameters.
I just want to ask what is the way to call this console app with some parameters from my installer?
Is it possible by creating some batch file or what?

ExecWait '"$instdir\myapp.exe" /foo "hello world" /bar' is the basic method.
Use nsExec if you want to hide the console window and ExecDos or ExecCmd if you need more control...

You have several options to execute programs from NSIS, as documented here: http://nsis.sourceforge.net/Docs/Chapter4.html#4.9.1.2
Exec : Execute the specified program and continue immediately
ExecShell: Execute the specified program using ShellExecute
ExecWait: Execute the specified program and wait for the executed process to quit
the last solution is probably what you need.

Related

background process launched by TFS is killed when switching to next step

I have some trouble keeping alive a background process when launched by TFS.
Usually I use a batch that launch a java server (new window), as long as I keep this window open it works properly.
C:\Users\TFSService\mbs-iot-sdk\osgi\bin\vms\jdk\server.bat
In order to make my process automatic, I include this in TFS. In the step I call a batch that contains the following:
cd C:\Users\TFSService\mbs-iot-sdk\osgi\bin\vms\jdk // necessary to find the batch
start C:\Users\TFSService\mbs-iot-sdk\osgi\bin\vms\jdk\server.bat
In my task manager, I can see in background tasks that java is launched (no new window is opened), exactly as it behaves when launching directly the batch. But after a few seconds, when TFS switches to the next step, it stops.
Then the next step carries on but fails as it requires the server to be launched.
Is there a particular way of doing it in TFS ?
thank you
Alexandre
It's suggest to launch the .bat file from a relative path not directly use cd to hard code the path.
Also recommend you to use Run Batch File task not Run Command Line task to launch the .bat file.
According to your description, seems you are using a run command line task in your build pipeline. Then run the command under the working directory c:\Build_work\5\s, the command cd to C:\Users\TFSService\mbs-iot-sdk\osgi\bin\vms\jdk\ on the build agent, find the server.bat, run the server.bat.
First check if the .bat file is located at the path you are specifying on the build agent. Not sure if the bat file have to run under C:\Users\TFSService\mbs-iot-sdk\osgi\bin\vms\jdk\, guess you are also hard code the path in your server.bat file. Suggest you change all the path to relative path, you could use some built-in variable in TFS.
As for your workaround in comment, seems you want to chain builds in TFS. The official docs literally say "not yet" and have a uservoice in planed. However you could use some workaround, such as create or use other's customize extension (use rest api) to call another build. Detail ways please refer huserben's answer in this question: How to chain builds in TFS 2015?
Note sure you have to go deep into this area for your original issue. Just add some related info in case you are interested or need.
Well,
Just in case someone else goes through the same kind of issue, I found a workaround:
I wish to mix different command line steps, some of them launching Python scripts:
I have one step for launching the server that is required for my testing tool, one step for my testing tool and one Python step for differential testing
I realized that I could embed everything in a Python script.
It can handle server launching process in a separate window (with subprocess), launch my Python part and launch another process for my validation tool.
I have to test the whole chain but, at least, I solved my problem of launching a background process and detach it from TFS

Windows service recovery - run a program wont work

How do i do this?
i've tried all i can think of.
Browsing for my .exe file i want to run.
run a bat file
writing forcedos.exe in program textbox and path to my bat file in command line parameters textbox
Why cant it just work with an normal exe?
and i know it should run a program because it can restart the service correctly.
EDIT
Application: test.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.Exception
This is my latest try to make it work.
the script has the code
Dim objShell
Set objShell = WScript.CreateObject( "WScript.Shell" )
objShell.Run("iexplore")
Set objShell = Nothing
Now the script opens internet explorer if i run the cmd command
wscript.exe "C:\asfh.vbs"
The "run a program" recovery option for when a service crashes runs the specified executable in the same way as the service, i.e., it runs in session 0 (and so is affected by session 0 isolation, see also related questions) and it runs with the same security context as the service.
This means that it can't interact directly with the user (you can display a GUI, but nobody will see it) but it also restricts what the executable or script can do. For example, some shell API functions will not work properly unless the user account has been interactively logged in at some point. In the example script you posted, the script itself is probably running, but is unable to launch Internet Explorer because IE is only designed to run in an interactive session.
Provided you restrict yourself to basic functionality, it should all work as expected. (There is no master list that I know of describing what functionality is safe to use in a service context, but it is usually easy to guess. You can resort to trial and error if necessary!)
Also note that as far as I know forcedos.exe is no longer present in modern versions of Windows. If you want to run a batch file, you can specify cmd.exe as the application and /c myscript.bat as the command line parameters.

Start Play Application and Close Window

I have a play application on a Windows 7 machine which I want to start via double click on a batch file.
This batch file starts a service. Calls the play application to run in production mode, waits for 5 seconds and open a browser with a specified url.
Therefore I used the following script:
call net start service1
CALL "D:\play-1.2.5\play.bat" start --%%%%prod -Dprecompiled=true
TIMEOUT /T 4
call "C:\Program Files (x86)\Mozilla Firefox\firefox.exe" localhost:9000
exit
Now when I start the batch file the window opens and all commands are executed. Sadly Play is still writing his output to cmd and the window is not disappearing. If I close the window manually play is stop executing.
If I run play with "play start" from cmd, play is starting in the background and everything is fine. Play still runs even if I close the window.
I want to have exactly this behaviour when I start the application with my batch file.
Thanks
If you were using a linux-like environment, I' d recommend you to use 'nohup' command and a '&' sign in the end. However, as far as I know there is no direct equivalent of beautiful 'nohup' command on Windows, unfortunately. So, what I can think of is, you can create a tiny win api application that utilizes CreateProcess command and give it the required parameter to hide command line window as soon as the process is created. There are also other process creation functions such as WinExec that you can use to hide command line.
I don't know what Play is so I can only take a guess :) but try using the batch without the call's as I don't think they are necessary, and you never know, might fix the issue.
1) You see Play's output because ot redirect only system.out but write system.err to the same console.
2) I also have this problem and looking for a solution. As a workaround you could try to use some Java Wrapper and install your Play! application as a Windows Service.
3) Play! app could be started via Ant task. I haven't tried this yet.

WinAPI C - RunAsUser from REDMON_USER and REDMON_SESSIONID

I installed a PostScript printer driver and have setup REDMON (redmonnt.dll) for redirecting postscript output to my program. In my rather simple c program I capture the data from STDIN and I am able to successfully save it into a .ps file. The file looks OK.
However, I want to start gsview.exe for viewing the file. If I call ShellExecute it fails in Windows 7 because of permission issues. It seems that my program is called under a different user account (LOCAL SERVICE). So I am looking for a way to run gsview.exe under a specific username (the user who initiated the print job) which is available to the program in a variable called REDMON_USER along with the SESSIONID as well.
Q: What are the minimum WinAPI calls required to start a program given a username and a sessionid?
Any code examples in C/C++, .NET would be very helpful.
EDIT: What I am trying accomplish is something very similar to redrunee (from redmonee). I don't want to use redrunee because it opens about a console window for a brief moment.
Note:
1) The program is called by the printer service as [LOCAL SERVICE] account.
2) The first parameter Username (REDMON_USER), in effect, points to the user currently looking at the screen
Look at CreateProcessAsUser.
Also look at CreateProcessWithLogonW and CreateProcess.
They are linked from the CreateProcessAsUser
EDIT In reply to comments by OP.
Follow advice from this thread.
I am copying this here verbatim, in case the original link stops working:
The same code works for us on Vista as
on XP, etc. The service is running as
the Local System.
use WTSGetActiveConsoleSessionId to get the ID of the current active
Windows session at the console (i.e.
the machine keyboard and display, as
opposed to WTS sessions).
use WTSQueryUserToken to get the token for that session.
use DuplicateTokenEx(hToken,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,
&hTokenDup) to duplicate that token.
use CreateEnvironmentBlock to create an environment that you will be
passing to the process.
use CreateProcessAsUser with the duplicated token and the created
environment. Actually, we use
CreateProcessAsUserW, since the A
version had some sort of bug on some
older systems.
Don't forget to CloseHandle on the various tokens, etc, and to
DestroyEnvironmentBlock the
environment.
Thank you efratian.
PS. Oh joy of Windows programming, did not do it for quite a while. Now I remember why. The only thing that is close or even worse documented is OpenSSH programming.
The documentation describes the "Run as User" feature, which seems to be exactly what you want:
Run as User is intended for launching a GUI program such as GSview locally via RedRun.

How do I launch a WPF app from command.com. I'm getting a FontCache error

I know this is not ideal, but my constraint is that I have a legacy application written in Clipper.
I want to launch a new, WinForms/WPF application from inside the application (to ease transition). This legacy application written in Clipper launches using:
SwpRunCmd("C:\MyApp\MyBat.bat",0)
The batch file contains something like this command:
C:\PROGRA~1\INTERN~1\iexplore "http://QASVR/MyApp/AppWin/MyCompany.MyApp.AppWin.application#MyCompany.MyApp.AppWin.application"
It is launching a WinForms/WPF app that is we deploy via ClickOnce. Everything has been going well until we introduced WPF into the application. We were able to easily launch from the legacy application.
Since we have introduced WPF, however, we have the following behavior. If we launch via the Clipper application first, we get an exception when launching the application. The error text is:
The type initializer for 'System.Windows.FrameworkElement' threw an exception.
at System.Windows.FrameworkElement..ctor()
at System.Windows.Controls.Panel..ctor()
at System.Windows.Controls.DockPanel..ctor()
at System.Windows.Forms.Integration.AvalonAdapter..ctor(ElementHost hostControl)
at System.Windows.Forms.Integration.ElementHost..ctor()
at MyCompany.MyApp.AppWin.Main.InitializeComponent()
at MyCompany.MyApp.AppWin.Main..ctor(String[] args)
at MyCompany.MyApp.AppWin.Program.Main(String[] args)
The type initializer for 'System.Windows.Documents.TextElement' threw an exception.
at System.Windows.FrameworkElement..cctor()
The type initializer for 'System.Windows.Media.FontFamily' threw an exception.
at System.Windows.Media.FontFamily..ctor(String familyName)
at System.Windows.SystemFonts.get_MessageFontFamily()
at System.Windows.Documents.TextElement..cctor()
The type initializer for 'MS.Internal.FontCache.Util' threw an exception.
at MS.Internal.FontCache.Util.get_WindowsFontsUriObject()
at System.Windows.Media.FontFamily.PreCreateDefaultFamilyCollection()
at System.Windows.Media.FontFamily..cctor()
Invalid URI: The format of the URI could not be determined.
at System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind)
at System.Uri..ctor(String uriString, UriKind uriKind)
at MS.Internal.FontCache.Util..cctor()
If we launch the application via the URL (in IE) or via the icon on the desktop first, we do not get the exception and application launches as expected.
The neat thing is that whatever we launch with first determines whether the app will launch at all. So, if we launch with legacy first, it breaks right away and we can't get the app to run even if we launch with the otherwise successful URL or icon. To get it to work, we have to logout and log back in and start it from the URL or icon.
If we first use the URL or the icon, we have no problem launching from the legacy application from that point forward (until we logout and come back in).
One other piece of information is that we are able to simulate the problem in the following fashion. If we enter a command prompt using "cmd.exe" and execute a statement to launch from a URL, we are successful. If, however, we enter a command prompt using "command.com" and we execute that same statement, we experience the breaking behavior.
We assume it is because the legacy application in Clipper uses the equivalent of command.com to create the shell to spawn the other app. We have tried a bunch of hacks like having command.com run cmd.exe or psexec and then executing, but nothing seems to work.
We have some ideas for workarounds (like making the app launch on startup so we force the successful launch from a URL, making all subsequent launches successful), but they all are sub-optimal even though we have a great deal of control over our workstations.
To reduce the chance that this is related to permissions, we have given the launching account administrative rights (as well as non-administrative rights in case that made a difference).
Any ideas would be greatly-appreciate. Like I said, we have some work arounds, but I would love to avoid them.
Thanks!
It sounds like the Presentation Font Cache service has trouble starting when the app is launched in this way.
If you have control over the client environment, you could try setting the Windows Presentation Font Cache startup to automatic instead of manual.
This is a shot in the dark made with incomplete information:
command.com and cmd.exe are quite different. AFAIK, command.com exists for legacy compatibility, so applications you run from it will run differently. I can't test anything to complete my post because I believe that command.com runs in 16-bit mode and 64bit versions of Windows (on which I'm running) don't support that mode anymore so no more command.com for me.
That being said, there should be no difference when trying to run 32-bit applications (including managed applications).
I'm not aware of what are the limitations of your environment, but some things you may try are:
Rename you .bat into .cmd to make sure it starts with cmd.exe rather than command.com
Make your .bat start the program using the start console command
Have a non-WPF program to invoke your WPF one with a more sane environment
The problem is that the windir environmental variable is not set when using command.com.
So, in your case, adding the line set windir=C:\Windows to the beginning of the bat file will solve the problem (assuming that you have your Windows instalation in C:\Windows.
An additional issue might be that the host application is running command.com in compatibility mode. The best is to list all the environmental variables after running cmd.exe (using the set command) and comparing it to the output of the set command that you set in your bat file

Resources