How to automatically save PowerShell session - powershell

How can i redirect everything what happens within a PowerShell windows (inputs and outputs) automatically to a file? I don't mean single commands instead i would like to have something like a logger which captures everything and logs into a local file so that i have a history of things done within the powershell window.

You're looking for PowerShell's Start-Transcript cmdlet, which:
creates a record of all or part of a Windows PowerShell session to a text file. The transcript includes all command that the user types and all output that appears on the console.
Running transcripts must be stopped explicitly, with the Stop-Transcript cmdlet.

Related

Powershell Start-Process VS Invoke-Item

What's the difference between Start-Process and Invoke-Item? I noticed that you can't Invoke-Item chrome. I assume that Invoke-Item is specifically for files with a given file path. But are there any advantages to using Invoke-Item instead of Start-Process (besides that typing ii is faster than typing start)?
The Invoke-Item cmdlet performs the default action on the specified item. For example, it runs an executable file or opens a document file in the application associated with the document file type. The default action depends on the type of item and is determined by the PowerShell provider that provides access to the data.
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/invoke-item?view=powershell-6
The Start-Process cmdlet starts one or more processes on the local computer. To specify the program that runs in the process, enter an executable file or script file, or a file that can be opened by using a program on the computer. If you specify a non-executable file, Start-Process starts the program that is associated with the file, similar to the Invoke-Item cmdlet.
You can use the parameters of Start-Process to specify options, such as loading a user profile, starting the process in a new window, or using alternate credentials.
https://learn.microsoft.com/en-us/powershell/module/Microsoft.PowerShell.Management/Start-Process?view=powershell-6

Powershell - Log file

I have a PowerShell script, at its begining I added: $ErrorActionPreference = "Stop". It's good, if there is an error the script won't go further.
Fact is that when an error occurs, the script stop and exit itself and so, I can not see the error.
The best option is to crate a logfile that will write EVERYTHING that was in the PowerShell terminal, including succesful lines.
If not, at least make the terminal keep opened even if an error occurs, but stop the script.
I would recommend Start-Transcript:
The Start-Transcript cmdlet creates a record of all or part of a
PowerShell session to a text file. The transcript includes all command
that the user types and all output that appears on the console.

Is it possible to start Powershell ISE with specified (not default) profile?

I want to have several (more than one) PowerShell profiles which will create different environments.
More specifically I need way for start separate PowerShell ISE for work with TFS and other PowerShell ISE instance for regular work. 'TFS' environment require loading some additional snappins, modules, modify prompt and so on. I do not want all this stuff will be executed for regular PowerShell ISE sessions but only when I want to.
I found that I can automatically load arbitrary script through command line parameter -File, but it does not executed automatically..
I do it by creating a shortcut for PowerShell ISE with a default directory :
In the default Directory (here called D:\TFS) I create a .PS1 file called local_profile.ps1.
In the beginning of the current profile file (C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1) I add :
# Try to load local profile
Get-ChildItem "local_profile.ps1" -ErrorAction SilentlyContinue | %{.$_}
You just have to add your initialization code to D:\TFS\local_profile.ps1.
powershell ISE has a profile too.
Probably is something like:
E:\Users\UserName\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1
Or you can open powershell ise and look at $profile variable.
After locate your profile file, write your modules import and custom scripts in it.

Redirect PowerShell stdout to a file when executed in a remote session

I need to log everything printed to stdout to a file. Start-Transcript/Stop-Transcript works great and does exactly this, but only for the local PowerShell sessions. The problem is that Transcripts are not supported when executing PowerShell scripts in a remote session (using Enter-PSSession cmd).
Is there another (preferably simple) way to redirect all output to a file, even if the .ps1 script is executed in a remote session?
I'd prefer not to have to add >> or Tee or out-file etc. to every line in the script that has output.
I also do not want to Start-Transcript before entering the remote session. I'm remoting to many destinations in a loop and I need each remote session's stdout logged to a separate file (local to the endpoint), not all bundled into a single file.
I suggest using the Start-Transcript before entering the session, and using the -Path option of that cmdlet to point to a separate file for each session. Perhaps something like
Start-Transcript -Path C:\Logs\$MachineName-$($(Get-Date).ToString("yyyyMMddhhmm")).log
Or something similar. My personal preference is a date-time appendage for historical purposes.

My PowerShell script only works when running from ISE

I can't post all of the script contenet, but the basic idea is that it downloads JSON and converts it to objects using the ConvertFrom-Json cmdlet. Some objects are filtered out, and the rest are written to an XML/XLS document (in the Excel 2003 format). This file is then attached to an email and sent to various people.
The problem I'm having is that it only works when run from the Powershell ISE. Once I try setting up a scheduled task, calling it from cmd, or even calling it from powershell, the attached file is completely empty. It is as if some functions do not run (the one that loops through and creates all rows).
I can continue to run from ISE for the time being, but the idea of this script is to send out an automatic email that will require no intervention. Any ideas as to what could be causing this?
You need to run the script "dot sourced"
which can be done like this
powershell.exe -noexit -file c:\test.ps1
or
pwershell.exe -noexit ". c:\test.ps1"
See this link under the -File section
http://technet.microsoft.com/en-us/library/hh847736.aspx
Based on the answer from the comments to the original post, it seems that the script was (unexpectedly?) working in the ISE because of the bug/quirk/feature that allows scripts run in the ISE to be aware of variables used in the console window and vice-versa.
This can often cause logic problems or unexpected results when a script runs with a variable already defined (and not initialized carefully in the script).
Ways to avoid this problem:
Try to test your code in as clean an environment as possible.
http://powershell.com/cs/blogs/tips/archive/2015/02/12/getting-a-clean-powershell-environment.aspx
To make sure a script runs in a completely clean test environment, you
could of course restart the PowerShell ISE. A more convenient way is
to open another PowerShell tab: in the PowerShell ISE, choose File/New
PowerShell Tab.
Use Set-StrictMode 2 in your script to catch undefined variables, etc.
https://technet.microsoft.com/en-us/library/hh849692.aspx
Set-StrictMode -Version 2.0
Prohibits references to uninitialized variables (including uninitialized variables in strings).
Prohibits references to non-existent properties of an object.
Prohibits function calls that use the syntax for calling methods.
Prohibits a variable without a name (${}).
I have had this problem be for and for me executing the scrip using single-threaded function from powershell worked.
You could also try some other options, go to this link to find more info.
Example
powershell.exe -noexit c:\test.ps1 -sta
Change the missing variable or function to global.
function global:mycall{}
Start your Script with:
[cmdletbinding()]