View Łukasz Herman's LinkedIn profileView my profile

statystyki www stat.pl

piątek, 23 grudnia 2011

Ostatnio powróciłem do tematu wdrażania SCOMa i zaobserwowałem na kilku komputerach ostrzeżenia związane z fragmentacją dysków. Gdyby to były zwykłe komputery a nie maszyny wirtualne, to kwestia byłaby jasna, ale czy należy defragmentować dyski maszyn wirtualnych?

Odpowiedź powinna brzmieć tak, należy je defragmentować ale należy zwrócić uwagę na to by:

1. Nie defragmentować dysków które mająsnapshoty,

2. Jeżeli nie ma snapshotów, upewnić się że dyski są zmerge'owane (tj. wszystkie snapshoty jakie były zostały już włączone do dysku),

3. Nie defragmentować dysków na wielu maszynach jednocześnie gdy korzystają one z tego samego zasobu/macierzy

Bardziej obszernie: Defragmenting virtual machine disk files 

Tagi: Hyper-V
02:38, hermanluk , Off Topic
Link Komentarze (2) »
wtorek, 20 grudnia 2011

Walczę z powiadomieniami w SCOMie i natknąłem się na taki komunikat błędu. Przy czym maila mam wprowadzonego poprawnie.

Okazuje się, że problemem jest przesłanie maila przez serwer SMTP (ponieważ nie odblokowałem Relaya dla SCOMa).

SCOM R2 E-Mail Notifications do not work: Error message ‘Recipient address is not valid’ is shown

Tagi: SCOM
14:26, hermanluk , Off Topic
Link Dodaj komentarz »
czwartek, 08 grudnia 2011

Ostatnio zacząłem zastanawiać się jakiego laba sobie zrobić w domu, by móc czasem coś przetestować/przeklikać i doszedłem do wniosku że warto mieć na boku jakiś serwer z maszynami wirtualnymi.

Postawiłem więc Hyper-V Server na cztero letnim laptopie, w którym wcześniej miałem problem z grafiką. Radość nie trwałą długo gdyż:

1. 3 GB pamięci to trochę mało by zainstalować cośz rodziny System Center, nie wspominając że trzeba zostawić coś hostowi i drugiej maszynce z kontrolerem domeny.

2. Dysk twardy 100GB to mało by bawić się w wirtualizację, a o snapshotach można zapomnieć.

 

No to mam przed sobą nowego laptopa, którego nawet w 10% nie wykorzystuję. Tylko że mam na nim Windows 7, a nie Hyper-V Server. W dodatku nie chce mi się niczego na nowo instalować. Wziąłem więc toola z dawnego Sysinternals - Disk2Vhd.

Bardzo fajne narzędzie, działa na funkcjonującym systemie, więc nie musiałem przerywać pracy :) Z uwag to pamiętać trzeba by robić obraz partycji systemowej oraz tej 100MB rezerwowanej przy partycjonowaniu, bo inaczej nie da się uruchomić systemu jako maszynę wirtualną.

Plik VHD podrzuciłem pod Hyper-V Server i... przypomniałem sobie jak system wolno działa na dysku, który nie jest w technologii SSD. Ale działa.

 

Teraz zastanawiam się czy dzielić mojego "twardziela" SSD 60 GB na dwa systemy, bo nie wyobrażam sobie pracowania na systemie zainstalowanym na tradycyjnym twardzielu, czy w ogóle zrezygnować z tematu i poczekać na Windows 8, który będzie miał jakieś wbudowane Hyper-V.

VirtualPC odpada ze względu na brak obsługi systemów 64-bitowych, VirtualBox bo za często pada (miałem mase problemów ze stawianiem maszyn wirtualnych), a produkty VMware ze względu na cene i że na co dzień z nich nie korzystam.

Kusi mnie wykorzystanie Hyper-V na tym laptopie, ze względu na to że system jestem w stanie postawić na SSD, oraz że mam drugi dysk (w miejsce napędu optycznego). I tu raczej problemu z przestrzenią dyskową nie będzie, bo jak tylko dyski stanieją to kupię coś dużego w rozmiarze 2,5 :)

niedziela, 23 października 2011

Krótko i na temat:

dism /online /cleanup-image /spsuperseded

Potrafi wywalić nawet parę zbędnych GB. 

Tagi: win7 winsxs
07:58, hermanluk , Off Topic
Link Dodaj komentarz »
czwartek, 29 września 2011

Zacząłem bawić się w konfigurację WSUSa. Wszystko fajnie działało, dopóki na jednej z maszyn jedna z aktualizacji nie chciała się zalogować. Restarty nie pomagała, a co gorsza Server Manager nie potrafił wyświetlić zainstalowanych ról plując błędem.

Rozwiązanie jest bardzo proste i ciekawe. A odpowiada za nie KB947821. Instalując ten pakiet, skanuje on i nawet poprawia błędy!

Szczegóły jak sobie radzić z błędami, gdy któraś z poprawek nie chce się zainstalować znajdziemy pod adresem How to fix Server Manager Errors after installing updates (HRESULT:0x800F0818 / HRESULT:0x800B0100)

U mnie wystarczyło odpalić instalację poprawki, żeby w logu przeczytać że znaleziono jeden błąd i go poprawiono :)

Co ciekawe na kilkanaście serwerów, błąd ten pojawił się już na dwóch. Ciekawe co jak zacznę używać WSUSa na większą skalę? 

środa, 21 września 2011

Rozpoczęcie pracy z PowerShellem nie jest moim zdaniem proste. Przynajmniej ja miałem duży problem zanim zrozumiałem jak to mniej więcej działa.

Najważniejszą informacją jest to, że w Windows 7 i Windows Server 2008 R2 znajduje się domyślnie zainstalowany PowerShell 2. Ponadto mamy również dostęp do przydatnego edytora skryptów - Windows PowerShell ISE. Warto o tym wiedzieć, bo ja dotąd ręcznie szlifowałem skrypty w Notepad++ nie zdając sobie sprawy, że mam lepsze narzędzie pod nosem ;)

Druga sprawa to uruchamianie skryptów. Domyślnie, jeżeli mam skrypt w pliku tekstowym, nie możemy go uruchomić w najprostszy sposób. Jest to zabezpieczone w odpowiedni sposób, żeby przypadkiem nieświadomie nie uruchomić jakiegoś skryptu. Dlatego często tworzę sobie specjalny skrót uruchamiający skrypt:

%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy bypass -noexit -File script.ps1

PowerShell posiada wiele modułów, w tym do zarządzania Active Directory lub Exchange. Jeżeli znajdziemy w internecie skrypt korzystający z tych modułów, może się okazać że u nas to nie chce działać.

Wynika to z braku zaimportowanych modułów. Możemy zaimportować je ręcznie, bądź skorzystać z specjalnej, predefiniowanej konsoli PowerShella, która automatycznie ładuje potrzebne moduły. Po instalacji AD lub Exchange, pojawiają się w systemie odpowiednie skróty do tych predefiniowanych konsol (najlepiej szukać ich w narzędziach administracyjnych). 

sobota, 09 lipca 2011

Jakiś czas temu wymyśliłem sobie, ża fajnie by było, gdyby wszystkie zaplanowane zadania, takie jak na przykład backup, konfigurowane były z jednego centralnego miejsca. Oczywiście najlepszym na to rozwiązaniem było skorzystanie z GPO, a zaplanowane zadanie uruchamiać w kontekście dedykowanego użytkownika (z rolą Backup Operator, bo chce tylko backupy robić).

Wielkie było jednak moje zdziwienie, gdy okazało się że nie mogę ręcznie uruchamiać zadań z Task Schedulera, mimo że ustawiłem możliwość uruchamiania On Demand.

Po wielu mozolnych testach, rekonfiguracji, itd. zauważyłem że tylko konto Administrator może uruchamiać ręcznie to zadanie. Inny użytkownik, nawet jeżeli byłby w grupie Enterprise Admin, za każdy razem dostaje komunikat:

"The user account does not have permission to run this task"

Trochę googlowania przyniosło efekt odnalezienie wątku na technecie z podobnym problemem. Padło tam przypuszczenie, że jest to bug w Group Policy Preferences. Faktycznie, tworząc to zadanie ręcznie z dokładnie taką samą konfiguracją (porównywałem XMLe po wyeksportowaniu zadania), zadanie utworzone lokalnie działa jak powinno, zadanie utworzone przez GPO wywala błąd o braku uprawnień.

Po dalszych wnikliwych poszukiwaniach w końcu odnalazłem rozwiązanie problemu. Zadania tworzone przez GPO różnią się jednym małym szczegółem od tych utworzonych lokalnie.

Otóż aby zaczęło to działać, ręcznie musimy dodać uprawnienie Full Control dla grupy BUILTIN\Administrators do utworzonego zadania. Zadanie tworzone lokalnie ma to domyślnie, zadanie utworzone z poziomu GPO daje uprawnienia grupie NT AUTHORITY\SYSTEM zamiast administratorom. Czy jest to bug, czy może zamierzone działania, nie mam pojęcia. Ale chyba  nie powinno to tak wyglądać.

Teraz wystarczy ręcznie nadać odpowiednie uprawnienia wykonując polecenie:

cacls %systemroot%\system32\Tasks\[NAZWA ZADANIA] /e /g BUILTIN\Administrators:F

Oczywiście skoro chce scentralizować zadanie, nie będę biegał po wszystkich serwerach, tylko skorzystam ponownie z GPO i ustawie zabezpieczenia na katalog z wszystkimi zadaniami. Wadą nadawania uprawnień przez GPO jest brak możliwości dodania uprawnienia, zawsze nadpisywane są aktualne listy ACL.

 

 

czwartek, 30 grudnia 2010

Genialne narzędzie do przycinania PDFów. Nie konwerstujące do obrazków. Można nawet jednego PDFa pociąć na kilka mniejszych stron.

Jedyna wada, że trzeba odpalać z palca z lini komend jeżeli nie mamy java.exe w zmiennych środowiskowych.

http://sourceforge.net/projects/briss/

niedziela, 28 listopada 2010

Myślałem że skorzystam z IsolatedStorage w ASP.NET, ale wychodzi na to że nie działa to gdy korzystamy z WebService. No trudno...

Mając już wszystkie providery OleDB czas na sterowniki ODBC ;) Całą noc nad tym problemem siedziałem to wolę to tutaj utrwalić.

Kod wygląda bardzo niepozornie:

public string getODBC()
{
string ret = "";
string registryPath = @"SOFTWARE\ODBC\ODBCINST.INI";
RegistryKey hklm = Registry.LocalMachine;
hklm = hklm.OpenSubKey(registryPath);
string[] values = hklm.GetSubKeyNames();
foreach (var value in values)
{
ret += value;
}
return ret;
}

Ale w praktyce wyciąga z rejestru dużo więcej niż ja mogłem zobaczyć odpalając regedita.

W moim przypadku kod ten zwraca listę 27 elementów. Ja w rejestrze widzę nie więcej jak 5, więc różnica jest.

Dalej metodą prób, błędów i googla testowałem różne konfiguracje na hostingu. Aż do skutku. Oj bolało, możliwości jest masa!

W tej chwili mój connection string to wyciągania danych z bazy DBF (VisualFoxPro) bez posiadania sterownika VFP jest już kompletny, chociaż w pewnym stopniu hardkodowany. Później go poprawię jak należy, ważne że działa :)

A wygląda on tak:

Driver={Driver do Microsoft dBase (*.dbf)};DriverID=277;Dbq=" + @"dluga_sciezka_do_katalogu\DataManager\";

Ważne jest to, że parametr 'DBQ' wskazuje na KATALOG a nie na plik!

Tagi: DBF ODBC
07:57, hermanluk , Bazy danych
Link Dodaj komentarz »

Najprościej z rejestru. Potrzebowałem poznać jakie dostępne są na serwerze na któym mam wykupiony hosting. Znalazłem kod VB który to robi, przekonwertowałem go na C# (jakimś online'owym konwerterem) i trochę zmodyfikowałem, żeby zwracał mi w miarę czytelnego stringa.

Konwerter.

Oryginalny kod.

using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using Microsoft.Win32;


namespace DataManager
{
class Module1
{

public String CountASAS()
{
int i = 0;
DictionaryEntry[] de = SearchOleDbProviders();
string wynik = "";

// Displays the ProgID and name of each provider
for (i = 0; i <= de.Length - 1; i++)
{
wynik += de[i].Key + " - ";
wynik += de[i].Value + " ; ";
}

//Waits for user input
return wynik;
}

public DictionaryEntry[] SearchOleDbProviders()
{
DictionaryEntry[] Providers = null;
Int16 nProviders = 0;

nProviders = -1;
Providers = new DictionaryEntry[1];

// I am only interested in the CLSID subtree
RegistryKey keyCLSID = Registry.ClassesRoot.OpenSubKey("CLSID", false);
string[] keys = keyCLSID.GetSubKeyNames();
DictionaryEntry de = default(DictionaryEntry);
Int32 i = 0;

// Search through the tree just one level
for (i = 0; i <= keys.Length - 1; i++)
{
RegistryKey key = keyCLSID.OpenSubKey(keys[i], false);

// Search for OLE DB Providers
de = SearchKeys(key);
if ((de.Key != null))
{
// Found one, add it to the Dictionary
nProviders += 1;
Array.Resize(ref Providers, nProviders + 1);
Providers[nProviders] = de;
}
}
return Providers;
}

public DictionaryEntry SearchKeys(RegistryKey key)
{
Int32 i = default(Int32);
DictionaryEntry de = default(DictionaryEntry);

//Tries to find the "OLE DB Provider" key
RegistryKey key2 = key.OpenSubKey("OLE DB Provider");

if ((key2 != null))
{
// Found it, fills the DictionaryEntry
de = new DictionaryEntry();
string[] sValues = key2.GetValueNames();
de.Key = key.OpenSubKey("ProgID", false).GetValue(sValues[0]);
string[] sValues2 = key2.GetValueNames();
de.Value = key2.GetValue(sValues2[0]);
}
return de;
}
}
}

 

czwartek, 25 listopada 2010

Potrzebowałem wyciągnąć z SQLa wszystkie znaki do jakich mam dostęp przez funkcję CHAR.

Wyszło coś takiego:

declare @counter int
set @counter = 0
while @counter <255
begin
set @counter = @counter + 1
print cast(@counter as char) + ' ' + cast(CHAR(@counter) as char)
end

Tagi: Sql
01:51, hermanluk , Bazy danych
Link Dodaj komentarz »
wtorek, 23 listopada 2010

Taki komunikat otrzymuję tworząc paczkę SSIS. Rozwiązanie robocze to zmiana we właściwościach OLEDB Source:

1. AlwaysUseDefaultCodePage=true

2. Zmiany DefaultCodePage na 1252

Po tym wystąpił kolejny błąd (jakby mnie to zdziwiło...)

SQL Server Destination] Error: Unable to prepare the SSIS bulk insert for data insertion.
[SSIS.Pipeline] Error: component "SQL Server Destination" failed the pre-execute phase and returned error code 0xC0202071.

Tutaj jest już jasne rozwiązanie z MS Knowledge Base: You may get "Unable to prepare the SSIS bulk insert for data insertion" error on UAC enabled systems

Ok. Nie jest źle. SSIS działa. Importuje nawet dane. Tylko muszę powalczyć z kodowaniem znaków bo mam krzaki w bazie.

Jak robiłem Selecta bezpośrednio z Visual FoxPro, to musiałem jeszcze przekonwertować dane za pomocą:

SELECT CPCONVERT(620, 1250,kolumna) FROM KOLUMNA.DBF

Dziwne jest to, że ze źródła wychodzą dobre kodowanie, a podczas zapisywania do bazy docelowej kodowanie się rozjeżdża.

Po wielu kombinacjach (w zasadzie to chyba wszystkie przetestowałem), doszedłem do tego że kodowanie wszędzie ma być ustawione na 1250. Z pliku DBF dane wyciągam korzystając z kodu SQL i robię od razu konwersję za pomocą CPConvert (patrz wyżej).

Następnie dane wędrują do bazy MSSQL, ale nie jako standardowe połączenie z MSSQLem, ale korzystając z OleDB. Tylko w ten sposób kodowanie pozostaje prawidłowe.

Bardzo fajny opis jak dobrać się do danych zapisanych w formacie XML z poziomu SQLa:

Generating Relational data from xml datatype Part 1

Generating Relational data from xml datatype Part 2

Tagi: Sql xml
01:28, hermanluk , Bazy danych
Link Dodaj komentarz »
niedziela, 21 listopada 2010

Tworzę paczkę SSIS (SQL Server Integration Services) żeby wgrać pliki z bazy Visual FoxPro (.DBF) do MSSQL. Niestety nic nie działa tak jak powinno 'by default'.

Pierwsze co, to w wizardzie nie ma możliwości wyboru odpowiedniego Providera do odczytu plików DBF.

Stworzyłem więc paczkę od zera.

1. Utworzenie nowego Data Flow

2. Dodanie OLEDB Source i stworzenie połączenia do pliku DBF

2. Dodanie SQL Server Destination i wskazanie bazy docelowej (MSSQL)

3. Połączyłem je razem, ustawiłem mapowanie kolumn.

Pierwszy błąd jak w tytule. Kliknąłem więc prawym klawiszem myszki na OLEDB Source i wybrałem Show Advanced Editor -> Input and Output Properties -> Source Output -> Output Columns, wybrałem kolumnę która zgłasza błąd i zmieniłem jej DataType na four-byte signed integer (DT_I4).

Przeszło :)

Teraz zgłasza mi błąd "cannot be processed because more than one code page (1250 and 1252) are specified for it."...

Tagi: DBF Sql SSIS
14:27, hermanluk , Bazy danych
Link Dodaj komentarz »

Zapamiętać: Server project zawsze modyfikuje bazę Master.

Już myślałem, że z moim Visual Studio jest coś nie tak, bo usilnie zmieniał mi bazę na Master, zamiast korzystać z tej ustawionej przeze mnie. Po prostu za szybko przeczytałem opis czym te dwa projekty się różnią.

czwartek, 18 listopada 2010

ASP.NET oferuje nam specjalną izolatkę (przestrzeń dyskową) dla naszych aplikacji.

Potrzebując wrzucić na serwer jakiś plik, nie musimy przejmować się poziomem uprawnień użytkownika na którym działa proces IISa, tylko zapisujemy plik korzystając z tej funkcjonalności.

Taki krótki kodzik, który zapisuje przekazany plik, zwracając ścieżkę do katalogu gdzie został zapisany:

public string SaveFile(byte[] binaryFile, string path)
{
 IsolatedStorageFile isf = IsolatedStorageFile.GetStore(
IsolatedStorageScope.User | IsolatedStorageScope.Domain |
IsolatedStorageScope.Assembly, null, null);
 try
 {
 IsolatedStorageFileStream file = new IsolatedStorageFileStream(path, 
FileMode.Create, isf);
 file.Write(binaryFile, 0, binaryFile.Length);
 file.Close();
 }
 catch (Exception ex)
 {
 }

 string path2 = isf.GetType().GetField("m_RootDir", 
BindingFlags.Instance | BindingFlags.NonPublic).GetValue(isf).ToString();
 return path2;

Wrrrr, kto wymyślił wyświetlanie wyjątków w języku polskim? Przecież to się do niczego nie nadaje...

Jak się tego pozbyć? Chyba się nie da. Zmieniać ustawień regionalnych nie mam zamiarua

A zmiana ustawień z poziomu kodu jak to zostało przedstawione w wątku C# - Exception messages in English?, przy każdym wywołaniu przeraża mnie. No trudno, trzeba nauczyć się czytać polskie błędy.

PS. Błąd z tytułu oznacza, że korzystam ze starej wersji sterownika, która nie jest już kompatybilna z tym co chcę zrobić.

środa, 17 listopada 2010

Fajny i bardzo prosty sposób jak zbudować kontrolkę Menu, wraz z implementacją dodatkowych atrybutów które deklarujemy sobie w pliku web.sitemap

W tym wypadku jest to atrybut odpowiedzialny za wyświetlanie, bądź nie, pozycji z pliku mapy strony. Ja dopisałem sobie atrybut odpowiedzialny za klasę CSS. Działa wyśmienicie :)

I bet you didn't know that adding custom attributes to your web.sitemap was this easy!

poniedziałek, 15 listopada 2010

W pisanej aplikacji potrzebuję prostego sprawdzenia czy użytkownik wpisał dobrą zawartość pola. Dokładniej to robię upload plików, chcąc mieć pewność, że podano prawidłową nazwę pliku (lub dobry typ pliku).

Pomyślałem żeby zrobić to poprzez Visual Studio i kontrolkę Validate i sprawdzać wyrażenie regularne. Zalet jest sporo, nie martwimy się o to, jak działa to na różnych przeglądarkach, oraz mamy sprawdzanie kodu po stronie klienta (jeżeli sobie tego zażyczymy) oraz sprawdzanie po stronie serwera (czyli to co najważniejsze).

Minusy?

  • Sprawdzanie po stronie klienta wymaga umieszczania na stronie kodu JavaScript. Tylko kontrolka dodaje cały swój kod, a nie tylko ten, który będziemy wykorzystywać. Po co mi sprawdzanie czy wprowadza się dobrą liczbę, skoro ja sprawdzam tylko wyrażenie regularne?
  • Nawet jak wyłączymy sprawdzanie po stronie klienta, dodawanych jest mnóstwo JavaScriptów, które raczej nie są wykorzystywane.

Napisałem własnego JavaScripta sprawdzającego wyrażenie regularne. Cały kod związany z validacją po stronie klienta to ok. 20 linijek. Nie widzę żadnego sensu wrzucania masy niepotrzebnego kodu na stronę.

Swoją drogą, sprawdzenie tego samego wyrażenia regularnego po stronie serwera to ok. 5 linijek kodu, czyli mniej niż potrzeba na dodanie kontrolki Validator...

Bardzo obszerny post na jednym z blogów. Masa linków powiązanych z tematem uwierzytelniania w aplikacjach ASP.NET, wszystko co związane z tematami: Membership, Roles, Forms Authentication i Security Resources.

ASP.NET 2.0 Membership, Roles, Forms Authentication, and Security Resources

niedziela, 14 listopada 2010

Bardzo ciekawy wpis na jednym z SQLowych blogów. Dlaczego nie powinniśmy korzystać z typu money?

Otóż pociąga za sobą ogromne błędy obliczeniowe. Co prawda nie zawsze spotka to nas, ale lepiej dmuchać na zimne i korzystać ze sprawdzonego typu decimal ;)

Throw Your MONEY Away

Znalazłem fajny opis w jaki sposób dodać zewnętrzny kod JavaScriptowy do mojej kontrolki.

Jest kilka sposobów w jaki możemy odwoływać się do skryptów JS. Ja potrzebowałem aby mój zewnętrzny plik był ładowany zawsze tam, gdzie używam mojej kontrolki.

Rozwiązanie: Creating Custom ASP.NET Server Controls with Embedded JavaScript

Jedyna różnica jest taka, że musiałem ręcznie dodać "[assembly..."  na początku mojej kontrolki, żeby kod JS był widoczny. A dokładniej:

[assembly: WebResource("WI_Controls.Scripts.FileExtensionController.js", "java-script")]

zaraz przed namespace.

 

piątek, 05 listopada 2010

Jakiś czas temu w pracy natknąłem się na dziwną przypadłość w VB Scriptcie. Tworząc procedury lub funkcje, w żaden sposób interpreter nas nie pilnuje czy nie zadeklarowaliśmy tej samej procedury dwa (lub więcej) razy. Pamięta ostatnio zadeklarowaną wersję i z niej możemy korzystać.

Chyba, że skorzystamy z funkcji Execute. Przydaje sięona, gdy chcemy korzystać z funkcji zawartych w zewnętrznych plikach (repozytorium procedur lub coś w tym stylu). Wtedy za każdym razem VB Script wykonuje ostatnio wykonaną funkcję zadeklarowaną przez Execute.

Dim X ' Declare X in global scope.
X = "Global" ' Assign global X a value.

Sub Proc1
Dim X ' Declare X in local scope.
X = "Local" ' Assign local X a value.
' The Execute statement here creates a
' procedure that, when invoked, prints X.
' It print the global X because Proc2
' inherits everything in global scope.
Execute "Sub Proc2: WScript.Echo X: End Sub"
WScript.Echo Eval("X") ' Print local X.
Proc2 ' Invoke Proc2 in Proc1's scope.
End Sub

'Proc2 ' This line causes an error since
' Proc2 is unavailable outside Proc1.
Proc1 ' Invoke Proc1.
Execute "Sub Proc2: WScript.Echo X: End Sub"
Proc2 ' This invocation succeeds because Proc2
' is now available globally.

Warto sobie przeanalizować ten przykład (i trochę pomodyfikować).

Stanąłem przed zastanawiającą kwestią. Potrzebuje uploudować dwa pliki z dysku lokalnego na serwer poprzez WebServices. Wariantów jest sporo. Można skorzystać z kontrolekFileUpload, dodać ręcznie pola wyboru i przyciski, skorzystać z gotowych kontrolek (NeatUpload), albo napisać coś własnego.

Wybrałem (na razie) rozwiązanie bezpośrednie. Napiszę własną kontrolkę (warto się tego nauczyć), która będzie zbudowana z dwóch kontrolek FileUpload.

Teoretycznie najprostszym sposobem byłoby rozszerzenie kontrolki FileUpload o potrzebną mi funkcjonalność, ale potrzebuję co najmniej dwóch takich kontrolek. Wpadłem więc na pomysł, żeby stworzyć własną kontrolkę, która będzie zawierała w sobie inne kontrolki.

Po zrobieniu małego researchu udało mi się dojść do tego, że muszę stworzyć kontrolkę rozszerzając klasę CompositeControl zamiast WebControl (jak to się robi pisząc najprostszą kontrolkę) i to działa bardzo fajnie :)

Wystarczy nadpisać procedurę CreateChildControls i możemy dodawać do własnej kontrolki cokolwiek zapragniemy.

Więcej: http://www.joe-stevens.com/2010/04/16/creating-a-composite-server-control-with-asp-net/

 
1 , 2 , 3 , 4 , 5 ... 10