When executing Powershell from within PSExec or VBScript .exec method, powershell appears to hang.
In summary, Powershell doesn’t play nice with console applications.
From what I can gather it maintains a separate footprint for its console streams and therefore, any console based applications relying on STDOUT, STDERR, STDIN manipulation do not operate as expected.
To reproduce using PSExec.exe;
Test.ps1
Write-Output “HELLO”
Psexec –s c:\windows\system32\windowspowershell\v1.0\powershell.exe C:\Test.ps1
Hit CTRL-C and the script outputs “HELLO” as expected.
This suggests that the streams are only returned to the calling console when the script exits.
Blog Index
Monday, April 28, 2008
PowerShell appears to "hang" when executed from a console application
Wednesday, April 23, 2008
Need to move the Microsoft Deployment Distribution (BDD) file location?
Recently, I needed to move the contents of the LAB deployment point in Microsoft Deployment Toolkit (MDT) to a different location on the filesystem.
As it turns out, this was quite simple.
Edit the Deploy.xml located in the MDT installation directory, by default this is located in %PROGRAMFILES%\Microsoft Deployment Toolkit\Control.
Just find the
HKLM\Software\Microsoft\Deployment 4\
Value: Distribution_Dir
Type: REG_SZ
Data: [NewDistributionDirectoryPath]
Fix Broken Windows Scripting Host
Recently during an SMS application deployment we had an application installation remove the .vbs, .wsf and .js file associations.
I used the following command coupled with psexec.exe to restore functionality to the affected machines remotely.
Rundll32.exe setupapi,InstallHinfSection DefaultInstall 128 C:\Windows\inf\Wsh.inf
Using this method restores the files associations for .wsh, .vbs, .vbe, .js, .jse, .wsf, .wsc and also ensures that all WSH files are installed. This is the same command that XP Setup uses to install WSH.
Tuesday, April 22, 2008
Set Location in "Regional and Language Options" control panel applet
Having done my share of unattended XP builds for various, invariably one of the items that I am asked is how to change the Country under the Location Tab found in the "Regional and Language options" Control Panel applet.
Originally, this took some finding as it is doesn't appear to be a supported entry for sysprep.inf or unattend.txt.
HKU\.Default\Control Panel\International\Geo
OR
HKCU\Control Panel\International\Geo
Value: Nation
Type: REG_SZ
Data: "12"
(0xC) 12 is the code for Australia.
Tip: To set this in an unattended build, set the HKU\.Default\Control Panel\International\GEO value, as SysPrep does not apply this setting to all users when the HKCU setting is configured.
A complete list of nation codes can be found at
http://msdn2.microsoft.com/en-us/library/ms776390(VS.85).aspx
GetGeoInfo
http://msdn2.microsoft.com/en-us/library/ms776300(VS.85).aspx
Dial up connections do not use LAN proxy settings
The default behaviour changed with Internet Explorer 5 and later, in that each connection has unique proxy settings.
Resolution:
A hotfix is available from Microsoft, see the KB reference. After installing the hotfix, the following registry key can be added per user or per machine.
HKLM\Software\Microsoft\Windows\CurrentVersion\Internet Settings
OR
HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings
DialupUseLanSettings REG_DWORD [01]
http://support.microsoft.com/?kbid=818060
Thursday, April 17, 2008
Ever needed an Automated RunAs?
I went down this path for a Microsoft Deployment Toolkit (BDD) SOE build, as it was running in the wrong context for inserting details into a SQL database (computers and members of an Active Directory Group had access but the local administrator account didn't).
This powershell script accepts a number of arguments and then launches the process as the specified user;
Usage:
Start-RunAs.ps1 process Path [Arguments] [Domain] [User] [Password]
Examples;
Start-RunAs.ps1 "notepad.exe" "$($Env:SystemRoot)\System32"
Start-RunAs.ps1 "notepad.exe" "$($Env:SystemRoot)\System32" "" "domain"
"user"
Start-RunAs.ps1 "notepad.exe" "$($Env:SystemRoot)\System32" ""
"password" "user" "password"
The script could do with some tidying up for day to day use, but you get the idea...
Whilst I have some misgivings about the security of the "SecureString" it may be useful for some user's who wish to run their shell using Principle of Least Privilege...
Probably most notably though was the exercise and the way the PSH team decided to implement the SecureString concept.
It doesn't seem too secure, but as the PSH team offer, it wasn't meant to be, after all the owner of the process (interactive user) already knows the password they just typed in.
The following Powershell code snippet suggests that the password entry is secure. However, in the current session, the password can be found.
$PWD = Read-Host "Enter your password" -assecurestring[Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServi
ces.Marshal]::SecureStringToBSTR($PWD))
Running the above commands results in;
Enter your password:: ****
System.Security.SecureString
Test
Still from the angle of security by obscurity, it would stop most prying eyes.
A simpler Runas I hear you ask?
$psi = New-Object System.Diagnostics.ProcessStartInfo "notepad.exe"
$psi.Verb = "runas"
[System.Diagnostics.Process]::Start($psi)
This launches the RunAs GUI, and then the process.
ConvertTo-SecureString
http://technet.microsoft.com/en-us/library/bb978707.aspx
http://www.leeholmes.com/blog/PowerShellCredentialsAndGetNetworkCredential.aspx
Windows PowerShell Securing the Shell
http://technet.microsoft.com/en-us/magazine/cc137808.aspx
param( [string] $FileName = $(throw "Please specify a filename to execute"),
[string] $FilePath = $(throw "Please specify a path to the filename"),
[string] $Arguments,
[string] $UserDomain,
[string] $UserName,
[string] $UserPassword
)
$Scripts = Split-Path $Myinvocation.Mycommand.Path
# Start a specified process as a specific user (RunAs)
#Set Error Handling
$ErrorActionPreference = "SilentlyContinue"
$Me = "Start-RunAs"
# Ensure the supplied filename/path exists
$TaskDesc = "Verify FileName exists"
get-item $FilePath\$FileName
If ($? -eq $False) {
Write-Host " $($TaskDesc) $($Error[0])"
Exit 1
}
# When a username but no password has been supplied, request credentials from user
If ($UserName -ne "" -and $UserPassword -eq "") {
$TaskDesc = "Request User Credentials for $($UserName)"
$UserCred = Get-Credential "$($UserDomain)\$($UserName)"
If ($? -eq $True) {
$UserDomain = $UserCred.UserName.Split("\")[0]
$UserName = $UserCred.UserName.Split("\")[1]
$UserPassword = $UserCred.GetNetworkCredential().Password
} Else {
Write-Host " $($TaskDesc): $($Error[0])"
Exit 2
}
$UserPassword = $UserCred.GetNetworkCredential().Password
} Else {
# present a blank credentials window for the user to populate
$TaskDesc = "Request User Credentials"
$UserCred = Get-Credential
If ($? -eq $True) {
$UserDomain = $UserCred.UserName.Split("\")[0]
$UserName = $UserCred.UserName.Split("\")[1]
$UserPassword = $UserCred.GetNetworkCredential().Password
} Else {
Write-Host " $($TaskDesc): $($Error[0])"
Exit 2
}
}
# A local domain can also be specified
$DOMAINUSER = $UserName
$DOMAINUSERPASSWORD = $UserPassword
$DOMAINUSERDOMAIN = $UserDomain
$SleepInterval = 2
# Number of seconds to wait for process to exit
$psi = New-Object System.Diagnostics.ProcessStartInfo "$($FileName)"
# Configure other process execution parameters
$psi.UseShellExecute = $False
$psi.UserName = $DOMAINUSER
$psi.Password = ConvertTo-SecureString "$($DOMAINUSERPASSWORD)" -AsPlainText -Force
$psi.Domain = $DOMAINUSERDOMAIN
$psi.WorkingDirectory = $FilePath
# $psi.WindowStyle = "Hidden"
$psi.Arguments = $Arguments
$TaskDesc = "Execute process;
"Write-Host "$($TaskDesc)"
Write-Host "$($psi.WorkingDirectory)\$($psi.FileName) $($psi.Arguments) as user $($psi.Domain)\$($psi.UserName)"
$ProcessStart = [System.Diagnostics.Process]::Start($psi)
If ($?) {
While ($ProcessStart.HasExited -ne $TRUE) {
Start-Sleep -s $SleepInterval
}
$ProcessStart.HasExited
} Else {
Write-Host "$($TaskDesc) failed, $($Error[0])"
}
LTI deployment fails with error "A connection to the deployment share (\\Server\Share$) could not be made. The deployment will not proceed."
A connection to the deployment share (\\Server\Share$) could not be made. The deployment will not proceed.
Cause:
A previous build did not complete correctly.
Resolution:
Remove the MDT specific components.
rd c:\minint /s/q
rd c:\_SMSTaskSequence /s/q (if exists)
del x:\Deploy\Tools\x86\TS.xml (if exists)
Run X:\Deploy\Scripts\LiteTouch.wsf (or reboot computer from the MDT Deployment CD)
ZTI PreInstall phase fails with error 214700057
Also the BDD.log file may contain the error
"Unable to get WinNT ADSI provider: (-2147221020)".
Cause:
One cause of this error is that a network location was used for the WinPE source files when running the "Update PE" wizard in SMS.
Resolution:
Extract the "Generic_OSD_x86.iso" to a local directory that is hosting the SMS console and select this location for the WinPE source files when executing the "Update PE" wizard.
ZTI Package update leaves .$M$ file(s)
When updating the Operating System Package files in the SMS Console, you may find that the SMS source location is not updated correctly and some files in the SMS Source location with a .$M$ extension.
Symptoms:
A check of the SMS Source directory for the ZTI image shows files with the .$M$ extension. You may also see entries in the SMS Server logs \SMS\Logs\OSDImage.log file similar to the following;
Failed to get file attributes file://%5BSMSServer%5D/%5BSMSSource%5DZTI_Master_Image/CustomSettings.ini (80070002)
Cause:
The update process compares the existing file with the file from the Windows Deployment Server, in this case the source file has been removed, therefore, the process has no file to compare against. The final rename operation is then not completed. The update process copies new or updated files to the source directory with a temporary name (*.$M$).
Resolution:
Replace the removed file, or create a blank file of the same name. This allows the update process to compare the two files and successfully complete processing.
To permanently remove the file from the comparison process, configure the SMS OSD ZTI program, select the Advanced tab, Click the "ZTI - Validation" phase and remove the file from the file list.
Error creating ZTI CD when using local SMS Console
When running the SMS Admin console locally on your administrative workstation, the CD generated may be different from one generated on the SMS Server.
Depending on your configuration you may receive the error; "unable to load sql server oledb..."
Cause:
The files used to generate the CD locally typically reside in C:\SMSAdmin\OSD
Resolution:
Make sure that the files in your local C:\SMSAdmin\OSD directory have been syncronised with those on the SMS server, [SMSInstallDirectory]\OSD.
Of particular note are the osdshell.exe and OSDWinPE.wim files.
The OSDWinPE.wim contains the customised background that you specified in the Windows PE tab of the MS Deployment workbench.
Wednesday, April 16, 2008
Various WMIC commands
Find the Serial number of a computer
wmic /node:WSNAME1 path win32_computersystemproduct get identifyingnumber
wmic /node:WSNAME1 csproduct get identifyingnumber
Query Active Directory using WMI
WMIC /NAMESPACE:\\root\directory\ldap PATH ds_user WHERE ds_cn="user1" GET ds_department /VALUE
Issue:
WMIC returns error "Invalid Global Switch."
Cause:
This is caused by the computer name containing the "-" special character.
Workaround:
Enclose the computer name with double quotes.
Various DSQUERY commands
Find Hosts having a specified Service Principal Name
dsquery * domainroot -limit 0 -filter "(&(objectCategory=Computer)(servicePrincipalName=*ALIASNAME*))" -attr cn
show intersite transports
dsquery * "CN=IP,CN=Inter-Site Transports,CN=Sites,CN=Configuration,DC=test,DC=com"
dsquery * "CN=IP,CN=Inter-Site Transports,CN=Sites,CN=Configuration,DC=test,DC=com" -attr cost cn description replInterval -q
dsquery * "CN=Subnets,CN=Sites,CN=Configuration,DC=test,DC=com" -attr cn Location SiteObject -qdsquery * forestroot -limit 500
dsquery * domainroot -limit 0 -filter "(&(objectCategory=Computer)(objectClass=Computer)(operatingSystem=*server*))" -attr cn operatingSystem
dsquery * domainroot -limit 0 -filter "(&(objectCategory=Group)(objectClass=Group)(cn=group*_suffix))" -attr member
Find disabled user accounts
dsquery * domainroot -limit 0 -filter "(&(objectCategory=Person)(objectClass=User)(userAccountControl=514))" -attr cn userAccountControl
Find user accounts that are not disabled
dsquery * domainroot -limit 0 -filter "(&(objectCategory=Person)(objectClass=User)(!userAccountControl=514))" -attr cn userAccountControl
Find user accounts that have password set to never expire
dsquery * "OU=UserOU,DC=test,dc=com" -limit 0 -filter "(&(objectCategory=Person)(objectClass=User)(userAccountControl:1.2.840.113556.1.4.803:=65536))"
Find user with a givenName
dsquery * "OU=UserOU,DC=test,dc=com" -limit 0 -filter "(&(objectCategory=Person)(objectClass=User)(givenName=Jenny))" -attr cn GivenName
Disable accounts that have been stale for over 120 days and that have not already been disabled.
for /f "tokens=2 delims==," %i in ('dsquery user "OU=UserOU,DC=test,DC=com" -stalepwd 120') do @dsquery * "OU=UserOU,DC=test,DC=com" -limit 0 -filter "(&(objectCategory=Person)(objectClass=User)(!userAccountControl:1.2.840.113556.1.4.803:=2)(cn=%i))" dsmod user -disabled yes
Find all users for an exchange server
dsquery * domainroot -limit 0 -filter "(&(objectCategory=Person)(objectClass=User)(msExchHomeServerName=*exch*))" -attr cn
Find users who have been granted the logon to computer right.
dsquery * domainroot -limit 0 -filter "(&(objectCategory=Person)(objectClass=User)(userWorkstations=*exch*))" -attr cn
LDAP query for email alias address
"dsquery * -s myexchangeserver domainroot -limit 0 -filter "(&(objectCategory=Group)(proxyAddresses=smtp*))" -attr adspath cn mail info distinguishedName
Find Service connection points
dsquery * domainroot -limit 0 -filter "(&(objectClass=serviceConnectionPoint)(keywords=RIS*))" -attr serviceDNSName
Find Service connection points excluding those in a particular site
dsquery * domainroot -limit 0 -filter "(&(objectClass=serviceConnectionPoint)(keywords=RIS*)(!keywords=Site:Site1))" -attr cn serviceDNSName
Check if computer deletion has replicated to all DC's
for /f "tokens=2 delims==," %i in ('dsquery server') do dsquery computer -name WSName1 -s %i
Lookup done by Roaming SMS client to determine site assignment.
dsquery * domainroot -limit 0 -filter "(&(ObjectClass=mSSMSSite)((mSSMSRoamingBoundaries=10.0.1.0)(mSSMSRoamingBoundaries=TST)))"
Find the Terminal Services profile path for all users in the domain
for /f "tokens=2 delims=,=" %i in ('dsquery user "DC=mydomain,DC=com,DC=au"') do @tsprof /q /domain:MYDOMAIN %i && echo .
To see more useful commands check out this url: http://waynes-world-it.blogspot.com/2008/03/useful-commands.html
Using ImageX to compress a WIM file after modification
When using ImageX to inject or remove files in a WIM file, it may be beneficial to compress the WIM.
Example; a BDD build containing the windows source files was around 1Gb.
After removing the files and without compression resulted in the same size file.
Using the /export function resulted in a reduction of the WIM file of around 400Mb.
imagex /export "c:\Test\003.wim" 1 "c:\Test\003_Compressed.wim" 003CDrive
When installing Windows XP on ESX you may receive stop 0x0000007b error
By default ESX uses LSILogic SCSI driver which is not on the ESX CD.
http://virtrix.blogspot.com/2007/09/vmware-installing-windows-xp-on-esx.html
Download and install the LSILogic SCSI driver for controller 'LSI20320-R' from www.lsilogic.com
VMWare Workstation - After WinPE deploy of sysprep image you receive a stop 0x0000007b error
Cause:
By default in VMWare Workstation 6, the SCSI adapter is configured to be present.
Workaround:
Close the Virtual Machine, and edit the .vmx file, changing the scsi0.present line from TRUE to FALSE
scsi0.present="FALSE"
Pre-Stage Computer resource record in SMS
Specifying the Computer name and MAC address provides a more accurate means of ensuring that the intended computer will assume the pre-staged SMS resource record.
The MAC address is optional, however, it increases the chance that the original physical computer will assume the new SMS Resource record.
Once the pre-staged record has been created, advertisements can be assigned to the record.
The advantage of this is that when the computer is built, it assumes the record and automatically receives the pre-configured advertisements.
See KB 307026 for list of elements checked during SMS client installation
http://support.microsoft.com/kb/307026
SMSResGen.dll is the SMS Resource Generator Object, which is included with the Active Directory/SMS Synchronization Tools. This tool is available from the Microsoft Web site at http://www.microsoft.com/smserver
VBScript Code for pre-staging a computer resource record in SMS
Const ADDPPROP_NONE = &H0
Const ADDPROP_GUID = &H2
Const ADDPROP_KEY = &H8
Const ADDPROP_NAME = &H44
'get the current GUID, if available
sComputer="TEST-WS1"
Set DDR=CreateObject("SMSResGen.SMSResGen.1")
DDR.DDRNew "System", "PrestageAgent", ""
' DDR.DDRAddString "SMS Unique Identifier", GUID, 64, ADDPROP_NAME
DDR.DDRAddString "Name", sComputer, 64, ADDPROP_NAMEDDR.DDRAddString "Netbios Name", sComputer, 64, ADDPROP_KEY
Dim IPAddress(3), IPSubnet(3), MACAddress(3)
IPAddress(0)=""
IPSubnet(0)=""
MACAddress(0)="00:0C:29:96:53:F2"
DDR.DDRAddStringArray "IP Addresses", Array(IPAddress(0),IPAddress(1)), 64, ADDPROP_ARRAY
DDR.DDRAddStringArray "MAC Addresses", Array(MACAddress(0),MACAddress(1)), 64, ADDPROP_ARRAY
DDR.DDRAddStringArray "IP Subnets", Array(IPSubnet(0),IPSubnet(1)), 64, ADDPROP_ARRAY
DDR.DDRWrite sComputer & ".DDR"
DDR.DDRSendtoSMS
Set FSO=CreateObject("Scripting.FileSystemObject")
'FSO.GetFile(sComputer & ".DDR").Delete
Windows Path issues may prevent Group Policy from applying correctly
Issue:
Even though the event log displays EventID 1704 "Security policy in the Group policy objects are applied successfully. ", group policy still has not applied successfully;
Resolution:
Check the Windows Path; it should contain at a minimum the following locations and be less than 1024 characters in length.
C:\Windows;C:\Windows\System32;C:\Windows\System32\WBEM
Hiding or Displaying Default Desktop icons
The default desktop icons can be hidden or displayed using the registry or Group policy. However, before they can be managed using Group Policy the icons must have the following registry keys present.
{20D04FE0-3AEA-1069-A2D8-08002B30309D} - My Computer
{450D8FBA-AD25-11D0-98A8-0800361B1103} - My Documents
{208D2C60-3AEA-1069-A2D7-08002B30309D} - My Network Places
{871C5380-42A0-1069-A2EA-08002B30309D} - Internet Explorer
{645FF040-5081-101B-9F08-00AA002F954E} - Recycle Bin
A DWORD value of 0 displays the icon, 1 hides the icon.
Setting this value in HKCU takes precedence over HKLM.
To hide the icons from the Start Menu add the Key and value to - \Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu To hide the icons from the Desktop add the Key and value to - \Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel
ImportGPO.wsf may not import GPO's using a Migration Table on Windows Server 2003
The ImportGPO.wsf script doesn't correctly test for null values at Line 162.
Cause: Incorrect testing of null value on Line 162
Resolution: See KB911800
http://support.microsoft.com/kb/911800
Permissions for Moving a Computer Account
How to Grant Permission to Move Computer Accounts to a User or Group
http://support.microsoft.com/kb/818091
Summarising this article, the permissions you need to allocate to an account object for creating and moving (deleting!) computer accounts in the domain.
Create account in OU
Read access for OU's from the top-level domain, down the tree to the OU. Very Important
Create/Delete "Computer Objects"
Reset/Change Password for "Computer Objects"
As per Create
Write all properties this is the key permission that allows objects to be moved out of the OU