středa 27. ledna 2010

Seznam přihlášených uživatelů

Dnešní příspěvek je opravdu dlouhý, ale ve skutečnosti popisuje vcelku jednoduchou věc - PowerShellový skript pro snadné získání seznamu přihlášených uživatelů. Taková informace je při údržbě AX prostředí potřeba dost často, pokud chcete brát ohledy na přihlášené uživatele a nevypínat jim služby pod rukama. Lze se samozřejmě přihlásit do AX, otevřít modul Administrace, formulář Uživatelé online a tam ověřit, zda je někdo přihlášený. To ale dost zdržuje a tak jsem si tento úkol trochu zjednodušil skriptem, který umožní zvolit konfigurační soubor Dynamics AX, připojí se pomocí Business Connectoru a vypíše přihlášené uživatele do konzolového okna. Trochu blíže k předpokladům pro tento skript:
  • Konfigurační soubory (.axc) pro všechna prostředí jsou uložena v jednom adresáři (viz proměnnou $configurationPath) a týkají se Dynamics AX 2009. V tomto ohledu jsem jen využil existující systém v naší firmě, vy si možná budete muset skript upravit.
  • Nainstalovaný Business Connector
  • PowerShell 2.0
  • .NET 3.0+ (kvůli WPF)
První skript příjmá jako parametr ($args[0]) jméno konfiguračního souboru. Načte sestavení BussinessConnectorNet.dll, vytvoří objekt typu Axapta a zaloguje se pomocí konfiguračního souboru (v něm je adresa AOS atd.). V dalším kroku se dotáže na uživatelská připojení (tabulka SysClientSessions), popř. další informace o uživateli a AOS. Tyto informace zabalí do objektu (což usnadňuje další zpracování) a ten předá na výstup. Ukázka výsledku: Zdrojový kód vypadá takto (některé řádky byly kvůli přehlednosti zalomeny):
$connectorDllPath = 'C:\Program Files\Microsoft Dynamics AX\50\' `
    + 'Client\Bin\Microsoft.Dynamics.BusinessConnectorNet.dll'
$configurationPath = 'D:\CONFIGURATIONS'
$configurationName = $args[0]
$configFile = Join-Path $configurationPath $configurationName

if (!(Test-Path $configFile))
{
    throw "Konfigurace $configFile nebyla nalezena"
}

#zalogování do AX pomocí Business Connectoru
try
{
    [void][reflection.Assembly]::Loadfile($connectorDllPath)
    $ax = New-Object Microsoft.Dynamics.BusinessConnectorNet.Axapta
    $ax.logon('', '', '', $configFile)
}
catch
{
    throw 'Přihlášení pomocí Business Connectoru se nezdařilo'
}

#objekty představující AX tabulky
$sysClientSessions = $ax.CreateAxaptaRecord('SysClientSessions');
$sysServerSessions = $ax.CreateAxaptaRecord('SysServerSessions');

#dotaz na aktivní uživatele přihlášené přes GUI
$sysClientSessions.ExecuteStmt('select * from %1 where %1.Status == 1 ' `
    + '&& %1.ClientType == 0');
if (!$sysClientSessions.Found)
{
    '0 aktivních uživatelů'
}

#iterace přes uživatele, získaní podrobných informací a zabalení do objektu
while ($sysClientSessions.Found)
{
    $userId = $sysClientSessions.get_Field('UserId')
    $userName = $ax.CallStaticClassMethod('UserInfoHelp', 'userName', $userId)

    $sysServerSessions.ExecuteStmt('select * from %1 where %1.ServerId == ' `
       + $sysClientSessions.get_Field('ServerId'))
    $aosInstanceName = $sysServerSessions.get_Field('AOSId')

    #zabalení do objektu
    New-Object PSObject -Property @{
       AosName = $aosInstanceName
       UserId = $userId
       UserName = $userName}

   [void]$sysClientSessions.Next();
}
#odhlášení z AX
[void]$ax.logoff()
Druhý skript slouží k výběru konfigurace AX a jméno této konfigurace předává prvnímu skriptu. Seznam konfigurací je zobrazen v grafickém okně, protože kliknutí mi přišlo jako nejrychlejší způsob výběru. GUI je vytvořeno pomocí WPF (Windows Presentation Foundation) a vypadá takto (s tím rozdílem, že já tam mám konfigurací celkem 42): Seznam konfigurací je naplněn pomocí příkazu Get-ChildItem (alias dir). Zvolená konfigurace ($listBox.SelectedItem) je použita jako parametr pro výše uvedený skript a daný kód je umístěn v obsluze kliknutí na tlačítko ($button.add_Click()).
$configurationPath = 'D:\CONFIGURATIONS'
Add-Type –assemblyName PresentationFramework
Add-Type –assemblyName PresentationCore

Add-Type –assemblyName WindowsBase

$window = New-Object Windows.Window
$window.Title = 'AX konfigurace'
$window.SizeToContent = 'WidthAndHeight'
$label = New-Object Windows.Controls.Label
$label.Content = 'Seznam konfigurací:'

$listBox = New-Object Windows.Controls.Listbox
$listBox.ItemsSource = (% {Get-ChildItem $configurationPath -Include *.axc -Name})

$button = New-Object Windows.Controls.Button
$button.Content = 'Zobraz přihlášené uživatele'
$button.add_Click(
{
    if ($listBox.SelectedItem)
    {
        $window.Hide()
        Write-Host $listBox.SelectedItem

        try
        {
            #volání samostatného skriptu na získání informace o uživatelích
            $activeUsers = (absolutníCesta\prvníSkript.ps1 $listBox.SelectedItem)
        }
        catch
        {
            Write-Host $error[0] -ForegroundColor Red
            exit
        }
   }
})

$stackPanel = New-Object Windows.Controls.StackPanel
$stackPanel.Orientation = 'Vertical'

[void]$stackPanel.Children.Add($label)
[void]$stackPanel.Children.Add($listbox)
[void]$stackPanel.Children.Add($button)

$window.Content = $stackPanel

[void]$window.ShowDialog()

$textbox.Text
$activeUsers
Protože WPF okno vyžaduje běh v STA módu (Single-Threaded Apartment; neznám smysluplný překlad), nelze tento skript spustit běžným způsob. Jednou (a nejjednoduší) možností je zavolání PowerShellu s parametrem -STA, takže spuštěcí příkaz lze napsat (a uložit do .lnk) třeba takto:
C:\WINDOWS\system32\WindowsPowerShell\v1.0\powershell.exe
-STA
-noexit
-command cesta\jmenoSkriptu.ps1

1 komentář: