Archive

Archive for August, 2009

I jak tutaj przetestować uaktualnienie.

August 27th, 2009 No comments

Ehh, jak to zwykle bywa przymierzyłem się do instalacji SP2 na jednej z produkcyjnych maszyn. Na początku testy na maszynach wirtualnych z podobnymi usługami. Wszystko przechodzi bez problemu. Skoro udało się na jednej, przeszło też na drugiej to kolej na uaktualnienie jednego z serwerów produkcyjnych. Aby nie powodować przestojów wstałem sobie wcześnie i na 7.00 byłem już w pracy. Szybkie odpalenie instalacji i zrobienie kawy. Dobiega 8.00 Instalator SP2 zamyka system. Ponowne uruchomienie Stage 1 –20 minut, Stage 2 – 30 minut, Stage 3 –40 minut. Dobiega 9.30 – trochę nerwowa sytuacja, powoli dzwonią telefony. Nagle Stage 3 of 3 100% Complete. Człowiek zadowolony zasiada przy konsoli by sprawdzić czy wszystko działa poprawnie a tutaj nagle komunikat: Service Pack didn’t install. Reverting changes ??:/ Godzina 11 cofanie zmian trwa i ciekawe czy się dziś skończy. Na szczęście system podniósł odpowiednie usługi i telefony ucichły. Teraz przypominają mi się komunikaty jak aktualizowałem sobie Linuxa, masa przewijającego się tekstu. Zawsze zastanawiałem się dlaczego nie zrobią paska postępu i nie wrzucą komunikatów w jakieś ukryte okno. Teraz chciałbym zobaczyć, zamiast “ Service Pack didn’t install. Reverting changes.”, przewijające sie tony tekstu, które jasno wskazywały, że instalator nadal pracuje a nie tylko rusza ładnym kółkiem:(

Categories: Ogólne Tags:

Pobieranie nazwy hosta z dhcp.

August 26th, 2009 6 comments

Jakiś tydzień temu zabrałem się za kończenie nowych obrazów dla komputerów na salach laboratoryjnych. Poza drobnymi zmianami (dystrybucja lekkich aplikacji via SCCM) chciałem zminimalizować czas jaki poświęcałem na zmianę nazw komputerów po klonowaniu. Kilka lat temu przyjęliśmy, że komputery na salach będą się nazywać KompXXX-YY. Gdzie XXX to numer sali a YY to komputer na miejscu YY licząc od prawej strony sali. W systemach Linux rozwiązanie było proste :) Dorzuciliśmy opcję 12 do DHCP i systemy pobierały sobie odpowiednią nazwę z serwera DHCP. W przypadku Windows sprawa się komplikuje i dobrze by było nazwy zmienić na samym początku by nie robić sobie bałaganu. Nazwę można pobrać czy wygenerować na kilka sposobów:

  • pobranie nazwy z DNS – wszystko fajnie, tylko jak nazwy nie mam w DNS bo pojawi się po dodaniu Windowsa do domeny
  • wykorzystanie Sysprepa do generowania nazwy Komp400-XX – Muszę mieć kilka plików unattend do Sysprepa :/
  • przeparsowanie otrzymanego Adresu IP i wygenerowanie nazwy komputera.  – Czasem od naszej reguły nazewnictwa zdarzają się wyjątki:)
  • pobranie nazwy z DHCP – idealne rozwiązanie.

 

Skoro miałem wszystkie nazwy w DHCP to teraz wystarczyło pobrać odpowiednią opcje i zamienić nazwę stanowiska:) Jak sie okazało otrzymanie nazwy komputera z DHCP i wrzucenie jej do jakieś zmiennej nie jest takie proste. Jedyne dostępne API dla Windowsowego klienta DHCP jest napisane w C++:/  Opcje z DHCP pobieramy za pomocą funkcji DHCPRequestParams, która przyjmuje na wejściu kilka parametrów. Między innymi wymagane jest podanie nazwy interfejsu sieciowego. TUTAJ UWAGA nazwa interfejsu jest rozumiana jako identyfikator urządzenia a nie jako np. “Połączenie lokalne”. Identyfikator również możemy sobie wyciągnąć za pomocą API do interfejsów sieciowych.  Przyznam się, że stworzenie działającej aplikacji, która pobiera identyfikator pierwszego interfejsu a następnie wyciąga z DHCP odpowiednią nazwę zepsuł mi trochę krwi. Najpierw musiałem sobie przypomnieć pewne podstawy Visual C++, potem musiałem załapać, że w nazwie interfejsu mam podać identyfikator. Następnie musiałem rozgryźć jak dynamicznie wyszukać ten identyfikator. Koniec końców udało mi się napisać mały programik w VC++, który pobiera odpowiednią opcje z DHCP i za pomocą newsida zmienia nazwę i SID. Poniżej kod, który pobiera id pierwszego interfejsu i następnie wyciąga z DHCP nazwę stacji.  Przypominam iż z zawodu nie jestem programistą i na samym początku dążę do tego by kod działał wedle moich oczekiwaniami. Następnie jak mam czas to staram się go upiększać. W kodzie częściowo starałem się wykorzystać przykłady dostępne na stronach MSDN.

#include < winsock2.h>
#include < iphlpapi.h >
#include < stdio.h >
#include < stdlib.h >
#include < windows.h >
#include < dhcpcsdk.h >
#include < string >
#include < wchar.h >
#pragma comment( lib, "dhcpcsvc.lib" )
#pragma comment(lib, "IPHLPAPI.lib")
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))

int __cdecl main()
{
	CONST int iAdapterIDLenght= 260;
	CONST int iHostnameLenght=60;
	int dw;
	CHAR pszHostNameBuf[iHostnameLenght];
	DWORD dwError, dwSize;
	CHAR TmpBuffer[iHostnameLenght];
	WCHAR wcAdapterName[iAdapterIDLenght];
    PIP_ADAPTER_INFO pAdapterInfo;
    PIP_ADAPTER_INFO pAdapter = NULL;
    DWORD dwRetVal = 0;
	ULONG ulOutBufLen = sizeof (IP_ADAPTER_INFO);

    pAdapterInfo = (IP_ADAPTER_INFO *) MALLOC(sizeof (IP_ADAPTER_INFO));
    if (pAdapterInfo == NULL)
	{
        printf("Error allocating memory needed to call GetAdaptersinfo\n");
        return 1;
    }
    if (GetAdaptersInfo(pAdapterInfo, &ulOutBufLen) == ERROR_BUFFER_OVERFLOW)
	{
        FREE(pAdapterInfo);
        pAdapterInfo = (IP_ADAPTER_INFO *) MALLOC(ulOutBufLen);
        if (pAdapterInfo == NULL)
		{
            printf("Error allocating memory needed to call GetAdaptersinfo\n");
            return 1;
        }
    }

    if ((dwRetVal = GetAdaptersInfo(pAdapterInfo, &ulOutBufLen)) == NO_ERROR)
	{
        pAdapter = pAdapterInfo;
		dw = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pAdapter->AdapterName, -1, wcAdapterName, 0);
		MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pAdapter->AdapterName, -1, wcAdapterName, dw);

		DHCPCAPI_PARAMS DhcpApiHostNameParams = {
				0,                // Flags
				OPTION_HOST_NAME, // OptionId
				FALSE,            // vendor specific?
				NULL,             // data filled in on return
				0                 // nBytes
			};
		DHCPCAPI_PARAMS_ARRAY RequestParams = {
            1,  // only one option to request
            &DhcpApiHostNameParams
        };

		DHCPCAPI_PARAMS_ARRAY SendParams = {0,NULL};

		dwSize = sizeof(TmpBuffer);
		dwError = DhcpRequestParams(
            DHCPCAPI_REQUEST_SYNCHRONOUS, // Flags
            NULL,                         // Reserved
            wcAdapterName,					// Adapter Name
            NULL,                         // not using class id
	           SendParams,		          // sent parameters
            RequestParams,                // requesting params
            (PBYTE) TmpBuffer,            // buffer
            &dwSize,                      // buffer size
            NULL                          // Request ID
        );

		if( ERROR_MORE_DATA == dwError )
		{
			printf("Error: %s",dwError);
		}

		if( NO_ERROR == dwError )
		{

            if( DhcpApiHostNameParams.nBytesData )
            {

                CopyMemory(pszHostNameBuf, DhcpApiHostNameParams.Data,DhcpApiHostNameParams.nBytesData);
                pszHostNameBuf[DhcpApiHostNameParams.nBytesData] = '\0';
				printf("(12) DHCP Host Name: %s\n",pszHostNameBuf);
                return 0;
            }
		}
		else
		{
			printf("Error: %u",dwError);
		}

	}
	else
	{
        printf("GetAdaptersInfo failed with error: %d\n", dwRetVal);

    }
    if (pAdapterInfo)
        FREE(pAdapterInfo);
	getchar();
    return 0;
} 

W wolnej chwili postaram się napisać małą bibliotekę do podpięcia pod C#, tak bym mógł pobrać dowolne opcje z DHCP.

Categories: C / C++, Oprogramowanie klienckie Tags: