Showing posts with label Windows. Show all posts
Showing posts with label Windows. Show all posts

Thursday, 26 June 2014

Powershell: OS Detection

What OS am I executing on? What bitness? Some Handy Functions to Use


Sometimes, it's important to know what OS you are running on, and/or how many bits that OS has. Here are some useful functions which can be reused in other Powershell scripts (a future post may include putting such things into a Powershell Module). Please note that this hasn't been 100% tested on all of the OSes identified, but should work*.

The other two functions are about detecting bitness - Get-OSBitness() will tell you if you are on a 64-bit or 32-bit OS, and Get-CurrentProcessBitness() will tell you what the current Powershell execution-engine is (ie you can detect if you are running on the 32-bit powershell.exe on a 64-bit OS). I can't really image G-CPB() being used much, but here it is anyway.

* Please also note that the Win8.1/2012R2 detection is known to be sometimes incorrect, and these OSes can instead show up as Win8/2012 (respectively); this is because Microsoft broke the detection mechanism in these OSes, and each application now must use a manifest.xml file to flag itself as a Win8.1/2012R2 app (as ooposed to a legacy <= Win8) - I'm pretty sure Powershell.exe is properly manifested and should detect as Win8.1, but the default Powershell ISE is not (at this current time) and will show Win8.



Function Get-OSVersion() {
    # Version numbers as per http://www.gaijin.at/en/lstwinver.php
    $osVersion = "Version not listed"
    $os = (Get-WmiObject -class Win32_OperatingSystem)
    Switch (($os.Version).Substring(0,3)) {
        "5.1" { $osVersion = "XP" }
        "5.2" { $osVersion = "2003" }
        "6.0" { If ($os.ProductType -eq 1) { $osVersion = "Vista" } Else { $osVersion = "2008" } }
        "6.1" { If ($os.ProductType -eq 1) { $osVersion = "7" } Else { $osVersion = "2008R2" } }
        "6.2" { If ($os.ProductType -eq 1) { $osVersion = "8" } Else { $osVersion = "2012" } }
        # 8.1/2012R2 version detection can be broken, and show up as "6.2", as per http://www.sapien.com/blog/2014/04/02/microsoft-windows-8-1-breaks-version-api/
        "6.3" { If ($os.ProductType -eq 1) { $osVersion = "8.1" } Else { $osVersion = "2012R2" } }
    }
    return $osVersion
}


Function Get-CurrentProcessBitness() {
    # This function finds the bitness of the powershell.exe process itself (ie can detect 32-bit powershell.exe on a win64)
    $thisProcessBitness = 0
    switch ([IntPtr]::Size) {
        "4" { $thisProcessBitness = 32 }
        "8" { $thisProcessBitness = 64 }
    }
    return $thisProcessBitness
}

Function Get-OSBitness() {
    # This function finds the bitness of the OS itself (ie will detect 64-bit even if you're somehow using 32-bit powershell.exe)
    $OSBitness = 0
    switch ((Get-WmiObject Win32_OperatingSystem).OSArchitecture) {
        "32-bit" { $OSBitness = 32 }
        "64-bit" { $OSBitness = 64 }
    }
    return $OSBitness
}


Tuesday, 24 June 2014

Windows Update Client - Useful Commands


Windows Update is a key tool in diagnosing many Windows-related problems. It's handy to know a few shortcuts to assist in diagnosis.

GUI

There is a basic GUI built into Windows (since Vista). This can be instantly accessed by typing the command  "wuapp", which works if you type this word into a Cmd window, into the Win7 Start Menu and also into the Windows 8/8.1/2012 Metro interface Start Menu.

This GUI will tell you if Updates are working, and show you a history of installed updates.

Command Line Client

The following commands will force the local client to do things:
REM Check for new updates:
wuauclt /detectnow
REM Install any new pending updates (warning, this may reboot your machine)
wuauclt /updatenow
REM NB: above command doesn't seem to work properly any more on Server 2012

REM Forec a Report into WSUS (may be useful if client says it is updated in WUapp, but WSUS says it is still missing patches):
wuauclt /reportnow
REM Force a machine to reregister with its WSUS server (not usually that useful):
wuauclt /resetauthorization /detectnow

Restart the Windows Service

Quite a few problems are resovled by restarting the WU service on a client. The easiest way to restart the service is via the command line:
net stop wuauserv
net start wuauserv

Key Registry Locations

Check the following keys for information:
General Settings will show you a few items, including NextDetectionTime (the Policy key is usually more useful though):
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate

 (Group) Policy Settings include which (if any) local WSUS server you are using, and what the scheduled settings are:
HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate

Log File

Log file is located here: %windir%\WindowsUpdate.Log
I won't go through it much, but the log file often contains a lot of errors which aren't neccessarily relevant. The important bits are:
  • Can the WU Service on the machine access the WSUS server and/or internet to check-for and download patches?
  • Is there a problematic update which is failing to apply?
  • Are there other obvious errors?

Web Proxy Issues

Often, downloading issues are caused by a web proxy. Check and/or Reset the Machine's proxy settings (which are different to the logged in users' settings) with the following script (written in "Batch" to work across the whole gamut of OSes). Please note I haven't needed to try this on Server 2012/Win8 yet, so it may have changed.

@setlocal
@echo off

REM This Script resets the machine-level proxy config to autodetect & autoscript.

REM We need bitsadmin to do this - which is built into =>2008/Vista+, but not =<XP/2003
SET bitsadmin=bitsadmin
if not exist %windir%\system32\bitsadmin.exe SET bitsadmin="%~dp02003_bitsadmin_x86.exe"
REM Please note the above line probably doesn't cover 64-bit 2003...

Echo **
Echo ** Output current proxies to the screen (in case someone is watching this)
Echo **
%bitsadmin% /util /getieproxy networkservice 2>/nul
%bitsadmin% /util /getieproxy localservice 2>/nul
%bitsadmin% /util /getieproxy localsystem 2>/nul


Echo **
Echo ** Reset the proxy config on the machine to autodetect/Autoscript
Echo **
proxycfg -d 2>/nul
netsh winhttp reset proxy 2>/nul

%bitsadmin% /util /setieproxy networkservice NO_PROXY 2>/nul
%bitsadmin% /util /setieproxy localservice NO_PROXY 2>/nul
%bitsadmin% /util /setieproxy localsystem NO_PROXY 2>/nul

%bitsadmin% /util /setieproxy networkservice AUTODETECT 2>/nul
%bitsadmin% /util /setieproxy localservice AUTODETECT 2>/nul
%bitsadmin% /util /setieproxy localsystem AUTODETECT 2>/nul

%bitsadmin% /util /setieproxy networkservice AUTOSCRIPT http://wpad/wpad.dat 2>/nul
%bitsadmin% /util /setieproxy localservice AUTOSCRIPT http://wpad/wpad.dat 2>/nul
%bitsadmin% /util /setieproxy localsystem AUTOSCRIPT http://wpad/wpad.dat 2>/nul



Last Resort: Reset the WU Service

The following commands perform a full reset of the WU client-side stuff. Try not to do this unless you know that your machine is quite busted.
This works on all OSes 2012R2 and below, and mostly works on XP/2003, but you need a copy of bistadmin.exe from the 2003R2 Tools (or Resource Kit, I forget).  This is written in "Batch" to work across the whole gamut of OSes.

echo ********************************************************
echo ** Now resetting Windows Update Services on this machine

echo ********************************************************

REM Set the date format for later use. Please note this is __highly__ Locale Dependent, for non-Australian machines "old" is used instead.
FOR %%A IN (%Date%) DO (
    FOR /F "tokens=1-3 delims=/-" %%B in ("%%~A") DO (
        SET ISODATE=%%D%%B%%C
    )
)
SET ISODATE=%ISODATE:~0,8%
echo %ISODATE% | findstr /r "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]" >NUL 2>&1
IF ERRORLEVEL 1 SET ISODATE=Old

echo ********************************************************echo ** We start by stopping the services
echo ********************************************************
sc config wuauserv start= disabled
net stop wuauserv

echo.
echo ********************************************************echo ** Now we reset all BITS downloads and stop BITS serviceecho ********************************************************SET bitsadmin="bitsadmin"
if not exist "%windir%\system32\bitsadmin.exe" SET bitsadmin="%~dp02003_bitsadmin_x86.exe"
%Bitsadmin% /RESET /ALLUSERS
%Bitsadmin% /RESET
sc config bits start= disabled
net stop bits
net stop wuauserv

echo.
echo *******************************************************
echo ** Next, we delete the detection times
echo *******************************************************
reg delete "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update" /v AUState /f >nul 2>&1
reg delete "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update" /v NextDetectionTime /f >nul 2>&1
reg delete "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update" /v ScheduledInstallDate /f >nul 2>&1
reg delete "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update" /v DownloadExpirationTime /f >nul 2>&1

echo.
echo *******************************************************
echo ** Now we archive the log
echo *******************************************************
move "%windir%\WindowsUpdate.log" "%windir%\WindowsUpdate.log.%ISODATE%"

echo.
echo *******************************************************
echo ** Now we archive the internal datastore
echo *******************************************************
move "%windir%\SoftwareDistribution" "%windir%\SoftwareDistribution.%ISODATE%"
rmdir /q /s "%ALLUSERSPROFILE%\Application Data\Microsoft\Network\Downloader"

echo.
echo *******************************************************
echo ** Now we re-register all the DLLs (just to be safe)
echo *******************************************************
regsvr32 /s wuapi.dll
regsvr32 /s wuaueng.dll
regsvr32 /s wuaueng1.dll
regsvr32 /s wuauserv.dll
regsvr32 /s wucltui.dll
regsvr32 /s wups.dll
regsvr32 /s wups2.dll
regsvr32 /s wuweb.dll
regsvr32 /s qmgrprxy.dll
regsvr32 /s qmgr.dll
regsvr32 /s atl.dll
regsvr32 /s jscript.dll
regsvr32 /s msxml3.dll

echo.
echo *******************************************************
echo ** Now we restart the services, and see how we go
echo *******************************************************
REM We set it twice, first to auto then delayed; sometimes the sc call fails for -delayed, and we don't want to leave it in a Disabled state
sc config wuauserv start= auto
sc config bits start= auto
sc config wuauserv start= delayed-auto
sc config bits start= delayed-auto
net start bits
net start wuauserv

echo.
echo *******************************************************
echo ** Now we wait for 30 seconds, and then we trigger a client detection
echo *******************************************************
ping -n 30 127.0.0.1 >nul
wuauclt /resetauthorization /detectnow

echo.
echo *******************************************************
echo ** All done (fingers crossed!)
echo *******************************************************





Monday, 12 May 2014

Configuring a new Windows Machine


Today I learnt a new way to configure a new Windows machine: with a PowerShell package manager. A bit like like YUM for Windows! All thanks to https://chocolatey.org/. As a side-note, this package manager, although currently third-party, will be built into Windows itself fairly soon, via One-Get in Powershell v5.

This assumes you have Powershell >= 3 installed already.

Into a cmd Window:
@powershell -NoProfile -ExecutionPolicy unrestricted -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" && SET PATH=%PATH%;%systemdrive%\chocolatey\bin

And into a PowerShell Window, some useful stuff:
cinst notepadplusplus.install
cinst Firefox
cinst GoogleChrome
cinst 7zip
cinst flashplayeractivex
cinst flashplayerplugin
cinst putty
cinst sysinternals
cinst 
cinst procexp

cinst sublimetext2
cinst curl
cinst Wget
cinst winmerge
cinst wireshark



Remove Windows 8 Default CrApps:

And a bonus Windows 8 tidbit that I made up on my very own: how to remove a lot of crappy apps shipped by default with Windows 8.1 (and maybe in 8.0) in PowerShell:

$CrappyApps = @("Microsoft.BingFinance ","Microsoft.BingFoodAndDrink",`
"Microsoft.BingHealthAndFitness","Microsoft.BingMaps",`
"Microsoft.BingNews","Microsoft.BingSports","Microsoft.BingTravel",`
"Microsoft.BingWeather","Microsoft.HelpAndTips",`
"microsoft.windowscommunicationsapps","Microsoft.WindowsReadingList",`
"Microsoft.XboxLIVEGames","Microsoft.ZuneMusic","Microsoft.ZuneVideo",`
"CheckPoint.VPN","f5.vpn.client","JuniperNetworks.JunosPulseVpn","Microsoft.MoCamera","SonicWALL.MobileConnect")
 

$CrappyApps | % { Get-AppxPackage -Name $_ | Remove-AppxPackage 2>&1 | Out-Null }

Note, the above few commands haven't been run in production - I ran each Get|Remove command individually on my own machine, and then arrayified it all for this post, so there may be an error lurking in there.

Tuesday, 6 May 2014

NTP on Windows


A Windows Domain needs NTP set on it's PDC Emulator to ensure the domain has correct time sync. These commands set this for Windows systems, with an emphasis on Australian settings.


This can be set simply by pasting the commands into a cmd window (I recommend setting NTP1 to your actual local NTP server/router if you have one). These commands are expected to work on Server 2008 onwards.

SET TARGET=localhost
SET NTP1=192.168.1.1
SET NTP2=2.pool.ntp.org
SET NTP3=3.pool.ntp.org
w32tm /config /computer:%TARGET% /update /manualpeerlist:"%NTP1% %NTP2% %NTP3%" /syncfromflags:MANUAL


Australian Settings

Same commands as above, just swap in these variables instead.

Internode version:

SET TARGET=localhost
SET NTP1=192.168.1.1
SET NTP2=ntp.on.net
SET NTP3=3.au.pool.ntp.org


Telstra version:

SET TARGET=localhost
SET NTP1=192.168.1.1
SET NTP2=toc.ntp.telstra.net
SET NTP3=tic.ntp.telstra.net

Confirm Settings

Validate this with the query command:
w32tm /query /configuration /computer:%TARGET%