In one of my current projects, the customer wants to change the password of the Active Directory built-in Administrator account. This account was used several years for setting up tasks, running services and all kinds of things. To ensure that all major business applications will not be affected by that change, we needed to identify all processes and persons using the Administrator account and create separate service accounts for these applications.
During several Active Directory migration projects I needed to change the DNS server IP addresses on several computers if the DNS service was installed on the Active Directory Domain Controller. Therefore I wrote a little PowerShell script to connect to remote computer and change the DNS server IP address in the network connection via WMI to the onces specified in the script.
This makes changing the IP address of a DNS server much easier because all Windows systems based on Windows Server 2008 / Vista or newer can be edited by using this PowerShell script.
Lots of companies are using Mozilla Firefox in their corporate environment. Firefox came up with a great new feature in the latest version – it will support Windows enterprise trusted root certificates! No more need for adding certificates to Firefox separately using the keytool:
Just use the Windows Active Directory Group Policies to deploy your certificates – most of you already do this for use with Microsoft Internet Explorer and other software. To enable this great new feature Firefox introduced a new configuration parameter named security.enterprise_roots.enabled this needs to be set to true in the about:config page:
I’ve created several PowerShell scripts that utilize Windows Presentation Foundation (WPF) for displaying a graphical user interface (GUI). The ability to use WPF GUIs enables you to combine PowerShell scripting and professional-looking GUIs – not like the old-school HTA GUIs in VBScripts.
WPF is completely being build on XML / XAML files – and these files can be build using the graphical forms designer in Visual Studio Community Edition
####################################################################### ## (C) 2015 Michael Miklis (michaelmiklis.de) ## ## ## Filename: Fix-Printer.ps1 ## ## Version: 1.0 ## ## Release: Final ## ## Requirements: -none- ## ## Description: Script for fixing fqdn during computer domain ## movement. ## ## This script is provided 'AS-IS'. The author does not provide ## any guarantee or warranty, stated or implied. Use at your own ## risk. You are free to reproduce, copy & modify the code, but ## please give the author credit. ## #################################################################### Set-PSDebug -Strict Set-StrictMode -Version latest function Fix-Printer { <# .SYNOPSIS Fixes printer fqdn references in registry .DESCRIPTION The Fix-Printer CMDlet fixes the serverName, uNCName and url registry key for the windows spooler service .PARAMETER OldDomain FQDN of the old domain .PARAMETER NewDomain FQDN of the new domain .EXAMPLE Fix-Printer -OldDomain "olddomain.com" -NewDomain "newdomain.com" .NOTES You need to run this CMDlet with elevated permissions #> param ( [parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()]$OldDomain, [parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()]$NewDomain ) foreach ($printer in (Get-ChildItem -Path HKLM:SYSTEMCurrentControlSetControlPrintPrinters)) { if ((Test-RegistryValue -Path ("HKLM:SYSTEMCurrentControlSetControlPrintPrinters" + $printer.PSChildName + "DsSpooler") -Value ("serverName")) -eq $true) { $strOldVal = (Get-ItemProperty -Path ("HKLM:SYSTEMCurrentControlSetControlPrintPrinters" + $printer.PSChildName + "DsSpooler")).serverName Set-ItemProperty -Path ("HKLM:SYSTEMCurrentControlSetControlPrintPrinters" + $printer.PSChildName + "DsSpooler") -Name "serverName" -Value $strOldVal.Replace($olddomain, $newdomain) } if ((Test-RegistryValue -Path ("HKLM:SYSTEMCurrentControlSetControlPrintPrinters" + $printer.PSChildName + "DsSpooler") -Value ("uNCName")) -eq $true) { $strOldVal = (Get-ItemProperty -Path ("HKLM:SYSTEMCurrentControlSetControlPrintPrinters" + $printer.PSChildName + "DsSpooler")).uNCName Set-ItemProperty -Path ("HKLM:SYSTEMCurrentControlSetControlPrintPrinters" + $printer.PSChildName + "DsSpooler") -Name "uNCName" -Value $strOldVal.Replace($olddomain, $newdomain) } if ((Test-RegistryValue -Path ("HKLM:SYSTEMCurrentControlSetControlPrintPrinters" + $printer.PSChildName + "DsSpooler") -Value ("url")) -eq $true) { $strOldVal = (Get-ItemProperty -Path ("HKLM:SYSTEMCurrentControlSetControlPrintPrinters" + $printer.PSChildName + "DsSpooler")).url Set-ItemProperty -Path ("HKLM:SYSTEMCurrentControlSetControlPrintPrinters" + $printer.PSChildName + "DsSpooler") -Name "url" -Value $strOldVal.Replace($olddomain, $newdomain) } } } #___________________________________________________________________ function Test-RegistryValue { <# .SYNOPSIS Tests existence of regisry value (C) by Jonathan Medd .DESCRIPTION The Test-RegistryValue CMDlet was created by Jonathan Medd .PARAMETER Path Registry path .PARAMETER Value Registry value .EXAMPLE Test-RegistryValue -Path "HKCU:Environment" -Value "TEMP" #> param ( [parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()]$Path, [parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()]$Value ) try { Get-ItemProperty -Path $Path | Select-Object -ExpandProperty $Value -ErrorAction Stop | Out-Null return $true } catch { return $false } } Fix-Printer -OldDomain "olddomain.com" -NewDomain "newdomain.com"
Sometimes you want to disable IPv6 only on a specified network interface, instead of disabling IPv6 completely:
Microsoft has released a KB article how to disable the individual IPv6 components in Windows – but not for an individual interface:
https://support.microsoft.com/en-us/kb/929852
I wrote a small PowerShell script that unbinds the IPv6 protocol. The PowerShell script is modifying the bindings in the registry – therefore a reboot is needed for this setting to take effect:
$UnbindID = $(Get-WmiObject -Class 'Win32_NetworkAdapter' | Where-Object {$_.NetConnectionID -eq 'Ethernet'}).GUID $LinkageKey = $(Get-ItemProperty -Path 'HKLM:SYSTEMCurrentControlSetservicesTcpip6Linkage').Bind | Select-String -Pattern $UnbindID -NotMatch -SimpleMatch Set-ItemProperty -Path 'HKLM:SYSTEMCurrentControlSetservicesTcpip6Linkage' -Name 'Bind' -Type MultiString -Value $LinkageKey
Note: According to your environment and operating system version and language, you may need to change the network connection name (‘Ethernet’ in my example’) to fit your interface / connection name.
During some research for PowerShell best practices I came across the following blog post on the Hey Scripting Guy Blog from Microsoft:
http://blogs.technet.com/b/heyscriptingguy/archive/2014/12/03/enforce-better-script-practices-by-using-set-strictmode.aspx
By using the Set-StrictMode cmdlet, we can enforce some common “best practice” coding techniques that you can use with your scripts. In yesterday’s post, I used the –Strict parameter with Set-PSDebug. This enforces the variable declaration in a script. But with Set-StrictMode, we get that plus a little more. The scope is limited to the current scope and child scopes. By default, Set-StrictMode is turned off to prevent error messages while you are writing the script.
From now on, all my PowerShell scripts will start with “Set-StrictMode -Version latest” and “Set-PSDebug -Strict”:
Set-PSDebug -Strict Set-StrictMode -Version latest
One of my customers needed a PowerShell script to get all running processes with their corresponding CPU load. This was script should be triggered by their monitoring system if the system total CPU usage exceeds a configured threshold.
They’re running a mid-sized Citrix XenDesktop farm with Server-OS (formerly known as XenApp a.k.a. terminal services) and sometimes applications are using a high CPU amount.
This is the small script I wrote for them:
##################################################################### ## ## (C) 2015 Michael Miklis (michaelmiklis.de) ## ## ## Filename: Get-Tasks.ps1 ## ## Version: 1.0 ## ## Release: Final ## ## Requirements: -none- ## ## Description: PowerShell Tasklist with CPU usage and memory ## usage ## ## This script is provided 'AS-IS'. The author does not provide ## any guarantee or warranty, stated or implied. Use at your own ## risk. You are free to reproduce, copy & modify the code, but ## please give the author credit. ## #################################################################### <# .SYNOPSIS Lists all running task including cpu and memory usage .DESCRIPTION The Get-Tasks function uses Windows Management Instrumentation (WMI) to retrieve process Name, ProcessId, SessionId, VirtualSizeMB, Handles, Owner, PercentProcessorTime and ThreadCount .PARAMETER computerName Computername or IP Adress of the computer to query .PARAMETER credential Credentials to query computer as System.Management.Automation.PSCredential .EXAMPLE Get-Tasks Get-Tasks -computerName "server.domain.com" -credential $credential .NOTES You need to run this CMDlet with elevated permissions #> function Get-Tasks { [CmdletBinding()] param ( [parameter(Mandatory=$true,ValueFromPipeline=$false)] [string]$computername, [parameter(Mandatory=$true,ValueFromPipeline=$false)] [System.Management.Automation.PSCredential]$credential ) PROCESS { $colProcs = Get-wmiobject win32_process -computername $computername -Credential $credential | select *,@{Name=”Owner”;Expression={($_.GetOwner()).User}} $colPerfs = Get-wmiobject win32_perfformatteddata_perfproc_process -computername $computername -Credential $credential $colTasklist = @() foreach ($proc in $colProcs) { $process = New-Object System.Object $perf = $colPerfs | Where-Object { $_.IDProcess -eq $proc.ProcessId } $process | Add-Member -type NoteProperty -name "Name" -value $proc.Name $process | Add-Member -type NoteProperty -name "ProcessId" -value $proc.ProcessId $process | Add-Member -type NoteProperty -name "SessionId" -value $proc.SessionId $process | Add-Member -type NoteProperty -name "VirtualSizeMB" -value ([math]::Round(($proc.VirtualSize / 1024 /1024), 2)) $process | Add-Member -type NoteProperty -name "Handles" -value $proc.Handles $process | Add-Member -type NoteProperty -name "Owner" -value $proc.Owner $process | Add-Member -type NoteProperty -name "PercentProcessorTime" -value $perf.PercentProcessorTime $process | Add-Member -type NoteProperty -name "ThreadCount" -value $perf.ThreadCount $colTasklist += $process } $colTasklist | Sort-Object PercentProcessorTime -Desc return $colTasklist } }
DOWNLOAD
sessionid.exe
I was looking for a way to display the session-ID of my current terminal server session regardless of the protocol I’m using in a batch file. I tried numerous workarounds by parsing the output of qwinsta.exe or quser.exe – but both ways didn’t work in a reliable manner.
After some research, I figured out that the session ID is available as a property within the .NET Framework. Therefore, I decided to write a small executable that will output the session id.
Attached to this post you’ll find the SESSIONID.EXE – feel free to use it within your project.
Here are some code snippets how to use the sessionid.exe:
FOR /F "tokens=*" %%A IN ('sessionid.exe') DO SET SESSIONID=%%A ECHO %SESSIONID%
During most of my Infrastructure and Migration projects, most customers have the same issue. After migrating the file data to a new server, old documents may try to access their original document template on which they are based on.
Unfortunately, the referenced path is not a mapped network drive or a relative path – it is a UNC Path containing the old server name.
Therefore, I wrote a little script that will process all Word Documents within a given path and replace the old Server and or Share name with the new ones. After that, the launch of these old documents will be much faster.
You need write permissions to all Word Documents which should be changed and of course you need to have Microsoft Word (I used Word 2010) installed:
' ##################################################################### ' ## ' ## (C) 2012 Michael Miklis (michaelmiklis.de) ' ## ' ## ' ## Filename: ChangeWordDocumentTemplate.vbs ' ## ' ## Version: 1.0 ' ## ' ## Release: Final ' ## ' ## Requirements: -none- ' ## ' ## Description: Changes the template in doc files ' ## ' ## This script is provided 'AS-IS'. The author does not provide ' ## any guarantee or warranty, stated or implied. Use at your own ' ## risk. You are free to reproduce, copy & modify the code, but ' ## please give the author credit. ' ## ' #################################################################### Option Explicit Dim strFilePath Dim strPath Dim intCounter Dim strFileName Dim OldServer Dim NewServer Dim objDoc Dim objTemplate Dim dlgTemplate Dim objWord Dim strFileArr Dim objFs Dim i Const wdDialogToolsTemplates = 87 Set objFS = CreateObject("Scripting.Filesystemobject") Set objWord = CreateObject("Word.Application") objWord.Visible = false strFilePath = "C:Usersmichaeldesktop" OldServer = "vv" NewServer = "OLD-FILESERVERsharefolder1" If Right(strFilePath, 1) = "" Then strFilePath = Left(strFilePath, Len(strFilePath) - 1) strFileArr = Split(CreateFileList(objFS.GetFolder(strFilePath),true), vbCr) For i=0 to UBound(strFileArr) If NOT strFileArr(i) = "" then strFileName = strFileArr(i) wscript.echo "--------------------------------------------------" wscript.echo "Processing File: " & strFilename Set objDoc = objWord.Documents.Open(strFileName) Set objTemplate = objDoc.AttachedTemplate Set dlgTemplate = objWord.Dialogs(wdDialogToolsTemplates) strPath = dlgTemplate.Template wscript.echo "Old Template Name: " & strPath '// Only process templates based on old server If LCase(Left(strPath, Len(OldServer))) = LCase(OldServer) Then wscript.echo "Template needs to be changed..." 'objDoc.AttachedTemplate = NewServer & Mid(strPath, Len(OldServer) + 1) wscript.echo "New Template Name: " & NewServer & Mid(strPath, Len(OldServer) + 1) End If objDoc.Save objDoc.Close wscript.echo "--------------------------------------------------" wscript.echo "" End If Next Set objDoc = Nothing Set objTemplate = Nothing Set dlgTemplate = Nothing '// Close Word objWord.Quit (False) '______________________FUNCTIONS & SUB ROUTINES_______________________ Function CreateFileList(objFolder, bRecursive) '// <summary> '// Creates a List containing all Files '// </summary> '//Root-Folder for searching '//Search recursive Dim objFile, objSubFolder For each objFile in objFolder.Files If Right(lcase(objFile),4) = ".doc" OR Right(lcase(objFile),5) = ".docx" AND NOT Left(objFile.Name,1) = "~" then CreateFileList = CreateFileList & objFile.Path & vbCr End If Next If bRecursive = true then For each objSubFolder in objFolder.Subfolders CreateFileList = CreateFileList & CreateFileList(objSubFolder, true) Next End If End Function