Markdown parser done right. Fast and easy to extend.
Table of content
node.js & bower:
npm install markdown-it --save
bower install markdown-it --save
browser (CDN):
See also:
// node.js, "classic" way:
var MarkdownIt = require('markdown-it'),
md = new MarkdownIt();
var result = md.render('# markdown-it rulezz!');
// node.js, the same, but with sugar:
var md = require('markdown-it')();
var result = md.render('# markdown-it rulezz!');
// browser without AMD, added to "window" on script load
// Note, there is no dash in "markdownit".
var md = window.markdownit();
var result = md.render('# markdown-it rulezz!');
Single line rendering, without paragraph wrap:
var md = require('markdown-it')();
var result = md.renderInline('__markdown-it__ rulezz!');
(*) presets define combinations of active rules and options. Can be
"commonmark"
, "zero"
or "default"
(if skipped). See
API docs for more details.
// commonmark mode
var md = require('markdown-it')('commonmark');
// default mode
var md = require('markdown-it')();
// enable everything
var md = require('markdown-it')({
html: true,
linkify: true,
typographer: true
});
// full options list (defaults)
var md = require('markdown-it')({
html: false, // Enable HTML tags in source
xhtmlOut: false, // Use '/' to close single tags (
).
// This is only for full CommonMark compatibility.
breaks: false, // Convert '\n' in paragraphs into

langPrefix: 'language-', // CSS language prefix for fenced blocks. Can be
// useful for external highlighters.
linkify: false, // Autoconvert URL-like text to links
// Enable some language-neutral replacement + quotes beautification
typographer: false,
// Double + single quotes replacement pairs, when typographer enabled,
// and smartquotes on. Could be either a String or an Array.
//
// For example, you can use '«»„“' for Russian, '„“‚‘' for German,
// and ['«\xA0', '\xA0»', '‹\xA0', '\xA0›'] for French (including nbsp).
quotes: '“”‘’',
// Highlighter function. Should return escaped HTML,
// or '' if the source string is not changed and should be escaped externaly.
highlight: function (/*str, lang*/) { return ''; }
});
var md = require('markdown-it')()
.use(plugin1)
.use(plugin2, opts, ...)
.use(plugin3);
Apply syntax highlighting to fenced code blocks with the highlight
option:
var hljs = require('highlight.js') // https://highlightjs.org/
// Actual default values
var md = require('markdown-it')({
highlight: function (str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
return hljs.highlight(lang, str).value;
} catch (__) {}
}
try {
return hljs.highlightAuto(str).value;
} catch (__) {}
return ''; // use external default escaping
}
});
If you are going to write plugins - take a look at Development info.
Embedded (enabled by default):
Via plugins:
By default all rules are enabled, but can be restricted by options. On plugin load all its rules are enabled automatically.
// Activate/deactivate rules, with curring
var md = require('markdown-it')()
.disable([ 'link', 'image' ])
.enable([ 'link' ])
.enable('image');
// Enable everything
md = require('markdown-it')('full', {
html: true,
linkify: true,
typographer: true,
});
Here is the result of readme parse at MB Pro Retina 2013 (2.4 GHz):
$ benchmark/benchmark.js readme
Selected samples: (1 of 28)
> README
Sample: README.md (7774 bytes)
> commonmark-reference x 1,222 ops/sec ±0.96% (97 runs sampled)
> current x 743 ops/sec ±0.84% (97 runs sampled)
> current-commonmark x 1,568 ops/sec ±0.84% (98 runs sampled)
> marked-0.3.2 x 1,587 ops/sec ±4.31% (93 runs sampled)
Note. CommonMark version runs with simplified link normalizers for more "honest" compare. Difference is ~ 1.5x.
As you can see, markdown-it
doesn't pay with speed for it's flexibility.
Slowdown of "full" version caused by additional features not available in
other implementations.
markdown-it is the result of the decision of the authors who contributed to 99% of the Remarkable code to move to a project with the same authorship but new leadership (Vitaly and Alex). It's not a fork.
Big thanks to John MacFarlane for his work on the CommonMark spec and reference implementations. His work saved us a lot of time during this project's development.
Related Links:
Ports


Norman Lo
Economist / Data Scientist
Adjunct College Instructor
San Francisco
Visit Date:
Teaching History
San Francisco State University (SFSU)
Year: 2015 - 2021
University of San Francisco (USF)
Year: 2016 - 2021
City College of San Francisco (CCSF)
Year: 2016 - 2021
St. Mary's College (SMC)
Year: 2020 - 2021
Metropolitan State University (MSU)
Year: 2017 - 2019
Diablo Valley College (DVC)
Year: 2015 - 2016
Timeline Visualization


| {{"funds.withdraw_coin.balance_Total" | t}} | {{ total_balance(account.balance, account.locked) | number : withdraw_channel.fixed }}{{account.currency | uppercase}} |
| {{"funds.withdraw_coin.order_in" | t}} | {{ account.locked | number : withdraw_channel.fixed }} {{account.currency | uppercase}} |
| {{"funds.withdraw_coin.balance_available" | t}} | {{ account.balance | number : withdraw_channel.fixed }} {{account.currency | uppercase}} |


Part of elita.util View In Hierarchy
Written to parse our auto-generated ssh configs. Entries of the format are only indented to one level
write new de-duped file
parse into dict: { alias: { config_statement: [ list, of, params ] }}


描述
Given a binary tree, return the bottom-up level order traversal of its nodes’ values. (ie, from left to right, level by level from leaf to root).
For example:
Given binary tree {3,9,20,#,#,15,7},
1 | 3 |
return its bottom-up level order traversal as:
1 | [ |


panelmap creates panels for summarizing binary data, categorical data (more than 2 categories) and continuous data for known groups. Groups can arise from classification algorithms such as kmeans, or other class labels as provided by the user. panelmap is a visual aid to understand associations and trends in data instead from tedious tables and trying to infer multiple plots.
Each row of panelmap is called a panelet (singular). Many panelets assemble together to make a panelmap . We first begin by making a panelet for the solution. See panelet_group
. Rest of the variables are plotted according to the nature of the data - discrete (binary/categorical) - See panelet_category
, or continuous - See panelet_continuous
. The function, makepanel
, is a wrapper function of the above mentioned functions.
makepanel
is a wrapper function that outputs a legend, an association table and the panelmap, all with one command. You need to provide the meta information of your data set like, colors, data type, labels color etc.
We will use mtcars
data set to illustrate the usage of panelmap.
See below an example of panelmap
.
We will illustrate panlemap by sorting mtcars data according to variable cyl
and plotting mpg, vs, am
and gear
to understand the relationship between them.
#sort everything by cyl
mtcars.sort = mtcars[order(mtcars$cyl),]
#otehr features to plot
mat = mtcars.sort[,c("mpg","vs","am","gear")]
#color assigned to each feature
mat.col=list(am=c("white","black"), vs=c("white","black"), gear=c("yellow","orange","brown"), mpg=c("white", "darkred"))
#type of each feature. type=1 for discrete and type=2 for continuous.
mat.type= c(2,1,1,1)
tab=makepanel(gr=mtcars.sort$cyl, gr.name="cyl",gr.col=c("red","blue","green"), mat=mat, mat.col=mat.col, mat.type=mat.type, border=TRUE, legend=TRUE, get.pval=TRUE)
## Performing Kruskal-Wallis test
## Performing Fisher's Exact test
## Performing Fisher's Exact test
## Performing Fisher's Exact test
One can see, how all the variables align with vehicles with 4,6 and 8 cylinder engines, all at a single glance!
vs
- Binary variable signaling the engine cylinder configuration a V-shape (vs=0) or Straight Line (vs=1). V
am
- A binary variable signaling whether vehicle has automatic (am=0) or manual (am=1) transmission configuration.
| 4 | 6 | 8 | RowTotal | pval | |
|---|---|---|---|---|---|
| mpg | 26[21.4-33.9] | 19.7[17.8-21.4] | 15.2[10.4-19.2] | P<0.0001 | |
| NA | 0 | 0 | 0 | ||
| vs | P<0.0001 | ||||
| 0 | 1(9%) | 3(43%) | 14(100%) | 18(56.25%) | |
| 1 | 10(91%) | 4(57%) | 0(0%) | 14(43.75%) | |
| am | 0.0091 | ||||
| 0 | 3(27%) | 4(57%) | 12(86%) | 19(59.38%) | |
| 1 | 8(73%) | 3(43%) | 2(14%) | 13(40.62%) | |
| gear | P<0.0001 | ||||
| 3 | 1(9%) | 2(29%) | 12(86%) | 15(46.88%) | |
| 4 | 8(73%) | 4(57%) | 0(0%) | 12(37.5%) | |
| 5 | 2(18%) | 1(14%) | 2(14%) | 5(15.62%) |
Association table corresponding to panelmap
circomap is a visualizing tool to plot and analyze multiple panelmaps, inspired by the circlize1 package.
To illustrate the functionality of circomap we will draw the above panelmap three times in a circular layout.
#dataset 1
dat1 = mtcars[order(mtcars$cyl),]
#dataset 2
dat2 = mtcars[order(mtcars$cyl),]
#dataset 3
dat3 = mtcars[order(mtcars$cyl),]
#put all the datasets in a list
datasets<-list()
datasets[[1]]=dat1; datasets[[2]]=dat2; datasets[[3]]=dat3
names(datasets) = c("dat1", "dat2", "dat3")
#names of datasets will be used to labek the datasets
#group variable to plot same as panelet_group
gtoplot<-c("cyl")
gcol = c("red","blue","green")
gheight = 0.10 #track height of the group variable
#features to plot - same as in panelmap example
ftoplot<-c("mpg", "vs", "am", "gear")
ftype= c(2,1,1,1)
fcol=list(am=c("white","black"), vs=c("white","black"), gear=c("yellow","orange","brown"), mpg=c("white", "darkred"))
fheight<-list(); fheight[1:length(ftoplot)] = 0.08
#Voila!!
circomap(datasets, gtoplot, gcol, gheight, ftoplot, ftype, fcol, fheight)


--- layout: mocks title: Follows --- Here's everything you follow 👂🏿 Choice Card 🧐 Which of the following topics does electronic music not cover? ✂ Cut Subject 📖 Electronic Music ✂ Cut Choice Card 🧐 What is tape music? ✂ Cut 🏡 Dashboard 🔔 Notices 👂🏿 Follows 🛠 Settings 👋🏾 Log out


This is an R package for rendering parameterized SQL, and translating it to different SQL dialects. SqlRender can also be used as a stand-alone Java library and a command-line executable.
This exampe shows the use of parameters, as well as SqlRender’s {if} ? {then} : {else} syntax:
sql <- renderSql("SELECT * FROM @a; {@b != ''}?{USE @b;}", a = "my_table", b = "my_schema")$sql
will produce the variable sql
containing this value:
"SELECT * FROM my_table; USE my_schema;"
subsequently running this code
sql <- translateSql(sql, "sql server", "oracle")$sql
will produce the variable sql
containing this value:
"SELECT * FROM my_table; ALTER SESSION SET current_schema = my_schema;"
The SqlRender package is an R package wrapped around a Java library. The rJava package is used as interface.
The Java library is available as a JAR file.
Running the package requires R with the package rJava installed. Also requires Java 1.6 or higher.
In R, use the following commands to install the latest stable version from CRAN:
install.packages("SqlRender")
To install the latest development version directly from GitHub, use:
install.packages("devtools")
library(devtools)
install_github("ohdsi/SqlRender")
Once installed, you can try out SqlRender in a Shiny app that comes with the package:
library(SqlRender)
launchSqlRenderDeveloper()
You can fetch the JAR file in the inst/java folder of this repository, or use Maven:
First add the SqlRender repository so that maven can find and download the SqlRender artifact automatically:
<repositories>
<repository>
<id>ohdsi</id>
<name>repo.ohdsi.org</name>
<url>http://repo.ohdsi.org:8085/nexus/content/repositories/releases</url>
</repository>
<repository>
<id>ohdsi.snapshots</id>
<name>repo.ohdsi.org-snapshots</name>
<url>http://repo.ohdsi.org:8085/nexus/content/repositories/snapshots</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
2: Include the SqlRender dependency in your pom.xml
<dependency>
<groupId>org.ohdsi.sql</groupId>
<artifactId>SqlRender</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
Apache License 2.0


#include <AcknowledgePdu.h>
Public Member Functions | |
| AcknowledgePdu () | |
| virtual | ~AcknowledgePdu () |
| virtual void | marshal (DataStream &dataStream) const |
| virtual void | unmarshal (DataStream &dataStream) |
| unsigned short | getAcknowledgeFlag () const |
| void | setAcknowledgeFlag (unsigned short pX) |
| unsigned short | getResponseFlag () const |
| void | setResponseFlag (unsigned short pX) |
| unsigned int | getRequestID () const |
| void | setRequestID (unsigned int pX) |
| virtual int | getMarshalledSize () const |
| bool | operator== (const AcknowledgePdu &rhs) const |
Protected Attributes | |
| unsigned short | _acknowledgeFlag |
| unsigned short | _responseFlag |
| unsigned int | _requestID |
Copyright (c) 2007-2009, MOVES Institute, Naval Postgraduate School. All rights reserved.
| AcknowledgePdu::AcknowledgePdu | ( | ) |
| AcknowledgePdu::~AcknowledgePdu | ( | ) | [virtual] |
| unsigned short AcknowledgePdu::getAcknowledgeFlag | ( | ) | const |
| int AcknowledgePdu::getMarshalledSize | ( | ) | const [virtual] |
Reimplemented from DIS::SimulationManagementFamilyPdu.
| unsigned int AcknowledgePdu::getRequestID | ( | ) | const |
| unsigned short AcknowledgePdu::getResponseFlag | ( | ) | const |
| void AcknowledgePdu::marshal | ( | DataStream & | dataStream | ) | const [virtual] |
Reimplemented from DIS::SimulationManagementFamilyPdu.
| bool AcknowledgePdu::operator== | ( | const AcknowledgePdu & | rhs | ) | const |
| void AcknowledgePdu::setAcknowledgeFlag | ( | unsigned short | pX | ) |
| void AcknowledgePdu::setRequestID | ( | unsigned int | pX | ) |
| void AcknowledgePdu::setResponseFlag | ( | unsigned short | pX | ) |
| void AcknowledgePdu::unmarshal | ( | DataStream & | dataStream | ) | [virtual] |
Reimplemented from DIS::SimulationManagementFamilyPdu.
unsigned short DIS::AcknowledgePdu::_acknowledgeFlag [protected] |
type of message being acknowledged
unsigned int DIS::AcknowledgePdu::_requestID [protected] |
Request ID that is unique
unsigned short DIS::AcknowledgePdu::_responseFlag [protected] |
Whether or not the receiving entity was able to comply with the request


skyux watch runs the test command and watches the file system for changes. The watch command monitors changes in much the same way as the serve command, but for testing, the watch command is always running, much like debug mode in Visual Studio. If you change a test, the window is watching that and runs the test.  The skyux watch command also runs the TSLint static analysis tool to check the TypeScript code in the files in the src folder.
Options


|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: INNER | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Object | +--org.apache.velocity.runtime.resource.ResourceManagerImpl
Class to manage the text resource for the Velocity Runtime.
| Field Summary | |
protected ResourceCache |
globalCache
Object implementing ResourceCache to be our resource manager's Resource cache. |
private boolean |
logWhenFound
switch to turn off log notice when a resource is found for the first time. |
static int |
RESOURCE_CONTENT
A static content resource. |
private static java.lang.String |
RESOURCE_LOADER_IDENTIFIER
token used to identify the loader internally |
static int |
RESOURCE_TEMPLATE
A template resources. |
private boolean |
resourceLoaderInitializersActive
Each loader needs a configuration object for its initialization, this flags keeps track of whether or not the configuration objects have been created for the resource loaders. |
protected java.util.ArrayList |
resourceLoaders
The List of templateLoaders that the Runtime will use to locate the InputStream source of a template. |
protected RuntimeServices |
rsvc
|
private java.util.ArrayList |
sourceInitializerList
This is a list of the template input stream source initializers, basically properties for a particular template stream source. |
private java.util.Hashtable |
sourceInitializerMap
This is a map of public name of the template stream source to it's initializer. |
| Constructor Summary | |
ResourceManagerImpl()
|
| Method Summary | |
private void |
assembleResourceLoaderInitializers()
This will produce a List of Hashtables, each hashtable contains the intialization info for a particular resource loader. |
java.lang.String |
getLoaderNameForResource(java.lang.String resourceName)
Determines is a template exists, and returns name of the loader that provides it. |
Resource |
getResource(java.lang.String resourceName,
int resourceType)
Deprecated. Use getResource(String resourceName, int resourceType,
String encoding ) |
Resource |
getResource(java.lang.String resourceName,
int resourceType,
java.lang.String encoding)
Gets the named resource. |
void |
initialize(RuntimeServices rs)
Initialize the ResourceManager. |
protected Resource |
loadResource(java.lang.String resourceName,
int resourceType,
java.lang.String encoding)
Loads a resource from the current set of resource loaders |
protected void |
refreshResource(Resource resource,
java.lang.String encoding)
Takes an existing resource, and 'refreshes' it. |
| Methods inherited from class java.lang.Object |
|
| Field Detail |
public static final int RESOURCE_TEMPLATE
public static final int RESOURCE_CONTENT
private static final java.lang.String RESOURCE_LOADER_IDENTIFIER
protected ResourceCache globalCache
protected java.util.ArrayList resourceLoaders
private java.util.ArrayList sourceInitializerList
private java.util.Hashtable sourceInitializerMap
private boolean resourceLoaderInitializersActive
private boolean logWhenFound
protected RuntimeServices rsvc
| Constructor Detail |
public ResourceManagerImpl()
| Method Detail |
public void initialize(RuntimeServices rs) throws java.lang.Exception
initialize
in interface ResourceManager
private void assembleResourceLoaderInitializers()
public Resource getResource(java.lang.String resourceName, int resourceType, java.lang.String encoding) throws ResourceNotFoundException, ParseErrorException, java.lang.Exception
Template
to RESOURCE_TEMPLATE
).getResource
in interface ResourceManager
resourceName
- The name of the resource to retrieve.resourceType
- The type of resource (RESOURCE_TEMPLATE
,
RESOURCE_CONTENT
, etc.).encoding
- The character encoding to use.ResourceNotFoundException
- if template not found
from any available source.ParseErrorException
- if template cannot be parsed due
to syntax (or other) error.java.lang.Exception
- if a problem in parseprotected Resource loadResource(java.lang.String resourceName, int resourceType, java.lang.String encoding) throws ResourceNotFoundException, ParseErrorException, java.lang.Exception
resourceName
- The name of the resource to retrieve.resourceType
- The type of resource (RESOURCE_TEMPLATE
,
RESOURCE_CONTENT
, etc.).encoding
- The character encoding to use.ResourceNotFoundException
- if template not found
from any available source.ParseErrorException
- if template cannot be parsed due
to syntax (or other) error.java.lang.Exception
- if a problem in parseprotected void refreshResource(Resource resource, java.lang.String encoding) throws ResourceNotFoundException, ParseErrorException, java.lang.Exception
resource
- resource to refreshResourceNotFoundException
- if template not found
from current source for this ResourceParseErrorException
- if template cannot be parsed due
to syntax (or other) error.java.lang.Exception
- if a problem in parsepublic Resource getResource(java.lang.String resourceName, int resourceType) throws ResourceNotFoundException, ParseErrorException, java.lang.Exception
getResource(String resourceName, int resourceType,
String encoding )
Template
to RESOURCE_TEMPLATE
).resourceName
- The name of the resource to retrieve.resourceType
- The type of resource (RESOURCE_TEMPLATE
,
RESOURCE_CONTENT
, etc.).ResourceNotFoundException
- if template not found
from any available source.ParseErrorException
- if template cannot be parsed due
to syntax (or other) error.java.lang.Exception
- if a problem in parsepublic java.lang.String getLoaderNameForResource(java.lang.String resourceName)
getLoaderNameForResource
in interface ResourceManager
resourceName
- Name of template or content resource
|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: INNER | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |


Preparation time
30 mins to 1 hour
Cooking time
over 2 hours
Serves
Serves 8
This rich fruit pudding is a classic Scottish dessert, serve with clotted cream and a dram of whisky.
Sift the flour, bicarbonate of soda, spices and salt into a bowl and stir in the sugar, suet, dried fruits, and the grated carrot or apple.
Mix the black treacle with the egg and some of the buttermilk and mix into the dry ingredients to give soft mixture with a cake-like dropping consistency.
 Lay it out on a surface and sprinkle a 30cm/12in circle in the centre with the 25g/1oz of flour and the 1 tbsp of caster sugar. Spoon pudding mixture on top and tie securely with string, leaving a little room for the pudding to expand.
Rest a large heatproof trivet or container in the base of a large pan so that the pudding is not in direct contact with the heat. Place the pudding on the trivet/container, knotted side up. Pour in enough water almost to cover the pudding, cover with a tight-fitting lid and simmer gently for 3-4 hours. Take a peek every now and then and then to check the water level and top it up if necessary.
Preheat the oven to 180C/350F/Gas 4. Lift the pudding out of the pan and dip it briefly in a bowl of cold water (to ensure that the outside of the pudding does not stick to an ovenproof serving plate). Then remove remove the cloth and place the pudding on an ovenproof dish/plate. Slide it into the oven and leave it for 15 minutes until the outside of the pudding has dried off.
Serve in chunky wedges with scoops of clotted cream and perhaps a small glass of whisky.


Hi {{name}},
A new request has been submitted #{{requestId}} by {{updater}}. Log in to OCWA to see more


| Sunday | Monday | Tuesday | Wednesday | Thursday | Friday | Saturday |
|---|---|---|---|---|---|---|
8:30am-8:00pm |
8:00am-10:00pm |
8:00am-10:00pm |
8:00am-10:00pm |
8:00am-10:00pm |
8:00am-10:00pm |
8:00am-10:00pm |
| Phone Number |<PHONE_NUMBER> |
|---|---|
| Fax |<PHONE_NUMBER> |
<EMAIL_ADDRESS>|
|
| Address | 12345 Snow Rd. Government Camp OR, 97028 |


{% assign conferences_grouped_by_year = sorted_conferences | group_by_exp:"conference", "conference.date_start | date: '%Y'" %} {% for conferences_by_year in conferences_grouped_by_year %}


This library adds functions for using the Parallax LCD Display These functions convert the byte code data into functions for easy reference.
More...
#include "simpletools.h"
Go to the source code of this file.
|
| void | Lcd_Open (char Tx, int Baud) |
| | Open a Connection to the LCD Display. More...
|
| |
| void | Lcd_PosCursor (int Col, int Row) |
| | Position cursor on the LCD display. More...
|
| |
| void | Lcd_PlayNote (int Note, int Length) |
| | Play a note form A to G for a given length of time. More...
|
| |
|
void | Lcd_Clr (void) |
| | Clear the LCD display and place the cursor at 0,0 with underline.
|
| |
| void | Lcd_Set (int On, int Cursor, int Blink) |
| | Set LCD display to turn display on/off, Cursor on/off, and Blink on/off. More...
|
| |
| void | Lcd_BackLight (int OnOff) |
| | Turn LCD backlight on or off. More...
|
| |
| void | Lcd_Chars (char *String) |
| | Send a set of characters to the LCD display. More...
|
| |
| void | Lcd_Char (char c) |
| | Send a single character to the LCD display. More...
|
| |
|
void | Lcd_Close (void) |
| | Close Connection to the LCD Display.
|
| |
This library adds functions for using the Parallax LCD Display These functions convert the byte code data into functions for easy reference.
- Author
- Michael Burmeister
- Date
- January 15, 2015
◆ Lcd_BackLight()
| void Lcd_BackLight |
( |
int |
OnOff | ) |
|
Turn LCD backlight on or off.
- Parameters
-
| OnOff | Turns Backlight on/off (0/1). |
◆ Lcd_Char()
Send a single character to the LCD display.
- Parameters
-
| c | Character to display on LCD |
◆ Lcd_Chars()
| void Lcd_Chars |
( |
char * |
String | ) |
|
Send a set of characters to the LCD display.
- Parameters
-
| String | Character string to display on LCD null terminated |
◆ Lcd_Open()
| void Lcd_Open |
( |
char |
Tx, |
|
|
int |
Baud |
|
) |
| |
Open a Connection to the LCD Display.
- Parameters
-
| Tx | Transmitt data Pin. |
| Baud | Baud rate of LCD Display |
◆ Lcd_PlayNote()
| void Lcd_PlayNote |
( |
int |
Note, |
|
|
int |
Length |
|
) |
| |
Play a note form A to G for a given length of time.
- Parameters
-
| Note | Note to play from 0 to 6 |
| Length | Length of time to play note 64 - full |
◆ Lcd_PosCursor()
| void Lcd_PosCursor |
( |
int |
Col, |
|
|
int |
Row |
|
) |
| |
Position cursor on the LCD display.
- Parameters
-
| Col | Column number from 0 |
| Row | Row number from 0 |
◆ Lcd_Set()
| void Lcd_Set |
( |
int |
On, |
|
|
int |
Cursor, |
|
|
int |
Blink |
|
) |
| |
Set LCD display to turn display on/off, Cursor on/off, and Blink on/off.
- Parameters
-
| On | Turns the LCD Display On or Off |
| Cursor | Set the Cursor Character On or Off |
| Blink | Set the Cursor Character to Blink |


--- layout: post esbma_id: 3034 title: An hour with FAKEGRIMLOCK date: 2013-09-03 12:00:00 ---
I recently had the privilege of speaking for an hour or so with FAKEGRIMLOCK. I received this "GRIMSULTATION" when I helped fund his book project on Kickstarter. It looks like you can now buy your own grimsultation (or a copy of the book) on his online store.
He answers the call in his character voice, which was, well, awesome.  He's right, an hour would have been too much, but I wouldn't have complained if I had gotten 30 seconds of the voice instead of 3 seconds.
Basically, I spent the hour describing and inviting his feedback on our strategy for Zumero, our mobile database sync stuff.
(Since launching Zumero's "Minimum Viable Product" six months ago, we've been iterating fast. Feedback from these early customer interactions is helping us figure out what Zumero should be, not just where it needs to be polished. I figure if "lean" is only about bug-fixing and feature requests, it should probably be called "beta". Anyway, as we finish our conclusions about which Zumero use cases deserve our focus, I'll write more specifics. For now, this blog entry is mostly just to admit that I'm a FAKEGRIMLOCK fanboy.)
Processing these issues with FG was an entirely pleasant conversation. During my 25 years in this industry I have been fortunate to interact with plenty of very sharp people. FAKEGRIMLOCK is somewhere in the top five.
His primary background is technical (as is mine). I described our product and he understood it immediately. I could discuss issues which require deep technology understanding without the need to explain anything to him.
At the same time, his range is incredible. I have been told that my discernment and judgment on business issues are unusually good (for a nerd), but I think this guy is a lot sharper than I am. He seemed to easily see some stuff that we've spent months trying to figure out.
FG is one of those rare people who really understands the importance of context. Tactic X can be a great idea for startup A while simultaneously being a terrible idea for startup B, because A and B are in different situations. It's much more common to encounter someone who once used tactic X successfully and now recommends it as the right move for everyone. I suspect FG's high cluefulness proceeds from a background that includes multiple successes and failures in a variety of contexts.
My favorite part of the call was his rant about "the myth that people want simple products". FG claims (my paraphrasing) that what people actually want is products that seem simple, but which have the depth to meet more needs as the user gets further in. Shallow products don't win. Products win when they have power but hide it.
The whole secret identity thing is just a lot of fun. Almost nobody knows who FAKEGRIMLOCK actually is. I don't. By day he works at a startup company. His coworkers have no idea that he is FAKEGRIMLOCK.
He says he is located in Washington DC. At this point, I'm guessing that is misdirection, and actually DC is the one place we know he is not. :-)
There are some people with whom FG interacts as both Bruce Wayne AND as Batman, and they haven't figured it out.
So cool.
Maybe someday he will reveal his human identity. I'll admit that I'm curious.
Unless FAKEGRIMLOCK is actually Ben Affleck, in which case, I really don't wanna know.


ABOUT ME
ABOUT ME
ABOUT ME
ABOUT ME
ABOUT ME
ABOUT ME
ABOUT ME
ABOUT ME
ABOUT ME
As a graphic designer I utilize my creativity, imagination and skill set to transform brands into effective designs. My philosophy is to explore different ways of successfully communicating the mission and identity of the brand, benefiting from the chance to grow from these collaborative experiences. It is from this viewpoint that I make my designs eye-catching and impactful.
I am a Junior at Portland State University majoring in Graphic Design. Over the years, I have absorbed many skills from professionals in the industry, spanning from a large array of tools for a designer, with an awareness of appropriate designs, and effective communication. Throughout my education, I have collaborated with my peers thus strengthening my ability to work effectively as a team, and learning from the experience and perspective of others.
Deep understanding of the design process for word webs, mind maps, moodboards, concept sketches, art styles, color palettes, type studies, hand lettering, and more.
Utilizing HTML, CSS, Jquery, Sublime Text, along with constructing wireframes in Adobe XD to create websites.
Strong grasp of type treatment including picking appropriate typefaces, and adjusting them to achieve design goals.
Knowledgable on design appropriate aesthetics and how to digitally replicate them for design directions.
I am currently available for selective consulting opportunities. Would love to collaborate with creatives and brands who are passionate about their vision and ambitious about their impact.


Introduction on Developing Activity Implementor
The following steps are needed to define an activity implementor:
- Create an implementor Java or Kotlin class
- Using MDW Studio, add the implementor to the tool panel
Create Implementor Class
The main requirement for an activity implementor class that extends
com.centurylink.mdw.workflow.activity.DefaultActivityImpl
,
or one of its subclasses, built-in or user defined. It is more common to extend
a built-in implementor class, and for adapter, task, event wait, timer wait,
synchronization activities, it is almost impossible not to start from the built-in
activities. The rest of this document covers how to implement activity
implementor from the base activity and common tasks for new implementors,
please refer to corresponding documentation when extending from a built-in activity
implementor.
There is really only one method that must be implemented by an activity
implementor:
- public Object execute(ActivityRuntimeContext runtimeContext) throws ActivityException
- The code logic to execute this activity. The default implementation does
nothing.
Additionally, you can implement the following trace annotation
- @Tracked(LogLevel.TRACE)
- You can apply this annotation to your implementor class to automatically track timings for activity lifecycle stages.
With the annotation applied, timings will be logged as follows if logging is turned on at the specified level for your implementation class.
[(t)20100105.13:40:05.232 p12370.63065 a12416.14985] ScriptExecuterActivity Get Activity Impl Instance: 0.02 ms
[(t)20100105.13:40:05.232 p12370.63065 a12416.14985] ScriptExecuterActivity Prepare Activity: 0.0040 ms
[(t)20100105.13:40:07.045 p12370.63065 a12416.14985] ScriptExecuterActivity Execute Activity: 1789.761 ms
[(t)20100105.13:40:07.123 p12370.63065 a12416.14985] ScriptExecuterActivity Finish Activity: 77.64 ms
If the implementor needs a constructor, it must have one taking no argument,
and it should always invoke the base constructor first.
In a later section, we summarize all methods that are defined in the base
class and can be used in your implementor. You should only use these methods,
and IntelliJ/Eclipse make it easy to find out what methods are available.
Additional notes:
- Do not reference to variables by their names directly, use attributes to get their names instead.
In this way, your implementor can easily be reused in a different place, as
variable names can be configured at design time.
- Use getAttributeValue, so that attribute value
can resolve binding expressions with dynamic runtime values in addition to static text.
- If you extend some subclasses, you may need to override some of the specific methods used by base implementation of execute(), instead. For activities implementing SuspendibleActivity,
you will need to implement resume(), or override it from an existing implementor implementing the activity interface.
- Use setReturnCode() to set return code (default null). You can also set it to
ABORT:
,
CORRECT:
, DELAY:
, ABORT:mycode
, etc.
Do not set it to ERROR:
throw exception instead.
Pagelet
The configurator Design tab for an activity in MDW Studio requires instructions
on the configurable attributes to display. This is achieved through a pagelet definition, which is
a JSON string stored as an attribute of the implementor.
As an example, the pagelet for Expression Evaluator
activity implementor looks like:
{"widgets": [
{
"default": "Groovy",
"label": "Language",
"name": "SCRIPT",
"options": [
"Groovy",
"javax.el",
"Kotlin Script",
"JavaScript"
],
"type": "dropdown"
},
{
"languages": "Groovy,javax.el,Kotlin Script,JavaScript",
"name": "Expression",
"type": "expression"
}
]}
The pagelet description follows a simple syntax:
- Each first level child object defines a widget ,
typically representing an attribute configurable in the activity.
- Each first level child object has a set of properties
for common things like the size and location of the widget
The following table lists all supported properties of widgets.
| Property | Description |
| name | Name of the activity attribute. This is required
if the widget describes an activity attribute. |
| label | Label shown on the dialog. If this is missing,
then NAME is used as the label |
| lx | X coordinate of the label. If this is not present,
the location will be automatically computed. |
| ly | Y coordinate of the label. If this is not present,
the location will be automatically computed. |
| lw | Width of the label. The default
is 160 (pixels) if this is not present |
| vx | X coordinate of the value area. If this is not present,
the location will be automatically computed. |
| vy | Y coordinate of the value area. If this is not present,
the location will be automatically computed. |
| vw | Width of the value area. If this is not present,
the width of the input area takes a default value specific
to each widget type. |
| vh | Height of the value area. If this is not present,
the height of the input area takes a default value specific
to each widget type. |
Here are the supported widget types.
- text
- A general text input field. There is no nested element. An
additional attribute SIZE is used to specify the maximum
number of characters allowed in the text input field
- rule
- A text input area for scripting languages. There is no nested element.
- list
- This widget allows to set attribute is a list of values, separated
by "#". The attribute DELIMITER can be used to change
the delimiter.
- dropdown
- This displays a group of radio buttons
for the user to select from one value
out of a list. The list of candidate values are specified
by child elements OPTION, one for each option.
- note
- This simply generates some static text, typically for
instructions. The actual text to display is included
as the contents of the tag.
- link
- This generates a hyper link to a URL. The URL is specified
in the attribute "URL" and the content of the tag
will be displayed as a hyper link.
- mapping
- This is used to specify parameter mappings for process
invocation activities. It displays a table of formal parameters
needed by the subprocess and allows user to specify actual
parameters. No nested elements and no additional attributes
are supported by this widget.
- table
- to be completed
Configure the Implementor via Annotations
Your implementors must contain the @Activity annotation to be used.
These attributes are supported:
categoryOne of the following category classes:
- GeneralActivity - Basic activity for programmatic logic.
- EventWaitActivity - Wait for some event to occur.
- StartActivity.
- FinishActivity.
- SynchronizationActivity - Wait for multiple upstream activities to complete.
- InvokeProcessActivity - Launch a subflow with variable bindings.
- TaskActivity - Manual task activity.
- ScriptActivity - Invoke Kotlin, Groovy, or other supported script.
valueThis is the label displayed in the MDW Studio and MDWHub toolbox.
iconAsset path for the icon to display in the toolbox.
pageletPagelet definition as described above.
API For Implementing Implementor
The base class DefaultActivityImpl
contains methods (API) for
assisting your implementations. Please refer to its java doc (following
above hyperlink, or through IntelliJ/Eclipse IDE) for detailed description of the methods.
Implementing Adapter Activity Implementers
Although the framework is packaged with quite a few
customizable adapter activities, it cannot be possible to cover all
needs and hence you will likely need to define an adapter activity
yourself. There are two primary ways to do this.
The first is to extend a built-in adapter. Refer to the documentation
of that adapter for how to do that.
The second is to extend the base adapter activity class,
AdapterActivityBase
, which is an abstract class.
Follow this link for the detailed documentation for the usage of this class.


|
| Value |
Description |
Notes |
|
| 01 |
Front cover |
|
| 02 |
Back cover |
|
| 03 |
Cover / pack |
Not limited to front or back. |
| 04 |
Contributor picture |
Photograph or portrait of contributor(s). |
| 05 |
Series image / artwork |
|
| 06 |
Series logo |
|
| 07 |
Product image / artwork |
|
| 08 |
Product logo |
|
| 09 |
Publisher logo |
|
| 10 |
Imprint logo |
|
| 11 |
Contributor interview |
|
| 12 |
Contributor presentation |
Contributor presentation and/or commentary. |
| 13 |
Contributor reading |
|
| 14 |
Contributor event schedule |
Link to a schedule in iCalendar format. |
| 15 |
Sample content |
For example: sample chapter text, page images, screenshots. |
| 16 |
Widget |
A ‘look inside’ feature presented as a small embeddable application. |
| 17 |
Review |
Use the <TextContent> composite for review quotes carried in the ONIX record. Use the <CitedContent> composite for a third-party
review which is referenced from the ONIX record. Use <SupportingResource> only for a review which is offered for reproduction
as part of promotional material for the product.
|
| 18 |
Other commentary / discussion |
|
| 19 |
Reading group guide |
|
| 20 |
Teacher’s guide |
|
| 21 |
Feature article |
Feature article provided by publisher. |
| 22 |
Character ‘interview’ |
Fictional character ‘interview’. |
| 23 |
Wallpaper / screensaver |
|
| 24 |
Press release |
|
| 25 |
Table of contents |
A table of contents held on a webpage, not in the ONIX record. |
| 26 |
Trailer |
A promotional video, similar to a movie trailer (sometimes referred to as a ‘book trailer’). |
| 27 |
Cover thumbnail |
Intended ONLY for transitional use, where ONIX 2.1 records referencing existing thumbnail assets of unknown pixel size are
being re-expressed in ONIX 3.0. Use code 01 for all new cover assets, and where the pixel size of older assets is known.
|
| 28 |
Full content |
The full content of the product (or the product itself), supplied for example to support full-text search. |
| 29 |
Full cover |
Includes cover, back cover, spine and – where appropriate – any flaps. |
| 30 |
Master brand logo |
|
|


<#include "../banner.include.html">
>
Home
Registered datasets
<#if message??>
${message}
#if> <#list datasetsViews as ds>
${ds.title}
${ds.organization}
${ds.type}
more details...
#list>
<#if running??>
Tasks in execution:
${running}
#if>
<#include "../footer.include.html">


{{template "header.html" .Header}}
Please enter the activation code you received in the signup e-mail.


MENTOR MATCHES
Select the mentors you would like to chat with
Dr. Allison J. Morgan
Professor
An assistant professor of Information Systems and Decision Sciences.
Dr. Allison J. Morgan
Dr. Legand Burge
Dept Chair
Develops and deploys large scale distributed systems and is a strong advocate for student entrepreneurship and innovation.
Dr. Legand Burge
Lynn Cooper
Entrepreneur
Specializes in training,coaching and developing effective digital strategies for academic, government, corporate and nonprofit entities.
Lynn Cooper
Grant M. Warner, Ph.D.
Director
The Director of Innovation and Entrepreneurship at Howard University and the Managing director at HowU Innovate Lab
Grant M. Warner, Ph.D.
Lauren Burton
Developer
Passionate about using technology for change and innovation.
Lauren Burton
Derek Lloyd
CTO consultent
Has served as Technical Moderator for Congresswoman Eddie-Bernice Johnson of Texas and is on the Board of the Malcolm X Dr. Betty Shabazz Education Center.
Derek Lloyd
Julie Diaz-Asper
Entrepreneur
Has spent more than two decades helping large organizations including American Express, Booz Allen and AARP innovate and pursue new market opportunities.
Julie Diaz-Asper
John J. Bienko
Director
Serves as an advocate for entrepreneurial development through a variety of management and technical assistance programs and services designed for small business success.
John J. Bienko


labeled
by None at 2021-03-04 14:42:19.labeled
by None at 2021-03-04 14:42:35.mentioned
by Trey Pendragon at 2021-03-04 16:11:28.subscribed
by Trey Pendragon at 2021-03-04 16:11:28.review_requested
by None at 2021-03-04 16:11:34.referenced
by None at 2021-03-04 18:05:44.merged
by None at 2021-03-04 18:05:44.closed
by None at 2021-03-04 18:05:44.head_ref_deleted
by None at 2021-03-04 18:05:45.labeled
by None at 2021-03-04 14:41:41.labeled
by None at 2021-03-04 14:41:58.labeled
by None at 2021-03-04 14:41:58.head_ref_force_pushed
by None at 2021-03-04 17:05:00.head_ref_force_pushed
by None at 2021-03-04 18:40:40.mentioned
by Kevin Reiss at 2021-03-04 18:49:04.subscribed
by Kevin Reiss at 2021-03-04 18:49:04.closed
by None at 2021-03-04 22:11:27.@hackartisan what's the best way to manage the bulk updating of the location flags mapped to their new alma location codes in the bibdata alma environment? I will also add the two locations need for processing scsb records, scsbnypl and scsbcul, to the data.
mentioned
by None at 2021-03-04 23:27:11.subscribed
by None at 2021-03-04 23:27:11.referenced
by Esmé Cowles at 2021-03-03 22:01:46.merged
by Esmé Cowles at 2021-03-03 22:01:46.closed
by Esmé Cowles at 2021-03-03 22:01:46.head_ref_deleted
by Esmé Cowles at 2021-03-03 22:01:47.review_requested
by Cliff Wulfman at 2021-03-04 19:41:53.review_dismissed
by Cliff Wulfman at 2021-03-04 21:09:17.referenced
by Esmé Cowles at 2021-03-04 21:39:12.merged
by Esmé Cowles at 2021-03-04 21:39:12.closed
by Esmé Cowles at 2021-03-04 21:39:12.head_ref_deleted
by Esmé Cowles at 2021-03-04 21:39:13.head_ref_force_pushed
by Francis Kayiwa at 2021-03-04 14:04:06.head_ref_force_pushed
by Francis Kayiwa at 2021-03-04 14:10:31.referenced
by Francis Kayiwa at 2021-03-04 20:23:57.merged
by Francis Kayiwa at 2021-03-04 20:23:57.closed
by Francis Kayiwa at 2021-03-04 20:23:58.head_ref_deleted
by Francis Kayiwa at 2021-03-04 20:23:58.milestoned
by None at 2021-03-03 22:32:11.Yup, you can close this. Thanks.
closed
by Trey Pendragon at 2021-03-03 22:44:30.closed
by Christina Chortaria at 2021-03-04 01:19:54.referenced
by Christina Chortaria at 2021-03-04 01:19:54.merged
by Christina Chortaria at 2021-03-04 01:19:54.closed
by Christina Chortaria at 2021-03-04 01:19:54.head_ref_deleted
by Christina Chortaria at 2021-03-04 01:19:55.referenced
by Christina Chortaria at 2021-03-04 01:21:47.merged
by Christina Chortaria at 2021-03-04 01:21:47.closed
by Christina Chortaria at 2021-03-04 01:21:48.head_ref_deleted
by Christina Chortaria at 2021-03-04 01:21:48.assigned
by Trey Pendragon at 2021-03-03 23:14:28.referenced
by Trey Pendragon at 2021-03-03 23:15:04.closed
by Christina Chortaria at 2021-03-04 01:21:48.closed
by Shaun Ellis at 2021-03-04 20:04:10.@ccleeton since I will be away next week, here is an attempt to tighten this up for the switch over. Let me know what you think. Totally open to rewording, would like to aim for this length. I'm trying to think of the most succinct way to get users the critical info.
I left out the "feedback" link because we don't have one yet. I also think there are much better places for a feedback call to action. Let's address that when we are ready.
I have asked Sara for an edit to the Mudd one but I might not hear back until tomorrow on that one. We do need to link out from that to this - https://library.princeton.edu/special-collections/policies/access-mudd-library-during-renovation That she will want for sure.
I am also asking if we can remove the covid one completely. I will let you know.
mentioned
by Christa Cleeton at 2021-03-04 21:31:00.subscribed
by Christa Cleeton at 2021-03-04 21:31:00.@tpendragon I think this is ready for review, tests, and/or further discussion. I had to remove the ChildTable from the Collection Overview tab pane as it was rendering the table twice in the DOM and creating id collisions. (Pulfa 2.0 does not have this on the Collection Overview screen.)
This is great work! A small bug I noticed is container info doesn't seem to be propagating via the button. I need to add some tests to the builder, do you want me to pick up from here?
Converted back to draft - we're going to have to do this via some sort of ajax for cases like https://pulfalight-staging.princeton.edu/catalog/RBD1-1_c18905, where there's hundreds of or thousands of child components.
This ajax method works, but loading the one above takes -several- minutes, and when it finally loads the page basically crashes while it tries to render the DOM. I'm gonna call it a night, we should talk about this.
mentioned
by Trey Pendragon at 2021-03-04 16:12:39.subscribed
by Trey Pendragon at 2021-03-04 16:12:39.unassigned
by Shaun Ellis at 2021-03-04 19:25:04.assigned
by Trey Pendragon at 2021-03-04 19:25:04.head_ref_force_pushed
by Trey Pendragon at 2021-03-04 23:31:52.ready_for_review
by Trey Pendragon at 2021-03-04 23:37:45.renamed
by Trey Pendragon at 2021-03-04 23:40:00.deployed
by Trey Pendragon at 2021-03-04 23:42:44.deployed
by Trey Pendragon at 2021-03-04 23:46:32.convert_to_draft
by Trey Pendragon at 2021-03-04 23:49:44.deployed
by Trey Pendragon at 2021-03-05 00:40:52.deployed
by Trey Pendragon at 2021-03-05 00:45:14.deployed
by Trey Pendragon at 2021-03-05 01:03:51.head_ref_force_pushed
by None at 2021-03-04 15:36:33.head_ref_force_pushed
by None at 2021-03-04 20:21:46.


|
SACSHelp This guide is designed to assist you in installing, configuring, using, and troubleshooting SACS. Note for Chrome users: mht files do not always display properly in Chrome. To view the guide correctly in Chrome, you may need an MHT viewer extension. Like this one: https://chrome.google.com/webstore/detail/eml-mht-viewer-with-drive/ahbjckdnggnfmchoildeljnilenlkoao |
Contents More than just a job scheduler A brief look at the innards of SACS Server and Container Installation Windows Management Console Installation Web Management Console Installation Configuring the Server and Container Configuring the Windows Management Console Step 2: Deploy the Service App Step 3: Manage the Service Apps on the server View configuration information Service app details, deployment and manipulation SACS.WindowsService.exe.config configuration Manual Windows Management Console Installation SACS.Windows.exe.config configuration Manual Web Management Console Installation Tutorial: Creating a Service App Service App Debugging and Testing “Access Denied” when selecting the Install/Update
option Agent start timeout after 30 seconds Windows Management Console Issues “There was a problem loading the state of the service”
Error “Error Executing GET for resource path…” Error under
logs or on Application window. |
SACS is a centralized Windows service manager. It draws inspiration from Windows Task Scheduler, Windows services, and SQL jobs, combining their concepts into a single package. It is designed to help developers, testers, and support engineers expedite the building, validation, deployment, and maintenance of Windows-like services. The premise of SACS banks on improving the reliability of existing Windows services, drastically cutting down on development time by taking over the boilerplate, peripheral, and ancillary items which are required when setting up a new Windows service. These items include, but are not limited to: allowing multiple instances of the same service on the same system, error logging, notifications, scheduling, and enabling analytics. Although SACS can execute your services at any to-the-minute interval you throw at it, you can just as easily not specify a job schedule and instead have your service remain in an always-on state. This is especially important if your service will contain listeners that don’t need to be on a timer (like a file system watcher or a message queue broker).  First, a Service App (SA) is created. This is the executable that is written in an app-like fashion, with the intention for it to be deployed as a service. These service apps are not restricted to running in SACS – they are plain old .NET console applications with the added feature of being able to send and receive communications that SACS understands. Testing the service app is as simple as running it as a normal console application and providing it with commands in the same way that SACS would instruct it. (See Creating a Service App for more information on what instructions a service app understands). At this point, nothing other than the payload of the service app is developed and tested. No more need to worry about timers, error logging, support emailing… The service app is then deployed to a Service App Container (SAC). These will usually reside on the same server. Service app deployment typically involves manually copying, or using an automated file drop service, to place the service app files on the same server as the SAC and then using a Windows management console to load the service app into the container. The last “S” in SACS is the Server which combines all the components, such as the container, into a cohesive system. Along with the container described above, the server is also made up of a few other core components: SACS Agent – This is the Windows service handler for the server. It controls the starting, stopping, and restarting of SACS as a Windows service (the only Windows service you will need from this point on), including all its components. Scheduler – This manages the timings for all service apps that have been configured to run according to a schedule. The container relies on the scheduler to tell it when to execute service apps. System monitor – When active, this component constantly monitors the health of SACS; keeping track of key CPU and memory metrics across all the service apps hosted in the containers. Communicator – This component is the gate between the server and the various management consoles that communicate with it. Windows 7 / 8 / 10 / Server 2008 R2 / Server 2012 / Server 2012 R2 Microsoft .NET 4.5.1 and above Microsoft SQL Server 2008 R2 and above 200MB free space 4GB Ram Administrator privileges – for installation, changing file/folder access, and configuring ports The setup wizard is the easiest way to get SACS installed onto a target system. All required files and deployment scripts are bundled into the installer so no further downloads are necessary. Only the prerequisite .NET and SQL Server versions are required before proceeding with the setup. To run the wizard, locate and execute the SACS.Setup.exe.
The different Setup stagesThe wizard offers 3 setup stages: 1. Install / Upgrade – For new installations and for upgrading existing installations. Note the version number of the wizard (displayed in the title bar). This represents the version of the system that will potentially be installed onto the target machine. Once this section is complete, the wizard automatically moves to the configure section. 2. Configure – This is used to make any tweaks to the configuration settings of the server and management consoles, as well as deploying any database updates that are required. 3. Uninstall – This will identify any known installs of SACS and delete those instances. Any existing service apps on the machine will remain untouched.
Figure 1: Example of what updates to the server and Windows console would look like Server and Container InstallationInstallation of the server is the main requirement for SACS. The wizard identifies an existing installation by searching for the installed service agent on the target machine. If it can find it, the location of the agent is used and it cannot be changed without first uninstalling the existing instance.
On clicking the “Install Now” or “Update Now” button and passing the prompt checks, the following will take place: 1. The service will be stopped automatically if it is already installed. It will not be started again from within the wizard – use a Windows management console to start the service again. 2. Existing files will be backed up into a zip file called SACS.WindowsService <date>.zip. 3. The file version from the installer will be copied over to the destination, ignoring any custom configuration files. 4. Once installed, the entire section will be disabled and an Installation Complete message will be displayed. This section of the installation can be skipped for any reason. To do so, check “skip this part”. This will disable the section and no further actions are possible. Windows Management Console InstallationThe setup wizard will first search for an existing installation of the console by checking the start programs for a shortcut that references an existing Windows management console executable. If it finds an existing location, that will be used for installations and cannot be changed without first removing the shortcut or uninstalling the existing management console. Worth noting is that locations containing existing Windows management console files can be used. You will be prompted that the files will be upgraded in this location and will be used as the install location. During the installation a shortcut will be added to the start menu programs which allows both ease of access to the console, as well as enables the wizard to locate the primary Windows management console installation. As with the server and container installation, this section of the installation can be skipped for any reason.
Web Management Console InstallationComing soon. Configuring the Server and Container
Figure 2: The configuration screen for the server and container. The server and container configuration is broken down into 3 sections: 1. Service Account configuration This is the account the SACS server will be starting up as. The refresh button will show any updates to the service’s account. Clicking on “Open Services” will attempt to open the service properties on Windows so that the account can be changed. This does not always work so if the main services window is the only window shown, search for the “SACS – Agent” service and open its properties.
If the database will be installed to a different server, use an account which has limited read/write rights to a SACS database and can also be made as an administrator on the machine with the server. Refer to Troubleshooting SACS if there are any issues starting the service. 2. Database deployment SACS requires a SQL database in order to start up. A local database file is included with each installation of SACS, however if there are schema changes to the database, or if the database cannot run on the same server as SACS (e.g. if SQL Server is not installed) then this section can be used to install or upgrade the database. Click on “Deploy Scripts” to kick off the database upgrade. 3. Configuration file The App.config section contains
all settings that are modifiable for the server and container. This includes
app settings, connection strings and SMTP settings. Refer to Configuring the Server for any specific
configuration issues.
Configuring the Windows Management Console
Figure 3: Example settings in the Windows Management console configuration The configuration file’s app settings can be updated in the Windows Console tab. When configuring the Windows console, consider the following: 1. The Alternate Log Location can be an absolute or a relative path. The management consoles fundamentally act as shells so even the log files are served from the SACS server. So this setting is used in the case when the server is offline so that the log files are still available.
SACS aims to make getting started with services incredibly easy. This is allows the focus to be turned to what the service will do and not have to consider all the various typical “boilerplate” tasks required to get a service running – since SACS will take care of that for you. Refer to the Service App Development section under Developer Notes for a tutorial on how to create a service app. Once a service app has been developed and tested, it can be deployed to a SACS container (with a default instance residing on the SACS server after installation). Usually the files will sit on the same Windows server so that SACS can easily control the start/stop/execution of the services. A Windows management console is required to deploy a Service App. To deploy a service app: 1. Copy the compiled service app executable and supporting files to the machine with SACS installed. 2. Open a Windows management console on that server configured to point to SACS. 3. The console will make various attempts to contact the server. If the server is offline, start the server and refresh the sections. On successful connection, navigate to the Application Management tab and click on Add. 4. On the right hand side, the details of the service app can be entered, including the name, location and schedule it should run on. 5. Click save. If successful, the service will appear on the left-hand side. The Windows Management Console section contains more detailed instructions on how to deploy a service app. With the service app now deployed to SACS, from here it is possible to start, stop, and run the service app. Every action performed on a service is logged and is available for viewing. Performance data is also saved, although it is not accessible directly from the console and requires a third-party analytics tool to view. Should there be an issue in a service and it crashes during execution, an email will be automatically generated and sent to the support email address defined in the server’s app.config section as per the wizard installation. The Windows management console is the primary means of communicating with a SACS server and provides all of the features required to manage the server and service apps. Its primary features include: 1. Managing the SACS server. This involves: a. Stopping and starting the server (through the SACS agent) b. Accessing the logs which are written to the server c. Viewing the latest live CPU and memory performance graphs of the server d. Viewing the configuration settings that both the server and the console contain 2. Managing service apps by: a. Facilitating the deploying and removal of service apps from the SACS container. b. Editing the deployment details of service apps, from their location, start up type and execution schedule.
Figure 4: Example of the Windows Management Console On opening the Windows management console, the first view will be the “Server Management” tab. The console will make multiple attempts to connect to the server it is configured to connect to. If the server is not running, various error messages will display indicating that there was an issue reaching the server.
Starting the serverClick on the “Start Server” button. This will send a command to the agent to commence the start-up sequence. The console will update with “Start up in progress”. Clicking on the refresh button will fetch the latest status of the start-up process. Bear in mind that it will take upwards of 8 seconds to start the server. Once the server is started, the service apps which were deployed to the container will spin up in sequence. Stopping the server performs the process in reverse and is kicked off by clicking on “Stop Server”. Each service app is given 15 seconds to finalize its processing and exit before it is force-stopped by the server. There are two graphs available on the right-hand side of the Server Management tab: CPU usage and memory usage. The CPU usage graph shows what the total usage of SACS and its service apps are at a point in time. SACS periodically checks the health of the service apps and CPU usage may spike slightly as log records are requested. Otherwise it is incredibly rare for the server to have high CPU usage (more than 1% usage). The CPU usage of service apps is collated and displayed on the same graph. The memory graph shows the memory footprint of SACS and its service apps at a point in time. SACS typically consumes between 20-50 MB when logs have not been requested, and 50-100 MB when it filters and serves log records. This drops back down to 20-50 MB after a few minutes. The default “look-back” time for the graphs is 2 days. This is configurable for both graphs in the app.config settings for the console and can be done by the setup wizard. The graphs record their data every one minute, on the minute, and they will refresh every minute thereafter. A refresh link is available at the bottom of the graphs which will fetch the latest graph information immediately. View configuration information Each management console displays configuration related to both its setup and the server’s setup. This is viewable at the bottom of the Server Management tab by expanding the “Configuration” section. The details in this configuration are not editable from within the console. Use the setup wizard to make any amendments to an existing installation of either the server or the Windows management console. LogsThe list of logs are sourced and served through the SACS server. In the event that the server is offline, the Windows console will perform a physical file search for the logs using the “Alternative Log Location” path specified in the app.config section for the console. All logs are physical files in an XML format, with the default maximum log size being 4 MB. Once a log rolls over that size, it will be backed up to the name of the log with the log number at the end. E.g. SACS_logs.xml.1. These logs are still viewable by the log viewer and all logs that reside in the configured location will be displayed in the list. There is no mechanism in place to automatically clean out old log files so be sure to clean out or archive old logs periodically. Selecting a log and clicking on the “Open Log” button will open the Log Viewer.
Figure 5: Example logs inside the log viewer The log viewer displays the logs in an easy to read format which can be filtered, sorted, and searched on.
Figure 6: The Filter logs dialog Clicking on the Filter menu will bring up the Filter Logs dialog where it is currently possible to filter logs my username, level and message. Clicking on OK will apply the filter. To clear the filter, either close and reopen then log viewer, or click on the filter button again and click OK while leaving all the fields blank. The Search in the top right section will currently search the Level and Message columns in the log for the specified text. The log search occurs from the selected log record downwards. If the end of the log is reached, a message is displayed indicating that the search has stopped. When selecting a log to view the details, the fields displayed at the bottom half are as follows: ·
Item
– The log item number within the specific log. ·
Line
– The line number in the source file where the log message originated. ·
File
– The location of the source file that contained the code that produced the
log message. ·
Timestamp
– The time, in UTC when the error occurred. This is translated into the local
time zone before display. ·
Hostname
– The name of the server where the log message originated from. ·
Method
– The method within the source file where the message originated. ·
Machine
Name – The name of the machine where the log message originated from. ·
Username
– The username, typically that of the SACS server, which produced the log
entry. ·
Class
– The class within the source file where the message originated from. ·
Thread
– The thread ID that was used to process the code which resulted in the log
entry. ·
App
– The name of the app that created the log entry. This will typically be the
SACS Windows service as it logs errors and messages on behalf of the services
that it starts and runs. The two tabs at the bottom give a detailed account of the log record: ·
Message
– Shows any message that was recorded along with the log entry. · Throwable – Shows the full stack trace that occurred, if there was an error that was logged. This tab is only viewable when clicking on a log entry to view its details.
Figure 7: The service app list Click on the “Application Management” tab to view and administer service apps. From this tab it is possible to refresh service apps, add new service apps, remove existing service apps (only from the container, not from the system), export the service app list, and control service apps remotely. The Refresh button will contact the server and fetch the current status of its service apps. The Add button will kick off the process of adding (deploying) a service app. The Export button will export the existing list of services to a csv or a tab delimited file. The Metrics button is a work in progress. In the meantime, third party analytics tools can be connected to the SACS database to enable that functionality. The Help button will open the current help manual.
The list on the left-hand side shows the service apps currently deployed to the server. The columns are as follows: · [Status image]. This shows the current status of the service app. The current list of statuses are: o - The service app is stopped. In this state it can be changed or removed. o - The service app has a new message and the list should be refreshed to see the changes. o - The service app has started successfully and is set to run automatically according to its prescribed schedule. o - The service app has started successfully but is set to manual execution. Therefore, despite the schedule assigned to it, it will not run unless it is manually triggered using the “Run immediately” button in the service app details. o - The service app is started, but there was a problem detected during start-up. The state of the service app cannot be tracked and no commands, other than “stop” can be processed by the app. This usually occurs when the application loaded into the container could not be recognized as a service app. Since service apps are plain old console applications, which happen to contain a specific library, when SACS starts a service app, it kicks off a handshake process with the application to determine if it is indeed a service app and gets its version and capabilities. If any part of the handshake process fails then this warning sign is displayed. o - The service app has errored out during execution. The last message is shown on the right-hand side under the “Last message” section or by viewing the logs. An email will be sent to the configured support email when this occurs. o - The service app has been disabled and cannot accept any further instructions. To take a service app out of a disabled state, click on the service app and at the bottom of the details, click Edit and change the start-up type. o - The state of the service app is unknown as some its details have been altered. Please refresh the list to see the updated state. ·
Name,
Environment, Description o These three columns describe the service app. The “Name” column is a unique identifier for the service app. The “Environment” column shows what grouping it belongs to. The “Description” is a short description of the service app. ·
Startup
Type o Automatic – means the service app will run according to the prescribed schedule o Manual – means the service app will only run when manually triggered o Disabled – means the service app will not start and will not receive any commands. ·
App
version o Displays the product version of the service app. ·
Send
Success Notification o If true, then every time a service app completes execution, it will send an email to the support email setup in the app.config file for the server. See Creating a Service App on how to create a service app. Service app details, deployment and manipulation The service app details section on the right-hand side displays all extra information related to a selected service app, allows the manipulation of a service app, and also allows editing and deployment of service apps
Figure 8: Example existing service app. For a new service app, the "service App Name" at the top would be editable. Clicking on the Add button will start the process of deploying a service app into the container. Make sure that the files are already present on the machine before proceeding. The various sections of the service app detail are: · Service App Name: o This is the unique identifier of the service app. Once the service app is created, it cannot be altered. · Last Message: o Displays the last activity message related to the selected service app. · “Start”, “Stop”, “Run” Immediately buttons: o These buttons allow control over the service app. o The buttons will be disabled when editing a service app. o Start – Sends the command to start the service app, if it is not in a disabled state. o Stop – Sends the command to stops the service app. If the service app is busy processing, the service is given 15 seconds to quit before it is force stopped by the server. o Run Immediately – Sends the command to run immediately, despite the schedule given to the service. This can be fired as many times in succession as possible, however, based on the execution mode that has been setup within the service app, the multiple commands may, or may not be fulfilled. See Service App Development for further information on the execution modes that affect a service app. · Startup Type: o Determines the start-up mode for the service app when SACS is started. The types are o
Automatic
– The service app will start up when the SACS server starts up and it will
automatically start running according to its prescribed schedule. o
Manual
– The service app will start up when the SACS server starts up, but it will
not run on a schedule. Its execution must be manually triggered by clicking
on the “Run Immediately” button after the service has been started. o
Disabled
– The service app will not start up when the SACS server starts up. Moreover,
it cannot be started unless it is taken out of disabled mode. ·
Environment: o
This is the name of the group that the service
app belongs to. Typical values include: “Development”, “Testing”, “Staging”,
“Production”, but this accepts any text. ·
Description: o
This is a short description of the service
app. ·
App File: o
This is the location of the service app’s .exe file. This file should reside on
the same server as SACS and it should have all necessary files and DLLs
installed in order to function – similar to if it were executed as a normal
console application. Notice that no config file needs to be specified, once again, each
service app is treated as a console application – but with added
communication features – therefore any required config files should be
bundled with the service app being deployed. ·
Notifications: o
The “Send Success Notification” checkbox can
be checked so that emails are sent to the support box on successful execution
of a service. This is included for both automatic and manually triggered
runs. ·
Identity: o
This is the user account that the service will
run under. Clicking on “Choose…” will open the “Select Account” dialog where
the SACS account or a separate, custom account can be selected. The account
password is never stored on the Windows console. After entering the account
details, the password is immediately encrypted and is deleted once
transferred to the server. Figure 9: Example Identity selection
box o
The identity can be left as the built-in
account which will allow the service app to run under the SACS account, or it
can be entered so that the service will start and run under a different
context from the SACS account. ·
Schedule: o
This defines the schedule that service apps in
an “Automatic” start-up type will follow. The details shown on this section
are written in a natural language format. However it is not possible to
specify natural language to the scheduler. Click on the “Choose…” button to
open the schedule selection window. o
The schedule dialog allows for the configuring
of schedules in 5 parts: minutes, hours, days, months, and days of the week. o
The calendar and hour/minute break down within
the description section allow you to select a day and visualize what the run
times will look like.
Figure 10: The schedule selection dialog. The various parts of the schedule dialog are explained as follows:
o Clicking OK will apply the schedule to the service app · Configure o This is where the Save, Remove, Cancel, and Edit buttons will be available. o Save – Will validate and save the current service app changes. o Cancel – Will undo any current changes and cancel the edit view. o Remove – Will remove the service app from the SACS container. This will not remove the service app files from the system o Edit – Will kick off editing of a service app once it has been stopped. The web management console is a slimmed down version of the Windows management console. It is designed for remote administration of deployed service apps. Currently it has to be installed manually. See Manual Web Management Console Installation for further installation information.
Figure 11: Example main dashboard page of the Web management console Once the web console has been installed, navigate to it. The Dashboard page is the default page that is displayed. Like its Windows management console counterpart, the dashboard displays the list of logs, CPU and memory performance, and configuration details of both the server and the web console. Unlike its Windows counterpart, the web console does not display the server details as currently it has not be built to administer the server remotely. Clicking on the “view” button against a particular log will open up its details, much like the windows log viewer. Clicking on the Logs link on the left-hand side will expand the list of logs on a new page. As with the windows console, the location of the logs is controlled by the SACS server and all log requests go via that server. However, if the server is offline, the logs will be inaccessible as there is currently no mechanism built into the web project to probe a remote machine for the logs. Clicking on the Service Apps link on the menu will load the list of service apps currently loaded into the SACS container that the web console is pointing to.
Figure 12: Example service app list in the web console. Similar to the Windows management console, the web console will display the current status of all the service apps in the container. Clicking on the refresh button link will fetch any updated status. The buttons function similar to the Windows console counterpart. · Start, if enabled, will send a command to the server to start the targeted service app. A popup will display indicating that the command was sent successfully. The Refresh button can be clicked to receive updates on the status of the service app. · Stop, if enabled, will send a command to the server to stop the targeted service app. A popup will display indicating that the command was sent successfully. The Refresh button can be clicked to receive updates on the status of the service app. · Run, if enabled, will send a command to the server to run the targeted service app immediately. A popup will display indicating that the command was sent successfully. At which point, it is up to the service app to determine how to process the run command. The Refresh button can be clicked to receive updates on the status of the service app.
If for any reason the setup wizard proves inadequate to install SACS, an installation can still be achieved through a manual process. This section of the help will explain how to deploy SACS without the wizard. Currently the web deployment is not handled by the wizard, therefore this guide will need to be followed to deploy the web management console. The first part of the installation involves deploying the server. Requirements: - SACS.WindowsService files. - An admin account capable of doing installations and Windows service deployments. - Access to a SQL server instance where the server database will be placed and that there is access to SQL instance from the server SACS will reside on. - A service account with admin rights to the machine that SACS will reside on. That service account will need access to the database that SACS will use, or (optionally) a separate SQL login that the SACS server can use to connect to the database. - Rights to deploy data and schema changes to the SACS database. Process: Locate the windows service files. The location of the files will be specified in the same folder as SACS.Setup.
Figure 13: Partial example of what the server files would look like Copy the files to the target server, to a folder where the server will be required to reside in. To install the server, run the Install.bat file located in the folder.
Figure 14: Example of what a successful installation would look like The server’s agent will be installed and should be available in the machine’s Windows services list, as “SACS – Windows Service Agent” (SACS.Agent) or similar. It should also appear in a “stopped” state. If the installation does not look like the screenshot above, there was an error during the installation so peruse the console output to find out what failed, along with the failure message. Refer to Troubleshooting SACS for possible solutions. To update an existing server installation there is no need to uninstall and reinstall the service. Instead, perform the following: 1. Stop SACS – Windows Service Agent 2. Backup the files to a safe place. 3. Copy the updated files over to the existing location, being sure to not overwrite the following: a. AppList.xml b. SACS.mdf (if using the provided database file) c. SACS.WindowsService.exe.config d. SACS_log.ldf (if using the provided database file) 4. Run any new database scripts, perform any configuration updates as explained in the Configuring the Server section. Once reconfigured as per below, the SACS.Agent can be restarted again. Wait until the service displays as “Started” to ensure there are no issues. Refer to Troubleshooting SACS if there are any issues starting the service. Configuring the ServerOnce the server has been installed/updated, it must be reconfigured. Refer to the ReleaseNotes.txt in the install folder to see what has changed and what needs to be configured. On first installation, the following needs to be performed: Run the database create scripts – Do this if the provided MDF file will not be used. Each version of SACS will have its own version of the scripts the run. The scripts will be contained in the “Database” folder – find the correct version of the scripts to run and execute them on the database. It is highly recommended that the database is backed up first before the deployment scripts are run. Configure a service account to have administrator privileges – SACS will need rights to spawn and monitor processes and “redirect the standard input/output streams” (i.e. send/receive messages from service apps via a simulated console). This requires administrator privileges to be available. If an account local to the machine is used, the database will have to reside on the same machine or a separate SQL login will be required to connect to a remote database. If it is a domain account it will need to be added to the admin group either via a group policy change or a manual addition to the Administrators group on the local machine. To add the account to the local admin group, open Computer Management and navigate to System Tools à Local Users and Groups à Groups, double-click on Administrators and add the account to the Members list.
Update the account the SACS.Agent will use to the local admin user – Once a suitable service account has been determined, perform the following: 1. Run services.msc 2. Locate SACS – Windows Service Agent à right-click à select Properties 3. Click on the “Log On” tab and enter in the appropriate account details. Although LocalSystem is the default account, it cannot easily access remote SQL databases using integrated security. Using a separate service account is feasible. If doing so, ensure that the account has been granted the following privileges on the system: · Log on as a batch job · Log on as a service · Adjust memory quotas for a process · Replace a process level token If the database will be installed to a different server, use an account or SQL login, preferably with only read/write rights, with access to a SACS database. Refer to Troubleshooting SACS if there are any issues starting the service. Make sure that the start type is set to Automatic. SACS.WindowsService.exe.config configurationThis table details how to update each section of the configuration file. Note that XPath is used to denote the location of the configuration settings.
If any setting appears ambiguous, it is possible to view the latest stock version of the config file from the User/temp/SACS.WindowsService folder when the SACS wizard is opened. Requirements: - SACS.Windows files. - An existing and running instance of the SACS server on the machine. - Administrator rights to be able to copy files and setup start menu shortcuts. Process: Locate the windows console files. The location of the files will be specified in the same folder as SACS.Setup.
Figure 15: Example of what the Windows console files will look like. Determine a location on the machine where the files will reside. A new deployment involves the following: 1. Copy the files over to the new location. 2. Add a shortcut to the Start menu programs a. This shortcut is used by the wizard to locate the correct instance of the Windows management console. b. Point the shortcut to the SACS.Windows.exe file. c. Be sure to place the shortcut within the programs, and not within the pinned shortcuts as the wizard is currently unable to search the pinned shortcuts (and the desktop) for the correct location. 3. Configure the console according to the SACS.Windows.exe.config section below. For upgrades and redeployments, first make sure that no instances of the windows console are running then: 1. Backup the existing files to a safe location. 2. Copy the new files over to the location, be sure to not overwrite the following files: a. SACS.Windows.exe.config 3. Ensure that the shortcut in the start menu still points to the correct instance of the windows console. 4. Configure the console according to the SACS.Windows.exe.config section below.
SACS.Windows.exe.config configuration This table details how to update each section of the configuration file. Note that XPath is used to denote the location of the configuration settings.
Requirements: - SACS.Web files. - An existing and running instance of the SACS server on the same network as the web console. - Administrator rights to be able to copy files and perform IIS configurations. Process: Locate the web console files. The location of the files will be specified in the same folder as SACS.Setup.
Figure 16: An example of what the published web files look like. To perform a new installation, or to update an existing version of the SACS web management console, perform the following: 1. If an existing installation exists, backup the files to a safe location. 2. Copy the files over to the intended location a. If files already exist, be sure to not overwrite the web.config file. 3. Open IIS and deploy the web application a. The default application name for the web console is “ManageSACS” b. When selecting an App Pool, be sure to select one with the following settings in place: i. .NET Framework Version: v4.0 ii. Enable 32-Bit Applications: False iii. Managed Pipeline Mode: Integrated iv. Identity: <an identity with the ability to make web API calls>
c. The SACS web console makes use of windows credentials and assumes it will be deployed within an organization’s domain. Make sure Windows Authentication is enabled, and that Anonymous authentication is disabled. 4. Configure the web.config file as per the configuration section below.
This table details how to update each section of the configuration file. Note that XPath is used to denote the location of the configuration settings.
Show me the codeService Apps are designed to be built on top of Windows console applications. To create a new, basic service app: 1. Create a new .NET 4.5, or above, Windows Desktop Console Application. 2. Locate the SACS.Setup folder. Within the folder there is a lib folder containing SACS.Implementation.dll. Add this dll to your solution and add a reference to it in the new project. 3. Add this code to the Program.cs file:
4. Build the solution 5. Right-click on the console project, hover over Debug, and select Start new Instance
You should see an output window that looks something like this:
6. To run the service app and see it in action, type the following and press enter action: "run" The results will look like the following. Notice the “Hello World” text in the middle.
7. To exit the service app, type “exit” (without quotes) and press enter. The breakdown(Referring to the comments in the code in “Show me the code”): 1. Our program needs to implement ServiceAppBase as the first part in turning it into a service app. This can easily be added onto a separate class, in a separate project – as long as it has the right references. 2. In the Initialize method, anything related to the service app gets initialized. In this case it is the message to be proclaimed. 3. In the Execute override, the “run” action of the service app is performed. Here the Proclaimer proclaims the message. 4. A method is created to access the protected ServiceAppBase.Start() method. A service app can be started in one of three execution modes through which it dictates how often the call to execute can be fulfilled. 5. Here we create a new instance of Proclaimer which will perform our service app actions. 6. The process of turning our console application into a service app begins with the final call to the proclaimer to start. Points to ponderOne way of making sure that the SACS.Implementation dll is the same across all service apps on a server is to add it to the GAC and reference it from there. Components, like authentication, and anything else that can be done in a normal console app, can be done in the service app. All plain messages written to the Console within a service app are recorded in SACS as info log entries. So use Console.WriteLine to log event information. Any unhandled exceptions from a service app are re-packaged and sent to SACS for logging before the app attempts to recover from the error. Debugging and testing the service app can be done directly as a console application – whether it has been deployed already or not. The service app emits JSON which is designed to be consumed by a SACS container. To debug a service app, either: 1. Run the console exe and attach a debug process to it, or 2. Start a debug session from directly in Visual Studio using the Debug à Start new instance menu (recommended) In either case, when the console application starts up, only the Initialize method is called. To call the Execute method, a run action command will have to be typed in the console (as such à action: "run"). There are other commands available and are explained below. Service App CommandsThe following commands can be typed in the console to perform different actions on a service app to test it. They are:
Since service apps are console applications at their heart, the behaviour of a configuration file within the application does not change. There are certain configuration settings that are used by SACS.Implementation that can alter the service app behaviour. These settings can be added to the configuration file and are all optional. The various settings are detailed below:
Figure 17: Example of SACS.Implementation configuration Service App DeploymentA deployment of a service app involves these steps: 1. If there is an existing service app deployed, make sure that it is not started. This can be done either via any Windows or web management console that is pointing to the correct server, or making sure that the service app’s process is not running (this requires logging onto the machine). 2. Copy the compiled files over to the destination of the deployment, making sure to backup existing files in the process. 3. Perform the steps outlined in Step 2: Deploy the Service App to deploy the service to the container. In an event where service apps cannot be deployed to a server container, there are still a number of ways in which service apps can be deployed.
Because service apps are console applications which can also receive command line arguments on start-up, the following methods are available to deploy service apps outside of a SACS server: 1. Run the console application as standalone program. Use this method if the service app is typically only run once on start-up. To add it to start-up, create a shortcut which points to the executable. a. Open the shortcuts properties and in the “target” add the command flags that would be required of the service. To add multiple commands, surround them in the JSON array syntax. Only one of each command is allowed. E.g. { action: ["run",
"stop"] } b. Add the shortcut to the Startup folder in the start menu so that it starts with the system reboot. 2. Run as a Windows Scheduled Task. Use this method to run the service app at set intervals. The service app can be setup as follows: a. Open Task Scheduler and click on Create Basic Task b. Enter the name and description and click next c. Select when you want the task to run d. Choose “start a program” e. Enter the path the executable. Add arguments to the arguments box, remembering that the commands are treated as JSON f. Click Next and Finish. When setting up a service app using either of these methods, some features will become unavailable such as email notifications and logging. This is because the SACS server contains this functionality. The documentation for SACS.Implementation is found in the same directory where the dll is located within the setup directory hierarchy. This section details known issues, along with possible remedies, that could occur when installing, or running SACS. Sometimes there will be issues running the installer. Most problems will occur due to insufficient rights. Here are some common problems and how to solve them. When running the setup wizard, all installation steps are saved to a log file. It is available at %TEMP%\SACS.Setup\InstallLog.txt “Access Denied” when selecting the Install/Update optionPossible causes: - The setup wizard searches the start menu programs as part of arranging an installation/upgrade. The user may have insufficient rights to view all the start menu programs. Remedies: - Be sure to be an administrator on the system with the rights to view all start menu programs. Most server start issues originate from database connection being severed and service account not having sufficient rights. Here are some server start problems and how to solve them: “Access Denied” on startPossible causes: - The account that the SACS server is running as does not have access to the database. - SQL server is not installed on the target machine. - The local MDF file was created with a different login - If attempted from the Windows management console, the logged in user has not started the console with administrator privileges. Remedies: - Check that the account that accesses the SACS database has sufficient rights to log in and read/write records. - Make sure SQL server is installed on the target machine and that the server is configured to point to it. - If the local MDF file that comes with SACS is used, then bear in mind that only one user can log onto that database at the same time. So make sure that SACS is the only login accessing the database. If there are access issues on an existing database, it means that a different login is claiming rights to the database, this gets handled in the LDF file that accompanies the MDF file. Delete this file and they try to start the server again. - A red symbol should appear next to the server status if the logged in user does not start he Windows console with administrator privileges. To remedy, the user should either start the Windows console as an administrator, or ensure that they have logged on the machine with full administrator rights. Agent start timeout after 30 secondsPossible causes: - Connection to the database has deadlocked and may have timed out. Remedies: - Open up the latest log file (found at <SACS.Service location>\Logs\SACS_logs.xml) and view the latest message. If it states that there was a timeout, try restarting the agent. If restarting does not work, check if there are any deadlocks on the SACS tables in the database and resolve and discrepancies. Restart the service agent afterwards. Server is hanging on startPossible causes: - The provided MDF file is corrupt. Remedies: - Reinstall SACS or configure the server to use a different database that resides on an accessible SQL server. Be sure to check that the account SACS is using has access to that database. “There was a problem loading the state of the service” ErrorPossible causes: - If this error is accompanied by “Invalid URI” errors underneath the logs, it may be a configuration issue. Remedies: - Expand the Configuration section at the bottom of the window. o If each entry is empty, it means that the config file was not copied over during installation. Reinstall the latest version of SACS to resolve the issue o If the Configuration section is not empty make sure that the user has administrator privileges to SACS. “Error Executing GET for resource path…” Error under logs or on Application window.Possible causes: - The server has been stopped. - The console is pointing to the wrong server URL. - The server URL is inaccessible. Remedies: - Check that the SACS server is running. Do this by seeing if the SACS Agent has started. - Check the configuration files of both the SACS server and the console to make sure that they have the same address. - Check that the port that the server is on is accessible to the console. Possible causes: -
This is a generic message showing that no
connection to the SACS server succeeded. Remedies: - Check the web server log to see details of the error. Or use browser dev tools to monitor the network requests and see the underlying failure. Usually the server is offline. If the server is online, check the configuration settings on both the server and the console to make sure that the base URL is the same. If there are still issues, check that the port is open and that the console application can ping it. Restart SACS server after making any change. Possible causes: - Windows authentication is not enabled for the website. - The user does not have access to the web management console. Remedies: - Within IIS, check that the Authentication type is set to Windows. Under Providers, the typical order of providers is “Negotiate”, followed by “NTLM”. If this order is different, check with your network administrator to confirm that the choices are correct. If there is still a log in failure, restart IIS. - The user must be granted access to the application via Windows AD. Service App Issues“Access denied” Possible causes: -
The service account that SACS is running under
does not have rights to the folder where the service app resides. Remedies: - If not using the LocalSystem account for SACS, check that the configured service account has been granted at least read rights to the folder where the service app resides. and message “starting service app” shown indefinitely Possible causes: -
The exe that was loaded is not a service app.
or -
The exe process crashed before it started Remedies: - Check that code is correctly setup to start as a service app. See Tutorial: Creating a Service App to confirm what the code layout should be. - The process should show in task manager. If it is not present, it means that it exited before it started and SACS was not informed. The errors can usually be found in the Windows event log, focussing in the System log. |