Powershell from batch file not working

Powershell

From Powershell I can run this

PS C:\UTIL> . .\Get-PendingReboot.ps1
PS C:\UTIL> $Servers = Get-Content C:\UTIL\Servers.txt
PS C:\UTIL> Get-PendingReboot -ComputerName $Servers | Export-CSV C:\Util\PendingRebootReportServers.csv -NoTypeInformation

That works great

I would like to run this as a task on a regular basis so I setup a rebootstatus.cmd file that looks like this

@echo off

%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe . .\Get-PendingReboot.ps1
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe $Servers = Get-Content C:\UTIL\Servers.txt
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe Get-PendingReboot -ComputerName $Servers | Export-CSV C:\Util\PendingRebootReportServers.csv -NoTypeInformation
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe $Computers = Get-Content C:\UTIL\Computers.txt
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe Get-PendingReboot -ComputerName $Computers | Export-CSV C:\Util\PendingRebootReportComputers.csv -NoTypeInformation

Exit 

Open in new window


When I run it I get this


C:\Util>rebootstatus
'Export-CSV' is not recognized as an internal or external command,
operable program or batch file.

C:\Util>

What am I missing?

Thanks

Tom
LVL 23
Thomas GrassiSystems AdministratorAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

footechCommented:
That won't work with all the separate commands, each started by a new instance of powershell.exe.  It's a matter of scope.  When you start one, it won't have any idea about what the previous one did.  You need to put it all into one .ps1 file.  I'd say just append this to the Get-PendingReboot.ps1 file, after the function.
$Servers = Get-Content C:\UTIL\Servers.txt
Get-PendingReboot -ComputerName $Servers | Export-CSV C:\Util\PendingRebootReportServers.csv -NoTypeInformation
$Computers = Get-Content C:\UTIL\Computers.txt
Get-PendingReboot -ComputerName $Computers | Export-CSV C:\Util\PendingRebootReportComputers.csv -NoTypeInformation

Open in new window


Then your task can just be
powershell.exe
with argument
-file Get-PendingReboot.ps1
You could put the bold text as a single line in a batch file as well.
Thomas GrassiSystems AdministratorAuthor Commented:
Footech

Thanks for responding

New code
echo off

%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -file Get-PendingReboot.ps1
$Servers = Get-Content C:\UTIL\Servers.txt
Get-PendingReboot -ComputerName $Servers | Export-CSV C:\Util\PendingRebootReportServers.csv -NoTypeInformation
$Computers = Get-Content C:\UTIL\Computers.txt
Get-PendingReboot -ComputerName $Computers | Export-CSV C:\Util\PendingRebootReportComputers.csv -NoTypeInformation

Exit

Open in new window


Results
C:\Util>rebootstatus
'$Servers' is not recognized as an internal or external command,
operable program or batch file.
'Get-PendingReboot' is not recognized as an internal or external command,
operable program or batch file.

C:\Util>


Thoughts

Thanks
footechCommented:
The code I posted should be part of the .ps1 file, not the batch file.  Then all you need in the batch file is line 3 from your last post.
SD-WAN: Making It Work for You

As bandwidth requirements and Internet costs grow, businesses naturally want to manage budgets by reducing reliance on their most expensive connection types. Learn more about how to make SD-WAN work for your business in our on-demand webinar!

Thomas GrassiSystems AdministratorAuthor Commented:
footech

Thanks

The script is not my code I got from here
https://gallery.technet.microsoft.com/scriptcenter/Get-PendingReboot-Query-bdb79542

Function Get-PendingReboot
{
<#
.SYNOPSIS
    Gets the pending reboot status on a local or remote computer.

.DESCRIPTION
    This function will query the registry on a local or remote computer and determine if the
    system is pending a reboot, from either Microsoft Patching or a Software Installation.
    For Windows 2008+ the function will query the CBS registry key as another factor in determining
    pending reboot state.  "PendingFileRenameOperations" and "Auto Update\RebootRequired" are observed
    as being consistant across Windows Server 2003 & 2008.
  
    CBServicing = Component Based Servicing (Windows 2008)
    WindowsUpdate = Windows Update / Auto Update (Windows 2003 / 2008)
    CCMClientSDK = SCCM 2012 Clients only (DetermineIfRebootPending method) otherwise $null value
    PendFileRename = PendingFileRenameOperations (Windows 2003 / 2008)

.PARAMETER ComputerName
    A single Computer or an array of computer names.  The default is localhost ($env:COMPUTERNAME).

.PARAMETER ErrorLog
    A single path to send error data to a log file.

.EXAMPLE
    PS C:\> Get-PendingReboot -ComputerName (Get-Content C:\ServerList.txt) | Format-Table -AutoSize
  
    Computer CBServicing WindowsUpdate CCMClientSDK PendFileRename PendFileRenVal RebootPending
    -------- ----------- ------------- ------------ -------------- -------------- -------------
    DC01           False         False                       False                        False
    DC02           False         False                       False                        False
    FS01           False         False                       False                        False

    This example will capture the contents of C:\ServerList.txt and query the pending reboot
    information from the systems contained in the file and display the output in a table. The
    null values are by design, since these systems do not have the SCCM 2012 client installed,
    nor was the PendingFileRenameOperations value populated.

.EXAMPLE
    PS C:\> Get-PendingReboot
  
    Computer       : WKS01
    CBServicing    : False
    WindowsUpdate  : True
    CCMClient      : False
    PendFileRename : False
    PendFileRenVal : 
    RebootPending  : True
  
    This example will query the local machine for pending reboot information.
  
.EXAMPLE
    PS C:\> $Servers = Get-Content C:\Servers.txt
    PS C:\> Get-PendingReboot -Computer $Servers | Export-Csv C:\PendingRebootReport.csv -NoTypeInformation
  
    This example will create a report that contains pending reboot information.

.LINK
    Component-Based Servicing:
    http://technet.microsoft.com/en-us/library/cc756291(v=WS.10).aspx
  
    PendingFileRename/Auto Update:
    http://support.microsoft.com/kb/2723674
    http://technet.microsoft.com/en-us/library/cc960241.aspx
    http://blogs.msdn.com/b/hansr/archive/2006/02/17/patchreboot.aspx

    SCCM 2012/CCM_ClientSDK:
    http://msdn.microsoft.com/en-us/library/jj902723.aspx

.NOTES
    Author:  Brian Wilhite
    Email:   bwilhite1@carolina.rr.com
    Date:    08/29/2012
    PSVer:   2.0/3.0
    Updated: 05/30/2013
    UpdNote: Added CCMClient property - Used with SCCM 2012 Clients only
             Added ValueFromPipelineByPropertyName=$true to the ComputerName Parameter
             Removed $Data variable from the PSObject - it is not needed
             Bug with the way CCMClientSDK returned null value if it was false
             Removed unneeded variables
             Added PendFileRenVal - Contents of the PendingFileRenameOperations Reg Entry
#>

[CmdletBinding()]
param(
  [Parameter(Position=0,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
  [Alias("CN","Computer")]
  [String[]]$ComputerName="$env:COMPUTERNAME",
  [String]$ErrorLog
  )

Begin
  {
    # Adjusting ErrorActionPreference to stop on all errors, since using [Microsoft.Win32.RegistryKey]
        # does not have a native ErrorAction Parameter, this may need to be changed if used within another
        # function.
    $TempErrAct = $ErrorActionPreference
    $ErrorActionPreference = "Stop"
  }#End Begin Script Block
Process
  {
    Foreach ($Computer in $ComputerName)
      {
        Try
          {
            # Setting pending values to false to cut down on the number of else statements
            $PendFileRename,$Pending,$SCCM = $false,$false,$false
                        
                        # Setting CBSRebootPend to null since not all versions of Windows has this value
                        $CBSRebootPend = $null
            
            # Querying WMI for build version
            $WMI_OS = Get-WmiObject -Class Win32_OperatingSystem -Property BuildNumber, CSName -ComputerName $Computer

            # Making registry connection to the local/remote computer
            $RegCon = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]"LocalMachine",$Computer)
            
            # If Vista/2008 & Above query the CBS Reg Key
            If ($WMI_OS.BuildNumber -ge 6001)
              {
                $RegSubKeysCBS = $RegCon.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\").GetSubKeyNames()
                $CBSRebootPend = $RegSubKeysCBS -contains "RebootPending"
                  
              }#End If ($WMI_OS.BuildNumber -ge 6001)
              
            # Query WUAU from the registry
            $RegWUAU = $RegCon.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\")
            $RegWUAURebootReq = $RegWUAU.GetSubKeyNames()
            $WUAURebootReq = $RegWUAURebootReq -contains "RebootRequired"
            
            # Query PendingFileRenameOperations from the registry
            $RegSubKeySM = $RegCon.OpenSubKey("SYSTEM\CurrentControlSet\Control\Session Manager\")
            $RegValuePFRO = $RegSubKeySM.GetValue("PendingFileRenameOperations",$null)
            
            # Closing registry connection
            $RegCon.Close()
            
            # If PendingFileRenameOperations has a value set $RegValuePFRO variable to $true
            If ($RegValuePFRO)
              {
                $PendFileRename = $true

              }#End If ($RegValuePFRO)

            # Determine SCCM 2012 Client Reboot Pending Status
            # To avoid nested 'if' statements and unneeded WMI calls to determine if the CCM_ClientUtilities class exist, setting EA = 0
            $CCMClientSDK = $null
                        $CCMSplat = @{
                            NameSpace='ROOT\ccm\ClientSDK'
                            Class='CCM_ClientUtilities'
                            Name='DetermineIfRebootPending'
                            ComputerName=$Computer
                            ErrorAction='SilentlyContinue'
                            }
                        $CCMClientSDK = Invoke-WmiMethod @CCMSplat
            If ($CCMClientSDK)
                            {
                                If ($CCMClientSDK.ReturnValue -ne 0)
                      {
                        Write-Warning "Error: DetermineIfRebootPending returned error code $($CCMClientSDK.ReturnValue)"
                            
                      }#End If ($CCMClientSDK -and $CCMClientSDK.ReturnValue -ne 0)

                    If ($CCMClientSDK.IsHardRebootPending -or $CCMClientSDK.RebootPending)
                      {
                        $SCCM = $true

                      }#End If ($CCMClientSDK.IsHardRebootPending -or $CCMClientSDK.RebootPending)

                            }#End If ($CCMClientSDK)
                        Else
                            {
                                $SCCM = $null

                            }                        
                        
                        # If any of the variables are true, set $Pending variable to $true
            If ($CBSRebootPend -or $WUAURebootReq -or $SCCM -or $PendFileRename)
              {
                $Pending = $true

              }#End If ($CBS -or $WUAU -or $PendFileRename)
              
            # Creating Custom PSObject and Select-Object Splat
                        $SelectSplat = @{
                            Property=('Computer','CBServicing','WindowsUpdate','CCMClientSDK','PendFileRename','PendFileRenVal','RebootPending')
                            }
            New-Object -TypeName PSObject -Property @{
                Computer=$WMI_OS.CSName
                CBServicing=$CBSRebootPend
                WindowsUpdate=$WUAURebootReq
                CCMClientSDK=$SCCM
                PendFileRename=$PendFileRename
                                PendFileRenVal=$RegValuePFRO
                RebootPending=$Pending
                } | Select-Object @SelectSplat

          }#End Try

        Catch
          {
            Write-Warning "$Computer`: $_"
            
            # If $ErrorLog, log the file to a user specified location/path
            If ($ErrorLog)
              {
                Out-File -InputObject "$Computer`,$_" -FilePath $ErrorLog -Append

              }#End If ($ErrorLog)
              
          }#End Catch
          
      }#End Foreach ($Computer in $ComputerName)
      
  }#End Process
  
End
  {
    # Resetting ErrorActionPref
    $ErrorActionPreference = $TempErrAct
  }#End End
  
}#End Function

Open in new window


Where would you suggest I place these lines?

$Servers = Get-Content C:\UTIL\Servers.txt
Get-PendingReboot -ComputerName $Servers | Export-CSV C:\Util\PendingRebootReportServers.csv -NoTypeInformation
$Computers = Get-Content C:\UTIL\Computers.txt
Get-PendingReboot -ComputerName $Computers | Export-CSV C:\Util\PendingRebootReportComputers.csv -NoTypeInformation

Open in new window


I thought the above are input values to the script?

I think I am missing quotes or something like that

This is all new to me trying to use more powershell than command prompt

Thanks
footechCommented:
Yep, I know.  :)
So if you append the mentioned lines to the file you will get
Function Get-PendingReboot
{
<#
.SYNOPSIS
    Gets the pending reboot status on a local or remote computer.

.DESCRIPTION
    This function will query the registry on a local or remote computer and determine if the
    system is pending a reboot, from either Microsoft Patching or a Software Installation.
    For Windows 2008+ the function will query the CBS registry key as another factor in determining
    pending reboot state.  "PendingFileRenameOperations" and "Auto Update\RebootRequired" are observed
    as being consistant across Windows Server 2003 & 2008.
  
    CBServicing = Component Based Servicing (Windows 2008)
    WindowsUpdate = Windows Update / Auto Update (Windows 2003 / 2008)
    CCMClientSDK = SCCM 2012 Clients only (DetermineIfRebootPending method) otherwise $null value
    PendFileRename = PendingFileRenameOperations (Windows 2003 / 2008)

.PARAMETER ComputerName
    A single Computer or an array of computer names.  The default is localhost ($env:COMPUTERNAME).

.PARAMETER ErrorLog
    A single path to send error data to a log file.

.EXAMPLE
    PS C:\> Get-PendingReboot -ComputerName (Get-Content C:\ServerList.txt) | Format-Table -AutoSize
  
    Computer CBServicing WindowsUpdate CCMClientSDK PendFileRename PendFileRenVal RebootPending
    -------- ----------- ------------- ------------ -------------- -------------- -------------
    DC01           False         False                       False                        False
    DC02           False         False                       False                        False
    FS01           False         False                       False                        False

    This example will capture the contents of C:\ServerList.txt and query the pending reboot
    information from the systems contained in the file and display the output in a table. The
    null values are by design, since these systems do not have the SCCM 2012 client installed,
    nor was the PendingFileRenameOperations value populated.

.EXAMPLE
    PS C:\> Get-PendingReboot
  
    Computer       : WKS01
    CBServicing    : False
    WindowsUpdate  : True
    CCMClient      : False
    PendFileRename : False
    PendFileRenVal : 
    RebootPending  : True
  
    This example will query the local machine for pending reboot information.
  
.EXAMPLE
    PS C:\> $Servers = Get-Content C:\Servers.txt
    PS C:\> Get-PendingReboot -Computer $Servers | Export-Csv C:\PendingRebootReport.csv -NoTypeInformation
  
    This example will create a report that contains pending reboot information.

.LINK
    Component-Based Servicing:
    http://technet.microsoft.com/en-us/library/cc756291(v=WS.10).aspx
  
    PendingFileRename/Auto Update:
    http://support.microsoft.com/kb/2723674
    http://technet.microsoft.com/en-us/library/cc960241.aspx
    http://blogs.msdn.com/b/hansr/archive/2006/02/17/patchreboot.aspx

    SCCM 2012/CCM_ClientSDK:
    http://msdn.microsoft.com/en-us/library/jj902723.aspx

.NOTES
    Author:  Brian Wilhite
    Email:   bwilhite1@carolina.rr.com
    Date:    08/29/2012
    PSVer:   2.0/3.0
    Updated: 05/30/2013
    UpdNote: Added CCMClient property - Used with SCCM 2012 Clients only
             Added ValueFromPipelineByPropertyName=$true to the ComputerName Parameter
             Removed $Data variable from the PSObject - it is not needed
             Bug with the way CCMClientSDK returned null value if it was false
             Removed unneeded variables
             Added PendFileRenVal - Contents of the PendingFileRenameOperations Reg Entry
#>

[CmdletBinding()]
param(
  [Parameter(Position=0,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
  [Alias("CN","Computer")]
  [String[]]$ComputerName="$env:COMPUTERNAME",
  [String]$ErrorLog
  )

Begin
  {
    # Adjusting ErrorActionPreference to stop on all errors, since using [Microsoft.Win32.RegistryKey]
        # does not have a native ErrorAction Parameter, this may need to be changed if used within another
        # function.
    $TempErrAct = $ErrorActionPreference
    $ErrorActionPreference = "Stop"
  }#End Begin Script Block
Process
  {
    Foreach ($Computer in $ComputerName)
      {
        Try
          {
            # Setting pending values to false to cut down on the number of else statements
            $PendFileRename,$Pending,$SCCM = $false,$false,$false
                        
                        # Setting CBSRebootPend to null since not all versions of Windows has this value
                        $CBSRebootPend = $null
            
            # Querying WMI for build version
            $WMI_OS = Get-WmiObject -Class Win32_OperatingSystem -Property BuildNumber, CSName -ComputerName $Computer

            # Making registry connection to the local/remote computer
            $RegCon = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey([Microsoft.Win32.RegistryHive]"LocalMachine",$Computer)
            
            # If Vista/2008 & Above query the CBS Reg Key
            If ($WMI_OS.BuildNumber -ge 6001)
              {
                $RegSubKeysCBS = $RegCon.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\").GetSubKeyNames()
                $CBSRebootPend = $RegSubKeysCBS -contains "RebootPending"
                  
              }#End If ($WMI_OS.BuildNumber -ge 6001)
              
            # Query WUAU from the registry
            $RegWUAU = $RegCon.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\")
            $RegWUAURebootReq = $RegWUAU.GetSubKeyNames()
            $WUAURebootReq = $RegWUAURebootReq -contains "RebootRequired"
            
            # Query PendingFileRenameOperations from the registry
            $RegSubKeySM = $RegCon.OpenSubKey("SYSTEM\CurrentControlSet\Control\Session Manager\")
            $RegValuePFRO = $RegSubKeySM.GetValue("PendingFileRenameOperations",$null)
            
            # Closing registry connection
            $RegCon.Close()
            
            # If PendingFileRenameOperations has a value set $RegValuePFRO variable to $true
            If ($RegValuePFRO)
              {
                $PendFileRename = $true

              }#End If ($RegValuePFRO)

            # Determine SCCM 2012 Client Reboot Pending Status
            # To avoid nested 'if' statements and unneeded WMI calls to determine if the CCM_ClientUtilities class exist, setting EA = 0
            $CCMClientSDK = $null
                        $CCMSplat = @{
                            NameSpace='ROOT\ccm\ClientSDK'
                            Class='CCM_ClientUtilities'
                            Name='DetermineIfRebootPending'
                            ComputerName=$Computer
                            ErrorAction='SilentlyContinue'
                            }
                        $CCMClientSDK = Invoke-WmiMethod @CCMSplat
            If ($CCMClientSDK)
                            {
                                If ($CCMClientSDK.ReturnValue -ne 0)
                      {
                        Write-Warning "Error: DetermineIfRebootPending returned error code $($CCMClientSDK.ReturnValue)"
                            
                      }#End If ($CCMClientSDK -and $CCMClientSDK.ReturnValue -ne 0)

                    If ($CCMClientSDK.IsHardRebootPending -or $CCMClientSDK.RebootPending)
                      {
                        $SCCM = $true

                      }#End If ($CCMClientSDK.IsHardRebootPending -or $CCMClientSDK.RebootPending)

                            }#End If ($CCMClientSDK)
                        Else
                            {
                                $SCCM = $null

                            }                        
                        
                        # If any of the variables are true, set $Pending variable to $true
            If ($CBSRebootPend -or $WUAURebootReq -or $SCCM -or $PendFileRename)
              {
                $Pending = $true

              }#End If ($CBS -or $WUAU -or $PendFileRename)
              
            # Creating Custom PSObject and Select-Object Splat
                        $SelectSplat = @{
                            Property=('Computer','CBServicing','WindowsUpdate','CCMClientSDK','PendFileRename','PendFileRenVal','RebootPending')
                            }
            New-Object -TypeName PSObject -Property @{
                Computer=$WMI_OS.CSName
                CBServicing=$CBSRebootPend
                WindowsUpdate=$WUAURebootReq
                CCMClientSDK=$SCCM
                PendFileRename=$PendFileRename
                                PendFileRenVal=$RegValuePFRO
                RebootPending=$Pending
                } | Select-Object @SelectSplat

          }#End Try

        Catch
          {
            Write-Warning "$Computer`: $_"
            
            # If $ErrorLog, log the file to a user specified location/path
            If ($ErrorLog)
              {
                Out-File -InputObject "$Computer`,$_" -FilePath $ErrorLog -Append

              }#End If ($ErrorLog)
              
          }#End Catch
          
      }#End Foreach ($Computer in $ComputerName)
      
  }#End Process
  
End
  {
    # Resetting ErrorActionPref
    $ErrorActionPreference = $TempErrAct
  }#End End
  
}#End Function

$Servers = Get-Content C:\UTIL\Servers.txt
Get-PendingReboot -ComputerName $Servers | Export-CSV C:\Util\PendingRebootReportServers.csv -NoTypeInformation
$Computers = Get-Content C:\UTIL\Computers.txt
Get-PendingReboot -ComputerName $Computers | Export-CSV C:\Util\PendingRebootReportComputers.csv -NoTypeInformation

Open in new window

Notice the last four lines.  Once a function is defined in a script, it can be called/run in that same script.  Save that as a .ps1, then you can run it (whether from within a batch file, scheduled task, etc.) with something like
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -file Get-PendingReboot.ps1

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Thomas GrassiSystems AdministratorAuthor Commented:
Footech

Worked

Thanks
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Powershell

From novice to tech pro — start learning today.