Windows Update install#

Ku pamięci -  na stronach MSDN, przy dokumentacji dotyczącej API do Windows Update, znajduję się skrypt który wymusza pobranie i instalacje aktualizacji z Windows Update:

 

Set updateSession = CreateObject("Microsoft.Update.Session")
Set updateSearcher = updateSession.CreateupdateSearcher()
WScript.Echo "Searching for updates..." & vbCRLF
Set searchResult = _
updateSearcher.Search("IsInstalled=0 and Type='Software'")
WScript.Echo "List of applicable items on the machine:"
For I = 0 To searchResult.Updates.Count-1
    Set update = searchResult.Updates.Item(I)
    WScript.Echo I + 1 & "> " & update.Title
Next
If searchResult.Updates.Count = 0 Then
	WScript.Echo "There are no applicable updates."
	WScript.Quit
End If
WScript.Echo vbCRLF & "Creating collection of updates to download:"
Set updatesToDownload = CreateObject("Microsoft.Update.UpdateColl")
For I = 0 to searchResult.Updates.Count-1
    Set update = searchResult.Updates.Item(I)
    WScript.Echo I + 1 & "> adding: " & update.Title 
    updatesToDownload.Add(update)
Next
WScript.Echo vbCRLF & "Downloading updates..."
Set downloader = updateSession.CreateUpdateDownloader() 
downloader.Updates = updatesToDownload
downloader.Download()
WScript.Echo  vbCRLF & "List of downloaded updates:"
For I = 0 To searchResult.Updates.Count-1
    Set update = searchResult.Updates.Item(I)
    If update.IsDownloaded Then
       WScript.Echo I + 1 & "> " & update.Title 
    End If
Next
Set updatesToInstall = CreateObject("Microsoft.Update.UpdateColl")
WScript.Echo  vbCRLF & _
"Creating collection of downloaded updates to install:" 
For I = 0 To searchResult.Updates.Count-1
    set update = searchResult.Updates.Item(I)
    If update.IsDownloaded = true Then
       WScript.Echo I + 1 & "> adding:  " & update.Title 
       updatesToInstall.Add(update)	
    End If
Next
	WScript.Echo "Installing updates..."
	Set installer = updateSession.CreateUpdateInstaller()
	installer.Updates = updatesToInstall
	Set installationResult = installer.Install()
	
	'Output results of install
	WScript.Echo "Installation Result: " & _
	installationResult.ResultCode 
	WScript.Echo "Reboot Required: " & _ 
	installationResult.RebootRequired & vbCRLF 
	WScript.Echo "Listing of updates installed " & _
	 "and individual installation results:" 
	
	For I = 0 to updatesToInstall.Count - 1
		WScript.Echo I + 1 & "> " & _
		updatesToInstall.Item(i).Title & _
		": " & installationResult.GetUpdateResult(i).ResultCode 		
	Next
Wednesday, June 17, 2009 11:07:56 PM (Central European Standard Time, UTC+01:00) #    Comments [0]  |  Trackback

 

Powershell Remoting w C##

W Powershell  2.0 mamy możliwość zdalnego wykonywania poleceń. Powershell domyślnie też umożliwia odwołania z kodu C#  do comandletów Powershellowych. Jednak połączenie remotingu Powershella oraz C# nie jest prostym zadaniem – brakuje po prostu przykładów. Nawet google jest w tym wypadku bezradny.

Po wnikliwej lekturze SDK do Powershell-a, możemy znaleźć klasę RunspaceConnectionInfo, ale niestety ta klasa ma prywatny konstruktor. Na szczęście jest klasa WSManConnection Info.

Jak więc zacząć? Zacznijmy od wymaganych klas:

using System.Collections.Generic;
using System.Management.Automation;
using System.Collections.ObjectModel;
using System.Management.Automation.Runspaces;

Przy czym odwołanie do System.Management.Automation; wymaga referencji do klasy System.Management.Automation.dll. Domyślnie klasa nie jest wrzucana do GAC, więc ręcznie musimy przeszukać katalog %WinDir% i ją sobie wyciągnąć.

Remote powershell ma ogrniczenie co do ilości sesji, więc musimy gdzieś przechowywać informacje o sesji. Tu na przykład przechowuję informację o tworzeniu sesji w globalnych zmiennych aplikacji:

  /// <summary>
        /// Opens remote runspace
        /// </summary>
        /// <param name="uri">Uri to connect to, for example https://pod51002psh.outlook.com/powershell/"</param>
        /// <param name="schema">Schema of connection, for example http://schemas.microsoft.com/powershell/Microsoft.Exchange</param>
        /// <param name="username">Username</param>
        /// <param name="password">Secure pasword</param>
        /// <returns></returns>
        public void openRunspace(string uri, string schema, string username, string livePass)
        {
            System.Security.SecureString password = new System.Security.SecureString();
            foreach (char c in livePass.ToCharArray())
            {
                password.AppendChar(c);
            }
            PSCredential psc = new PSCredential(username, password);
            WSManConnectionInfo rri = new WSManConnectionInfo(new Uri(uri), schema, psc);
            rri.AuthenticationMechanism = AuthenticationMechanism.Basic;
            Runspace runspace = RunspaceFactory.CreateRunspace(rri);
            runspace.Open();
            Application["runspace"] = runspace;
        }
A inicjalizacja takiej funkcji by wyglądała np tak:
protected void Application_Start(object sender, EventArgs e)
        {
            string psremoteserver = "https://pod51002psh.outlook.com/powershell/";
            string liveLogin = "liveadmin@domain.fqdn";
            string livePass = "Pass";
            string schema = "http://schemas.microsoft.com/powershell/Microsoft.Exchange";
            if (Application["runspace"] == null)
                openRunspace(psremoteserver, schema, liveLogin, livePass);
        }

Nie zapomnijmy o zamykaniu sesji:

 protected void Application_End(object sender, EventArgs e)
        {
            if (Application["runspace"] != null)
            {
                Runspace rs = (Runspace)Application["runspace"];
                rs.Close();
            }
        }
protected void Application_Error(object sender, EventArgs e)
        {
            if (Application["runspace"] != null)
            {
                Runspace rs = (Runspace)Application["runspace"];
                rs.Close();
            }
        }
Po stworzeniu połączenia nie pozostaje nam nic innego jak go użyć. Np tak:
   /// <summary>
        /// Opens remote runspace
        /// </summary>
        /// <param name="uri">Uri to connect to, for example https://pod51002psh.outlook.com/powershell/"</param>
        /// <param name="schema">Schema of connection, for example http://schemas.microsoft.com/powershell/Microsoft.Exchange</param>
        /// <param name="username">Username</param>
        /// <param name="password">Secure pasword</param>
        /// <returns></returns>
        public void openRunspace(string uri, string schema, string username, string livePass)
        {
            System.Security.SecureString password = new System.Security.SecureString();
            foreach (char c in livePass.ToCharArray())
            {
                password.AppendChar(c);
            }
            PSCredential psc = new PSCredential(username, password);
            WSManConnectionInfo rri = new WSManConnectionInfo(new Uri(uri), schema, psc);
            rri.AuthenticationMechanism = AuthenticationMechanism.Basic;
            Runspace runspace = RunspaceFactory.CreateRunspace(rri);
            runspace.Open();
            Application["runspace"] = runspace;
        }
        private Runspace getRunSpace()
        {
            Runspace runspace = (Runspace)Application["runspace"];
            if (runspace.RunspaceStateInfo.State != RunspaceState.Opened)
                runspace.Open();
            return runspace;
        }
        /// <summary>
        /// Invokes any powershell script
        /// </summary>
        /// <param name="scriptText">script to invoke</param>
        /// <returns></returns>
        public Collection<PSObject> RunScript(string scriptText)
        {
            Runspace runspace = getRunSpace();
            // create a pipeline and feed it the script text
            Pipeline pipeline = runspace.CreatePipeline();
            pipeline.Commands.AddScript(scriptText);
            // execute the script
            Collection<PSObject> results = new Collection<PSObject>();
            results = pipeline.Invoke();
            return results;
        }
        /// <summary>
        /// Invoke simple command
        /// Ex.
        ///  Collection<PSObject> col = RunCommand("Get-Mailbox");
        /// </summary>
        /// <param name="command">Command Name</param>
        /// <returns></returns>
        public Collection<PSObject> RunCommand(string command)
        {
            Command myCommand = new Command(command);
            Pipeline pipeLine = getRunSpace().CreatePipeline();
            pipeLine.Commands.Add(myCommand);
            return pipeLine.Invoke();
        }
        /// <summary>
        /// Invoke command with single paramtere
        /// </summary>
        /// <param name="command">Command</param>
        /// <param name="param">Command parameter</param>
        /// <returns></returns>
        public Collection<PSObject> RunCommand(string command, string param)
        {
            Command myCommand = new Command(command);
            myCommand.Parameters.Add(param);
            Pipeline pipeLine = getRunSpace().CreatePipeline();
            pipeLine.Commands.Add(myCommand);
            return pipeLine.Invoke();
        }
        /// <summary>
        /// Invoke command with single named parameter
        /// Ex.
        ///  Collection<PSObject> col = RunCommand("Get-Mailbox","Identity","usr@iscg.eu");
        /// </summary>
        /// <param name="command">Command to invoke</param>
        /// <param name="param">Parameter Name</param>
        /// <param name="paramValue">Parameter value</param>
        /// <returns></returns>
        public Collection<PSObject> RunCommand(string command, string param, object paramValue)
        {
            Command myCommand = new Command(command);
            myCommand.Parameters.Add(new CommandParameter(param, paramValue));
            Pipeline pipeLine = getRunSpace().CreatePipeline();
            pipeLine.Commands.Add(myCommand);
            return pipeLine.Invoke();
        }
        /// <summary>
        /// Invokes command with collection of paramters
        /// Ex.
        /// Collection<CommandParameter> cpc = new Collection<CommandParameter>();
        ///        cpc.Add(new CommandParameter("Identity", "user@iscg.eu"));
        ///        Collection<PSObject> col = RunCommand("Get-Mailbox",cpc);
        /// </summary>
        /// <param name="command"></param>
        /// <param name="param"></param>
        /// <returns></returns>
        public Collection<PSObject> RunCommand(string command, Collection<CommandParameter> param)
        {
            Command myCommand = new Command(command);
            foreach (CommandParameter cp in param)
                myCommand.Parameters.Add(cp);
            Pipeline pipeLine = getRunSpace().CreatePipeline();
            pipeLine.Commands.Add(myCommand);
            return pipeLine.Invoke();
        }
        public string translatePSObject(Collection<PSObject> input)
        {
            StringBuilder stringBuilder = new StringBuilder();
            foreach (PSObject obj in (input))
            {
                stringBuilder.AppendLine(obj.ToString() + obj.GetType() + obj.ImmediateBaseObject.GetType());
            }
            return stringBuilder.ToString();
        }
Wednesday, April 22, 2009 9:48:22 PM (Central European Standard Time, UTC+01:00) #    Comments [0]  |  Trackback

 

Rozszerzenia Kerberos v5 Microsoftu#

Microsoft opublikował szereg dokumentów opisujących wszystko co wykracza poza specyfikacje Kerberos v5. W końcu daje to nam podstawy do tego aby zrozumieć jak działa autentykacja użytkownika w środowisku Windowsowym.

Dla mnie najciekawsza jest informacja że w trakcie logowania za pomoca smartcard jest generowany ticket NTLM, co zostało opisane w PKCA:

[MS-PKCA] Public Key Cryptography for Initial Authentication (PKINIT) in Kerberos Protocol Specification - http://download.microsoft.com/download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-PKCA%5D.pdf

Specyfikacja NTLM:

[MS-NLMP]:  NT LAN Manager (NTLM) Authentication Protocol Specification http://download.microsoft.com/download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-NLMP%5D.pdf

Poniżej kilka dalszych specyfikacji dotyczących zmian w implementacji kerberosv5, ale i nie tylko:

[MS-KILE] Kerberos Protocol Extensions - http://download.microsoft.com/download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-KILE%5D.pdf

[MS-PAC]:  Privilege Attribute Certificate Data Structure - http://download.microsoft.com/download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-PAC%5D.pdf

[MS-SPNG]:  Simple and Protected Generic Security Service Application Program Interface Negotiation Mechanism (SPNEGO) Protocol Extensions http://download.microsoft.com/download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-SPNG%5D.pdf

[MS-LSAD]: 
Local Security Authority (Domain Policy) Remote Protocol Specification http://download.microsoft.com/download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-LSAD%5D.pdf

[MS-SECO]:  Windows Security Overview http://download.microsoft.com/download/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/%5BMS-SECO%5D.pdf

Tuesday, March 03, 2009 7:52:37 AM (Central European Standard Time, UTC+01:00) #    Comments [0]  |  Trackback

 

Outlook Integration Error w OCS Communicator#

umocs007

Czym jest najczęściej spowodowany ten problem? Odpowiedzi na to pytanie szukałem dość długo. Co dziwne, na niektórych stacjach wydawał się nie występować. Dziwne też było zachowanie jeśli chodzi o przynależność do sieci – na stacjach domenowych, wpiętych do sieci firmowej się nie pojawiał, natomiast już przy dostępie zewnętrznym występował zawsze.

Co dziwne, standardowe usługi z których korzystał komunikator wydawały się działać, i nie zdradzać istnienia błędów.

Jak więc rozwiązać ten problem? Ja najpierw sprawdziłem gdzie usługi Exchangowe się znajdują: -

umocs001 

Następnie sprawdziłem za pomocą przeglądarki czy nie pojawia się żaden problem przy dostępie do katalogów EWS i UnifiedMessanging – w szczególności problem z dostępem do certyfikatów:

umocs003

 

umocs002

Jak widać dostęp do witryn nie wygenerował żadnych błędów.

Co więc jest przyczyną tego błędu? Jak się okazuję jest to sprawdzanie odwołania certyfikatu serwera – takie standardowe ustawienie które przychodzi wraz z IE7. Użytkownicy wewnątrz pobierają CRL z LDAP, zgodnie z wpisem w certyfikacie, natomiast zewnętrzni próbują się dostać do strony CA:

umocs004

Rozwiązanie1:Opublikować CRL na zewnątrz firmy. Dosyć trudny proces, wymagający przeważnie wykorzystania ISA i/lub skryptów w celu utworzenia zewnętrznego repozytorium certyfikatów/CRL, bez publikacji samego CA.

Rozwiązanie2: Wyłączyć opcję w IE

umocs006

 

Podobnie się zachowuję Outlook 2007. O ile Out Of Office Assistant nie korzysta z sprawdzania CRL-i, to już UnifiedMessenging jak najbardziej z tego korzysta.

Monday, March 02, 2009 8:10:31 AM (Central European Standard Time, UTC+01:00) #    Comments [0]  |  Trackback

 

Hyper-V a 80070057#

Hyper-V to naprawdę solidna platforma wirtualizacyjna. Przeważnie podczas wszystkich pokazów i dem działa bez zarzutu. Problem pojawia się jak zawsze dopiero outs-de-the-test-box.

Otóż Hyper-V posiada pewien poważny błąd – przy próbie zaimportowania maszyny wirtualnej która została wyeksportowana na innym serwerze pojawia się błąd 0x80070057.

Rozwiązanie – dosyć proste:

1.Otworzyć katalog z maszyną wirtualną

2.Znajdujemy plik .Exp

3. Wyszukujemy:

  <PROPERTY NAME="ScopeOfResidence" TYPE="string">
    <VALUE>
      e7668fbc-216e-4ed1-8ce3-3b932b42e22b
    </VALUE>

  </PROPERTY>

4. Usuwamy część zaznaczoną na czerwono

Tuesday, January 06, 2009 2:36:55 PM (Central European Standard Time, UTC+01:00) #    Comments [0]  |  Trackback

 

Autentykacja Certyfiaktem do IIS7#

IIS7, podobnie jak II6 posiada możliwość autoryzacji certyfiaktem cyfrowym do strony.

Podonie jak w IIS 6, jest możliwość logowania za pomocą certyfikatów firm trzecich, jak również logowania certyfikatami skojarzonymi z kontami AD.

Problem pojawia się w momencie gdy chcemy skonfigurować takie rozwiązanie. Dla konfiguracji certyfikatem zewnętrznym do AD można znaleźć w sieci poradniki, ale do konfiguracji z uwierzytelnianiem z AD poradników nie ma. Niby wystarczy zainstalować dodatek do IIS7, włączyć w opcjach site, i już powinno działać. Ale niestety tak nie jest.

IIS7 ma poważne braki w interfejse do konfiguracji certyfikatów. O ile w opcjach całego serwera mamy możliwośc zanza`czenia uwierzytelnienia certyfikatem, to przy pojedynczym katalogu wirtualnym takiej możliwości nie ma. W związku z tym z cmd z podniesionymi uprawnieniami:

notepad %windir%\system32\inetsrv\config\applicationHost.config

Ta opcja jest ustawiana z automatu:

<Configuration>
<System.WebServer>
  <Security>
   <clientCertificateMappingAuthentication enabled="true" />

Wyszukujemy teraz interesujący nas site, np "Default Web Site/owa"

<location path="Default Web Site/owa">
<system.webServer>
  <security>
   <authentication>
    <windowsAuthentication enabled="false">
     <providers>
      <clear />
      <add value="Negotiate" />
      <add value="NTLM" />
     </providers>
    </windowsAuthentication>
    <anonymousAuthentication enabled="false" />
    <digestAuthentication enabled="false" />
    <basicAuthentication enabled="false" />
    <clientCertificateMappingAuthentication enabled="true" />
   </authentication>
  <access sslFlags="Ssl, SslNegotiateCert, SslRequireCert, Ssl128" />
</security>

Gdzie linijkę <clientCertificateMappingAuthentication enabled="true" /> trzeba po prostu dopisać, bo w GUI nie ma.

Jeśli chcemy mieć ClientCertificate + Windows Integrated

<windowsAuthentication enabled="true">
<clientCertificateMappingAuthentication enabled="true" />
<access sslFlags="Ssl, SslNegotiateCert, Ssl128" />

Monday, October 20, 2008 11:58:48 AM (Central European Standard Time, UTC+01:00) #    Comments [1]  |  Trackback

 

ShadowCopy w Windows 2008 x64#

Ostatnio podczas przenoszenia plików użytkowników natknąłem się na typowy problem w-files.

Otóż przenieśliśmy katalogi domowe użytkowników na nowy serwer w2k8 x64. Włączyliśmy shadow copies. Zdefiniowaliśmy kopiowanie backupowe dfs-r do centrali, w celu późniejszego zrzucania stanu na tasiemki. Serwer sobie spokojnie śmigał, i wszystko wydawało się takie idealne. Nawet użytkownicy nie wydawali się niezadowolenia.

Wszystko niestety zepsuł błąd skryptu, który uszkodził strukturę katalogów na macierzy w centrali. Jako że dfs-r działa prawie niezawodnie, szybko dało się odczuć braki katalogów w oddziale.

Ale przecież jest shadow copy, więc nie powinno być problemu. Tak więc postanowiliśmy wejść do shadow copy, i spróbować przywrócić foldery.

I tu pojawił się pierwszy problem - shadow copy udawał, że nie umie znaleźć plików w folderach - wyświetlał się komunikat o ścieżce nie do znalezienia. Hmmm... problem uprawnień. Wobec tego przelogowujemy się i próbujemy jeszcze raz.. znowu nic.

Niestety w oddziale nie było żadnego innego serwera, a tylko stacje klienckie z xp. Wobec tego logujemy się zdalnie na stacje,i próbujemy odzyskać pliki. Jest, udaje się, ale niestety uprawnienia do plików się nie przenoszą.

Próbujemy volrest z w2k3 resource tools, niestety bez skutecznie. Narzędzie nie może sie podpiąć do shadow copy z windows 2008 w2k8 x64.

... chwilka załamania i wizja ręcznego ustawiania uprawnień.... nagle pomysł.., przecież shadow copy sharuje folder udostępniony z tą samą nazwą tylko z przedrostkiem określającym datę... wobec tego wejdźmy do właściwości otworzonej kopi shadow copy i znajdźmy ścieżkę... o, jest.

To teraz tylko robocopy w trybie backup – robocopy /b /COPY:DATSO /s /e /r:1 /w:1 i juz. Tylko kilka godzi stresu dla administratorów, i tylko godzina szukania narzędzia do przeglądania shadow copy : )

Tuesday, September 02, 2008 11:30:23 AM (Central European Standard Time, UTC+01:00) #    Comments [0]  |  Trackback

 

Opcje DHCP -121 w w2k3, i 249 w w2k8#

Jak wiadomo opcja 249 w DHCP nie przyjeła się - RFC zdefiniowało tę opcję jako opcję 121. W produktach Microsoftu do serii 2003 niestety nie było możliwości wyboru opcjii 121. Aż do momentu pojawienia się 2k8.

I tu niespodzianka. W windows 2008 opcja 121 jest, ale nie ma opcji 249. Co więc zrobić kiedy musimy użyć opcjii 121 w w2k3? ALbo użyć opcji 249 w w2k8? Musimy stworzyć ją sami.

Logujemy się do konsolki netsh:

netsh

dhcp server \\nazwa_serwera

Tworzymy definicje obiektu:

add optiondef  121 "Classless Static Routes - new" BINARY 0

lub dla 249

add optiondef  249 "Classless Static Routes - old" BINARY 0

anastepnie przechodzimy do odpowiedniego scope - tu testowo 192.168.193.0

scope 192.168.193.0

wpisujemy wartosc

set optionvalue 121 binary 100a64c0a8c10110ac16c0a8c101180a0c01c0a8c10118c0a8d5c0a8c101180a0c02c0a8c101180a0c03c0a8c101180a0c04c0a8c101180a0c05c0a8c101180a0c06c0a8c101

Oczywiscie aby sie nie narobic, najprosciej jest wykorzystac GUI istniejacej klasy, i za pomoca polecnia show optionvalue na scope sprawdzic odpowiedni ciag odpwiedzialny za sciezki.

Tuesday, July 15, 2008 11:00:56 PM (Central European Standard Time, UTC+01:00) #    Comments [0]  |  Trackback

 

All content © 2010, Krzysztof Pietrzak
On this page
This site
Calendar
<September 2010>
SunMonTueWedThuFriSat
2930311234
567891011
12131415161718
19202122232425
262728293012
3456789
Archives
Sitemap
Blogroll OPML
  Tokyo by night
blog WiTa
  W-Files
blog n€x¤Ra
 .:fotoblog:.
blog Kfaza
 \\archon\blog$
blog archona
 Czasowstrzymywacz
Blog Fookyego
 Jog Pstryka
Jog Pstryka
 Mac OS X vs. Active Directory
techniczny blog kfaza

Maps
Locations of visitors to this page