Below is an example of a modified enovascript (C#). It’s possible to send this over the network and execute it locally on a server where an enova business service is installed. In this example the enova script (script.cs) executes a simple SQL query returning the database name.
using System; using System.Collections.Generic; using System.Data; using Wipcore.Core.Connectivity; using Wipcore.Core.SessionObjects; public class Script { public static void Run(string[] args) { ConnectionSettings settings = new ConnectionSettings(args[0], ConnectionProtocol.Tcp, int.Parse(args[1]), args[2], args[3]); Connection connection = new Wipcore.Core.Connectivity.Connection(settings); Context context = connection.Context; PrintDBName(context); return; } private static void PrintDBName(Context context) { string sql = "SELECT DB_NAME() as DBNAME"; DataRowCollection rows = context.ExecuteSqlSelect(sql, 0).DataTable.Rows; foreach (DataRow row in rows) { string dbName = row["DBNAME"].ToString(); Console.WriteLine("DB Name: '" + dbName + "'."); } } }
How do we send and execute this script? This way:
A powershell script (remoteexecute.ps1) reads the cs file, sends it over the network, saves it to disk on the remote server, compiles it, and executes it. How does this amazing powershell script look like?
# Run with: powershell -file remoteexecute.ps1 script.cs bsservers $ErrorActionPreference = "Stop" [string] $source = Get-Content $args[0] $cred = Get-Credential $env:username@wipcorehosted.local [string[]] $servers = $args[1].Split(",") | % { $_ + ".wipcorehosted.local" } Invoke-Command -cn $servers -cred $cred -args $source { [string] $imagepath = (gp "HKLM:\SYSTEM\CurrentControlSet\services\Wipcore eNOVA*BS").ImagePath [string] $bsfolder = Split-Path $imagepath.Substring(1, $imagepath.IndexOf("""", 1) - 1) copy $env:windir\System32\WindowsPowerShell\v1.0\powershell.exe $bsfolder $args[0] > script.cs [string] $hostname = hostname [string] $portnumber = (gp "HKLM:\SYSTEM\CurrentControlSet\services\Wipcore eNOVA*BS\Parameters").ServerTcpPort Set-Alias psh "$bsfolder\powershell.exe" [string] $script = ` "[string[]] `$args = @('$hostname','$portnumber','wadmin','wadmin') [string] `$source = gc script.cs Add-Type `$source -ra ((dir '$bsfolder\*.dll')+'System.Data.dll'+'System.Xml.dll') [Script]::Run(`$args)" psh -command $script del script.cs del $bsfolder\powershell.exe }
Apart from script.cs in this example doesn’t use the host object provided by the enova script console, it’s similar to an enova script, 3 line of code have been added. What are the benefits of running an enova script with powershell compared to the enova console?
- You can run C# script on any number of servers in parallel, a common case when you have different brands on different servers. This is actually trivial, just add comma separated server names on the command line.
- You don’t need to login with RDP or Citrix and start an application. This also enables you to install slimmed down windows servers in core mode, without any desktop.
- You don’t need to keep the dll files updated for the enova console installation. Actually no application at all, except for the enova business service itself, has to be installed to run the script.
- If you have strict policies (AD GPOs) which prevents idle RDP sessions, using a remotely installed enova console is a show stopper if you have long running scripts. Powershell is robust to disconnections.
- You can connect with IPC locally on the business server, this should be a drastic performance improvement compared to TCP over the network from a Citrix server.
- You can run the script from the command line, without any GUI interaction. This enables enova scripts to be executed at deploy time, when a new release is installed. All kind of human errors is then prevented.
- When you are able to run enova scripts non-interactive, it also enables you to create scripts which imports configuration with enovas xml api. That’s one step closer to 1-click deploy.
- You could of course change Script.Run in the script to Program.Main, like an ordinary C# console application. This might be useful when developing the script in Visual Studio. Also make sure the powershell script is executing this function.
Implementation details of the powershell script.
When executing scripts remotely, the WinRM service hosts the powershell script environment. This is different from running powershell.exe locally, although not very different, in both cases the host process is a thin layer on top of .net framework.
Note that Powershell 2.0, which is the default version in Windows7/2008R2, can only host .NET CLR 2.0. Powershell 3.0, which is the default in Windows8/2012, can only host .NET CLR 4.0. Powershell 3.0 is installable on older OSes, but be advised, some advanced features is not fully backward compatible.
This script doesn’t have much error checking, and assumes things about the environment.
- The installed business service must be named something that matches ”Wipcore eNOVA*BS”. Only one service must match this pattern. Change the script if this is not the case, or actually better, change the name of the installed service, this can be tricky though.
- The ImagePath registry entry for the installed business service must look something like this:
"D:\Enova\Services\Wipcore eNOVA BS\WipcoreEnovaService.exe" -n "Wipcore eNova BS"
This is usually not a problem because InstallUtil automatically creates this type of ImagePath when installing the business service. But if you installed the service by using ”sc create”, this is not the case. InstallUtil is the recommended application to use when installing windows services developed in .NET.
- IPC is not enabled by default when installing the business service. You have to specify a value for IPC in registry to enable IPC. This requires a restart of the business service.
- Powershell.exe is temporarily copied to the business service folder by the powershell script. This is done because powershell can only load dll files from the folder where powershell.exe resides. Dll files can of course also be loaded from the GAC. The WinRM service has the same restriction, this is why a new instance of a powershell host has to be started. Also note, required dll files from the .NET framework must be specified to the Add-Type cmdlet when compiling the script.
- The compiler used to compile the csharp script is integrated with .net framework. This compiler is different from Visual Studio in several ways. One obvious difference is that single line comments // doesn’t work, you have to use /**/ instead. If you have experience from the enova console, you have certainly stumbled upon these limitations already.
- The .NET compiler in powershell compiles C# code by default. Other languages are possible. Please do not use them. GOTO 6.
Postat i:Uncategorized
