<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Daniels Blog &#187; Scripting</title>
	<atom:link href="http://blog.danielhahn.eu/category/scripting/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.danielhahn.eu</link>
	<description>Themen rund um IT und das WWW</description>
	<lastBuildDate>Mon, 26 Dec 2011 13:54:16 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Internet Explorer 8 remote installieren</title>
		<link>http://blog.danielhahn.eu/2010/internet-explorer-8-remote-installieren/</link>
		<comments>http://blog.danielhahn.eu/2010/internet-explorer-8-remote-installieren/#comments</comments>
		<pubDate>Mon, 11 Oct 2010 13:28:10 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[VBScript]]></category>
		<category><![CDATA[Windows allgemein]]></category>
		<category><![CDATA[ie]]></category>
		<category><![CDATA[installation]]></category>
		<category><![CDATA[installieren]]></category>
		<category><![CDATA[Internet Explorer]]></category>
		<category><![CDATA[Remote]]></category>

		<guid isPermaLink="false">http://blog.danielhahn.eu/?p=493</guid>
		<description><![CDATA[Viele Administratoren werden sicherlich schon einmal vor der Problem gestanden haben, ein Programm auf mehreren Rechnern (nach-)installieren zu müssen, ohne dafür auf eine richtige Softwareverteilung zurückgreifen zu können. In so einem Falle hat man mehrere Möglichkeiten: Entweder man nimmt sich jeden Rechner einzeln vor, oder man baut sich seine eigene &#8220;Softwareverteilung&#8221;. Ersteres dürfte wohl nur &#8230; </p><p><a class="more-link block-button" href="http://blog.danielhahn.eu/2010/internet-explorer-8-remote-installieren/">Weiterlesen &#187;</a>]]></description>
			<content:encoded><![CDATA[<p>Viele Administratoren werden sicherlich schon einmal vor der Problem gestanden haben, ein Programm auf mehreren Rechnern (nach-)installieren zu müssen, ohne dafür auf eine richtige Softwareverteilung zurückgreifen zu können. In so einem Falle hat man mehrere Möglichkeiten: Entweder man nimmt sich jeden Rechner einzeln vor, oder man baut sich seine eigene &#8220;Softwareverteilung&#8221;. Ersteres dürfte wohl nur in relativ kleinen Netzwerken eine ernsthaft zu erwägende Option sein, da der Zeitaufwand spätestens ab zehn Rechnern in unverhältnismäßige Dimensionen steigt. Bleibt also nur der zweite Weg &#8211; und die Frage nach dem &#8220;Wie?&#8221;&#8230;<span id="more-493"></span></p>
<p>&#8230; Welche sich denn auch recht schnell und einfach beantworten lässt: mit knapp 60 Zeilen Skriptcode, ein wenig Basiswissen im Umgang mit VBScript und WMI, sowie einer passenden Installationsdatei. Im Falle des Internet Explorer 8 empfiehlt es sich, ein MSI-Paket zu verwenden, welches man sich aber leider erst selbst mit dem Internet Explorer Administration Kit (IEAK) 8 erstellen muss. Ist dies soweit gelungen, kann man sich an das Installationsskript machen. Ziel ist es, dass das Skript zentral ausgeführt wird und dann automatisch die Installation auf allen angegebenen Rechnern vornimmt. Und das Ergebnis sieht wie folgt aus:</p>
<pre class="brush: vb; title: ; notranslate">
'## Remote-Installationsskript v1.5 ##

Program = &quot;Internet Explorer 8&quot;
SrcPath = &quot;P:\Browser\Internet_Explorer_8\&quot;
SetupFile = &quot;IE8-Setup-Full.msi&quot;
InstOptions = &quot; /quiet /qn /norestart&quot;
ComputerListe = &quot;ComputerListe.txt&quot;
LogFile = ScrPath &amp; Program &amp; &quot; Installation.log&quot;

Set fso = createobject(&quot;scripting.filesystemobject&quot;)
Set oLogging = fso.OpenTextFile(LogFile, 8, true)
Set oComputerListe = fso.opentextfile(ComputerListe, 1, false)
if (Err.Number &lt;&gt; 0) then
WScript.echo &quot;Cannot open &quot; &amp; ComputerListe
WScript.quit
end if

WScript.Echo &quot;Beginning Remote Installation.&quot;

on error resume next

while not oComputerListe.atEndOfStream
Computer = oComputerListe.ReadLine()

'WScript.echo &quot;Copying files to &quot; &amp; Computer &amp; &quot; ...&quot;

fso.CopyFile SrcPath &amp; SetupFile, &quot;\\&quot; &amp; Computer &amp; &quot;\C$\Temp\&quot;, true
if (Err.Number &lt;&gt; 0) then
WScript.echo &quot;Failed to copy File(s) on &quot; &amp; Computer &amp; &quot; with &quot; &amp; Err.Number
end if

Err.Clear

'WScript.echo &quot;Connecting to &quot; &amp; Computer &amp; &quot;...&quot;

if (Err.Number &lt;&gt; 0) then
WScript.echo &quot;Failed to connect to &quot; &amp; Computer &amp; &quot;.&quot;
else

'WScript.echo &quot;Installing &quot; &amp; Program

Set oWMI = GetObject(&quot;winmgmts:{impersonationLevel=impersonate}!\\&quot; &amp; Computer &amp; &quot;\root\cimv2&quot;)
Set oProcess = oWMI.Get(&quot;win32_process&quot;)
oProcess.create &quot;C:\Windows\System32\msiexec.exe /i C:\Temp\&quot; &amp; SetupFile &amp; InstOptions
if (Err.Number &lt;&gt; 0) then
WScript.echo &quot;Failed to start process on &quot; &amp; Computer &amp; &quot;: &quot; &amp; Err.Number
else
oLogging.WriteLine(Computer &amp; &quot;: &quot; &amp; Date)
end if
end if

Err.Clear

wend

oComputerListe.close()
oLogging.close()

WScript.echo &quot;Exiting.&quot;
</pre>
<p>Das Skript greift auf die Datei &#8220;ComputerListe.txt&#8221; zu, in der die Zielhosts mit Name oder IP-Adresse definiert sind. Auf jeden Host wird das MSI-Paket nach C:\Temp kopiert. Ist der Kopiervorgang erfolgreich abgeschlossen, stellt das Skript eine WMI-Verbindung mit dem Zielhost her und startet auf diesem den Setupprozess. Ein fehlerfreier Start wird in einer Logdatei mit Datum protokolliert, eventuelle Fehlermeldung werden auf den Bildschirm ausgegeben. WICHTIG: Der Account, unter dem das Skript ausgeführt  wird, benötigt auf den Ziel PCs die notwendigen Rechte, um auf WMI  zugreifen und Programme installieren zu können. Im günstigsten Falle  startet man das Skript also unter einem Domänenadmin-Account.</p>
<p>Natürlich ist dies bei weitem nicht mit einer wirklichen Softwareverteilung zu vergleichen, aber mit ein Bisschen Fleißarbeit kann man das Skript noch etwas aufbohren. So können z.B. Hosts aus einem Active Directory ausgelesen werden, anstelle aus der Textdatei. Ebenso kann man auch durch Überprüfung der Installationslogs auf den Rechnern das Ergebnis der Installation abprüfen und dieses z.B. in eine Datenbank schreiben &#8211; VBScript bietet hier viele Möglichkeiten, die man sich mit ein wenig Zeit und Lust zu nutze machen kann. Viel Spaß beim Skripten!</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.danielhahn.eu/2010/internet-explorer-8-remote-installieren/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Selektives Löschen mit der Windows Powershell 1.0</title>
		<link>http://blog.danielhahn.eu/2009/selektives-loeschen-mit-der-powershell-10/</link>
		<comments>http://blog.danielhahn.eu/2009/selektives-loeschen-mit-der-powershell-10/#comments</comments>
		<pubDate>Fri, 02 Jan 2009 19:23:05 +0000</pubDate>
		<dc:creator>Daniel</dc:creator>
				<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[Powershell]]></category>
		<category><![CDATA[Scripting]]></category>
		<category><![CDATA[Windows allgemein]]></category>
		<category><![CDATA[leer]]></category>
		<category><![CDATA[löschen]]></category>
		<category><![CDATA[Ordner]]></category>
		<category><![CDATA[selektiv]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.danielhahn.eu/?p=60</guid>
		<description><![CDATA[Ich wünsche allen Leserinnen und Lesern meines Blogs ein gesundes und erfolgreiches Jahr 2009!! Ich möchte das Jahr mit einem Powershell (1.0) Skript einläuten, welches ich vor kurzem erstellt habe. Da es sich mit um eines meiner ersten &#8220;richtigen&#8221; Skripte für die Windows Powershell handelt und ich denke, dass die Problemstellung, die dem Ganzen zu &#8230; </p><p><a class="more-link block-button" href="http://blog.danielhahn.eu/2009/selektives-loeschen-mit-der-powershell-10/">Weiterlesen &#187;</a>]]></description>
			<content:encoded><![CDATA[<p>Ich wünsche allen Leserinnen und Lesern meines Blogs ein gesundes und erfolgreiches Jahr 2009!! Ich möchte das Jahr mit einem Powershell (1.0) Skript einläuten, welches ich vor kurzem erstellt habe. Da es sich mit um eines meiner ersten &#8220;richtigen&#8221; Skripte für die Windows Powershell handelt und ich denke, dass die Problemstellung, die dem Ganzen zu Grunde liegt, sicher auch für andere Administratoren interessant sein könnte, möchte ich Euch meine geistigen Ergüsse nicht vorenthalten und freue mich natürlich auch über Anregungen, was man an der einen oder anderen Stelle noch optimieren könnte.</p>
<p>Ich stand kürzlich in unserem Unternehmen vor dem Problem, dass ich auf einem windowsbasierten Serversystem aus bestimmten Ordnern unter einem Wurzelverzeichnis alle Dateien mit einem gewissen Alter, sowie alle leeren Unterordner löschen wollte. Klingt an und für sich so erst einmal nicht schwierig. Das Einfachste wäre sicher gewesen, mit der Windows Suchfunktion alle meinem Kriterium entsprechenden Dateien herausfischen zu lassen, und diese dann über den Explorer zu löschen. Halbwegs Praktikabel, wenn man auf das Löschen leerer Ordner verzichten kann und es sich um eine einmalige Sache handelt. Damit wollte ich mich aber nicht zufrieden geben; die leeren Verzeichnisse sollten ebenfalls eliminiert und der Vorgang jede Nacht automatisch gestartet werden. Es musste also ein Skript her, welches via Taskplaner jede Nacht ausgeführt wird. Doch in welcher Form? VBS, eine einfache Batchdatei mit DOS-Befehlen oder die neue Powershell? Ich habe mich für die Powershell (1.0) entschieden, da ich von den scheinbar endlosen Möglichkeiten dieses Werkzeugs begeistert bin.<span id="more-60"></span></p>
<p>Und so sieht das Ganze dann codemäßig aus (den Download findet ihr am Ende des Artikels):</p>
<pre class="brush: vb; title: ; notranslate">
# DeleteShareFolderContent.ps1
# Daniel Hahn - Dezember 2008

# -----------------------------------------------------

Write-Host
Write-Host
Write-Host &quot;Skript zum selektiven Leeren von Tauschordnern&quot;
Write-Host &quot;==============================================&quot;
Write-Host
Write-Host

# Hier das Wurzelverzeichnis angeben
$strRootFolder = &quot;Drive:Folder&quot;

# Logfile anlegen und Kopfzeilen schreiben
$strTimestamp = Get-Date -Format &quot;dd.MM.yyyy - HH:mm&quot;
$strTimestampFile = Get-Date -Format &quot;yyyy-MM-dd-HHmm&quot;
$strLogfileName = &quot;Tausch leeren &quot; + $strTimestampFile + &quot;.log&quot;
$strLogfile = $Env:Temp + &quot;\&quot; + $strLogfileName
&quot;Vorgang gestartet: $strTimestamp&quot; &gt;&gt; $strLogfile
&quot;&quot; &gt;&gt; $strLogfile

# -----------------------------------------------------
function CheckFiles
{
param([object] $objRootFolder)
$strRootFolder = $objRootFolder.Path
$strRootFolderName = $objRootFolder.Name
$colFiles = $objRootFolder.Files
$DirContent = $null
$DirContent = Get-ChildItem $strRootFolder

foreach($objFile in $colFiles)
{
$strFile = $strRootFolder + &quot;\&quot; + $objFile.Name
$dtFile = $objFile.DateCreated
$dtSys = Get-Date -Format &quot;dd.MM.yyyy HH:mm:ss&quot;
$iDif = (New-TimeSpan -Start $dtFile -End $dtSys).TotalDays

if($iDif -gt 7)
{
$FSO.DeleteFile($strFile, $true)
Write-Host &quot;Datei &quot; -NoNewline
Write-Host $strFile -ForegroundColor &quot;magenta&quot; -NoNewline
Write-Host &quot; gelöscht&quot;
&quot;Nach Frist gelöscht: $strFile&quot; &gt;&gt; $strLogfile
$script:iDeletedCount++
}
$script:iFileCount++
}

if(($DirContent -eq $null) -and ($strRootFolderName -notlike &quot;*04*Tausch&quot;))
{
$FSO.DeleteFolder($strRootFolder)
Write-Host &quot;Leeres Verzeichnis &quot; -NoNewline
Write-Host $strRootFolder -ForegroundColor &quot;magenta&quot; -NoNewline
Write-Host &quot; gelöscht&quot;
&quot;Leeres Verzeichnis gelöscht: $strRootFolder&quot; &gt;&gt; $strLogfile
$script:iFolderDeletedCount++
}
}

# -----------------------------------------------------
function FindSubFolders
{
param([object] $objRootFolder)
$colRootSubFolders = $objRootFolder.SubFolders

foreach($objRootSubFolder in $colRootSubFolders)
{
FindSubFolders $objRootSubFolder
CheckFiles $objRootSubFolder
$script:iFolderCount++
}
}

# -----------------------------------------------------
function FindShareFolders
{
param([object] $objRootFolder)
$colRootSubFolders = $objRootFolder.SubFolders

foreach($objRootSubFolder in $colRootSubFolders)
{
$strRootSubFolder = $objRootSubFolder.Name

if($strRootSubFolder -like &quot;*Tausch&quot;)
{
CheckFiles $objRootSubFolder
FindSubFolders $objRootSubFolder

$script:iFolderCount++
}
}
}

# -----------------------------------------------------
function WaitKey
{
$strPrompt = &quot;Beliebige Taste zum Verlassen drücken ... &quot;
Write-Host
Write-Host $strPrompt -NoNewline
$key = [Console]::ReadKey($true)
Write-Host
}

# -----------------------------------------------------
# main

$iFolderDeletedCount = 0
$iDeletedCount = 0
$iFolderCount = 0
$iFileCount = 0

Write-Host &quot;Temporäres Logfile:&quot; $strLogfile
Write-Host
Write-Host &quot;Beginne mit Durchsuchen der Tauschordner in &quot;
Write-Host $strRootFolder -ForegroundColor &quot;Cyan&quot; -NoNewline
Write-Host

$FSO = New-Object -COM Scripting.FileSystemObject

if(-not $FSO.FolderExists($strRootFolder))
{
Write-Host &quot;Fehler: Wurzelverzeichnis existiert nicht!&quot; -ForegroundColor &quot;Red&quot;
Write-Host
Write-Host &quot;Ausführung wird abgebrochen&quot;
WaitKey
exit
}

$objRootFolder = $FSO.GetFolder($strRootFolder)
FindShareFolders $objRootFolder

Write-Host
Write-Host &quot;Insgesamt&quot; $iFileCount &quot;Datei(en) in&quot; $iFolderCount &quot;Ordnern gefunden.&quot; -ForegroundColor &quot;magenta&quot;
Write-Host $iDeletedCount &quot;Datei(en) gelöscht&quot; -ForegroundColor &quot;magenta&quot;
Write-Host $iFolderDeletedCount &quot;leere(r) Ordner gelöscht&quot; -ForegroundColor &quot;magenta&quot;

$strTimestamp = Get-Date -Format &quot;dd.MM.yyyy - HH:mm&quot;
&quot;&quot; &gt;&gt; $strLogfile
&quot;$iDeletedCount Datei(en) gelöscht&quot; &gt;&gt; $strLogfile
&quot;$iFolderDeletedCount Ordner gelöscht&quot; &gt;&gt; $strLogfile
&quot;&quot; &gt;&gt; $strLogfile
&quot;Skript beendet: $strTimestamp&quot; &gt;&gt; $strLogfile

WaitKey

# -----------------------------------------------------
</pre>
<p>Das Skript ist vielleicht an der einen oder anderen Stelle nicht perfekt, erfüllt aber seinen Zweck. (Ich habe versucht, möglichst selbsterklärende Variablen- und Funktionsnamen zu verwenden, sowie die Verständlichkeit durch Kommentare zu verbessern)</p>
<p>[download#1]</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.danielhahn.eu/2009/selektives-loeschen-mit-der-powershell-10/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

