WinSCP + Powershell: How to sync folders via SSH

Wenn man einen Ordner zwischen dem lokalen Rechner und einem SSH-Host online syncen möchte, dann kann man das auch recht schön automatisieren. Dazu kann man WinSCP verwenden. Ich habe das mit Powershell umgesetzt, aber man kann WinSCP auf mit C#, J-Script usw. „automatisieren“.

Hier ein paar Links, die mir geholfen haben:

Which CMS is used by a specific website?

Falls ihr mal feststellen wollt, mit welchem CMS System eine Website aufgebaut, gibt es diese praktische Seite:

https://builtwith.com

Diese Website erkennt ziemlich viele CMS recht zuverlässig. ich habe das getestet mit Webseiten die mit Joomla, WordPress, Plone, Drupal und Typo3 erstellt wurden. Bie meinen Tests wurde alle richtig erkannt!

Javascript: mark.js – JavaScript keyword highlighter

Ich hatte die Anforderung auf einer Sharepoint-Seite eine einfache Suche einzubauen. Nichts großartiges: Nur eine Möglichkeit auf einer einzelnen Seite nach Vorkommen von bestimmten Buchstabenkombinationen zu suchen. Nach kurzem googeln fand ich mark.js. Das ist ein kleines aber feines jQuery-Plugin, mit dem man die Fundstellen von Such-Texten hervorheben kann.Das ist einfach einzubauen und die Hervorhebung kann auch einfach via CSS konfiguriert werden!

Sourcen:

 

Sharepoint: Set page to fullscreen mode using CSR

Hier ein kleines Schnipsel wie ich in einem meiner Projekte eine Page in den Full-Screen-Modus schalte. Die Source im WWW habe ich mir damals leider nicht notiert. ICh abe das damals verwendet um die Bedienung der Page auf einem Tablet zu erleichtern. Für den User wurde eine Hinweisemeldung eingeblendet, die nach 10 Sekunden wieder verschwand:

window.onload = function() {
    var width = $(window).width();
    console.log("width: " + width);

    if (width < 1000)
    {
        var addText = '<div id="fullScreenModeHint" style="color: red;">Da die Breite des Fensters weniger als 1000 Pixel (' + width + 'px) darstellt, wurde die Website in den "Vollbildmodus" geschalten! Um diesen zu verlassen klicken Sie bitte das entsprechende Icon oben rechts!<br><br><b>Diese Nachricht wird in 10 Sekunden ausgeblendet!!</b><br><br></div>';
        $("#WebPartWPQ3").html(addText + $("#WebPartWPQ3").html());
        //console.log("window onload - set full screen mode");
        SetFullScreenMode(true);        
        
        timeoutID = window.setTimeout(removeFullScreenModeHint, 10000);
    }
};

function removeFullScreenModeHint() {
    $("#fullScreenModeHint").html("");
}

 

SQL-Server: Use bcp to export table

Warum dieser Beitrag? Weil es bei der Verwendung von „bcp“ und einem CMD-Script ein paar Fallstricke gibt, über die ich ALLE heute gestolpert bin 😉

Ich fand dieses Beispiel:
https://stackoverflow.com/questions/23852295/export-sql-table-data-with-column-names-to-csv-file

@echo off
bcp "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '<table_name>'" queryout c:\file.csv -c -r, -T -S <server_name> -d <database_name>
bcp "select * from <table_name>" queryout c:\data.csv -c -t, -T -S <server_name> -d <database_name>
echo. >> c:\file.csv
type c:\data.csv >> c:\file.csv
del c:\data.csv

Hauptproblem war, dass wir hier im Deutschen Sprachraum Umlaute haben und bei dieser Version wurden diese komplett „zerstört“.Das Weiteren hatte ich das Problem, dass in meinen zu exportierenden Daten auch „Mehrzeilige Texte“ vorkamen. Spätestens beim Import nach z.B. Excel bekam ich das Problem, dass Excel nicht mehr unterscheiden konnte zwischen einem Zeilenumbrum innerhalb einer Zelle und einem Zeilenumbruch am Ende einer Zeile!

Zudem war es mir nicht variabel genug, da ich diese Funktion in näherer Zukunft für mehere Tabellen würde ausführen müssen.

Daher erstellte ich ein Powershell-Script:

#
# Getting the data from a sql-database
#
# Export the data via bcp and prepare the data
# with a few find-replace actions to a multi-line-string won'
# make problems at importing
#
# I had the best experience using Libre Office Calc for the import!!
#
#

# Var's to be changed:
$tableName = "talbename"
$db = "databasename"
$server = "servername\instancename"

# WHERE-Clause to limit output
$whereClause = ""

# No changes after here
# =============================================================================

# "home"-Folder
$baseFolder = Split-Path -Parent -Path $MyInvocation.MyCommand.Definition

# bcp-Path
$bcpPath = "C:\Program Files\Microsoft SQL Server\110\Tools\Binn\bcp.exe"

# FileNames
$headerFile = "$baseFolder\header.dat"
$dataFile = "$baseFolder\data.dat"
$resultsFile = "$baseFolder\$tableName.csv"

# Get the header
$queryStr = "Select COLUMN_NAME from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = '$tableName'" 
& $bcpPath "$queryStr" queryout "$baseFolder\header.dat" -w -r`°´ -T -S $server -d $db

# Get the data
$queryStr = "select * from $tableName"
if ($whereClause)
{
    $queryStr = $queryStr + " " + $whereClause
}
& $bcpPath "$queryStr" queryout "$baseFolder\data.dat" -w -t`°´ -r`~´ -T -S $server -d $db

# Write header-data to result file
$contentHeader = (Get-Content $headerFile -Raw)
$cTemp = $contentHeader.Replace('`°´','";"')
'"' + $cTemp + '"' > $resultsFile

#Write data to result file
$contentData = (Get-Content $dataFile -Raw)
$cTemp = $contentData.Replace('`°´','";"')
$cTemp2 = $cTemp.Replace('`~´','"' + "`n" + '"')
'"' + $cTemp2 + '"' >> $resultsFile

Remove-Item $headerFile
Remove-Item $dataFile

 

Powershell: How to batch-convert Word files to PDF

Kurz gegoogelt und, wie so oft, die Antwort bei stackoverflow gefunden:

$documents_path = 'c:\doc2pdf'

$word_app = New-Object -ComObject Word.Application

# This filter will find .doc as well as .docx documents
Get-ChildItem -Path $documents_path -Filter *.doc? | ForEach-Object {
    $document = $word_app.Documents.Open($_.FullName)
    $pdf_filename = "$($_.DirectoryName)\$($_.BaseName).pdf"
    $document.SaveAs([ref] $pdf_filename, [ref] 17)
    $document.Close()
}

$word_app.Quit()

Quelle: https://stackoverflow.com/questions/16534292/basic-powershell-batch-convert-word-docx-to-pdf

Powershell: Using hashtables or arrays to pass parameters to cmdlets

Was tun wenn man in einem PS-Script ein cmdlet aufrufen muss, diesem cmdlet aber eine variable Zahl an Parametern übergeben möchte?

Man könnte das machen:

if (varParam1)
{
    cmdlet -param "fix param" -param1 varParam1
}
else
{
    cmdlet -param "fix param"
}

oder man verwendet „splatting“. Dabei werden die Parameter mit Hashtables oder Arrays übergeben. Hier ein Beispiel mit Hashtable:
ACHTUNG!!! GANZ WICHTIG!!
Beachtet bei der Verwendung der Hashtable-Variable das @-Zeichen!!!

$Colors = @{ForegroundColor = "black"; BackgroundColor = "white"}
#Write a message with the colors in $Colors
Write-Host "This is a test." @Colors

Und wieder was gelernt 😉

Source:

Sharepoint 2016: use custom js files without problems due to MDS

Ich habe mir für das „Branding“ unserer Sharepoint-Sites eine Kopie der Seatlle-Masterpage erstellt. Die einzige Änderung dieser Kopie gegenüber dem Original ist diue Einbindung von eigenen JS und CSS Files.

Diese Einbindung sieht so aus. In der Masterpage ganz oben beim Tag „Sharepoint:AjaxDelta“

    <asp:ContentPlaceHolder id="PlaceHolderBodyAreaClass" Visible="true" runat="server" />
  </SharePoint:AjaxDelta>
  
        <!-- Referencing jQuery and custom js-files -->
    <!-- Pleas see at the end of the <body>-Tag!! -->
    <SharePoint:ScriptLink language="javascript" name="~sitecollection/SiteAssets/SKB-SP2016/jquery-3.2.1.min.js" 
      LoadAfterUI="true" OnDemand="false" runat="server" Localizable="false" />
    <SharePoint:ScriptLink language="javascript" name="~sitecollection/SiteAssets/SKB-SP2016/skb-sp2016.js" 
      LoadAfterUI="true" OnDemand="false" runat="server" Localizable="false" />

        <!-- Referencing custom css-files -->
        <!--<SharePoint:CssRegistration Name="<%$SPUrl:~sitecollection/Style Library/SKB-SP2016/SKB-SP2016.css%>" After="Themable/corev15.css" runat="server"/>-->
  
  <SharePoint:CssRegistration Name="Themable/corev15.css" runat="server" />
</head>
<body>

Ganz unten (vor dem Ende des Body-Tags) kommt dann noch das:

<SharePoint:ScriptBlock runat="server">
if (typeof asyncDeltaManager != "undefined") {
    asyncDeltaManager.add_endRequest($_global_myNameSpace_sp2016_async_js);
}
$_global_myNameSpace_sp2016_other_js();
</SharePoint:ScriptBlock>


</body>
</SharePoint:SPHtmlTag>

Wozu der Block unten in der Masterpage?

Die Javascript Function „$_global_my_sp2016_other_js“ wird ausgeführt, wenn die Site „neu“ geladen wird. Also wenn man das erste Mal dort ist oder wenn man z.B. „Strg“+“F5“ drückt. Aber auch wenn Sharepoint merkt, dass sich etwas an den benötigten Dateien geändert hat. Der springende Punkt ist: Nicht immer!!

Was hingegen bei „jedem Klick“ aufgerufen wird ist die Javascriptfunction „$_global_my_sp2016_async_js“. Diese wird auch ausgeführt, wenn die MDS aktiv ist und eigentlich nur differenzen zwischen der aktuellen Seite und der aufgerufenen Seite übertragen werden!

Nur der Vollständigkeit halber hier noch das JS File:

// reference jQuery
var $jq = jQuery.noConflict();

// declare namespace
/* This line would also do it: Function.registerNamespace('myNameSpace.sp2016');  */
window.myNameSpace = window.myNameSpace || {};
window.myNameSpace.sp2016 = window.myNameSpace.sp2016 || {};

// is not called on every klick because of MDS, ...
function $_global_myNameSpace_sp2016_js_init() {
    
    .....

};

// is called on every klick (MDS oder not!!)
function $_global_myNameSpace_sp2016_async_js() {
    
    // Remember: This code is executed for every klick! So don't forget to check
    //           if something is allready applied!!
 
    ...
    
};

_global_myNameSpace_sp2016_js_init

Kurzer Hinweis am Ende: Ich verwende eigene Scripte die diese Masterpage gemeinsam mit den restlichen Dateien für jede Website einer SiteCollection (bzw. genauer: für jede Website in allen Sitecollections einer WebApp) hochladen und als Theme aktivieren.

Die Sourcen dazu findet ihr in diesem Beitrag.

Sharepoint: custom javascript use singleton pattern to prevent multiple calls!

Bei mir wird in Sharepoint 2016 eine Javascript-Function direkt aus der Masterpage heraus ausgerufen. Durch MDS und andere Dinge wird diese Funktion bei einem „Strg“+“F5“ reload dadurch bis zu 3x aufgerufen. Um das zu verhindern gibt es die Singleton-Pattern. Dis sollte so aussehen:

function MySingletonClass () {

  if (arguments.callee._singletonInstance) {
    return arguments.callee._singletonInstance;
  }

  arguments.callee._singletonInstance = this;

  this.Foo = function () {
    // ...
  };
}

var a = new MySingletonClass();
var b = MySingletonClass();
console.log( a === b ); // prints: true

Da das bei mir so nicht korrekt funktioniert hat (vermutlich habe ich den richtigen Aufruf einfach nicht hinbekommen, habe ich das so abgewandelt:

// My simple "singleton Pattern"
var sp2016InitFirstRun = true;

// This function is called from at the bottom of my masterpage!!
function $_global_sp2016_js_init() {

    // My simple "singleton Pattern"
    if (!sp2016InitFirstRun) 
    {   
        return;   
    }
    else 
    {  
        sp2016InitFirstRun = false;    
    };
    
    // The following code is only run once!!
 
    ...
 
};

$_global_sp2016_js_init()

Funktioniert wie gewünscht: Der Code wird nur 1x gestartet. Egal wie oft Sharepoint die Function aufruft 😉

Quelle: stackexchange.com

Sharepoint 2016: Add custom js and deal with MDS problems!

Wenn man zu einer Sharepoint-Site eigenes CSS und JS hinzufügen möchte gibt es ja bekanntlich viele Möglichkeiten. Ich brauche das um das Layout und die Farben unserer Sahrepoint-Seiten anzupassen. Ich habe mir dazu eine Kopie der „Seattle-Masterpage“ erstellt und dort dann meine CSS und JS Files verlinkt. Das funktionierte alles soweit ganz OK. Mein Problem war allerdings, dass die Minimale Downloadstrategie (kurz „MDS“) hat mir einen Strich durch die JS-Rechnung gemacht! Mein JS-Code wurde nur ausgeführt wenn die Site komplett neu geladen wurde. Ich habe Tonnen von Websites, Blogs und sonstiger Info gelesen aber keine (funktionierende) Lösung gefunden. ERst nach einer Frage an die Stack-Exchange-Community erhielt ich endlich die richtige Antwort:

Des Rätsels Lösung ist der „AsnycDeltaManager“!

Hier ein paar Links die nun, nachdem das nun alles Funktioniert, endlich ein Gesamtbild ergeben. Zuerst kommen die Links, die mich zur Lösung brachten, danach dann die weiteren Links. Alles in allem habe ich zwar viel Zeit versch…en aber auch wieder einiges gelernt 😉

Quellen:

Links die zwar teilweise informativ sind/waren, aber mich nicht wirklich weiter gebracht haben: