Run a powershell script inside a windows service - powershell

I have a powershell script running very well ,
I'm calling this script within a power shelle command line :
PS C:> .\myscript.ps1 -var1 variable1 -var2 variable2
I need to mount this inside a service with a stupid sc create but i couldn't find a way to launch it
any help please ?
Thanks a lot.

Use Windows service wrapper. It's highly configurable and provides a lot of useful options, like log rotation, service account, on failure actions and so on. It even can automatically download resources from URL and place it locally as a file, so you can host your script somewhere and have it auto updated. Here is the basic steps to get your PowerShell service up and running:
Download\build winsw. Version 1.x binaries can be found here. To build latest winsw 2.x use Visual Studio Community 2013 (free for open-source projects). More detailed build instructions are here.
Create XML configuration file for your service. Example:
<service>
<id>MyPsSvc</id>
<name>My PowerShell Service</name>
<description>Does funny stuff with your PC</description>
<executable>PowerShell.exe</executable>
<logmode>reset</logmode>
<arguments>-ExecutionPolicy Bypass -NoLogo -NoProfile -NonInteractive -WindowStyle Hidden -File "myscript.ps1" -var1 variable1 -var2 variable2</arguments>
</service>
The configuration file must have the same basename as winsw executable, i.e.:
winsw.exe
winsw.xml
If you plan to use your service on the PC without internet connection, disable digital signature verification for winsw. To do this create file winsw.exe.config. Example:
<configuration>
<runtime>
<generatePublisherEvidence enabled="false"/>
</runtime>
</configuration>
If you're running Windows Server 2012 or Windows 8 and and don't want to install .Net 2.0 support, specify .NET 4.0 runtime support in the abovementioned config file:
<configuration>
<runtime>
<generatePublisherEvidence enabled="false"/>
</runtime>
<startup>
<supportedRuntime version="v2.0.50727" />
<supportedRuntime version="v4.0" />
</startup>
</configuration>
Install your service, running winsw.exe install from command line. Once the service is installed, you can start it from Windows service manager.

Related

Run node module in guest executable

I've got a global npm package installed, TileServer, that I run as service through command line. I'd like to convert this to a guest executable in service fabric, but I'm having trouble implementing.
Pre-Guest executable, I would invoke the following command in cmd:
tileserver-gl-light --port=8788 map.mbtiles
My configuration for my guest executable is:
<ExeHost>
<Program>tileserver-gl-light</Program>
<Arguments>--port=8788 c:\maptiles.mbtiles</Arguments>
<WorkingFolder>Work</WorkingFolder>
</ExeHost>
Unfortunately, the error I get when trying to run the service just says "There were deployment errors. Continue?"
Any ideas on how to get this working?
Thanks!
Can you check to see if that application package validates on your local machine by calling Test-ServiceFabricApplicationPackage?
Usually SF expects the file to be
Present in the application package and
Some sort of executable file that the OS understands (for windows .bat, .exe, etc.)
In this case I think what you're saying is that the tileserver bits are actually outside the package (wherever your node packages are), and you're actually trying to use node to start it (since the tileserver-gl packages aren't natively executable by Windows).
If that's the case your program should probably be something like a batch file that just says "tileserver-gl-light" and then your command line args in it.
Include that batch file in your code package and reference that as your program (and straighten out how you want to pass the args) and you should be good to go.
As #masnider pointed out, the files must be present in the application package, and we must call the executable as something the OS understands. This presents particular challenges for node modules as:
They must be wrapped in a .bat
They can't be called using the global command
They need parameters
They files, node_modules, often has issues with file path length issues
My end service had the following file structure:
- ApplicationPackageRoot
- MyService.ServicePkg
- Code
- 7za.exe
- node.exe
- npm.7z
- start.bat
My ServiceManifest.xml had these values in it:
<SetupEntryPoint>
<ExeHost>
<Program>7za.exe</Program>
<Arguments>x npm.7z<Arguments>
<WorkingFolder>CodeBase</WorkingFolder>
</ExeHost>
</SetupEntryPoint>
<EntryPoint>
<ExeHost>
<Program>start.bat</Program>
<Arguments><Arguments>
<WorkingFolder>CodeBase</WorkingFolder>
</ExeHost>
<EnvironmentVariables>
<EnvironmentVariable Name="Port" Value="8788"/>
<EnvironmentVariable Name="TilePath" Value="mytiles.mbtiles"/>
</EnvironmentVariables>
</EntryPoint>
And finally, my start.bat was comprised of the following line:
.\node.exe npm/node_modules/tileserver-gl-light/sc/main.js --port=%Port% %TilePath%
So how did this work? The npm.7z in the Code consisted of my node_modules, pre-zipped. The 7za was the portable version of 7zip which allows use to get around the file path length issues present on windows. 7za is called in the SetupEntryPoint.
Then the SF calls start.bat, which reads in the environmental variables of Port and TilePath. This has to called the exactly .js file called by the normal tileserver-gl-light command.
Doing this results in a properly working node application in a service fabric guest executable.

Powershell remote installation has problems with setup of util:ServiceConfig wix element during installation

I would like to ask you if there is any other way how to setup parts of wix element - util:ServiceConfig other than in MS installer?
I need to configure this parts of wix element:
FirstFailureActionType="restart"
SecondFailureActionType="restart"
ThirdFailureActionType="restart"
ResetPeriodInDays="1"
RestartServiceDelayInSeconds="60"
When I make comment from whole "util:ServiceConfig" part of code and build installer, everything is fine and remote installation will be executed without issues.
I am trying to find way how to configure it besides Microsoft installer but google did not give me desired answers.
Or is there any other solution how to make PowerShell remote installation somehow process that configuration?(I mean user rights and permissions or something similar)
I have found solution for this problem by myself.
I have created Custom action which is executing command calling "sc.exe failure" and configure FailureActions in that command.
I deleted whole util:ServiceConfig wix element and replaced it with this:
<CustomAction Id="ServiceRestarter"
Directory="INSTALLFOLDER"
ExeCommand=""[SystemFolder]sc.exe" failure "ServiceName" reset= 86400 actions= restart/60000/restart/60000/restart/60000"/>
<InstallExecuteSequence>
<Custom Action='ServiceRestarter' After='InstallFinalize'>(NOT Installed)</Custom>
</InstallExecuteSequence>
Now my PowerShell script doesn't have problem with remote installation of .msi package. Cheers, I hope it will help someone else than me.

Run a program taking parameters after installation

I have a Windows Service and I've created an installer for the service in the same project.
Now I want to deploy my service. So I've added a new project in my solution (Wix Setup Project).
What I want now is to run my program i.e. my Windows service after installation and send a parameter so that service installs. For example the command line shuld be like this:
MyService.exe /I
And also a want to send a parameter /U to uninstall my service.
Thanks
I've solved this on my own.
<InstallExecuteSequence>
<Custom Action="InstallWinService" Before="InstallFinalize">NOT Installed</Custom>
<Custom Action="UninstallWinService" Before="RemoveFiles">Installed AND NOT REINSTALL</Custom>
</InstallExecuteSequence>

Exception running powershell script from MSBuild Exec Task

i´m having a problem with MSBuild and Powershell. There is a PS-script that i want to execute within the MSBuild exec-Task.
The Problem: Running the Script direct from CMD works, but running the script within MSBuild I get an error.
Here the MSBuild script:
<Import Project="$(MSBuildExtensionsPath)\ExtensionPack\4.0\MSBuild.ExtensionPack.tasks"/>
<Import Project="$(MSBuildExtensionsPath)\MSBuildCommunityTasks\MSBuild.Community.Tasks.Targets"/>
<PropertyGroup>
<PathToSvnClient>C:\Program Files (x86)\CollabNet\Subversion Client</PathToSvnClient>
</PropertyGroup>
<ItemGroup>
<!-- set Folder to Svn Repository for svn info command-->
<SvnFolder Include="$(MSBuildProjectDirectory)\.."/>
</ItemGroup>
<Target Name="SvnInfo">
<!-- get SVN Revision and Repository Path -->
<SvnInfo LocalPath="%(SvnFolder.FullPath)" ToolPath="$(PathToSvnClient)">
<Output TaskParameter="Revision" PropertyName="Revision" />
<Output TaskParameter="RepositoryPath" PropertyName="RepositoryPath" />
</SvnInfo>
</Target>
<Target Name="SetProductVersion" DependsOnTargets="SvnInfo">
<Exec Command="powershell -file "Scripts\SetSth.ps1" -PARAM "$(PathToSth)" -SVNID $(Revision) -SVNFOLDER "$(RepositoryPath)"" LogStandardErrorAsError="true" ContinueOnError="false"/>
</Target>
The Command is executed exactly the same way as on CMD, but i get an exception from the Powershell Script for the SVNFOLDER param.
The Command that is executed looks like this:
powershell -file "Scripts\SetSth.ps1" -PARAM "C:\abc\cde" -SVNID 1234
-SVNFOLDER "https://domain/svn/rep/branches/xy%20(Build%2012)"
So from CMD it works, from within MSBuild not. I have no idea why. I hope you got an idea.
What about this approach playing with double and singles quotes:
<Target Name="SetProductVersion" DependsOnTargets="SvnInfo">
<Exec Command="powershell -command "& {Scripts\SetSth.ps1 -PARAM '$(PathToSth)' -SVNID '$(Revision)' -SVNFOLDER '$(RepositoryPath)'}"" LogStandardErrorAsError="true" ContinueOnError="false"/>
</Target>
Double check your paths.
Remember, powershell invoked in this way runs as Msbuild.exe under whatever user is executing the build. To msbuild.exe, a straight call to cmd.exe is going to start in the working directory where msbuild lives.
Assume -file "Scripts\SetSth.ps1" references C:\users\yourusername\Scripts\SetSth.ps1
So for you, calling cmd.exe and running that may work just fine, b/c your working directory is going to match C:\users\yourusername
For msbuild.exe, its likely unable to find that file, as its starting in something like *C:\Windows\Microsoft.NET\Framework\v4.0*
So it's looking for C:\Windows\Microsoft.NET\Framework\v4.0\Scripts\SetSth.ps1
I would try making that file path fully qualified. If that still doesn't work, have cmd.exe dump its results into a property and have msbuild log it. Then you can review the paths.

deploy tools: get a list of actions the tool will execute without executing the deploy script

We're in the process of evaluating MSBuild and Nant for deploys. We may roll our own tool. One thing that a different business unit -- let's call it DeptA -- would really like to have (as in it better have it) is the ability for someone in DeptA to read the script and see what it will do. Currently we do this with .bat files. We hates the bat files. Nasty nasty bat files's. But if we ask DeptA to learn a new script language (nant, msbuild) they may be resistant.
Ideally the build tool of choice would be able kick out a list of actions without doing anything else. Along the lines of:
Stop service ABC on server Z
Stop service DEF on server Z
Copy all files from
\server\dirA\dirB to \server2\dirC
Start service ABC on server Z
Start service DEF on server Z
Run all scripts in dir
\server\dirA\dirC
Is it possible to do this with MSBuild? NAnt? Without me re-learning XSL?
If I was you I would actually blend MSBuild and MSDeploy. You should have your MSBuild script perform the actions like start/stop service etc. Then let MSDeploy to the file copy. With MSDeploy you can use the -whatif switch to indicate that you only want a report of the actions to be executed instead of actually executing it. MSBuild unfortunately doesn't offer such an option out of the box you will have to "build" that into your scripts. You can do this with properties and conditions. For example it might look something like this:
<Project ...>
<PropertyGroup>
<!--
Create the property to use, and declare a default value.
Here I've defaulted this to true because it is better to force the
caller to explicitly specify when to perform the action instead of it
being the default.
-->
<SimulateExecution Condition= '$(SimulateExecution)'==''>true</SimulateExecution>
</PropertyGroup>
<Target Name="Deploy">
<Message Text="Deploy started" />
<Message Text="Stop service ABC on server Z"/>
<WindowsService ... Condition=" '$(SimulateExecution)'=='false' "/>
<Message Text="Stop service DEF on server Z"/>
<WindowsService ... Condition=" '$(SimulateExecution)'=='false' "/>
<!-- Call MSDeploy with the Exec task. -->
<PropertyGroup>
<MSDeployCommand>...\msdeploy.exe YOUR_OPTIONS_HERE</MSDeployCommand>
<!-- Append the -whatif to the command if this is just a simulation -->
<MSDeployCommand Condition= '$(SimulateExecution)'=='false' ">$(MSDeployCommand) -whatif</MSDeployCommand>
</PropertyGroup>
<Exec Command="$(MSDeployCommand)" />
... More things here
</Target>
</Project>
For the service actions you can use the WindowsService task from the MSBuild Extension Pack. You will have to fill in the blanks there.
When you call MSDeploy you should just use the Exec task to invoke msdeploy.exe with your parameters. If you pass the -whatif it will not actually perform the actions, just report what it would have done. These will be logged to the msbuild log. So if you invoke msbuild.exe with /fl you will get those actions written out to a file. The only issue that I've seen when taking this approach is that for msdeploy.exe you many times have to use full paths (those without ..) which can sometimes be tricky so be wary of such paths.