PowerShell equivalent for the "at" command - powershell

We are porting Unix scripts to PowerShell. I am totally new to PowerShell and have problem in finding replacement for the at command in Unix.
We have a script that is scheduled using the at command:
SEQ_NO=12; export SEQ_NO
A=R2.13575180; export A
B=R4.13575180.DAT; export B
chmod 777 R4.13575180.DAT
echo "sh R4.13575180.DAT > M.reclog " |
at now + 2 minutes
R4.13575180.DAT would contain PowerShell commands inside. I was able to find replacements for other commands. I need to find a replacement for the at command. I did go through certain links, but I am still not clear. Could you suggest a replacement?

Since you're new to PowerShell, here is some general advice:
Make sure you are running the latest operating system possible, to get the most recent features (eg. Windows 8.1)
Make sure you have installed the latest Microsoft .NET Framework version (eg. Microsoft .NET Framework 4.5.1)
The Microsoft .NET Framework 4.5.1 is already included with Windows 8.1
Make sure you are running the latest PowerShell (aka. Windows Management Framework (WMF) Core) version
The latest version of WMF is 4.0
The WMF / PowerShell 4.0 package is built into Windows 8.1 (Windows Server 2012 R2) and is available for Windows 7 (Server 2008 R2)
WMF 4.0 is not available for Windows 8.0
IMPORTANT: The ScheduledTasks PowerShell module is available only on Windows 8.1 with the Microsoft .NET Framework 4.5.1 and PowerShell version 4.0.
You're most likely looking for the PowerShell module named ScheduledTasks, if you want to schedule something to run in the future.
To find out what commands are in the ScheduledTasks module, use this command:
Get-Command -Module ScheduledTasks;
To be more specific in answer to your question, here is an example of how to create a ScheduledTask:
# 1. Create a trigger
$Trigger = New-ScheduledTaskTrigger -At '2013-12-30 12:00:00 AM' -Once;
# 2. Create an action
$Action = New-ScheduledTaskAction -Execute powershell.exe -Argument '-Command Write-Host -Object "hi";'
# 3. Create the scheduled task
$Task = New-ScheduledTask -Action $Action -Trigger $Trigger -Description PowerShell;
# 4. Register the ScheduledTask
Register-ScheduledTask -InputObject $Task -TaskName PowerShell;
# 5. [Optional] View / confirm the ScheduledTask object
Get-ScheduledTask -TaskName PowerShell;

Since you're running Windows 7 / PowerShell 2.0 you might want to grab the TaskScheduler module from PowerShellPack.
That will get you cmdlets for managing scheduled tasks.

Related

Why doesn't Console in PowerShell ISE use the latest installed version of PowerShell?

I have recently installed PowerShell 6.2.
If I start a PowerShell 6 (x64) command prompt and run $PSVersionTable.PSVersion this is the result
Major Minor Patch PreReleaseLabel BuildLabel
----- ----- ----- --------------- ----------
6 2 0
From the same prompt I run the ISE using powershell_ise.exe and the PowerShell ISE starts. However, in the console within ISE if I run $PSVersionTable.PSVersion it reports this:
Major Minor Build Revision
----- ----- ----- --------
4 0 -1 -1
Is there a setting to control where ISE looks for PowerShell? Or is there any way to ensure it is using the latest version installed?
UPDATE: As part of installing PowerShell Core (i.e. ver 6.2) I had to install Windows Management Framework 5.1. My understanding from this doc is that this should have upgraded the ISE console's version of PowerShell to 5.1 as well. I am still seeing ver 4.0 as noted above. What am I missing?
The latest version of PowerShell is 5.1, this is the most recent version that you can use in ISE as well.
PowerShell 6 is also known as PowerShell Core, which is not supported in ISE. You can download a tool called Visual Studio Code that can be used with PowerShell 6 (Core).
Bonus:
Interestingly enough, there was actually an article I read recently about a PowerShell 7 that Microsoft is currently working on which looks pretty interesting. See here as well for PowerShell 7.
Update: Thanks #Magnetron for updating in the comments. PowerShell 7 officially released this week.
Hope this helps!
I used the following link to add an add-on to Powershell ISE that will allow you to switch between Powershell 5 and 6. (See 'PowerShell ISE Add-On Command’) However, when you close out of Powershell ISE and open a new session you have to run the script again otherwise the option 'Add-ons' will not be there. I'm guessing the same process could be used when Powershell 7 is released.
Using PowerShell Core 6 and 7 in the Windows PowerShell ISE
There's also a new feature in VSCode that emulates the ISE: https://devblogs.microsoft.com/powershell/visual-studio-code-for-powershell-7/
How to use ISE mode in VScode: https://www.thomasmaurer.ch/2020/03/how-to-use-powershell-ise-mode-in-visual-studio-code/
I would take a read of this guide - https://ironmansoftware.com/using-powershell-core-6-and-7-in-the-windows-powershell-ise/
It allows the ISE process to switch the backend PowerShell to be version 7. It even includes creation of a menu item and shortcut to swap the backend version. This is very handy and I have been using it with ISE for some time.
For those who wants a shorter version of enabling this.
Run this while in ISE (taken from the link from the other answers)
$psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Clear()
$psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Switch to PowerShell 7", {
function New-OutOfProcRunspace {
param($ProcessId)
$ci = New-Object -TypeName System.Management.Automation.Runspaces.NamedPipeConnectionInfo -ArgumentList #($ProcessId)
$tt = [System.Management.Automation.Runspaces.TypeTable]::LoadDefaultTypeFiles()
$Runspace = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace($ci, $Host, $tt)
$Runspace.Open()
$Runspace
}
$PowerShell = Start-Process PWSH -ArgumentList #("-NoExit") -PassThru -WindowStyle Hidden
$Runspace = New-OutOfProcRunspace -ProcessId $PowerShell.Id
$Host.PushRunspace($Runspace)
}, "ALT+F5") | Out-Null
$psISE.CurrentPowerShellTab.AddOnsMenu.Submenus.Add("Switch to Windows PowerShell", {
$Host.PopRunspace()
$Child = Get-CimInstance -ClassName win32_process | where {$_.ParentProcessId -eq $Pid}
$Child | ForEach-Object { Stop-Process -Id $_.ProcessId }
}, "ALT+F6") | Out-Null
Then re-launch your ISE and go to Add-ons button next to File, Edit, View ant etc. There should be a Switch to Powershell 7 option now.
That's it! 1 min job.

SCCM Powershell Script Package

I have created a package in SCCM 2012 that should deploy and run a powershell script. I have looked at a previous post on here Other Post but there wasn't any information.
In the Program Command Line, I have the following command:
powershell.exe -ExecutionPolicy Bypass -force -WindowStyle Hidden .\PowershellUpdateScript.ps1
I am targeting a test group and setting it to deploy immediately however when I check the deployment status, it shows as status "In Progress" and Description "Received". It has been that way for over 2 hours. I am not sure where the issue is.
I know that the Scripts feature is there and super convenient but the client powershell version needs to be a minimum version 3. The irony is that this package will update client powershell versions.
Any suggestions or advise would be greatly appreciated.
Since you are updating the powershell version, instead of using a powershell script you should download the MS update package for the version of powershell.
You can then use the wusa.exe command to deploy the update. Then use this ps command as a detection method
Get-WmiObject Win32_QuickFixEngineering -filter "HotFixID='KB#######'"

Powershell running a cmdlet from a called script

I have a script that calls another script (with arguments). The called script contains the Install-WindowsFeature cmdlet. When I run the script, the called script runs, but returns the following error:
Install-WindowsFeature : The term 'Install-WindowsFeature' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path
Of course, I can run the cmdlet just fine from a PowerShell console. I can also run the called script from a PowerShell console and Install-WindowsFeature works fine. So, is it something to do with calling a script from a script that runs a cmdlet? Here is my calling code:
$script = "C:\Path\script.ps1"
$argumentList = #()
$argumentlist += ("-Arg1", "value")
$argumentlist += ("-Arg2", "value")
$argumentlist += ("-Arg3", "value")
Invoke-Expression "$script $argumentList"
In the called script, I called Install-WindowsFeature as below:
if ($someValue) { Invoke-Command -ScriptBlock {Install-WindowsFeature -Name RSAT-AD-Tools} }
I've also tried it as below:
if ($someValue) { Install-WindowsFeature -Name RSAT-AD-Tools }
12/16/16 EDIT: This script is running in a GUI built with Sapien PowerShell Studio. When I change the build type to "Native" it works. I have to reset my lab to check, but I suspect it will also run if I just run it in the x64 context. This article explains why I think this matters.
Running on Windows Server 2012 R2
Unless you've got a compelling reason for it, let's see if we can clean up your calling pattern a bit - and hopefully make your other issues go away by avoiding the contortionism.
Rather than creating your parameter list as a string, take advantage of parameter splatting. It's good to get out of the habit of treating PowerShell like other scripting languages that don't work with objects.
$splat = #{
Arg1 = "value1";
Arg2 = "value2";
Arg3 = "value3"
}
& c:\path\script.ps1 #splat
Using that on a script.ps1 something like this:
param(
$Arg1,
$Arg2,
$Arg3
)
Write-Host "Arg1 = $Arg1, Arg2 = $Arg2, Arg3 = $Arg3
You'll get an expected output of:
Arg1 = value1, Arg2 = value2, Arg3 = value3
Once you've got that, there's probably no reason to use Invoke-Command on the call to Install-WindowsFeature, unless you're leaving out details like invoking remotely to a server. Invoke-Command { Install-WindowsFeature } still works fine for me on Server 2012R2 with PowerShell 5, and there's no reason it shouldn't.
This assumes you're running this script on a Server that support Install-WindowsFeature, as the other comments point out. Client Windows doesn't support Install-WindowsFeature, and the RSAT tools are installed via a stand-alone RSAT .MSU package, which you manage differently.
Install-WindowsFeature is natively provided with Server Manager on Server 2012R2 - there's no need to Import-Module... unless you've done something to your profile or fouled up your modules folders. One of the earlier versions of Windows Server needed it - but that was a couple versions back. Likewise, Add-WindowsFeature was the old name - and it's still available as an alias for Install-WindowsFeature.
I'm assuming you've tried Install-WindowsFeature directly from the command line to ensure it's in working order, and Get-Module Install-WindowsFeature looks reasonable.
PS C:\Windows\system32> get-module ServerManager
ModuleType Version Name ExportedCommands
---------- ------- ---- ----------------
Script 2.0.0.0 ServerManager {Get-WindowsFeature, Install-WindowsFeature, Uninstall-Win...
While we're on the topic, there's very little reason to drop to DISM on Server that supports Install-WindowsFeature, and a number of reasons not to.
Server Manager and several other tools (including Win32_ServerFeature) rely on the feature states parsed and understood by the WMI provider used by Install-WindowsFeature. It's possible to enable the right set of features using DISM, but needs attention and detail. Enabling only "part" of a role and feature may get the functionality you want for specific cases, but the role or feature may not show up as installed in Get-WindowsFeature, may not be uninstallable via Remove-WindowsFeature, and may not offer relevant UI features in Server Manager like monitoring health of the role, viewing relevant events, or offering tools for administering it.
Install-WindowsFeature integrates with additional code from the role & features you're installing, and may run additional health and pre-requisite checks to ensure your correctly configured.
DISM featurenames tend to change more often than the role & feature name of Server Manager, so your script portability will be better.
There are other points, but I won't go into them since DISM was primarily a comment fork.
You are probably right, it seems like the script gets executed with x86 PowerShell. I want to share a snippet with you which I use for scripts that needs to run in a specific environment (e. g. x64 PowerShell).
The script restarts itself in a x64 PowerShell if its started as x86 process. Just put this at the top of your script:
# Reinvoke the script as x64 if its called from a x86 process.
if ($env:Processor_Architecture -eq "x86")
{
&"$env:windir\sysnative\WindowsPowerShell\v1.0\powershell.exe" -noprofile -file $myinvocation.Mycommand.path -executionpolicy bypass
exit
}
Also note that the Install-WindowsFeature cmdlet doesn't work on all windows versions so consider to use dism instead:
$featuresToInstall = #('RSAT-AD-Tools')
$dismParameter = #('/online', '/Enable-Feature', ($featuresToInstall | % { '/FeatureName:{0}' -f $_ }), '/NoRestart')
dism #dismParameter
The running environment determines what modules you have access to. When I created this project in PowerShell Studio, it took the default of x86 (a 32 bit environment). This worked but because I was running it on Windows Server 2012 R2 (a 64-bit environment) I did not have access to the powershell modules such as Import-Module and Install-WindowsFeature. Changing this to a x64 project resolved my issue.
In order to avoid this scenario, it is important to make sure you run PowerShell scripts and modules in the architecture that is native to the OS. You can do this by setting the project correctly (if using a tool like PowerShell Studio) or by verifying that you are running in the native mode for that OS with the code Martin Brandl provided.

Creating a scheduled task on Windows 7 using Powershell 4

Am I right in thinking that some of the newer Powershell commands related to the management of scheduled tasks (such as New-ScheduledTaskAction) are not available on Windows 7 or Server 2008 R2, even if Powershell 4 is installed?
Yes you right, some PowerShell cmdlet it depend on the windows kernel.
The command New-ScheduledTaskAction supported windows 8 / server 2012 and newer.
you can read about id in
https://technet.microsoft.com/en-us/library/jj649817.aspx .
In windows 7 / server 2008 R2 you can use the new-ScheduledJobOption and the Register-ScheduledJob cmdlet.
you can read more about it here https://msdn.microsoft.com/en-us/powershell/reference/5.1/psscheduledjob/psscheduledjob
Here you can see example:
New-ScheduledJobOption -RunElevated -ContinueIfGoingOnBattery
Register-ScheduledJob -FilePath C:\Users\User\Desktop\CreateFolderTest.ps1 -Name TestJob -RunNow
if you want to see the job in the Task Scheduler, go to `Task Scheduler Library -> Microsoft -> Windows -> PowerShell -> ScheduledJobs
for more option you can edit the Task in the "Task Schduler" and run the Get-ScheduledJobOption.
The last thing, the Get-ScheduledJob show only the jobs that you created with the Register-ScheduledJob!
I hope it will help you.
David,
Based on my own experience (I have the Server 2008 R2 and Powershell 4 is installed), the newer cmdlets for scheduled tasks (such as New-ScheduledTaskAction) are not recognizable by Server 2008 R2. I also tried to add the newer cmdlets into the system32\WindowsPowerShell\v1.0\Modules folder but it is still not working.
Other post I read said these Cmdlets are coming with server 2012 or Windows 8 or later.
thanks
Liang

How do I get PowerShell 4 cmdlets such as Test-NetConnection to work on Windows 7?

The situation. On a Windows 7 SP1 machine, I have updated with Windows6.1-KB2819745-x64-MultiPkg.msu. Furthermore, in PowerShell $PSVersionTable now reports ‘PSVersion 4.0’.
At present, my conclusion is that many PowerShell 4 cmdlets such Test-NetConnection, will only work on Windows 8.1. However, I was wondering if there was a work-around whereby I could import PowerShell 4 modules on my Windows 7 machine.
You cannot. They rely on the underlying features of the newer OS (8.0 or 8.1) and cannot be ported back to Windows 7 . The alternative is to write your own functions / modules to replicate the new cmdlets using .NET framework methods.
For instance, the Get-FileHash cmdlet is a one-liner in PowerShell 4.0, but to replicate in 2.0 we have to use .NET.
PowerShell v4
Get-FileHash -Algorithm SHA1 "C:\Windows\explorer.exe"
PowerShell v2
$SHA1 = new-object -TypeName System.Security.Cryptography.SHA1CryptoServiceProvider
$file = [System.IO.File]::Open("C:\Windows\explorer.exe",[System.IO.Filemode]::Open, [System.IO.FileAccess]::Read)
[System.BitConverter]::ToString($SHA1.ComputeHash($file)) -replace "-",""
$file.Close()
At least Test-NetConnection can be ported back to Windows 7. Just copy folders NetTCPIP, DnsClient, and NetSecurity from the supported Windows machine with the same PowerShell version (Windows 8.1, Windows 10, etc). Folder - C:\Windows\System32\WindowsPowerShell\v1.0\Modules. Then Import-Module -Name C:\Windows\System32\WindowsPowerShell\v1.0\Modules\NetTCPIP -Verbose
Alternatively, you can import a module from a remote machine (say win2012):
$rsession = New-PSSession -ComputerName win2012
Import-Module NetTCPIP -PSSession $rsession
I have had the same problem on my Windows 7 x64 and both solutions worked for me as of PowerShell 5.1.
Adding to Anton Krouglov's answer. PowerShell modules are cross-platform compatible. So a module copied from Windows Server 2012 R2 x64 can be imported to Windows 7 x86, and even if you are running as standard user without rights to copy them to C:\Windows\System32\WindowsPowerShell\v1.0\Modules you can copy it to any local folder, and run.
Assuming you copied the NetTCPIP, DnsClient, and NetSecurity modules from a Windows Server 2012 or higher machine, and save them to a folder you can import them using
Get-ChildItem -Directory .\psmodules | foreach { Import-Module -Name $_.FullName -Verbose}
Test-NetConnection -InformationLevel "Detailed"
As far as I know, Windows Server 2008 R2/Windows 7 simply doesn't have the counters that the .NET methods use to implement get-netstuff.
A new PowerShell version can implement hash compare, etc. since this is not related to anything, just a piece of code. But if you want to use, for example, Get-NetTCPConnection there is nothing to show.
I see several responses which assert portability, and my testing confirms their assertions:
Import all of the required modules, either from file, or via a PSSession to a host which has the required modules.
The architecture of PowerShell Console (x86 or x64) you run will determine which module architecture you import.
For those who are:
still unable to make this work
AND
do need a reliable TCP test, but may not need everything else provided by Test-NetConnection
AND
Need it all to work even on PowerShell v2.0
You may wish to try this.
# Create a TCP Client using .Net & attempt connection to target
$TCPClient = New-Object .net.sockets.tcpclient("[IP address or hostname]",[port])
# At the above point you may see familiar-looking Windows error messages in
# red text. (You may want to use "try/catch" if you intend to loop).
# Otherwise, check your new object's status to see if it worked
$TCPClient.Connected
# The response is either "True" or False"
# Now to avoid leaving idle connections, run:
$TCPClient.Close()
Naturally, it should be possible to create a loop which tests multiple connections, and outputs the results by selecting the properties of the $TCPClient.
My initial testing shows you would want to Select these properties
The address you tested
$TCPClient.Client.RemoteEndPoint.Address.IPAddressToString
The port you tested
$TCPClient.Client.RemoteEndPoint.Port
The result
$TCPClient.Connected
HIH
While PowerShell 4.0 is available on Windows 7, as Knuckle-Dragger states certain features rely on newer operating system functionality. Unfortunately Test-NetConnection is not available in Windows 7 as stated in the documentation.
Test-Connection, which is present, is basically ping. Test-NetConnection offers much more functionality, allowing a choice of things such as TCP ports, protocols, route tracing, and information levels.
There is a Send-Ping script available from the ScriptCenter in the TechNet gallery, but I think this is only really useful if you are stuck on PowerShell 3.0 for some reason.
I can only assume you installed the wrong package. Make sure you download the proper package from here.
Below you will see in running Windows 7 Service Pack 1 with PowerShell 4 using Test-Connection and Get-FileHash: