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

pondělí 25. ledna 2010

Zobrazení stavu uživatele v Dynamics AX

Dynamics AX ve verzi 2009 podporuje zobrazování stavu (K dispozici, Na schůzce apod.) z Microsoft Office Communicator Serveru. Pro společnosti, které Office Communicator používají, to může být velmi užitečná cesta ke zjednodušení a zrychlení komunikace. Například zobrazení stavu zaměstnance zodpovědného za objednávku může vypadat takto: V poli (pozor, nefunguje v gridu) je krom ID zaměstnance zobrazena také stavová ikona, na kterou je možné kliknout a spustit související funkce (poslat zprávu, zavolat atd.). Tyto funkce už řeší samostatné klientské aplikace (Office Communicator, Outlook), ne Dynamics AX. K tomu, aby to celé fungovalo, je třeba:
  • Dynamics AX 2009
  • Microsoft Office Communications Server 2007 R2
  • Microsoft Office Communicator 2007 R2
Dále je nutné nastavit cílové osobě veřejný kontakt (typ kontaktní informace musí mít jako komunikační metodu e-mail), vyplnit e-mailovou adresu a zaškrtnout Communicator sign-in address (Přihlašovací adresa komunikujícího). Takto je nastaven kontakt pro předchozí příklad (adresa typu Instant Messenger vyhovuje podmínce): Dynamics AX začne od této chvíle zobrazovat stavovou ikonu pro (skoro) všechna pole daného datového typu (ID zaměstnance, kontaktní osoby atd.). Jiný případ nastane, chcete-li použít stejnou logiku například pro ID dodavatele. Přestože nastavíte vyhovující kontaktní informace, stavová ikona se nezobrazí. Datový typ pro ID dodavatele totiž není defaultně nastaven pro podporu této funkcionality. Změna je však velmi jednoduchá, stačí na datovém typu definovat, jaká třída a metoda vrací informaci o stavu kontaktu (instanci třídy PresenceInfo). Patřičná logika pro ID dodavatele je v AX již připravena, stačí tedy na datovém typu VendAccount nastavit vlastnost PresenceClass na DirPresenceInfo a PresenceMethod na vendInfo.Třídu DirPresenceInfo je možné zobrazit v AOT a podívat se na implementaci příslušné metody. V případě jiného datového typu může být nutné patřičnou metodu vytvořit. Uživatelé často pracují spíše se jménem osoby než s jejím ID. Pro tento případ umožňuje AX nastavit formulářovému prvku jiný zdroj stavových informací než je jeho datový zdroj. Tuto logiku AX implementuje například pro jméno dodavatele, takže v předchozím případě je stavová ikona zobrazena ve formuláři Dodavatelé v poli Jméno (záložka Obecné). Ani tento krok není složitý - stačí na příslušném formulářovém prvku nastavit vlastnosti PresenceDataSource a PresenceDataField: Jak je z obrázků patrné, je také možné zakázat zobrazování stavové informace a to jak na úrovni konkrétního fomulářového prvku, tak na úrovni datového typu.

pondělí 11. ledna 2010

Klávesové zkratky

Dianne Siebold z Microsoftu na svém blogu nedávno vzpomněla klávesové zkratky pro Dynamics AX a přiložila jejich zjednodušený seznam (kompletní, ale méně přehledný HTML seznam lze vygenerovat zavoláním AX klienta s parametrem -internal=GENERATEKEYHELP). Pár zkratek pro mě bylo nových a některé další jsem si připomněl, tudíž doporučuji občas přečíst. Diannin dokument je samozřejmě v angličtině, ale seznam generovaný z AX je lokalizován (češtinu bohužel nemohu aktuálně vyzkoušet, prosím případného dobrodince o přidání informace do komentáře).

středa 6. ledna 2010

AX 2009 Development Cookbook

Náhodou se mi dostala do ruky kniha Microsoft Dynamics AX 2009 Development Cookbook a musím říct, že mě příjemně překvapila. Je neobvyklé, že kniha obsahuje více zdrojového kódu než vysvětlujícího textu, ale svůj cíl - poskytnout řešení častých programátorských úkolů - tak plní velmi dobře. Kniha obsahuje popis více než šedesáti úkolů - namátkou třeba vytváření lookupů, práci s číselnými řadami nebo účtování deníků. Vždy je uveden popis problému, zdrojový kód a vysvětlení implementace. Přestože lze tyto informace nalézt i jinde, přehledná referenční příručka je vždy přínosem.

úterý 5. ledna 2010

SysRecurrence

Formulář SysRecurrence slouží k definici opakování nějaké úlohy. Nejčastěji se používá pro nastavení dávkových úloh, takže lze například určit, že se má přepočet skladu spouštět automaticky každou sobotu. V základní podobě vypadá nějak takto: V horní části se nastavuje datum, čas (+ časové pásmo) prvního spuštění a případná ukončovací podmínka (po určitém počtu opakování nebo k určitém datu). V dolní části se pak definuje, jak se má úloha opakovat. Podle zvolené jednotky (minuty, hodiny, dny…) se v pravé části zobrazují další volby, například počet minut či den v týdnu. V případě dávkových úloh je tento formulář přístupný pomocí tlačítka Opakování (Recurrence) v dialogu dávkové úlohy:Získanou definici opakování je samozřejmě možné použít nejen pro dávkové úlohy, ale i třeba pro jednorázové generování plánovaných periodických úkolů a podobně. Implementace Otevřete-li formulář SysRecurrence v AOT, zjistíte, že Design je zcela prázdný. Design je totiž generován dynamicky na základě zadaných parametrů – je možné například vybrat jen určité jednotky nebo umožnit nastavit jen datum startu a nikoli konkrétní čas. Tuto logiku obstarává třída SysRecurrenceBuild. Z třídy SysRecurrenceBuild lze získat uživatelem zadané parametry opakování pomocí metody recurrence(). Ta vrací hodnotu typu SysRecurrenceData, což není nic jiného než obyčejný kontejner (v SysRecurrenceBuild.update() můžete prozkoumat způsob jeho plnění). SysRecurrenceData je pak možné zpracovávat pomocí třídy SysRecurrence. Ta poskytuje například metodu next(), vracející datum a čas dalšího opakování nebo metody čtoucí či modifikující SysRecurrenceData (např. setRecurrenceStartDate()). Použití může vypadat například takto:
SysRecurrenceBuild  recurrenceBuild = new SysRecurrenceBuild();
SysRecurrence       recurrence = new SysRecurrence();
SysRecurrenceData   recurrenceData;
date                runDate;
timeOfDay           runTime;
;

recurrence.initBuildDialog(recurrenceBuild);
recurrence.runBuildDialog();
recurrenceData = recurrence.recurrence();

if (recurrenceBuild.closeOk())
{
   runDate = SysRecurrence::getRecurrenceStartDate(recurrenceData);
   runTime = SysRecurrence::getRecurrenceTime(recurrenceData);

   while (runDate)
   {
       info(strFmt("%1 %2", runDate, time2str(runTime, -1, -1)));
       [runDate, runTime] = SysRecurrence::next(recurrenceData, runDate, runTime);
   }
}
Pokud jsou před vyvoláním dialogu změněny parametry SysRecurrenceBuild, vygeneruje se odlišný formulář. Například zavoláním
recurrenceBuild.addUnit(SysRecurrenceUnit::Day);
recurrenceBuild.addUnit(SysRecurrenceUnit::Week);
recurrenceBuild.addUnit(SysRecurrenceUnit::Month);
recurrenceBuild.showTime(false);
získá dialog následující podobu: Podobná, byť o něco složitější implementace se nachází ve třídě SysRecurrenceRun. Právě tato třída je volána z dialogu dávkových úloh (tlačítko je automaticky přidáno v BatchInfo.dialog()). Kromě podpory dávkových úloh umožňuje SysRecurrenceRun snadnou implementaci do libovolného formuláře – stačí přidat menu item SysRecurrenceRun a implementovat metodu recurrence(), kam SysRecurrenceRun předá kontejner SysRecurrenceData. Dále jsou podporované metody recurrenceText() pro textový popis opakování a recurrenceUnits() a recurrenceShowTime() pro ovlivnění designu formuláře. Ukázku lze najít na formuláři Tutorial_Recurrence.

pondělí 4. ledna 2010

Šťastný nový rok!

Vše nejlepší v roce 2010! V letošním roce se můžeme těšit na novou verzi Dynamics AX ("6" či "2011"), nové Office, SharePoint, Visual Studio, Team Foundation Server a tak dále, takže nudit se určitě nebudeme. Mimochodem, betaverze řady produktů je možné již nějaký čas testovat a můžete se tak s novinkami v klidu a včas seznámit. Nové produkty v mnoha případech vyžadují také nový operační systém, takže i v tomto směru nás jistě nás čekají změny, ve vetšině případů zatím odkládané. Pro mě osobně byla migrace na Windows 7 i příležitostí opustit 32-bitovou architekturu. Pokud bych si dával nějaká předsevzetí do nového roku, na místě by jistě byl slib dokončit všechny rozpracované příspěvky pro blog, který jsem v poslední době velmi zanedbával. Tak uvidíme, sám jsem zvědav, jak to stihnu... :-)