Invoke DOS Command in PowerShell

Unfortunately, there are still legacy dos applications that still provide value for Windows administrators.  Also, PowerShell isn’t yet installed on all our Windows servers and can’t be soley relied on:(  So being able to invoke a remote DOS command from PowerShell can be helpful at times.  I’ve written a script to do just that.  It works by creating a process on the remote system using WMI and writing the results to a temporary text file.  The function will then grab the results from the temp file on the remote system and return them.

Here I’m pulling netstat data from a remote system

5

Or maybe I don’t want to get anything back, but I want to force Windows Update to check for new updates

6

Function Code:

Invoke-DOSCommand

function Invoke-DOSCommand {
<#
.SYNOPSIS
Run a DOS command on a remote host and return results
.DESCRIPTION
Invoke-DOSCommand will run a dos command on a remote system and will return the results.
It does this using WMI to create a process and by creating a temporary file on the remote
to store the results if any
.EXAMPLE
Invoke-DOSCommand -Command "netstat -ano"

DESCRIPTION
-----------
This command will return the results from netstat on the local system
.EXAMPLE
Invoke-DOSCommand -Command "netstat -ano" -ComputerName "SERVER1"

DESCRIPTION
-----------
This command will return the results from netstat on the remote system SERVER1
.EXAMPLE
Invoke-DOSCommand -Command "netstat -ano" -ComputerName "SERVER1" | ?{$_ -match "LISTENING"}

DESCRIPTION
-----------
This command is the same as the previous example, but here we are returning only interfaces
that are in the listening state
#>
    [CmdletBinding()] param(                
        [Parameter(Mandatory=$true)] $Command,
        [Parameter(Mandatory=$false)] $ComputerName,
        [Parameter(Mandatory=$false)] [string]$TempLocalDirPath="C:\",
        [Parameter(Mandatory=$false)] [switch]$Force
    )
    
    process{
        
        #if computername is specified assume remote system
        if($ComputerName){
        
            $tempFileName = (get-date -UFormat "%Y%m%d%H%M%S") + "DOStemp.txt"
            
            #generate local file path
            if( $TempLocalDirPath.EndsWith('\') ) {
                $localFilePath = $TempLocalDirPath + $tempFileName
            }
            else {
                $localFilePath = $TempLocalDirPath + '\' + $tempFileName
            }
            
            #generate remote file path from local path using hidden admin share
            try {
                $remoteFolderPath = "\\$ComputerName\" + (Split-Path $TempLocalDirPath -Qualifier -ErrorAction Stop).TrimEnd(":") + "$" + (Split-Path $TempLocalDirPath -NoQualifier -ErrorAction Stop)
            }
            catch {
                Write-Host "`nERROR: Bad TempLocalDirPath value" -ForegroundColor Magenta
                Write-Host "`n" $_.Exception.Message "`n" -ForegroundColor Magenta
            }
            
            #test that folder exists and is reachable
            if( !(Test-Path $remoteFolderPath) ) {
                Write-Host "`nERROR: Remote path $remoteFolderPath desn't exist or is inaccessible`n" -ForegroundColor Magenta
                return
            }
            
            #add filename to path
            if( $remoteFolderPath.EndsWith('\') ) {
                $remoteFilePath = $remoteFolderPath + $tempFileName    
            }
            else {
                $remoteFilePath = $remoteFolderPath + '\' + $tempFileName
            }
            Write-Host "`nTemp file will be located at $remoteFilePath" -ForegroundColor Cyan

            #if there is already a file with this name -Force required
            if( (Test-Path $remoteFilePath) -and !($Force) ) {
                Write-Host "`nWARNING: File $remoteFilePath Already Exists" -ForegroundColor Yellow
                Write-Host "You can use the -Force parameter to overwrite or you can" -ForegroundColor Yellow
                Write-Host "specify a different temp path using -TempLocalDirPath" -ForegroundColor Yellow
                Write-Host "the default path is C:\`n" -ForegroundColor Yellow
                return
            }

            #create remote dos command
            $cmd = "cmd /c $Command > $localFilePath"
        
            #run command as process using WMI invocation
            try {
                $processID = (Invoke-WmiMethod -Class win32_process -Name create -ArgumentList $cmd -ComputerName $ComputerName -ErrorAction Stop).ProcessID
            }
            catch {
                Write-Host "`nERROR: creating process" -ForegroundColor Magenta
                Write-Host "`n$_`n" -ForegroundColor Magenta
                return
            }
            
            #wait for process to complete
            Write-Host "`nWaiting for process $processID to complete..." -ForegroundColor Cyan -NoNewline
            while (Get-Process -Id $processID -ComputerName $ComputerName -ErrorAction SilentlyContinue) {
               Start-Sleep -Seconds 2
               Write-Host "." -ForegroundColor Cyan -NoNewline
            }
            Write-Host ""
        
            #get results from temp file
            Start-Sleep -Seconds 4
            try {
                $result = Get-Content $remoteFilePath -ErrorAction Stop
            }
            catch {
                Write-Host "`nERROR: Couldn't get file $remoteFilePath" -ForegroundColor Magenta
                Write-Host "`n" $_.Exception.Message "`n" -ForegroundColor Magenta
                return
            }
        
            #cleanup temp file
            Remove-Item $remoteFilePath -Force -ErrorAction SilentlyContinue
            if( Test-Path $remoteFilePath ) {
                Write-Host "`nWARNING: Unable to remove remote file" -ForegroundColor Yellow
            }
        }
        #otherwise run command on local system
        else {
            $result = cmd /c $Command
        }
        
        #return command results
        if($result -eq $null) {
            Write-Host "`nNothing was returned by remote command`n" -ForegroundColor Cyan
            return
        }
        else {
            return $result
        }
    }
}

Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>