Druckeraccounting
Selbstverständlich gibt es auch viele kommerzielle Produkte, die allerdings meist eins gemeinsam haben:- sehr teuer
- viele Features von denen nur ein Bruchteil genutzt/ gebraucht wird
Das Funktionsprinzip ist:
Beim Eintreten eines Events (das kann das Schreiben eines Logfileeintrags sein, oder auch ein geplanter Task) wird ein Powershell- Script aufgerufen. Dieses Script analysiert das Logfile eines (Remote) Printservers und schreibt die gefundenen Werte in eine (Remote) SQL- Datenbank. Als Merker wertet das Script den Zeitstempel des letzten analysierten Eintrags aus und schreibt diesen ebenfalls in die Datenbank um beim nächsten Lauf erst dort wieder anzufangen.
Die erfassten Werte sind:
- Zeitstempel des Ausdrucks
- Benutzername
- Dokumentname
- Druckername
- Anzahl der Seiten
- Größe in Bytes
ACHTUNG: Das Script funktioniert ausschliesslich für Windows 2008 R2 Server. Das passende Script für nicht- R2- Server ist hier.
Powershellscript
# printserver accounting to sql database
$printserver = 'print.server.rs.de'
$dbserver = 'db.server.rs.de'
$dbuser = 'prnacc'
$dbpass = 'dodalgeheim'
$dbname = 'prnacc'
# load assemblies
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | Out-Null;
# connect to SQL Server
$server = New-Object -typeName Microsoft.SqlServer.Management.Smo.Server -argumentList "$dbserver"
# login using SQL authentication, which means we supply the username
# and password
$server.ConnectionContext.LoginSecure=$false;
$server.ConnectionContext.set_Login($dbuser)
$securePassword = ConvertTo-SecureString $dbpass -AsPlainText -Force
$server.ConnectionContext.set_SecurePassword($securePassword)
# clear the screen
cls
$conn = New-Object System.Data.SqlClient.SqlConnection("Server=$dbserver; Database=$dbname; Integrated Security=SSPI")
$conn.Open()
$cmd = $conn.CreateCommand()
$cmd.CommandText = "SELECT wert FROM [dbo].[configs] WHERE schluessel = 'lastinsertrow'"
$Reader = $cmd.ExecuteReader()
while ($Reader.Read()) {
$lastinsertrow = $Reader.GetValue(0)
}
$Reader.Close()
write-host "Starting with record: $lastinsertrow" -back red
$entries = Get-WmiObject -ComputerName $printserver -Query "SELECT RecordNumber, TimeGenerated, InsertionStrings FROM Win32_NTLogEvent WHERE SourceName = 'Microsoft-Windows-PrintService' AND EventCode=307 AND TimeGenerated > '$lastinsertrow'" | Select-Object RecordNumber, TimeGenerated , InsertionStrings
foreach($entry in $entries){
# recordnumber
if ( $entry.TimeGenerated -gt $lastinsertrow ) {
$lastinsertrow = $entry.TimeGenerated
write-host $lastinsertrow
}
# record
# [int]$entry.RecordNumber
# time
$datarr=$entry.TimeGenerated.split(".")
# user
#$entry.InsertionStrings[2]
# docname
#$entry.InsertionStrings[1]
# drucker
#$entry.InsertionStrings[3]
# pages
#$entry.InsertionStrings[6]
# bytes
#$entry.InsertionStrings[5]
write-host "working on $datarr..."
$cmd = $conn.CreateCommand()
$cmd.CommandText = "INSERT INTO [dbo].[jobs] (datetime, username, docname, printer, pages, size) VALUES ('" + $datarr[0] + "','" + $entry.InsertionStrings[2] + "','" + $entry.InsertionStrings[1] + "','" + $entry.InsertionStrings[4] + "'," + $entry.InsertionStrings[7] + "," + $entry.InsertionStrings[6] + ")"
$cmd.ExecuteNonQuery() | out-null
}
$cmd = $conn.CreateCommand()
$cmd.CommandText = "UPDATE [dbo].[configs] SET wert = '" + $lastinsertrow + "' WHERE schluessel = 'lastinsertrow'"
$cmd.ExecuteNonQuery() | out-null
$conn.close()
Write-Host "Latest-Record: $lastinsertrow" -back red
Datenbankschemas
Und hier noch die Datenbankschemas der beiden benötigten Tabellen. Der Datenbankname selbst ist hier prnacc und muss wenn er geändert wird auch noch im Powershell-Script angepasst werden.SQL Schema für Tabelle configs
USE [prnacc]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[configs](
[id] [int] IDENTITY(1,1) NOT NULL,
[schluessel] [nvarchar](50) NOT NULL,
[wert] [nvarchar](max) NOT NULL,
CONSTRAINT [PK_configs] PRIMARY KEY CLUSTERED
(
[id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SQL Schema für Tabelle jobs
USE [prnacc]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[jobs](
[datetime] [nvarchar](50) NOT NULL,
[username] [nvarchar](50) NOT NULL,
[docname] [nvarchar](max) NOT NULL,
[printer] [nvarchar](50) NOT NULL,
[pages] [int] NOT NULL,
[size] [bigint] NOT NULL
) ON [PRIMARY]
GO
Aufruf
Das Script selbst kann, wie bereits gesagt, über einen geplanten Task aufgerufen werden.Hierzu ist als Kommandozeile Folgendes zu verwenden:
powershell.exe -Noninteractive -Command "&{PFAD_ZUM_SCRIPT}"